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
40afd73f1bSNicholas Bellinger sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char *, u32, bool);
4162e46942SChristoph Hellwig static sense_reason_t sbc_execute_unmap(struct se_cmd *cmd);
42afd73f1bSNicholas Bellinger 
43afd73f1bSNicholas Bellinger static sense_reason_t
44de103c93SChristoph Hellwig sbc_emulate_readcapacity(struct se_cmd *cmd)
451fd032eeSChristoph Hellwig {
461fd032eeSChristoph Hellwig 	struct se_device *dev = cmd->se_dev;
478dc8632aSRoland Dreier 	unsigned char *cdb = cmd->t_task_cdb;
481fd032eeSChristoph Hellwig 	unsigned long long blocks_long = dev->transport->get_blocks(dev);
49a50da144SPaolo Bonzini 	unsigned char *rbuf;
50a50da144SPaolo Bonzini 	unsigned char buf[8];
511fd032eeSChristoph Hellwig 	u32 blocks;
521fd032eeSChristoph Hellwig 
538dc8632aSRoland Dreier 	/*
548dc8632aSRoland Dreier 	 * SBC-2 says:
558dc8632aSRoland Dreier 	 *   If the PMI bit is set to zero and the LOGICAL BLOCK
568dc8632aSRoland Dreier 	 *   ADDRESS field is not set to zero, the device server shall
578dc8632aSRoland Dreier 	 *   terminate the command with CHECK CONDITION status with
588dc8632aSRoland Dreier 	 *   the sense key set to ILLEGAL REQUEST and the additional
598dc8632aSRoland Dreier 	 *   sense code set to INVALID FIELD IN CDB.
608dc8632aSRoland Dreier 	 *
618dc8632aSRoland Dreier 	 * In SBC-3, these fields are obsolete, but some SCSI
628dc8632aSRoland Dreier 	 * compliance tests actually check this, so we might as well
638dc8632aSRoland Dreier 	 * follow SBC-2.
648dc8632aSRoland Dreier 	 */
658dc8632aSRoland Dreier 	if (!(cdb[8] & 1) && !!(cdb[2] | cdb[3] | cdb[4] | cdb[5]))
668dc8632aSRoland Dreier 		return TCM_INVALID_CDB_FIELD;
678dc8632aSRoland Dreier 
681fd032eeSChristoph Hellwig 	if (blocks_long >= 0x00000000ffffffff)
691fd032eeSChristoph Hellwig 		blocks = 0xffffffff;
701fd032eeSChristoph Hellwig 	else
711fd032eeSChristoph Hellwig 		blocks = (u32)blocks_long;
721fd032eeSChristoph Hellwig 
731fd032eeSChristoph Hellwig 	buf[0] = (blocks >> 24) & 0xff;
741fd032eeSChristoph Hellwig 	buf[1] = (blocks >> 16) & 0xff;
751fd032eeSChristoph Hellwig 	buf[2] = (blocks >> 8) & 0xff;
761fd032eeSChristoph Hellwig 	buf[3] = blocks & 0xff;
770fd97ccfSChristoph Hellwig 	buf[4] = (dev->dev_attrib.block_size >> 24) & 0xff;
780fd97ccfSChristoph Hellwig 	buf[5] = (dev->dev_attrib.block_size >> 16) & 0xff;
790fd97ccfSChristoph Hellwig 	buf[6] = (dev->dev_attrib.block_size >> 8) & 0xff;
800fd97ccfSChristoph Hellwig 	buf[7] = dev->dev_attrib.block_size & 0xff;
811fd032eeSChristoph Hellwig 
82a50da144SPaolo Bonzini 	rbuf = transport_kmap_data_sg(cmd);
838b4b0dcbSNicholas Bellinger 	if (rbuf) {
84a50da144SPaolo Bonzini 		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
851fd032eeSChristoph Hellwig 		transport_kunmap_data_sg(cmd);
868b4b0dcbSNicholas Bellinger 	}
871fd032eeSChristoph Hellwig 
882426bd45SRoland Dreier 	target_complete_cmd_with_length(cmd, GOOD, 8);
891fd032eeSChristoph Hellwig 	return 0;
901fd032eeSChristoph Hellwig }
911fd032eeSChristoph Hellwig 
92de103c93SChristoph Hellwig static sense_reason_t
93de103c93SChristoph Hellwig sbc_emulate_readcapacity_16(struct se_cmd *cmd)
941fd032eeSChristoph Hellwig {
951fd032eeSChristoph Hellwig 	struct se_device *dev = cmd->se_dev;
962d335983SNicholas Bellinger 	struct se_session *sess = cmd->se_sess;
979ef5466eSNicholas Bellinger 	int pi_prot_type = dev->dev_attrib.pi_prot_type;
989ef5466eSNicholas Bellinger 
99a50da144SPaolo Bonzini 	unsigned char *rbuf;
100a50da144SPaolo Bonzini 	unsigned char buf[32];
1011fd032eeSChristoph Hellwig 	unsigned long long blocks = dev->transport->get_blocks(dev);
1021fd032eeSChristoph Hellwig 
103a50da144SPaolo Bonzini 	memset(buf, 0, sizeof(buf));
1041fd032eeSChristoph Hellwig 	buf[0] = (blocks >> 56) & 0xff;
1051fd032eeSChristoph Hellwig 	buf[1] = (blocks >> 48) & 0xff;
1061fd032eeSChristoph Hellwig 	buf[2] = (blocks >> 40) & 0xff;
1071fd032eeSChristoph Hellwig 	buf[3] = (blocks >> 32) & 0xff;
1081fd032eeSChristoph Hellwig 	buf[4] = (blocks >> 24) & 0xff;
1091fd032eeSChristoph Hellwig 	buf[5] = (blocks >> 16) & 0xff;
1101fd032eeSChristoph Hellwig 	buf[6] = (blocks >> 8) & 0xff;
1111fd032eeSChristoph Hellwig 	buf[7] = blocks & 0xff;
1120fd97ccfSChristoph Hellwig 	buf[8] = (dev->dev_attrib.block_size >> 24) & 0xff;
1130fd97ccfSChristoph Hellwig 	buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff;
1140fd97ccfSChristoph Hellwig 	buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff;
1150fd97ccfSChristoph Hellwig 	buf[11] = dev->dev_attrib.block_size & 0xff;
11656dac14cSNicholas Bellinger 	/*
11756dac14cSNicholas Bellinger 	 * Set P_TYPE and PROT_EN bits for DIF support
11856dac14cSNicholas Bellinger 	 */
1192d335983SNicholas Bellinger 	if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
1209ef5466eSNicholas Bellinger 		/*
1219ef5466eSNicholas Bellinger 		 * Only override a device's pi_prot_type if no T10-PI is
1229ef5466eSNicholas Bellinger 		 * available, and sess_prot_type has been explicitly enabled.
1239ef5466eSNicholas Bellinger 		 */
1249ef5466eSNicholas Bellinger 		if (!pi_prot_type)
1259ef5466eSNicholas Bellinger 			pi_prot_type = sess->sess_prot_type;
1269ef5466eSNicholas Bellinger 
1279ef5466eSNicholas Bellinger 		if (pi_prot_type)
1289ef5466eSNicholas Bellinger 			buf[12] = (pi_prot_type - 1) << 1 | 0x1;
1292d335983SNicholas Bellinger 	}
1307f7caf6aSAndy Grover 
1317f7caf6aSAndy Grover 	if (dev->transport->get_lbppbe)
1327f7caf6aSAndy Grover 		buf[13] = dev->transport->get_lbppbe(dev) & 0x0f;
1337f7caf6aSAndy Grover 
1347f7caf6aSAndy Grover 	if (dev->transport->get_alignment_offset_lbas) {
1357f7caf6aSAndy Grover 		u16 lalba = dev->transport->get_alignment_offset_lbas(dev);
1367f7caf6aSAndy Grover 		buf[14] = (lalba >> 8) & 0x3f;
1377f7caf6aSAndy Grover 		buf[15] = lalba & 0xff;
1387f7caf6aSAndy Grover 	}
1397f7caf6aSAndy Grover 
1401fd032eeSChristoph Hellwig 	/*
1411fd032eeSChristoph Hellwig 	 * Set Thin Provisioning Enable bit following sbc3r22 in section
1421fd032eeSChristoph Hellwig 	 * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
1431fd032eeSChristoph Hellwig 	 */
1440fd97ccfSChristoph Hellwig 	if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws)
1457f7caf6aSAndy Grover 		buf[14] |= 0x80;
1461fd032eeSChristoph Hellwig 
147a50da144SPaolo Bonzini 	rbuf = transport_kmap_data_sg(cmd);
1488b4b0dcbSNicholas Bellinger 	if (rbuf) {
149a50da144SPaolo Bonzini 		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
1501fd032eeSChristoph Hellwig 		transport_kunmap_data_sg(cmd);
1518b4b0dcbSNicholas Bellinger 	}
1521fd032eeSChristoph Hellwig 
1532426bd45SRoland Dreier 	target_complete_cmd_with_length(cmd, GOOD, 32);
1541fd032eeSChristoph Hellwig 	return 0;
1551fd032eeSChristoph Hellwig }
1561fd032eeSChristoph Hellwig 
157972b29c8SRoland Dreier sector_t sbc_get_write_same_sectors(struct se_cmd *cmd)
1581fd032eeSChristoph Hellwig {
1591fd032eeSChristoph Hellwig 	u32 num_blocks;
1601fd032eeSChristoph Hellwig 
1611fd032eeSChristoph Hellwig 	if (cmd->t_task_cdb[0] == WRITE_SAME)
1621fd032eeSChristoph Hellwig 		num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);
1631fd032eeSChristoph Hellwig 	else if (cmd->t_task_cdb[0] == WRITE_SAME_16)
1641fd032eeSChristoph Hellwig 		num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
1651fd032eeSChristoph Hellwig 	else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */
1661fd032eeSChristoph Hellwig 		num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
1671fd032eeSChristoph Hellwig 
1681fd032eeSChristoph Hellwig 	/*
1691fd032eeSChristoph Hellwig 	 * Use the explicit range when non zero is supplied, otherwise calculate
1701fd032eeSChristoph Hellwig 	 * the remaining range based on ->get_blocks() - starting LBA.
1711fd032eeSChristoph Hellwig 	 */
1726f974e8cSChristoph Hellwig 	if (num_blocks)
1736f974e8cSChristoph Hellwig 		return num_blocks;
1741fd032eeSChristoph Hellwig 
1756f974e8cSChristoph Hellwig 	return cmd->se_dev->transport->get_blocks(cmd->se_dev) -
1766f974e8cSChristoph Hellwig 		cmd->t_task_lba + 1;
1771fd032eeSChristoph Hellwig }
178972b29c8SRoland Dreier EXPORT_SYMBOL(sbc_get_write_same_sectors);
1791fd032eeSChristoph Hellwig 
180de103c93SChristoph Hellwig static sense_reason_t
1811920ed61SNicholas Bellinger sbc_emulate_noop(struct se_cmd *cmd)
1821a1ff38cSBernhard Kohl {
1831a1ff38cSBernhard Kohl 	target_complete_cmd(cmd, GOOD);
1841a1ff38cSBernhard Kohl 	return 0;
1851a1ff38cSBernhard Kohl }
1861a1ff38cSBernhard Kohl 
187d6e0175cSChristoph Hellwig static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
188d6e0175cSChristoph Hellwig {
1890fd97ccfSChristoph Hellwig 	return cmd->se_dev->dev_attrib.block_size * sectors;
190d6e0175cSChristoph Hellwig }
191d6e0175cSChristoph Hellwig 
192d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_6(unsigned char *cdb)
193d6e0175cSChristoph Hellwig {
194d6e0175cSChristoph Hellwig 	/*
195d6e0175cSChristoph Hellwig 	 * Use 8-bit sector value.  SBC-3 says:
196d6e0175cSChristoph Hellwig 	 *
197d6e0175cSChristoph Hellwig 	 *   A TRANSFER LENGTH field set to zero specifies that 256
198d6e0175cSChristoph Hellwig 	 *   logical blocks shall be written.  Any other value
199d6e0175cSChristoph Hellwig 	 *   specifies the number of logical blocks that shall be
200d6e0175cSChristoph Hellwig 	 *   written.
201d6e0175cSChristoph Hellwig 	 */
202d6e0175cSChristoph Hellwig 	return cdb[4] ? : 256;
203d6e0175cSChristoph Hellwig }
204d6e0175cSChristoph Hellwig 
205d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_10(unsigned char *cdb)
206d6e0175cSChristoph Hellwig {
207d6e0175cSChristoph Hellwig 	return (u32)(cdb[7] << 8) + cdb[8];
208d6e0175cSChristoph Hellwig }
209d6e0175cSChristoph Hellwig 
210d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_12(unsigned char *cdb)
211d6e0175cSChristoph Hellwig {
212d6e0175cSChristoph Hellwig 	return (u32)(cdb[6] << 24) + (cdb[7] << 16) + (cdb[8] << 8) + cdb[9];
213d6e0175cSChristoph Hellwig }
214d6e0175cSChristoph Hellwig 
215d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_16(unsigned char *cdb)
216d6e0175cSChristoph Hellwig {
217d6e0175cSChristoph Hellwig 	return (u32)(cdb[10] << 24) + (cdb[11] << 16) +
218d6e0175cSChristoph Hellwig 		    (cdb[12] << 8) + cdb[13];
219d6e0175cSChristoph Hellwig }
220d6e0175cSChristoph Hellwig 
221d6e0175cSChristoph Hellwig /*
222d6e0175cSChristoph Hellwig  * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants
223d6e0175cSChristoph Hellwig  */
224d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_32(unsigned char *cdb)
225d6e0175cSChristoph Hellwig {
226d6e0175cSChristoph Hellwig 	return (u32)(cdb[28] << 24) + (cdb[29] << 16) +
227d6e0175cSChristoph Hellwig 		    (cdb[30] << 8) + cdb[31];
228d6e0175cSChristoph Hellwig 
229d6e0175cSChristoph Hellwig }
230d6e0175cSChristoph Hellwig 
231d6e0175cSChristoph Hellwig static inline u32 transport_lba_21(unsigned char *cdb)
232d6e0175cSChristoph Hellwig {
233d6e0175cSChristoph Hellwig 	return ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
234d6e0175cSChristoph Hellwig }
235d6e0175cSChristoph Hellwig 
236d6e0175cSChristoph Hellwig static inline u32 transport_lba_32(unsigned char *cdb)
237d6e0175cSChristoph Hellwig {
238d6e0175cSChristoph Hellwig 	return (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
239d6e0175cSChristoph Hellwig }
240d6e0175cSChristoph Hellwig 
241d6e0175cSChristoph Hellwig static inline unsigned long long transport_lba_64(unsigned char *cdb)
242d6e0175cSChristoph Hellwig {
243d6e0175cSChristoph Hellwig 	unsigned int __v1, __v2;
244d6e0175cSChristoph Hellwig 
245d6e0175cSChristoph Hellwig 	__v1 = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
246d6e0175cSChristoph Hellwig 	__v2 = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
247d6e0175cSChristoph Hellwig 
248d6e0175cSChristoph Hellwig 	return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
249d6e0175cSChristoph Hellwig }
250d6e0175cSChristoph Hellwig 
251d6e0175cSChristoph Hellwig /*
252d6e0175cSChristoph Hellwig  * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs
253d6e0175cSChristoph Hellwig  */
254d6e0175cSChristoph Hellwig static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
255d6e0175cSChristoph Hellwig {
256d6e0175cSChristoph Hellwig 	unsigned int __v1, __v2;
257d6e0175cSChristoph Hellwig 
258d6e0175cSChristoph Hellwig 	__v1 = (cdb[12] << 24) | (cdb[13] << 16) | (cdb[14] << 8) | cdb[15];
259d6e0175cSChristoph Hellwig 	__v2 = (cdb[16] << 24) | (cdb[17] << 16) | (cdb[18] << 8) | cdb[19];
260d6e0175cSChristoph Hellwig 
261d6e0175cSChristoph Hellwig 	return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
262d6e0175cSChristoph Hellwig }
263d6e0175cSChristoph Hellwig 
264cd063befSNicholas Bellinger static sense_reason_t
265cd063befSNicholas Bellinger sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
266d6e0175cSChristoph Hellwig {
2678e575c50SNicholas Bellinger 	struct se_device *dev = cmd->se_dev;
2688e575c50SNicholas Bellinger 	sector_t end_lba = dev->transport->get_blocks(dev) + 1;
269972b29c8SRoland Dreier 	unsigned int sectors = sbc_get_write_same_sectors(cmd);
270afd73f1bSNicholas Bellinger 	sense_reason_t ret;
271773cbaf7SNicholas Bellinger 
272d6e0175cSChristoph Hellwig 	if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
273d6e0175cSChristoph Hellwig 		pr_err("WRITE_SAME PBDATA and LBDATA"
274d6e0175cSChristoph Hellwig 			" bits not supported for Block Discard"
275d6e0175cSChristoph Hellwig 			" Emulation\n");
276cd063befSNicholas Bellinger 		return TCM_UNSUPPORTED_SCSI_OPCODE;
277d6e0175cSChristoph Hellwig 	}
278773cbaf7SNicholas Bellinger 	if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
279773cbaf7SNicholas Bellinger 		pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",
280773cbaf7SNicholas Bellinger 			sectors, cmd->se_dev->dev_attrib.max_write_same_len);
281773cbaf7SNicholas Bellinger 		return TCM_INVALID_CDB_FIELD;
282773cbaf7SNicholas Bellinger 	}
2838e575c50SNicholas Bellinger 	/*
2848e575c50SNicholas Bellinger 	 * Sanity check for LBA wrap and request past end of device.
2858e575c50SNicholas Bellinger 	 */
2868e575c50SNicholas Bellinger 	if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
2878e575c50SNicholas Bellinger 	    ((cmd->t_task_lba + sectors) > end_lba)) {
2888e575c50SNicholas Bellinger 		pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n",
2898e575c50SNicholas Bellinger 		       (unsigned long long)end_lba, cmd->t_task_lba, sectors);
2908e575c50SNicholas Bellinger 		return TCM_ADDRESS_OUT_OF_RANGE;
2918e575c50SNicholas Bellinger 	}
2928e575c50SNicholas Bellinger 
2935cb770bfSRoland Dreier 	/* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
2945cb770bfSRoland Dreier 	if (flags[0] & 0x10) {
2955cb770bfSRoland Dreier 		pr_warn("WRITE SAME with ANCHOR not supported\n");
2965cb770bfSRoland Dreier 		return TCM_INVALID_CDB_FIELD;
2975cb770bfSRoland Dreier 	}
298d6e0175cSChristoph Hellwig 	/*
299cd063befSNicholas Bellinger 	 * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
300cd063befSNicholas Bellinger 	 * translated into block discard requests within backend code.
301d6e0175cSChristoph Hellwig 	 */
302cd063befSNicholas Bellinger 	if (flags[0] & 0x08) {
303cd063befSNicholas Bellinger 		if (!ops->execute_write_same_unmap)
304cd063befSNicholas Bellinger 			return TCM_UNSUPPORTED_SCSI_OPCODE;
305d6e0175cSChristoph Hellwig 
306d0a91295SNicholas Bellinger 		if (!dev->dev_attrib.emulate_tpws) {
307d0a91295SNicholas Bellinger 			pr_err("Got WRITE_SAME w/ UNMAP=1, but backend device"
308d0a91295SNicholas Bellinger 			       " has emulate_tpws disabled\n");
309d0a91295SNicholas Bellinger 			return TCM_UNSUPPORTED_SCSI_OPCODE;
310d0a91295SNicholas Bellinger 		}
311cd063befSNicholas Bellinger 		cmd->execute_cmd = ops->execute_write_same_unmap;
312cd063befSNicholas Bellinger 		return 0;
313cd063befSNicholas Bellinger 	}
314cd063befSNicholas Bellinger 	if (!ops->execute_write_same)
315cd063befSNicholas Bellinger 		return TCM_UNSUPPORTED_SCSI_OPCODE;
316cd063befSNicholas Bellinger 
317afd73f1bSNicholas Bellinger 	ret = sbc_check_prot(dev, cmd, &cmd->t_task_cdb[0], sectors, true);
318afd73f1bSNicholas Bellinger 	if (ret)
319afd73f1bSNicholas Bellinger 		return ret;
320afd73f1bSNicholas Bellinger 
321cd063befSNicholas Bellinger 	cmd->execute_cmd = ops->execute_write_same;
322d6e0175cSChristoph Hellwig 	return 0;
323d6e0175cSChristoph Hellwig }
324d6e0175cSChristoph Hellwig 
325c8e63985SNicholas Bellinger static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success)
326d6e0175cSChristoph Hellwig {
327d6e0175cSChristoph Hellwig 	unsigned char *buf, *addr;
328d6e0175cSChristoph Hellwig 	struct scatterlist *sg;
329d6e0175cSChristoph Hellwig 	unsigned int offset;
330a6b0133cSNicholas Bellinger 	sense_reason_t ret = TCM_NO_SENSE;
331a6b0133cSNicholas Bellinger 	int i, count;
332d6e0175cSChristoph Hellwig 	/*
333d6e0175cSChristoph Hellwig 	 * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command
334d6e0175cSChristoph Hellwig 	 *
335d6e0175cSChristoph Hellwig 	 * 1) read the specified logical block(s);
336d6e0175cSChristoph Hellwig 	 * 2) transfer logical blocks from the data-out buffer;
337d6e0175cSChristoph Hellwig 	 * 3) XOR the logical blocks transferred from the data-out buffer with
338d6e0175cSChristoph Hellwig 	 *    the logical blocks read, storing the resulting XOR data in a buffer;
339d6e0175cSChristoph Hellwig 	 * 4) if the DISABLE WRITE bit is set to zero, then write the logical
340d6e0175cSChristoph Hellwig 	 *    blocks transferred from the data-out buffer; and
341d6e0175cSChristoph Hellwig 	 * 5) transfer the resulting XOR data to the data-in buffer.
342d6e0175cSChristoph Hellwig 	 */
343d6e0175cSChristoph Hellwig 	buf = kmalloc(cmd->data_length, GFP_KERNEL);
344d6e0175cSChristoph Hellwig 	if (!buf) {
345d6e0175cSChristoph Hellwig 		pr_err("Unable to allocate xor_callback buf\n");
346a6b0133cSNicholas Bellinger 		return TCM_OUT_OF_RESOURCES;
347d6e0175cSChristoph Hellwig 	}
348d6e0175cSChristoph Hellwig 	/*
349d6e0175cSChristoph Hellwig 	 * Copy the scatterlist WRITE buffer located at cmd->t_data_sg
350d6e0175cSChristoph Hellwig 	 * into the locally allocated *buf
351d6e0175cSChristoph Hellwig 	 */
352d6e0175cSChristoph Hellwig 	sg_copy_to_buffer(cmd->t_data_sg,
353d6e0175cSChristoph Hellwig 			  cmd->t_data_nents,
354d6e0175cSChristoph Hellwig 			  buf,
355d6e0175cSChristoph Hellwig 			  cmd->data_length);
356d6e0175cSChristoph Hellwig 
357d6e0175cSChristoph Hellwig 	/*
358d6e0175cSChristoph Hellwig 	 * Now perform the XOR against the BIDI read memory located at
359d6e0175cSChristoph Hellwig 	 * cmd->t_mem_bidi_list
360d6e0175cSChristoph Hellwig 	 */
361d6e0175cSChristoph Hellwig 
362d6e0175cSChristoph Hellwig 	offset = 0;
363d6e0175cSChristoph Hellwig 	for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
364d6e0175cSChristoph Hellwig 		addr = kmap_atomic(sg_page(sg));
365a6b0133cSNicholas Bellinger 		if (!addr) {
366a6b0133cSNicholas Bellinger 			ret = TCM_OUT_OF_RESOURCES;
367d6e0175cSChristoph Hellwig 			goto out;
368a6b0133cSNicholas Bellinger 		}
369d6e0175cSChristoph Hellwig 
370d6e0175cSChristoph Hellwig 		for (i = 0; i < sg->length; i++)
371d6e0175cSChristoph Hellwig 			*(addr + sg->offset + i) ^= *(buf + offset + i);
372d6e0175cSChristoph Hellwig 
373d6e0175cSChristoph Hellwig 		offset += sg->length;
374d6e0175cSChristoph Hellwig 		kunmap_atomic(addr);
375d6e0175cSChristoph Hellwig 	}
376d6e0175cSChristoph Hellwig 
377d6e0175cSChristoph Hellwig out:
378d6e0175cSChristoph Hellwig 	kfree(buf);
379a6b0133cSNicholas Bellinger 	return ret;
380d6e0175cSChristoph Hellwig }
381d6e0175cSChristoph Hellwig 
382a82a9538SNicholas Bellinger static sense_reason_t
383a82a9538SNicholas Bellinger sbc_execute_rw(struct se_cmd *cmd)
384a82a9538SNicholas Bellinger {
3857a971b1bSChristoph Hellwig 	struct sbc_ops *ops = cmd->protocol_data;
3867a971b1bSChristoph Hellwig 
3877a971b1bSChristoph Hellwig 	return ops->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents,
388a82a9538SNicholas Bellinger 			       cmd->data_direction);
389a82a9538SNicholas Bellinger }
390a82a9538SNicholas Bellinger 
391c8e63985SNicholas Bellinger static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
39268ff9b9bSNicholas Bellinger {
39368ff9b9bSNicholas Bellinger 	struct se_device *dev = cmd->se_dev;
39468ff9b9bSNicholas Bellinger 
395d8855c15SNicholas Bellinger 	/*
396d8855c15SNicholas Bellinger 	 * Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
397d8855c15SNicholas Bellinger 	 * within target_complete_ok_work() if the command was successfully
398d8855c15SNicholas Bellinger 	 * sent to the backend driver.
399d8855c15SNicholas Bellinger 	 */
400d8855c15SNicholas Bellinger 	spin_lock_irq(&cmd->t_state_lock);
401d8855c15SNicholas Bellinger 	if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status)
40268ff9b9bSNicholas Bellinger 		cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
403d8855c15SNicholas Bellinger 	spin_unlock_irq(&cmd->t_state_lock);
404d8855c15SNicholas Bellinger 
40568ff9b9bSNicholas Bellinger 	/*
40668ff9b9bSNicholas Bellinger 	 * Unlock ->caw_sem originally obtained during sbc_compare_and_write()
40768ff9b9bSNicholas Bellinger 	 * before the original READ I/O submission.
40868ff9b9bSNicholas Bellinger 	 */
40968ff9b9bSNicholas Bellinger 	up(&dev->caw_sem);
41068ff9b9bSNicholas Bellinger 
41168ff9b9bSNicholas Bellinger 	return TCM_NO_SENSE;
41268ff9b9bSNicholas Bellinger }
41368ff9b9bSNicholas Bellinger 
414c8e63985SNicholas Bellinger static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success)
41568ff9b9bSNicholas Bellinger {
41668ff9b9bSNicholas Bellinger 	struct se_device *dev = cmd->se_dev;
41768ff9b9bSNicholas Bellinger 	struct scatterlist *write_sg = NULL, *sg;
418db60df88SNicholas Bellinger 	unsigned char *buf = NULL, *addr;
41968ff9b9bSNicholas Bellinger 	struct sg_mapping_iter m;
42068ff9b9bSNicholas Bellinger 	unsigned int offset = 0, len;
42168ff9b9bSNicholas Bellinger 	unsigned int nlbas = cmd->t_task_nolb;
42268ff9b9bSNicholas Bellinger 	unsigned int block_size = dev->dev_attrib.block_size;
42368ff9b9bSNicholas Bellinger 	unsigned int compare_len = (nlbas * block_size);
42468ff9b9bSNicholas Bellinger 	sense_reason_t ret = TCM_NO_SENSE;
42568ff9b9bSNicholas Bellinger 	int rc, i;
42668ff9b9bSNicholas Bellinger 
427cf6d1f09SNicholas Bellinger 	/*
428cf6d1f09SNicholas Bellinger 	 * Handle early failure in transport_generic_request_failure(),
429c8e63985SNicholas Bellinger 	 * which will not have taken ->caw_sem yet..
430cf6d1f09SNicholas Bellinger 	 */
431c8e63985SNicholas Bellinger 	if (!success && (!cmd->t_data_sg || !cmd->t_bidi_data_sg))
432cf6d1f09SNicholas Bellinger 		return TCM_NO_SENSE;
433db60df88SNicholas Bellinger 	/*
434c8e63985SNicholas Bellinger 	 * Handle special case for zero-length COMPARE_AND_WRITE
435c8e63985SNicholas Bellinger 	 */
436c8e63985SNicholas Bellinger 	if (!cmd->data_length)
437c8e63985SNicholas Bellinger 		goto out;
438c8e63985SNicholas Bellinger 	/*
439db60df88SNicholas Bellinger 	 * Immediately exit + release dev->caw_sem if command has already
440db60df88SNicholas Bellinger 	 * been failed with a non-zero SCSI status.
441db60df88SNicholas Bellinger 	 */
442db60df88SNicholas Bellinger 	if (cmd->scsi_status) {
443db60df88SNicholas Bellinger 		pr_err("compare_and_write_callback: non zero scsi_status:"
444db60df88SNicholas Bellinger 			" 0x%02x\n", cmd->scsi_status);
445db60df88SNicholas Bellinger 		goto out;
446db60df88SNicholas Bellinger 	}
447cf6d1f09SNicholas Bellinger 
44868ff9b9bSNicholas Bellinger 	buf = kzalloc(cmd->data_length, GFP_KERNEL);
44968ff9b9bSNicholas Bellinger 	if (!buf) {
45068ff9b9bSNicholas Bellinger 		pr_err("Unable to allocate compare_and_write buf\n");
451a2890087SNicholas Bellinger 		ret = TCM_OUT_OF_RESOURCES;
452a2890087SNicholas Bellinger 		goto out;
45368ff9b9bSNicholas Bellinger 	}
45468ff9b9bSNicholas Bellinger 
455a1e1774cSMartin Svec 	write_sg = kmalloc(sizeof(struct scatterlist) * cmd->t_data_nents,
45668ff9b9bSNicholas Bellinger 			   GFP_KERNEL);
45768ff9b9bSNicholas Bellinger 	if (!write_sg) {
45868ff9b9bSNicholas Bellinger 		pr_err("Unable to allocate compare_and_write sg\n");
45968ff9b9bSNicholas Bellinger 		ret = TCM_OUT_OF_RESOURCES;
46068ff9b9bSNicholas Bellinger 		goto out;
46168ff9b9bSNicholas Bellinger 	}
462a1e1774cSMartin Svec 	sg_init_table(write_sg, cmd->t_data_nents);
46368ff9b9bSNicholas Bellinger 	/*
46468ff9b9bSNicholas Bellinger 	 * Setup verify and write data payloads from total NumberLBAs.
46568ff9b9bSNicholas Bellinger 	 */
46668ff9b9bSNicholas Bellinger 	rc = sg_copy_to_buffer(cmd->t_data_sg, cmd->t_data_nents, buf,
46768ff9b9bSNicholas Bellinger 			       cmd->data_length);
46868ff9b9bSNicholas Bellinger 	if (!rc) {
46968ff9b9bSNicholas Bellinger 		pr_err("sg_copy_to_buffer() failed for compare_and_write\n");
47068ff9b9bSNicholas Bellinger 		ret = TCM_OUT_OF_RESOURCES;
47168ff9b9bSNicholas Bellinger 		goto out;
47268ff9b9bSNicholas Bellinger 	}
47368ff9b9bSNicholas Bellinger 	/*
47468ff9b9bSNicholas Bellinger 	 * Compare against SCSI READ payload against verify payload
47568ff9b9bSNicholas Bellinger 	 */
47668ff9b9bSNicholas Bellinger 	for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, i) {
47768ff9b9bSNicholas Bellinger 		addr = (unsigned char *)kmap_atomic(sg_page(sg));
47868ff9b9bSNicholas Bellinger 		if (!addr) {
47968ff9b9bSNicholas Bellinger 			ret = TCM_OUT_OF_RESOURCES;
48068ff9b9bSNicholas Bellinger 			goto out;
48168ff9b9bSNicholas Bellinger 		}
48268ff9b9bSNicholas Bellinger 
48368ff9b9bSNicholas Bellinger 		len = min(sg->length, compare_len);
48468ff9b9bSNicholas Bellinger 
48568ff9b9bSNicholas Bellinger 		if (memcmp(addr, buf + offset, len)) {
48668ff9b9bSNicholas Bellinger 			pr_warn("Detected MISCOMPARE for addr: %p buf: %p\n",
48768ff9b9bSNicholas Bellinger 				addr, buf + offset);
48868ff9b9bSNicholas Bellinger 			kunmap_atomic(addr);
48968ff9b9bSNicholas Bellinger 			goto miscompare;
49068ff9b9bSNicholas Bellinger 		}
49168ff9b9bSNicholas Bellinger 		kunmap_atomic(addr);
49268ff9b9bSNicholas Bellinger 
49368ff9b9bSNicholas Bellinger 		offset += len;
49468ff9b9bSNicholas Bellinger 		compare_len -= len;
49568ff9b9bSNicholas Bellinger 		if (!compare_len)
49668ff9b9bSNicholas Bellinger 			break;
49768ff9b9bSNicholas Bellinger 	}
49868ff9b9bSNicholas Bellinger 
49968ff9b9bSNicholas Bellinger 	i = 0;
50068ff9b9bSNicholas Bellinger 	len = cmd->t_task_nolb * block_size;
50168ff9b9bSNicholas Bellinger 	sg_miter_start(&m, cmd->t_data_sg, cmd->t_data_nents, SG_MITER_TO_SG);
50268ff9b9bSNicholas Bellinger 	/*
50368ff9b9bSNicholas Bellinger 	 * Currently assumes NoLB=1 and SGLs are PAGE_SIZE..
50468ff9b9bSNicholas Bellinger 	 */
50568ff9b9bSNicholas Bellinger 	while (len) {
50668ff9b9bSNicholas Bellinger 		sg_miter_next(&m);
50768ff9b9bSNicholas Bellinger 
50868ff9b9bSNicholas Bellinger 		if (block_size < PAGE_SIZE) {
50968ff9b9bSNicholas Bellinger 			sg_set_page(&write_sg[i], m.page, block_size,
51068ff9b9bSNicholas Bellinger 				    block_size);
51168ff9b9bSNicholas Bellinger 		} else {
51268ff9b9bSNicholas Bellinger 			sg_miter_next(&m);
51368ff9b9bSNicholas Bellinger 			sg_set_page(&write_sg[i], m.page, block_size,
51468ff9b9bSNicholas Bellinger 				    0);
51568ff9b9bSNicholas Bellinger 		}
51668ff9b9bSNicholas Bellinger 		len -= block_size;
51768ff9b9bSNicholas Bellinger 		i++;
51868ff9b9bSNicholas Bellinger 	}
51968ff9b9bSNicholas Bellinger 	sg_miter_stop(&m);
52068ff9b9bSNicholas Bellinger 	/*
52168ff9b9bSNicholas Bellinger 	 * Save the original SGL + nents values before updating to new
52268ff9b9bSNicholas Bellinger 	 * assignments, to be released in transport_free_pages() ->
52368ff9b9bSNicholas Bellinger 	 * transport_reset_sgl_orig()
52468ff9b9bSNicholas Bellinger 	 */
52568ff9b9bSNicholas Bellinger 	cmd->t_data_sg_orig = cmd->t_data_sg;
52668ff9b9bSNicholas Bellinger 	cmd->t_data_sg = write_sg;
52768ff9b9bSNicholas Bellinger 	cmd->t_data_nents_orig = cmd->t_data_nents;
52868ff9b9bSNicholas Bellinger 	cmd->t_data_nents = 1;
52968ff9b9bSNicholas Bellinger 
53068d81f40SChristoph Hellwig 	cmd->sam_task_attr = TCM_HEAD_TAG;
53168ff9b9bSNicholas Bellinger 	cmd->transport_complete_callback = compare_and_write_post;
53268ff9b9bSNicholas Bellinger 	/*
53368ff9b9bSNicholas Bellinger 	 * Now reset ->execute_cmd() to the normal sbc_execute_rw() handler
53468ff9b9bSNicholas Bellinger 	 * for submitting the adjusted SGL to write instance user-data.
53568ff9b9bSNicholas Bellinger 	 */
53668ff9b9bSNicholas Bellinger 	cmd->execute_cmd = sbc_execute_rw;
53768ff9b9bSNicholas Bellinger 
53868ff9b9bSNicholas Bellinger 	spin_lock_irq(&cmd->t_state_lock);
53968ff9b9bSNicholas Bellinger 	cmd->t_state = TRANSPORT_PROCESSING;
54068ff9b9bSNicholas Bellinger 	cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
54168ff9b9bSNicholas Bellinger 	spin_unlock_irq(&cmd->t_state_lock);
54268ff9b9bSNicholas Bellinger 
54368ff9b9bSNicholas Bellinger 	__target_execute_cmd(cmd);
54468ff9b9bSNicholas Bellinger 
54568ff9b9bSNicholas Bellinger 	kfree(buf);
54668ff9b9bSNicholas Bellinger 	return ret;
54768ff9b9bSNicholas Bellinger 
54868ff9b9bSNicholas Bellinger miscompare:
54968ff9b9bSNicholas Bellinger 	pr_warn("Target/%s: Send MISCOMPARE check condition and sense\n",
55068ff9b9bSNicholas Bellinger 		dev->transport->name);
55168ff9b9bSNicholas Bellinger 	ret = TCM_MISCOMPARE_VERIFY;
55268ff9b9bSNicholas Bellinger out:
55368ff9b9bSNicholas Bellinger 	/*
55468ff9b9bSNicholas Bellinger 	 * In the MISCOMPARE or failure case, unlock ->caw_sem obtained in
55568ff9b9bSNicholas Bellinger 	 * sbc_compare_and_write() before the original READ I/O submission.
55668ff9b9bSNicholas Bellinger 	 */
55768ff9b9bSNicholas Bellinger 	up(&dev->caw_sem);
55868ff9b9bSNicholas Bellinger 	kfree(write_sg);
55968ff9b9bSNicholas Bellinger 	kfree(buf);
56068ff9b9bSNicholas Bellinger 	return ret;
56168ff9b9bSNicholas Bellinger }
56268ff9b9bSNicholas Bellinger 
56368ff9b9bSNicholas Bellinger static sense_reason_t
56468ff9b9bSNicholas Bellinger sbc_compare_and_write(struct se_cmd *cmd)
56568ff9b9bSNicholas Bellinger {
5667a971b1bSChristoph Hellwig 	struct sbc_ops *ops = cmd->protocol_data;
56768ff9b9bSNicholas Bellinger 	struct se_device *dev = cmd->se_dev;
56868ff9b9bSNicholas Bellinger 	sense_reason_t ret;
56968ff9b9bSNicholas Bellinger 	int rc;
57068ff9b9bSNicholas Bellinger 	/*
57168ff9b9bSNicholas Bellinger 	 * Submit the READ first for COMPARE_AND_WRITE to perform the
57268ff9b9bSNicholas Bellinger 	 * comparision using SGLs at cmd->t_bidi_data_sg..
57368ff9b9bSNicholas Bellinger 	 */
57468ff9b9bSNicholas Bellinger 	rc = down_interruptible(&dev->caw_sem);
575ee7619f2SNicholas Bellinger 	if (rc != 0) {
57668ff9b9bSNicholas Bellinger 		cmd->transport_complete_callback = NULL;
57768ff9b9bSNicholas Bellinger 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
57868ff9b9bSNicholas Bellinger 	}
579b7191253SNicholas Bellinger 	/*
580b7191253SNicholas Bellinger 	 * Reset cmd->data_length to individual block_size in order to not
581b7191253SNicholas Bellinger 	 * confuse backend drivers that depend on this value matching the
582b7191253SNicholas Bellinger 	 * size of the I/O being submitted.
583b7191253SNicholas Bellinger 	 */
584b7191253SNicholas Bellinger 	cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size;
58568ff9b9bSNicholas Bellinger 
5867a971b1bSChristoph Hellwig 	ret = ops->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents,
58768ff9b9bSNicholas Bellinger 			      DMA_FROM_DEVICE);
58868ff9b9bSNicholas Bellinger 	if (ret) {
58968ff9b9bSNicholas Bellinger 		cmd->transport_complete_callback = NULL;
59068ff9b9bSNicholas Bellinger 		up(&dev->caw_sem);
59168ff9b9bSNicholas Bellinger 		return ret;
59268ff9b9bSNicholas Bellinger 	}
59368ff9b9bSNicholas Bellinger 	/*
59468ff9b9bSNicholas Bellinger 	 * Unlock of dev->caw_sem to occur in compare_and_write_callback()
59568ff9b9bSNicholas Bellinger 	 * upon MISCOMPARE, or in compare_and_write_done() upon completion
59668ff9b9bSNicholas Bellinger 	 * of WRITE instance user-data.
59768ff9b9bSNicholas Bellinger 	 */
59868ff9b9bSNicholas Bellinger 	return TCM_NO_SENSE;
59968ff9b9bSNicholas Bellinger }
60068ff9b9bSNicholas Bellinger 
60119f9361aSSagi Grimberg static int
60238b57f82SNicholas Bellinger sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_type,
60319f9361aSSagi Grimberg 		       bool is_write, struct se_cmd *cmd)
60419f9361aSSagi Grimberg {
60519f9361aSSagi Grimberg 	if (is_write) {
60638b57f82SNicholas Bellinger 		cmd->prot_op = fabric_prot ? TARGET_PROT_DOUT_STRIP :
60738b57f82SNicholas Bellinger 			       protect ? TARGET_PROT_DOUT_PASS :
60819f9361aSSagi Grimberg 			       TARGET_PROT_DOUT_INSERT;
60919f9361aSSagi Grimberg 		switch (protect) {
61019f9361aSSagi Grimberg 		case 0x0:
61119f9361aSSagi Grimberg 		case 0x3:
61219f9361aSSagi Grimberg 			cmd->prot_checks = 0;
61319f9361aSSagi Grimberg 			break;
61419f9361aSSagi Grimberg 		case 0x1:
61519f9361aSSagi Grimberg 		case 0x5:
61619f9361aSSagi Grimberg 			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;
61719f9361aSSagi Grimberg 			if (prot_type == TARGET_DIF_TYPE1_PROT)
61819f9361aSSagi Grimberg 				cmd->prot_checks |= TARGET_DIF_CHECK_REFTAG;
61919f9361aSSagi Grimberg 			break;
62019f9361aSSagi Grimberg 		case 0x2:
62119f9361aSSagi Grimberg 			if (prot_type == TARGET_DIF_TYPE1_PROT)
62219f9361aSSagi Grimberg 				cmd->prot_checks = TARGET_DIF_CHECK_REFTAG;
62319f9361aSSagi Grimberg 			break;
62419f9361aSSagi Grimberg 		case 0x4:
62519f9361aSSagi Grimberg 			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;
62619f9361aSSagi Grimberg 			break;
62719f9361aSSagi Grimberg 		default:
62819f9361aSSagi Grimberg 			pr_err("Unsupported protect field %d\n", protect);
62919f9361aSSagi Grimberg 			return -EINVAL;
63019f9361aSSagi Grimberg 		}
63119f9361aSSagi Grimberg 	} else {
63238b57f82SNicholas Bellinger 		cmd->prot_op = fabric_prot ? TARGET_PROT_DIN_INSERT :
63338b57f82SNicholas Bellinger 			       protect ? TARGET_PROT_DIN_PASS :
63419f9361aSSagi Grimberg 			       TARGET_PROT_DIN_STRIP;
63519f9361aSSagi Grimberg 		switch (protect) {
63619f9361aSSagi Grimberg 		case 0x0:
63719f9361aSSagi Grimberg 		case 0x1:
63819f9361aSSagi Grimberg 		case 0x5:
63919f9361aSSagi Grimberg 			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;
64019f9361aSSagi Grimberg 			if (prot_type == TARGET_DIF_TYPE1_PROT)
64119f9361aSSagi Grimberg 				cmd->prot_checks |= TARGET_DIF_CHECK_REFTAG;
64219f9361aSSagi Grimberg 			break;
64319f9361aSSagi Grimberg 		case 0x2:
64419f9361aSSagi Grimberg 			if (prot_type == TARGET_DIF_TYPE1_PROT)
64519f9361aSSagi Grimberg 				cmd->prot_checks = TARGET_DIF_CHECK_REFTAG;
64619f9361aSSagi Grimberg 			break;
64719f9361aSSagi Grimberg 		case 0x3:
64819f9361aSSagi Grimberg 			cmd->prot_checks = 0;
64919f9361aSSagi Grimberg 			break;
65019f9361aSSagi Grimberg 		case 0x4:
65119f9361aSSagi Grimberg 			cmd->prot_checks = TARGET_DIF_CHECK_GUARD;
65219f9361aSSagi Grimberg 			break;
65319f9361aSSagi Grimberg 		default:
65419f9361aSSagi Grimberg 			pr_err("Unsupported protect field %d\n", protect);
65519f9361aSSagi Grimberg 			return -EINVAL;
65619f9361aSSagi Grimberg 		}
65719f9361aSSagi Grimberg 	}
65819f9361aSSagi Grimberg 
65919f9361aSSagi Grimberg 	return 0;
66019f9361aSSagi Grimberg }
66119f9361aSSagi Grimberg 
662f7b7c06fSNicholas Bellinger static sense_reason_t
663499bf77bSNicholas Bellinger sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
66419f9361aSSagi Grimberg 	       u32 sectors, bool is_write)
665499bf77bSNicholas Bellinger {
66619f9361aSSagi Grimberg 	u8 protect = cdb[1] >> 5;
66738b57f82SNicholas Bellinger 	int sp_ops = cmd->se_sess->sup_prot_ops;
66838b57f82SNicholas Bellinger 	int pi_prot_type = dev->dev_attrib.pi_prot_type;
66938b57f82SNicholas Bellinger 	bool fabric_prot = false;
67019f9361aSSagi Grimberg 
671f7b7c06fSNicholas Bellinger 	if (!cmd->t_prot_sg || !cmd->t_prot_nents) {
67238b57f82SNicholas Bellinger 		if (unlikely(protect &&
67338b57f82SNicholas Bellinger 		    !dev->dev_attrib.pi_prot_type && !cmd->se_sess->sess_prot_type)) {
67438b57f82SNicholas Bellinger 			pr_err("CDB contains protect bit, but device + fabric does"
67538b57f82SNicholas Bellinger 			       " not advertise PROTECT=1 feature bit\n");
676f7b7c06fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
677f7b7c06fSNicholas Bellinger 		}
678f7b7c06fSNicholas Bellinger 		if (cmd->prot_pto)
679f7b7c06fSNicholas Bellinger 			return TCM_NO_SENSE;
680f7b7c06fSNicholas Bellinger 	}
681499bf77bSNicholas Bellinger 
682499bf77bSNicholas Bellinger 	switch (dev->dev_attrib.pi_prot_type) {
683499bf77bSNicholas Bellinger 	case TARGET_DIF_TYPE3_PROT:
684499bf77bSNicholas Bellinger 		cmd->reftag_seed = 0xffffffff;
685499bf77bSNicholas Bellinger 		break;
686499bf77bSNicholas Bellinger 	case TARGET_DIF_TYPE2_PROT:
68719f9361aSSagi Grimberg 		if (protect)
688f7b7c06fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
689499bf77bSNicholas Bellinger 
690499bf77bSNicholas Bellinger 		cmd->reftag_seed = cmd->t_task_lba;
691499bf77bSNicholas Bellinger 		break;
692499bf77bSNicholas Bellinger 	case TARGET_DIF_TYPE1_PROT:
693499bf77bSNicholas Bellinger 		cmd->reftag_seed = cmd->t_task_lba;
694499bf77bSNicholas Bellinger 		break;
695499bf77bSNicholas Bellinger 	case TARGET_DIF_TYPE0_PROT:
69638b57f82SNicholas Bellinger 		/*
69738b57f82SNicholas Bellinger 		 * See if the fabric supports T10-PI, and the session has been
69838b57f82SNicholas Bellinger 		 * configured to allow export PROTECT=1 feature bit with backend
69938b57f82SNicholas Bellinger 		 * devices that don't support T10-PI.
70038b57f82SNicholas Bellinger 		 */
70138b57f82SNicholas Bellinger 		fabric_prot = is_write ?
70238b57f82SNicholas Bellinger 			      !!(sp_ops & (TARGET_PROT_DOUT_PASS | TARGET_PROT_DOUT_STRIP)) :
70338b57f82SNicholas Bellinger 			      !!(sp_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DIN_INSERT));
70438b57f82SNicholas Bellinger 
70538b57f82SNicholas Bellinger 		if (fabric_prot && cmd->se_sess->sess_prot_type) {
70638b57f82SNicholas Bellinger 			pi_prot_type = cmd->se_sess->sess_prot_type;
70738b57f82SNicholas Bellinger 			break;
70838b57f82SNicholas Bellinger 		}
709cceca4a6SNicholas Bellinger 		if (!protect)
710f7b7c06fSNicholas Bellinger 			return TCM_NO_SENSE;
71138b57f82SNicholas Bellinger 		/* Fallthrough */
712499bf77bSNicholas Bellinger 	default:
713cceca4a6SNicholas Bellinger 		pr_err("Unable to determine pi_prot_type for CDB: 0x%02x "
714cceca4a6SNicholas Bellinger 		       "PROTECT: 0x%02x\n", cdb[0], protect);
715cceca4a6SNicholas Bellinger 		return TCM_INVALID_CDB_FIELD;
716499bf77bSNicholas Bellinger 	}
717499bf77bSNicholas Bellinger 
71838b57f82SNicholas Bellinger 	if (sbc_set_prot_op_checks(protect, fabric_prot, pi_prot_type, is_write, cmd))
719f7b7c06fSNicholas Bellinger 		return TCM_INVALID_CDB_FIELD;
72019f9361aSSagi Grimberg 
72138b57f82SNicholas Bellinger 	cmd->prot_type = pi_prot_type;
722499bf77bSNicholas Bellinger 	cmd->prot_length = dev->prot_length * sectors;
723e2a4f55cSSagi Grimberg 
724e2a4f55cSSagi Grimberg 	/**
725e2a4f55cSSagi Grimberg 	 * In case protection information exists over the wire
726e2a4f55cSSagi Grimberg 	 * we modify command data length to describe pure data.
727e2a4f55cSSagi Grimberg 	 * The actual transfer length is data length + protection
728e2a4f55cSSagi Grimberg 	 * length
729e2a4f55cSSagi Grimberg 	 **/
730e2a4f55cSSagi Grimberg 	if (protect)
731e2a4f55cSSagi Grimberg 		cmd->data_length = sectors * dev->dev_attrib.block_size;
732e2a4f55cSSagi Grimberg 
733e2a4f55cSSagi Grimberg 	pr_debug("%s: prot_type=%d, data_length=%d, prot_length=%d "
734e2a4f55cSSagi Grimberg 		 "prot_op=%d prot_checks=%d\n",
735e2a4f55cSSagi Grimberg 		 __func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
73603abad9eSSagi Grimberg 		 cmd->prot_op, cmd->prot_checks);
737499bf77bSNicholas Bellinger 
738f7b7c06fSNicholas Bellinger 	return TCM_NO_SENSE;
739499bf77bSNicholas Bellinger }
740499bf77bSNicholas Bellinger 
741fde9f50fSNicholas Bellinger static int
742fde9f50fSNicholas Bellinger sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
743fde9f50fSNicholas Bellinger {
744fde9f50fSNicholas Bellinger 	if (cdb[1] & 0x10) {
745814e5b45SChristoph Hellwig 		/* see explanation in spc_emulate_modesense */
746814e5b45SChristoph Hellwig 		if (!target_check_fua(dev)) {
747fde9f50fSNicholas Bellinger 			pr_err("Got CDB: 0x%02x with DPO bit set, but device"
748fde9f50fSNicholas Bellinger 			       " does not advertise support for DPO\n", cdb[0]);
749fde9f50fSNicholas Bellinger 			return -EINVAL;
750fde9f50fSNicholas Bellinger 		}
751fde9f50fSNicholas Bellinger 	}
752fde9f50fSNicholas Bellinger 	if (cdb[1] & 0x8) {
753814e5b45SChristoph Hellwig 		if (!target_check_fua(dev)) {
754fde9f50fSNicholas Bellinger 			pr_err("Got CDB: 0x%02x with FUA bit set, but device"
755fde9f50fSNicholas Bellinger 			       " does not advertise support for FUA write\n",
756fde9f50fSNicholas Bellinger 			       cdb[0]);
757fde9f50fSNicholas Bellinger 			return -EINVAL;
758fde9f50fSNicholas Bellinger 		}
759fde9f50fSNicholas Bellinger 		cmd->se_cmd_flags |= SCF_FUA;
760fde9f50fSNicholas Bellinger 	}
761fde9f50fSNicholas Bellinger 	return 0;
762d6e0175cSChristoph Hellwig }
763d6e0175cSChristoph Hellwig 
764de103c93SChristoph Hellwig sense_reason_t
765de103c93SChristoph Hellwig sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
766d6e0175cSChristoph Hellwig {
767d6e0175cSChristoph Hellwig 	struct se_device *dev = cmd->se_dev;
768d6e0175cSChristoph Hellwig 	unsigned char *cdb = cmd->t_task_cdb;
7691fd032eeSChristoph Hellwig 	unsigned int size;
770d6e0175cSChristoph Hellwig 	u32 sectors = 0;
771de103c93SChristoph Hellwig 	sense_reason_t ret;
772d6e0175cSChristoph Hellwig 
7737a971b1bSChristoph Hellwig 	cmd->protocol_data = ops;
7747a971b1bSChristoph Hellwig 
775d6e0175cSChristoph Hellwig 	switch (cdb[0]) {
776d6e0175cSChristoph Hellwig 	case READ_6:
777d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_6(cdb);
778d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_21(cdb);
779d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
780a82a9538SNicholas Bellinger 		cmd->execute_cmd = sbc_execute_rw;
781d6e0175cSChristoph Hellwig 		break;
782d6e0175cSChristoph Hellwig 	case READ_10:
783d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_10(cdb);
784d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_32(cdb);
785499bf77bSNicholas Bellinger 
786fde9f50fSNicholas Bellinger 		if (sbc_check_dpofua(dev, cmd, cdb))
787fde9f50fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
788fde9f50fSNicholas Bellinger 
789f7b7c06fSNicholas Bellinger 		ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
790f7b7c06fSNicholas Bellinger 		if (ret)
791f7b7c06fSNicholas Bellinger 			return ret;
792499bf77bSNicholas Bellinger 
793d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
794a82a9538SNicholas Bellinger 		cmd->execute_cmd = sbc_execute_rw;
795d6e0175cSChristoph Hellwig 		break;
796d6e0175cSChristoph Hellwig 	case READ_12:
797d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_12(cdb);
798d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_32(cdb);
799499bf77bSNicholas Bellinger 
800fde9f50fSNicholas Bellinger 		if (sbc_check_dpofua(dev, cmd, cdb))
801fde9f50fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
802fde9f50fSNicholas Bellinger 
803f7b7c06fSNicholas Bellinger 		ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
804f7b7c06fSNicholas Bellinger 		if (ret)
805f7b7c06fSNicholas Bellinger 			return ret;
806499bf77bSNicholas Bellinger 
807d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
808a82a9538SNicholas Bellinger 		cmd->execute_cmd = sbc_execute_rw;
809d6e0175cSChristoph Hellwig 		break;
810d6e0175cSChristoph Hellwig 	case READ_16:
811d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_16(cdb);
812d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_64(cdb);
813499bf77bSNicholas Bellinger 
814fde9f50fSNicholas Bellinger 		if (sbc_check_dpofua(dev, cmd, cdb))
815fde9f50fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
816fde9f50fSNicholas Bellinger 
817f7b7c06fSNicholas Bellinger 		ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
818f7b7c06fSNicholas Bellinger 		if (ret)
819f7b7c06fSNicholas Bellinger 			return ret;
820499bf77bSNicholas Bellinger 
821d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
822a82a9538SNicholas Bellinger 		cmd->execute_cmd = sbc_execute_rw;
823d6e0175cSChristoph Hellwig 		break;
824d6e0175cSChristoph Hellwig 	case WRITE_6:
825d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_6(cdb);
826d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_21(cdb);
827d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
828a82a9538SNicholas Bellinger 		cmd->execute_cmd = sbc_execute_rw;
829d6e0175cSChristoph Hellwig 		break;
830d6e0175cSChristoph Hellwig 	case WRITE_10:
831d6e0175cSChristoph Hellwig 	case WRITE_VERIFY:
832d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_10(cdb);
833d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_32(cdb);
834499bf77bSNicholas Bellinger 
835fde9f50fSNicholas Bellinger 		if (sbc_check_dpofua(dev, cmd, cdb))
836fde9f50fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
837499bf77bSNicholas Bellinger 
838f7b7c06fSNicholas Bellinger 		ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
839f7b7c06fSNicholas Bellinger 		if (ret)
840f7b7c06fSNicholas Bellinger 			return ret;
841d6e0175cSChristoph Hellwig 
842d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
843a82a9538SNicholas Bellinger 		cmd->execute_cmd = sbc_execute_rw;
844d6e0175cSChristoph Hellwig 		break;
845d6e0175cSChristoph Hellwig 	case WRITE_12:
846d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_12(cdb);
847d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_32(cdb);
848499bf77bSNicholas Bellinger 
849fde9f50fSNicholas Bellinger 		if (sbc_check_dpofua(dev, cmd, cdb))
850fde9f50fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
851499bf77bSNicholas Bellinger 
852f7b7c06fSNicholas Bellinger 		ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
853f7b7c06fSNicholas Bellinger 		if (ret)
854f7b7c06fSNicholas Bellinger 			return ret;
855d6e0175cSChristoph Hellwig 
856d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
857a82a9538SNicholas Bellinger 		cmd->execute_cmd = sbc_execute_rw;
858d6e0175cSChristoph Hellwig 		break;
859d6e0175cSChristoph Hellwig 	case WRITE_16:
860d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_16(cdb);
861d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_64(cdb);
862499bf77bSNicholas Bellinger 
863fde9f50fSNicholas Bellinger 		if (sbc_check_dpofua(dev, cmd, cdb))
864fde9f50fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
865499bf77bSNicholas Bellinger 
866f7b7c06fSNicholas Bellinger 		ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
867f7b7c06fSNicholas Bellinger 		if (ret)
868f7b7c06fSNicholas Bellinger 			return ret;
869cd063befSNicholas Bellinger 
870d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
871d6e0175cSChristoph Hellwig 		cmd->execute_cmd = sbc_execute_rw;
872d6e0175cSChristoph Hellwig 		break;
873d6e0175cSChristoph Hellwig 	case XDWRITEREAD_10:
874d6e0175cSChristoph Hellwig 		if (cmd->data_direction != DMA_TO_DEVICE ||
875d6e0175cSChristoph Hellwig 		    !(cmd->se_cmd_flags & SCF_BIDI))
876d6e0175cSChristoph Hellwig 			return TCM_INVALID_CDB_FIELD;
877d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_10(cdb);
878d6e0175cSChristoph Hellwig 
879fde9f50fSNicholas Bellinger 		if (sbc_check_dpofua(dev, cmd, cdb))
880fde9f50fSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
881fde9f50fSNicholas Bellinger 
882d6e0175cSChristoph Hellwig 		cmd->t_task_lba = transport_lba_32(cdb);
883d6e0175cSChristoph Hellwig 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
884d6e0175cSChristoph Hellwig 
885d6e0175cSChristoph Hellwig 		/*
886d6e0175cSChristoph Hellwig 		 * Setup BIDI XOR callback to be run after I/O completion.
887d6e0175cSChristoph Hellwig 		 */
888d6e0175cSChristoph Hellwig 		cmd->execute_cmd = sbc_execute_rw;
889d6e0175cSChristoph Hellwig 		cmd->transport_complete_callback = &xdreadwrite_callback;
8900c2ad7d1SChristoph Hellwig 		break;
891d6e0175cSChristoph Hellwig 	case VARIABLE_LENGTH_CMD:
892d6e0175cSChristoph Hellwig 	{
893d6e0175cSChristoph Hellwig 		u16 service_action = get_unaligned_be16(&cdb[8]);
894d6e0175cSChristoph Hellwig 		switch (service_action) {
895d6e0175cSChristoph Hellwig 		case XDWRITEREAD_32:
8966f974e8cSChristoph Hellwig 			sectors = transport_get_sectors_32(cdb);
897de103c93SChristoph Hellwig 
898fde9f50fSNicholas Bellinger 			if (sbc_check_dpofua(dev, cmd, cdb))
899fde9f50fSNicholas Bellinger 				return TCM_INVALID_CDB_FIELD;
9006f974e8cSChristoph Hellwig 			/*
901d6e0175cSChristoph Hellwig 			 * Use WRITE_32 and READ_32 opcodes for the emulated
902d6e0175cSChristoph Hellwig 			 * XDWRITE_READ_32 logic.
903d6e0175cSChristoph Hellwig 			 */
904d6e0175cSChristoph Hellwig 			cmd->t_task_lba = transport_lba_64_ext(cdb);
905de103c93SChristoph Hellwig 			cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
906d6e0175cSChristoph Hellwig 
907d6e0175cSChristoph Hellwig 			/*
9081fd032eeSChristoph Hellwig 			 * Setup BIDI XOR callback to be run during after I/O
909d6e0175cSChristoph Hellwig 			 * completion.
910d6e0175cSChristoph Hellwig 			 */
911de103c93SChristoph Hellwig 			cmd->execute_cmd = sbc_execute_rw;
9126f974e8cSChristoph Hellwig 			cmd->transport_complete_callback = &xdreadwrite_callback;
913d6e0175cSChristoph Hellwig 			break;
914d6e0175cSChristoph Hellwig 		case WRITE_SAME_32:
915d6e0175cSChristoph Hellwig 			sectors = transport_get_sectors_32(cdb);
916d6e0175cSChristoph Hellwig 			if (!sectors) {
917d6e0175cSChristoph Hellwig 				pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
918d6e0175cSChristoph Hellwig 				       " supported\n");
919d6e0175cSChristoph Hellwig 				return TCM_INVALID_CDB_FIELD;
920d6e0175cSChristoph Hellwig 			}
921d6e0175cSChristoph Hellwig 
922d6e0175cSChristoph Hellwig 			size = sbc_get_size(cmd, 1);
923d6e0175cSChristoph Hellwig 			cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
924d6e0175cSChristoph Hellwig 
925d6e0175cSChristoph Hellwig 			ret = sbc_setup_write_same(cmd, &cdb[10], ops);
926d6e0175cSChristoph Hellwig 			if (ret)
9271fd032eeSChristoph Hellwig 				return ret;
928d6e0175cSChristoph Hellwig 			break;
929d6e0175cSChristoph Hellwig 		default:
930d6e0175cSChristoph Hellwig 			pr_err("VARIABLE_LENGTH_CMD service action"
931d6e0175cSChristoph Hellwig 				" 0x%04x not supported\n", service_action);
932de103c93SChristoph Hellwig 			return TCM_UNSUPPORTED_SCSI_OPCODE;
933d6e0175cSChristoph Hellwig 		}
934d6e0175cSChristoph Hellwig 		break;
935d6e0175cSChristoph Hellwig 	}
93668ff9b9bSNicholas Bellinger 	case COMPARE_AND_WRITE:
93768ff9b9bSNicholas Bellinger 		sectors = cdb[13];
93868ff9b9bSNicholas Bellinger 		/*
93968ff9b9bSNicholas Bellinger 		 * Currently enforce COMPARE_AND_WRITE for a single sector
94068ff9b9bSNicholas Bellinger 		 */
94168ff9b9bSNicholas Bellinger 		if (sectors > 1) {
94268ff9b9bSNicholas Bellinger 			pr_err("COMPARE_AND_WRITE contains NoLB: %u greater"
94368ff9b9bSNicholas Bellinger 			       " than 1\n", sectors);
94468ff9b9bSNicholas Bellinger 			return TCM_INVALID_CDB_FIELD;
94568ff9b9bSNicholas Bellinger 		}
94668ff9b9bSNicholas Bellinger 		/*
94768ff9b9bSNicholas Bellinger 		 * Double size because we have two buffers, note that
94868ff9b9bSNicholas Bellinger 		 * zero is not an error..
94968ff9b9bSNicholas Bellinger 		 */
95068ff9b9bSNicholas Bellinger 		size = 2 * sbc_get_size(cmd, sectors);
95168ff9b9bSNicholas Bellinger 		cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
95268ff9b9bSNicholas Bellinger 		cmd->t_task_nolb = sectors;
95368ff9b9bSNicholas Bellinger 		cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE;
95468ff9b9bSNicholas Bellinger 		cmd->execute_cmd = sbc_compare_and_write;
95568ff9b9bSNicholas Bellinger 		cmd->transport_complete_callback = compare_and_write_callback;
95668ff9b9bSNicholas Bellinger 		break;
957d6e0175cSChristoph Hellwig 	case READ_CAPACITY:
9581fd032eeSChristoph Hellwig 		size = READ_CAP_LEN;
9591fd032eeSChristoph Hellwig 		cmd->execute_cmd = sbc_emulate_readcapacity;
960d6e0175cSChristoph Hellwig 		break;
961eb846d9fSHannes Reinecke 	case SERVICE_ACTION_IN_16:
962d6e0175cSChristoph Hellwig 		switch (cmd->t_task_cdb[1] & 0x1f) {
963d6e0175cSChristoph Hellwig 		case SAI_READ_CAPACITY_16:
9641fd032eeSChristoph Hellwig 			cmd->execute_cmd = sbc_emulate_readcapacity_16;
965d6e0175cSChristoph Hellwig 			break;
966c66094bfSHannes Reinecke 		case SAI_REPORT_REFERRALS:
967c66094bfSHannes Reinecke 			cmd->execute_cmd = target_emulate_report_referrals;
968c66094bfSHannes Reinecke 			break;
969d6e0175cSChristoph Hellwig 		default:
970d6e0175cSChristoph Hellwig 			pr_err("Unsupported SA: 0x%02x\n",
971d6e0175cSChristoph Hellwig 				cmd->t_task_cdb[1] & 0x1f);
972de103c93SChristoph Hellwig 			return TCM_INVALID_CDB_FIELD;
973d6e0175cSChristoph Hellwig 		}
9741fd032eeSChristoph Hellwig 		size = (cdb[10] << 24) | (cdb[11] << 16) |
975d6e0175cSChristoph Hellwig 		       (cdb[12] << 8) | cdb[13];
976d6e0175cSChristoph Hellwig 		break;
977d6e0175cSChristoph Hellwig 	case SYNCHRONIZE_CACHE:
978d6e0175cSChristoph Hellwig 	case SYNCHRONIZE_CACHE_16:
979d6e0175cSChristoph Hellwig 		if (cdb[0] == SYNCHRONIZE_CACHE) {
980d6e0175cSChristoph Hellwig 			sectors = transport_get_sectors_10(cdb);
981d6e0175cSChristoph Hellwig 			cmd->t_task_lba = transport_lba_32(cdb);
982d6e0175cSChristoph Hellwig 		} else {
983d6e0175cSChristoph Hellwig 			sectors = transport_get_sectors_16(cdb);
984d6e0175cSChristoph Hellwig 			cmd->t_task_lba = transport_lba_64(cdb);
985d6e0175cSChristoph Hellwig 		}
9866ef31dc7SChristophe Vu-Brugier 		if (ops->execute_sync_cache) {
987ad67f0d9SChristoph Hellwig 			cmd->execute_cmd = ops->execute_sync_cache;
9886ef31dc7SChristophe Vu-Brugier 			goto check_lba;
9896ef31dc7SChristophe Vu-Brugier 		}
9906ef31dc7SChristophe Vu-Brugier 		size = 0;
9916ef31dc7SChristophe Vu-Brugier 		cmd->execute_cmd = sbc_emulate_noop;
992d6e0175cSChristoph Hellwig 		break;
993d6e0175cSChristoph Hellwig 	case UNMAP:
99414150a6bSChristoph Hellwig 		if (!ops->execute_unmap)
995de103c93SChristoph Hellwig 			return TCM_UNSUPPORTED_SCSI_OPCODE;
99614150a6bSChristoph Hellwig 
99761fdb4acSNicholas Bellinger 		if (!dev->dev_attrib.emulate_tpu) {
99861fdb4acSNicholas Bellinger 			pr_err("Got UNMAP, but backend device has"
99961fdb4acSNicholas Bellinger 			       " emulate_tpu disabled\n");
100061fdb4acSNicholas Bellinger 			return TCM_UNSUPPORTED_SCSI_OPCODE;
100161fdb4acSNicholas Bellinger 		}
10021fd032eeSChristoph Hellwig 		size = get_unaligned_be16(&cdb[7]);
100362e46942SChristoph Hellwig 		cmd->execute_cmd = sbc_execute_unmap;
1004d6e0175cSChristoph Hellwig 		break;
1005d6e0175cSChristoph Hellwig 	case WRITE_SAME_16:
1006d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_16(cdb);
1007d6e0175cSChristoph Hellwig 		if (!sectors) {
1008d6e0175cSChristoph Hellwig 			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
1009de103c93SChristoph Hellwig 			return TCM_INVALID_CDB_FIELD;
1010d6e0175cSChristoph Hellwig 		}
1011d6e0175cSChristoph Hellwig 
10121fd032eeSChristoph Hellwig 		size = sbc_get_size(cmd, 1);
1013d6e0175cSChristoph Hellwig 		cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
1014d6e0175cSChristoph Hellwig 
1015cd063befSNicholas Bellinger 		ret = sbc_setup_write_same(cmd, &cdb[1], ops);
10166b64e1feSDan Carpenter 		if (ret)
1017cd063befSNicholas Bellinger 			return ret;
1018d6e0175cSChristoph Hellwig 		break;
1019d6e0175cSChristoph Hellwig 	case WRITE_SAME:
1020d6e0175cSChristoph Hellwig 		sectors = transport_get_sectors_10(cdb);
1021d6e0175cSChristoph Hellwig 		if (!sectors) {
1022d6e0175cSChristoph Hellwig 			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
1023de103c93SChristoph Hellwig 			return TCM_INVALID_CDB_FIELD;
1024d6e0175cSChristoph Hellwig 		}
1025d6e0175cSChristoph Hellwig 
10261fd032eeSChristoph Hellwig 		size = sbc_get_size(cmd, 1);
1027d6e0175cSChristoph Hellwig 		cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
1028d6e0175cSChristoph Hellwig 
1029d6e0175cSChristoph Hellwig 		/*
1030d6e0175cSChristoph Hellwig 		 * Follow sbcr26 with WRITE_SAME (10) and check for the existence
1031d6e0175cSChristoph Hellwig 		 * of byte 1 bit 3 UNMAP instead of original reserved field
1032d6e0175cSChristoph Hellwig 		 */
1033cd063befSNicholas Bellinger 		ret = sbc_setup_write_same(cmd, &cdb[1], ops);
10346b64e1feSDan Carpenter 		if (ret)
1035cd063befSNicholas Bellinger 			return ret;
1036d6e0175cSChristoph Hellwig 		break;
1037d6e0175cSChristoph Hellwig 	case VERIFY:
10381fd032eeSChristoph Hellwig 		size = 0;
1039c52716deSChristophe Vu-Brugier 		sectors = transport_get_sectors_10(cdb);
1040c52716deSChristophe Vu-Brugier 		cmd->t_task_lba = transport_lba_32(cdb);
10411920ed61SNicholas Bellinger 		cmd->execute_cmd = sbc_emulate_noop;
1042c52716deSChristophe Vu-Brugier 		goto check_lba;
10431a1ff38cSBernhard Kohl 	case REZERO_UNIT:
10441a1ff38cSBernhard Kohl 	case SEEK_6:
10451a1ff38cSBernhard Kohl 	case SEEK_10:
10461a1ff38cSBernhard Kohl 		/*
10471a1ff38cSBernhard Kohl 		 * There are still clients out there which use these old SCSI-2
10481a1ff38cSBernhard Kohl 		 * commands. This mainly happens when running VMs with legacy
10491a1ff38cSBernhard Kohl 		 * guest systems, connected via SCSI command pass-through to
10501a1ff38cSBernhard Kohl 		 * iSCSI targets. Make them happy and return status GOOD.
10511a1ff38cSBernhard Kohl 		 */
10521a1ff38cSBernhard Kohl 		size = 0;
10531a1ff38cSBernhard Kohl 		cmd->execute_cmd = sbc_emulate_noop;
10541a1ff38cSBernhard Kohl 		break;
1055d6e0175cSChristoph Hellwig 	default:
10561fd032eeSChristoph Hellwig 		ret = spc_parse_cdb(cmd, &size);
1057d6e0175cSChristoph Hellwig 		if (ret)
1058d6e0175cSChristoph Hellwig 			return ret;
1059d6e0175cSChristoph Hellwig 	}
1060d6e0175cSChristoph Hellwig 
1061d6e0175cSChristoph Hellwig 	/* reject any command that we don't have a handler for */
106220959c4bSAndy Grover 	if (!cmd->execute_cmd)
1063de103c93SChristoph Hellwig 		return TCM_UNSUPPORTED_SCSI_OPCODE;
1064d6e0175cSChristoph Hellwig 
1065d6e0175cSChristoph Hellwig 	if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
10661fd032eeSChristoph Hellwig 		unsigned long long end_lba;
10676ef31dc7SChristophe Vu-Brugier check_lba:
10681fd032eeSChristoph Hellwig 		end_lba = dev->transport->get_blocks(dev) + 1;
1069aa179935SNicholas Bellinger 		if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
1070aa179935SNicholas Bellinger 		    ((cmd->t_task_lba + sectors) > end_lba)) {
10711fd032eeSChristoph Hellwig 			pr_err("cmd exceeds last lba %llu "
10721fd032eeSChristoph Hellwig 				"(lba %llu, sectors %u)\n",
10731fd032eeSChristoph Hellwig 				end_lba, cmd->t_task_lba, sectors);
107409ceadc7SRoland Dreier 			return TCM_ADDRESS_OUT_OF_RANGE;
1075d6e0175cSChristoph Hellwig 		}
1076d6e0175cSChristoph Hellwig 
107768ff9b9bSNicholas Bellinger 		if (!(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE))
10781fd032eeSChristoph Hellwig 			size = sbc_get_size(cmd, sectors);
10791fd032eeSChristoph Hellwig 	}
10801fd032eeSChristoph Hellwig 
1081de103c93SChristoph Hellwig 	return target_cmd_size_check(cmd, size);
1082d6e0175cSChristoph Hellwig }
1083d6e0175cSChristoph Hellwig EXPORT_SYMBOL(sbc_parse_cdb);
10846f23ac8aSChristoph Hellwig 
10856f23ac8aSChristoph Hellwig u32 sbc_get_device_type(struct se_device *dev)
10866f23ac8aSChristoph Hellwig {
10876f23ac8aSChristoph Hellwig 	return TYPE_DISK;
10886f23ac8aSChristoph Hellwig }
10896f23ac8aSChristoph Hellwig EXPORT_SYMBOL(sbc_get_device_type);
109086d71829SAsias He 
109162e46942SChristoph Hellwig static sense_reason_t
109262e46942SChristoph Hellwig sbc_execute_unmap(struct se_cmd *cmd)
109386d71829SAsias He {
109462e46942SChristoph Hellwig 	struct sbc_ops *ops = cmd->protocol_data;
109586d71829SAsias He 	struct se_device *dev = cmd->se_dev;
109686d71829SAsias He 	unsigned char *buf, *ptr = NULL;
109786d71829SAsias He 	sector_t lba;
109886d71829SAsias He 	int size;
109986d71829SAsias He 	u32 range;
110086d71829SAsias He 	sense_reason_t ret = 0;
110186d71829SAsias He 	int dl, bd_dl;
110286d71829SAsias He 
110386d71829SAsias He 	/* We never set ANC_SUP */
110486d71829SAsias He 	if (cmd->t_task_cdb[1])
110586d71829SAsias He 		return TCM_INVALID_CDB_FIELD;
110686d71829SAsias He 
110786d71829SAsias He 	if (cmd->data_length == 0) {
110886d71829SAsias He 		target_complete_cmd(cmd, SAM_STAT_GOOD);
110986d71829SAsias He 		return 0;
111086d71829SAsias He 	}
111186d71829SAsias He 
111286d71829SAsias He 	if (cmd->data_length < 8) {
111386d71829SAsias He 		pr_warn("UNMAP parameter list length %u too small\n",
111486d71829SAsias He 			cmd->data_length);
111586d71829SAsias He 		return TCM_PARAMETER_LIST_LENGTH_ERROR;
111686d71829SAsias He 	}
111786d71829SAsias He 
111886d71829SAsias He 	buf = transport_kmap_data_sg(cmd);
111986d71829SAsias He 	if (!buf)
112086d71829SAsias He 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
112186d71829SAsias He 
112286d71829SAsias He 	dl = get_unaligned_be16(&buf[0]);
112386d71829SAsias He 	bd_dl = get_unaligned_be16(&buf[2]);
112486d71829SAsias He 
112586d71829SAsias He 	size = cmd->data_length - 8;
112686d71829SAsias He 	if (bd_dl > size)
112786d71829SAsias He 		pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n",
112886d71829SAsias He 			cmd->data_length, bd_dl);
112986d71829SAsias He 	else
113086d71829SAsias He 		size = bd_dl;
113186d71829SAsias He 
113286d71829SAsias He 	if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) {
113386d71829SAsias He 		ret = TCM_INVALID_PARAMETER_LIST;
113486d71829SAsias He 		goto err;
113586d71829SAsias He 	}
113686d71829SAsias He 
113786d71829SAsias He 	/* First UNMAP block descriptor starts at 8 byte offset */
113886d71829SAsias He 	ptr = &buf[8];
113986d71829SAsias He 	pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u"
114086d71829SAsias He 		" ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);
114186d71829SAsias He 
114286d71829SAsias He 	while (size >= 16) {
114386d71829SAsias He 		lba = get_unaligned_be64(&ptr[0]);
114486d71829SAsias He 		range = get_unaligned_be32(&ptr[8]);
114586d71829SAsias He 		pr_debug("UNMAP: Using lba: %llu and range: %u\n",
114686d71829SAsias He 				 (unsigned long long)lba, range);
114786d71829SAsias He 
114886d71829SAsias He 		if (range > dev->dev_attrib.max_unmap_lba_count) {
114986d71829SAsias He 			ret = TCM_INVALID_PARAMETER_LIST;
115086d71829SAsias He 			goto err;
115186d71829SAsias He 		}
115286d71829SAsias He 
115386d71829SAsias He 		if (lba + range > dev->transport->get_blocks(dev) + 1) {
115486d71829SAsias He 			ret = TCM_ADDRESS_OUT_OF_RANGE;
115586d71829SAsias He 			goto err;
115686d71829SAsias He 		}
115786d71829SAsias He 
115862e46942SChristoph Hellwig 		ret = ops->execute_unmap(cmd, lba, range);
115986d71829SAsias He 		if (ret)
116086d71829SAsias He 			goto err;
116186d71829SAsias He 
116286d71829SAsias He 		ptr += 16;
116386d71829SAsias He 		size -= 16;
116486d71829SAsias He 	}
116586d71829SAsias He 
116686d71829SAsias He err:
116786d71829SAsias He 	transport_kunmap_data_sg(cmd);
116886d71829SAsias He 	if (!ret)
116986d71829SAsias He 		target_complete_cmd(cmd, GOOD);
117086d71829SAsias He 	return ret;
117186d71829SAsias He }
117241861fa8SNicholas Bellinger 
117366a3d5bcSNicholas Bellinger void
117466a3d5bcSNicholas Bellinger sbc_dif_generate(struct se_cmd *cmd)
117566a3d5bcSNicholas Bellinger {
117666a3d5bcSNicholas Bellinger 	struct se_device *dev = cmd->se_dev;
117766a3d5bcSNicholas Bellinger 	struct se_dif_v1_tuple *sdt;
117818213afbSAkinobu Mita 	struct scatterlist *dsg = cmd->t_data_sg, *psg;
117966a3d5bcSNicholas Bellinger 	sector_t sector = cmd->t_task_lba;
118066a3d5bcSNicholas Bellinger 	void *daddr, *paddr;
118166a3d5bcSNicholas Bellinger 	int i, j, offset = 0;
118218213afbSAkinobu Mita 	unsigned int block_size = dev->dev_attrib.block_size;
118366a3d5bcSNicholas Bellinger 
118418213afbSAkinobu Mita 	for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {
118518213afbSAkinobu Mita 		paddr = kmap_atomic(sg_page(psg)) + psg->offset;
118666a3d5bcSNicholas Bellinger 		daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
118766a3d5bcSNicholas Bellinger 
118818213afbSAkinobu Mita 		for (j = 0; j < psg->length;
118918213afbSAkinobu Mita 				j += sizeof(struct se_dif_v1_tuple)) {
119018213afbSAkinobu Mita 			__u16 crc;
119118213afbSAkinobu Mita 			unsigned int avail;
119266a3d5bcSNicholas Bellinger 
119318213afbSAkinobu Mita 			if (offset >= dsg->length) {
119418213afbSAkinobu Mita 				offset -= dsg->length;
119518213afbSAkinobu Mita 				kunmap_atomic(daddr - dsg->offset);
119618213afbSAkinobu Mita 				dsg = sg_next(dsg);
119718213afbSAkinobu Mita 				if (!dsg) {
119818213afbSAkinobu Mita 					kunmap_atomic(paddr - psg->offset);
119918213afbSAkinobu Mita 					return;
120018213afbSAkinobu Mita 				}
120118213afbSAkinobu Mita 				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
120266a3d5bcSNicholas Bellinger 			}
120366a3d5bcSNicholas Bellinger 
120418213afbSAkinobu Mita 			sdt = paddr + j;
120518213afbSAkinobu Mita 			avail = min(block_size, dsg->length - offset);
120618213afbSAkinobu Mita 			crc = crc_t10dif(daddr + offset, avail);
120718213afbSAkinobu Mita 			if (avail < block_size) {
120818213afbSAkinobu Mita 				kunmap_atomic(daddr - dsg->offset);
120918213afbSAkinobu Mita 				dsg = sg_next(dsg);
121018213afbSAkinobu Mita 				if (!dsg) {
121118213afbSAkinobu Mita 					kunmap_atomic(paddr - psg->offset);
121218213afbSAkinobu Mita 					return;
121318213afbSAkinobu Mita 				}
121418213afbSAkinobu Mita 				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
121518213afbSAkinobu Mita 				offset = block_size - avail;
121618213afbSAkinobu Mita 				crc = crc_t10dif_update(crc, daddr, offset);
121718213afbSAkinobu Mita 			} else {
121818213afbSAkinobu Mita 				offset += block_size;
121918213afbSAkinobu Mita 			}
122018213afbSAkinobu Mita 
122118213afbSAkinobu Mita 			sdt->guard_tag = cpu_to_be16(crc);
1222823ddd87SNicholas Bellinger 			if (cmd->prot_type == TARGET_DIF_TYPE1_PROT)
122366a3d5bcSNicholas Bellinger 				sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
122466a3d5bcSNicholas Bellinger 			sdt->app_tag = 0;
122566a3d5bcSNicholas Bellinger 
12266ae50408SNicholas Bellinger 			pr_debug("DIF %s INSERT sector: %llu guard_tag: 0x%04x"
122766a3d5bcSNicholas Bellinger 				 " app_tag: 0x%04x ref_tag: %u\n",
12286ae50408SNicholas Bellinger 				 (cmd->data_direction == DMA_TO_DEVICE) ?
12296ae50408SNicholas Bellinger 				 "WRITE" : "READ", (unsigned long long)sector,
12306ae50408SNicholas Bellinger 				 sdt->guard_tag, sdt->app_tag,
12316ae50408SNicholas Bellinger 				 be32_to_cpu(sdt->ref_tag));
123266a3d5bcSNicholas Bellinger 
123366a3d5bcSNicholas Bellinger 			sector++;
123466a3d5bcSNicholas Bellinger 		}
123566a3d5bcSNicholas Bellinger 
123618213afbSAkinobu Mita 		kunmap_atomic(daddr - dsg->offset);
123718213afbSAkinobu Mita 		kunmap_atomic(paddr - psg->offset);
123866a3d5bcSNicholas Bellinger 	}
123966a3d5bcSNicholas Bellinger }
124066a3d5bcSNicholas Bellinger 
124141861fa8SNicholas Bellinger static sense_reason_t
1242823ddd87SNicholas Bellinger sbc_dif_v1_verify(struct se_cmd *cmd, struct se_dif_v1_tuple *sdt,
124318213afbSAkinobu Mita 		  __u16 crc, sector_t sector, unsigned int ei_lba)
124441861fa8SNicholas Bellinger {
124541861fa8SNicholas Bellinger 	__be16 csum;
124641861fa8SNicholas Bellinger 
1247d7a463b0SNicholas Bellinger 	if (!(cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
1248d7a463b0SNicholas Bellinger 		goto check_ref;
1249d7a463b0SNicholas Bellinger 
125018213afbSAkinobu Mita 	csum = cpu_to_be16(crc);
125141861fa8SNicholas Bellinger 
125241861fa8SNicholas Bellinger 	if (sdt->guard_tag != csum) {
125341861fa8SNicholas Bellinger 		pr_err("DIFv1 checksum failed on sector %llu guard tag 0x%04x"
125441861fa8SNicholas Bellinger 			" csum 0x%04x\n", (unsigned long long)sector,
125541861fa8SNicholas Bellinger 			be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
125641861fa8SNicholas Bellinger 		return TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
125741861fa8SNicholas Bellinger 	}
125841861fa8SNicholas Bellinger 
1259d7a463b0SNicholas Bellinger check_ref:
1260d7a463b0SNicholas Bellinger 	if (!(cmd->prot_checks & TARGET_DIF_CHECK_REFTAG))
1261d7a463b0SNicholas Bellinger 		return 0;
1262d7a463b0SNicholas Bellinger 
1263823ddd87SNicholas Bellinger 	if (cmd->prot_type == TARGET_DIF_TYPE1_PROT &&
126441861fa8SNicholas Bellinger 	    be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
126541861fa8SNicholas Bellinger 		pr_err("DIFv1 Type 1 reference failed on sector: %llu tag: 0x%08x"
126641861fa8SNicholas Bellinger 		       " sector MSB: 0x%08x\n", (unsigned long long)sector,
126741861fa8SNicholas Bellinger 		       be32_to_cpu(sdt->ref_tag), (u32)(sector & 0xffffffff));
126841861fa8SNicholas Bellinger 		return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
126941861fa8SNicholas Bellinger 	}
127041861fa8SNicholas Bellinger 
1271823ddd87SNicholas Bellinger 	if (cmd->prot_type == TARGET_DIF_TYPE2_PROT &&
127241861fa8SNicholas Bellinger 	    be32_to_cpu(sdt->ref_tag) != ei_lba) {
127341861fa8SNicholas Bellinger 		pr_err("DIFv1 Type 2 reference failed on sector: %llu tag: 0x%08x"
127441861fa8SNicholas Bellinger 		       " ei_lba: 0x%08x\n", (unsigned long long)sector,
127541861fa8SNicholas Bellinger 			be32_to_cpu(sdt->ref_tag), ei_lba);
127641861fa8SNicholas Bellinger 		return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
127741861fa8SNicholas Bellinger 	}
127841861fa8SNicholas Bellinger 
127941861fa8SNicholas Bellinger 	return 0;
128041861fa8SNicholas Bellinger }
128141861fa8SNicholas Bellinger 
1282f75b6faeSSagi Grimberg void sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
128341861fa8SNicholas Bellinger 		       struct scatterlist *sg, int sg_off)
128441861fa8SNicholas Bellinger {
128541861fa8SNicholas Bellinger 	struct se_device *dev = cmd->se_dev;
128641861fa8SNicholas Bellinger 	struct scatterlist *psg;
128741861fa8SNicholas Bellinger 	void *paddr, *addr;
128841861fa8SNicholas Bellinger 	unsigned int i, len, left;
128910762e80SNicholas Bellinger 	unsigned int offset = sg_off;
129041861fa8SNicholas Bellinger 
129138b57f82SNicholas Bellinger 	if (!sg)
129238b57f82SNicholas Bellinger 		return;
129338b57f82SNicholas Bellinger 
129441861fa8SNicholas Bellinger 	left = sectors * dev->prot_length;
129541861fa8SNicholas Bellinger 
129641861fa8SNicholas Bellinger 	for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {
129716c0ae02SSagi Grimberg 		unsigned int psg_len, copied = 0;
129841861fa8SNicholas Bellinger 
129916c0ae02SSagi Grimberg 		paddr = kmap_atomic(sg_page(psg)) + psg->offset;
130016c0ae02SSagi Grimberg 		psg_len = min(left, psg->length);
130116c0ae02SSagi Grimberg 		while (psg_len) {
130216c0ae02SSagi Grimberg 			len = min(psg_len, sg->length - offset);
130316c0ae02SSagi Grimberg 			addr = kmap_atomic(sg_page(sg)) + sg->offset + offset;
130416c0ae02SSagi Grimberg 
130516c0ae02SSagi Grimberg 			if (read)
130616c0ae02SSagi Grimberg 				memcpy(paddr + copied, addr, len);
130716c0ae02SSagi Grimberg 			else
130816c0ae02SSagi Grimberg 				memcpy(addr, paddr + copied, len);
130916c0ae02SSagi Grimberg 
131016c0ae02SSagi Grimberg 			left -= len;
131116c0ae02SSagi Grimberg 			offset += len;
131216c0ae02SSagi Grimberg 			copied += len;
131316c0ae02SSagi Grimberg 			psg_len -= len;
131416c0ae02SSagi Grimberg 
131557636388SAkinobu Mita 			kunmap_atomic(addr - sg->offset - offset);
131657636388SAkinobu Mita 
1317d6a65fdcSSagi Grimberg 			if (offset >= sg->length) {
1318d6a65fdcSSagi Grimberg 				sg = sg_next(sg);
1319d6a65fdcSSagi Grimberg 				offset = 0;
1320d6a65fdcSSagi Grimberg 			}
132141861fa8SNicholas Bellinger 		}
132257636388SAkinobu Mita 		kunmap_atomic(paddr - psg->offset);
132316c0ae02SSagi Grimberg 	}
132441861fa8SNicholas Bellinger }
1325f75b6faeSSagi Grimberg EXPORT_SYMBOL(sbc_dif_copy_prot);
132641861fa8SNicholas Bellinger 
132741861fa8SNicholas Bellinger sense_reason_t
1328f75b6faeSSagi Grimberg sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors,
1329414e4627SSagi Grimberg 	       unsigned int ei_lba, struct scatterlist *psg, int psg_off)
133041861fa8SNicholas Bellinger {
133141861fa8SNicholas Bellinger 	struct se_device *dev = cmd->se_dev;
133241861fa8SNicholas Bellinger 	struct se_dif_v1_tuple *sdt;
133318213afbSAkinobu Mita 	struct scatterlist *dsg = cmd->t_data_sg;
133441861fa8SNicholas Bellinger 	sector_t sector = start;
133541861fa8SNicholas Bellinger 	void *daddr, *paddr;
133618213afbSAkinobu Mita 	int i;
133741861fa8SNicholas Bellinger 	sense_reason_t rc;
133818213afbSAkinobu Mita 	int dsg_off = 0;
133918213afbSAkinobu Mita 	unsigned int block_size = dev->dev_attrib.block_size;
134041861fa8SNicholas Bellinger 
134118213afbSAkinobu Mita 	for (; psg && sector < start + sectors; psg = sg_next(psg)) {
134218213afbSAkinobu Mita 		paddr = kmap_atomic(sg_page(psg)) + psg->offset;
134341861fa8SNicholas Bellinger 		daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
134441861fa8SNicholas Bellinger 
134518213afbSAkinobu Mita 		for (i = psg_off; i < psg->length &&
134618213afbSAkinobu Mita 				sector < start + sectors;
134718213afbSAkinobu Mita 				i += sizeof(struct se_dif_v1_tuple)) {
134818213afbSAkinobu Mita 			__u16 crc;
134918213afbSAkinobu Mita 			unsigned int avail;
135041861fa8SNicholas Bellinger 
135118213afbSAkinobu Mita 			if (dsg_off >= dsg->length) {
135218213afbSAkinobu Mita 				dsg_off -= dsg->length;
135318213afbSAkinobu Mita 				kunmap_atomic(daddr - dsg->offset);
135418213afbSAkinobu Mita 				dsg = sg_next(dsg);
135518213afbSAkinobu Mita 				if (!dsg) {
1356414e4627SSagi Grimberg 					kunmap_atomic(paddr - psg->offset);
135718213afbSAkinobu Mita 					return 0;
135818213afbSAkinobu Mita 				}
135918213afbSAkinobu Mita 				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
136041861fa8SNicholas Bellinger 			}
136141861fa8SNicholas Bellinger 
136218213afbSAkinobu Mita 			sdt = paddr + i;
136341861fa8SNicholas Bellinger 
136441861fa8SNicholas Bellinger 			pr_debug("DIF READ sector: %llu guard_tag: 0x%04x"
136541861fa8SNicholas Bellinger 				 " app_tag: 0x%04x ref_tag: %u\n",
136641861fa8SNicholas Bellinger 				 (unsigned long long)sector, sdt->guard_tag,
136741861fa8SNicholas Bellinger 				 sdt->app_tag, be32_to_cpu(sdt->ref_tag));
136841861fa8SNicholas Bellinger 
136941861fa8SNicholas Bellinger 			if (sdt->app_tag == cpu_to_be16(0xffff)) {
137018213afbSAkinobu Mita 				dsg_off += block_size;
137118213afbSAkinobu Mita 				goto next;
137241861fa8SNicholas Bellinger 			}
137341861fa8SNicholas Bellinger 
137418213afbSAkinobu Mita 			avail = min(block_size, dsg->length - dsg_off);
137518213afbSAkinobu Mita 			crc = crc_t10dif(daddr + dsg_off, avail);
137618213afbSAkinobu Mita 			if (avail < block_size) {
1377414e4627SSagi Grimberg 				kunmap_atomic(daddr - dsg->offset);
137818213afbSAkinobu Mita 				dsg = sg_next(dsg);
137918213afbSAkinobu Mita 				if (!dsg) {
138018213afbSAkinobu Mita 					kunmap_atomic(paddr - psg->offset);
138118213afbSAkinobu Mita 					return 0;
138218213afbSAkinobu Mita 				}
138318213afbSAkinobu Mita 				daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
138418213afbSAkinobu Mita 				dsg_off = block_size - avail;
138518213afbSAkinobu Mita 				crc = crc_t10dif_update(crc, daddr, dsg_off);
138618213afbSAkinobu Mita 			} else {
138718213afbSAkinobu Mita 				dsg_off += block_size;
138818213afbSAkinobu Mita 			}
138918213afbSAkinobu Mita 
139018213afbSAkinobu Mita 			rc = sbc_dif_v1_verify(cmd, sdt, crc, sector, ei_lba);
139118213afbSAkinobu Mita 			if (rc) {
139218213afbSAkinobu Mita 				kunmap_atomic(daddr - dsg->offset);
139318213afbSAkinobu Mita 				kunmap_atomic(paddr - psg->offset);
139476736db3SSagi Grimberg 				cmd->bad_sector = sector;
139541861fa8SNicholas Bellinger 				return rc;
139641861fa8SNicholas Bellinger 			}
139718213afbSAkinobu Mita next:
139841861fa8SNicholas Bellinger 			sector++;
139941861fa8SNicholas Bellinger 			ei_lba++;
140041861fa8SNicholas Bellinger 		}
140141861fa8SNicholas Bellinger 
140218213afbSAkinobu Mita 		psg_off = 0;
1403414e4627SSagi Grimberg 		kunmap_atomic(daddr - dsg->offset);
140418213afbSAkinobu Mita 		kunmap_atomic(paddr - psg->offset);
140541861fa8SNicholas Bellinger 	}
140641861fa8SNicholas Bellinger 
140741861fa8SNicholas Bellinger 	return 0;
140841861fa8SNicholas Bellinger }
1409f75b6faeSSagi Grimberg EXPORT_SYMBOL(sbc_dif_verify);
1410