102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * osd_initiator - Main body of the osd initiator library.
302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *
402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Note: The file does not contain the advanced security functionality which
502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * is only needed by the security_manager's initiators.
602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *
702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Copyright (C) 2008 Panasas Inc.  All rights reserved.
802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *
902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Authors:
10aa281ac631008b9c18c405c8880007789f659c7dBoaz Harrosh *   Boaz Harrosh <ooo@electrozaur.com>
1102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *   Benny Halevy <bhalevy@panasas.com>
1202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *
1302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * This program is free software; you can redistribute it and/or modify
1402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * it under the terms of the GNU General Public License version 2
1502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *
1602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Redistribution and use in source and binary forms, with or without
1702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * modification, are permitted provided that the following conditions
1802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * are met:
1902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *
2002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *  1. Redistributions of source code must retain the above copyright
2102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *     notice, this list of conditions and the following disclaimer.
2202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *  2. Redistributions in binary form must reproduce the above copyright
2302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *     notice, this list of conditions and the following disclaimer in the
2402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *     documentation and/or other materials provided with the distribution.
2502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *  3. Neither the name of the Panasas company nor the names of its
2602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *     contributors may be used to endorse or promote products derived
2702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *     from this software without specific prior written permission.
2802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *
2902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
4102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
425a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
43acf3368ffb75fc4a83726655d697e79646fe4eb3Paul Gortmaker#include <linux/module.h>
445a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo
4502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include <scsi/osd_initiator.h>
4602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include <scsi/osd_sec.h>
471b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh#include <scsi/osd_attributes.h>
4898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#include <scsi/osd_sense.h>
4998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
5002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include <scsi/scsi_device.h>
5102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
5202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include "osd_debug.h"
5302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh#ifndef __unused
554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh#    define __unused			__attribute__((unused))
564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh#endif
574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshenum { OSD_REQ_RETRIES = 1 };
5902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
60aa281ac631008b9c18c405c8880007789f659c7dBoaz HarroshMODULE_AUTHOR("Boaz Harrosh <ooo@electrozaur.com>");
6102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshMODULE_DESCRIPTION("open-osd initiator library libosd.ko");
6202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshMODULE_LICENSE("GPL");
6302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
6402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic inline void build_test(void)
6502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
6602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* structures were not packed */
6702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
68c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
6902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
7002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
7102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
721b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harroshstatic const char *_osd_ver_desc(struct osd_request *or)
731b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh{
741b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
751b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh}
761b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
771b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
781b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
792cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harroshstatic int _osd_get_print_system_info(struct osd_dev *od,
802cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	void *caps, struct osd_dev_info *odi)
811b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh{
821b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	struct osd_request *or;
831b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	struct osd_attr get_attrs[] = {
841b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
851b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
861b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
871b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
881b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
891b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
901b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
911b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
921b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
931b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
941b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		/* IBM-OSD-SIM Has a bug with this one put it last */
951b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
961b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	};
971b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	void *iter = NULL, *pFirst;
981b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	int nelem = ARRAY_SIZE(get_attrs), a = 0;
991b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	int ret;
1001b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1011b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	or = osd_start_request(od, GFP_KERNEL);
1021b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (!or)
1031b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		return -ENOMEM;
1041b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1051b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	/* get attrs */
1061b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_req_get_attributes(or, &osd_root_object);
1071b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
1081b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1091b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	ret = osd_finalize_request(or, 0, caps, NULL);
1101b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (ret)
1111b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		goto out;
1121b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1131b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	ret = osd_execute_request(or);
1141b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (ret) {
1151b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
1161b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		goto out;
1171b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	}
1181b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1191b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
1201b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1211b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("Detected %s device\n",
1221b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		_osd_ver_desc(or));
1231b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1241b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
125de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("VENDOR_IDENTIFICATION  [%s]\n",
1261b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1271b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1281b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
129de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("PRODUCT_IDENTIFICATION [%s]\n",
1301b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1311b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1321b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
133de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("PRODUCT_MODEL          [%s]\n",
1341b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1351b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1361b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
137de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("PRODUCT_REVISION_LEVEL [%u]\n",
13897218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? get_unaligned_be32(pFirst) : ~0U);
1391b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1401b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
141de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("PRODUCT_SERIAL_NUMBER  [%s]\n",
1421b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1431b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1442cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	odi->osdname_len = get_attrs[a].len;
1452cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	/* Avoid NULL for memcmp optimization 0-length is good enough */
1462cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	odi->osdname = kzalloc(odi->osdname_len + 1, GFP_KERNEL);
1476d1f6621fa12800fc84f62db9e0b7a6b623eb439Dan Carpenter	if (!odi->osdname) {
1486d1f6621fa12800fc84f62db9e0b7a6b623eb439Dan Carpenter		ret = -ENOMEM;
1496d1f6621fa12800fc84f62db9e0b7a6b623eb439Dan Carpenter		goto out;
1506d1f6621fa12800fc84f62db9e0b7a6b623eb439Dan Carpenter	}
1512cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	if (odi->osdname_len)
1522cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh		memcpy(odi->osdname, get_attrs[a].val_ptr, odi->osdname_len);
1532cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	OSD_INFO("OSD_NAME               [%s]\n", odi->osdname);
1541b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	a++;
1551b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1561b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
157de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("TOTAL_CAPACITY         [0x%llx]\n",
15897218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
1591b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1601b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
161de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("USED_CAPACITY          [0x%llx]\n",
16297218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
1631b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1641b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
165de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("NUMBER_OF_PARTITIONS   [%llu]\n",
16697218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
16797218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh
16897218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh	if (a >= nelem)
16997218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		goto out;
1701b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1711b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	/* FIXME: Where are the time utilities */
1721b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
173de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh	OSD_INFO("CLOCK                  [0x%02x%02x%02x%02x%02x%02x]\n",
1741b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		((char *)pFirst)[0], ((char *)pFirst)[1],
1751b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		((char *)pFirst)[2], ((char *)pFirst)[3],
1761b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		((char *)pFirst)[4], ((char *)pFirst)[5]);
1771b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1781b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
1791b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		unsigned len = get_attrs[a].len;
1801b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		char sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
1811b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1821b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
1831b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh				   sid_dump, sizeof(sid_dump), true);
184de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh		OSD_INFO("OSD_SYSTEM_ID(%d)\n"
185de6b20385b1c14f97ccdf7da173b4c9a7405083bBoaz Harrosh			 "        [%s]\n", len, sid_dump);
1862cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh
1872cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh		if (unlikely(len > sizeof(odi->systemid))) {
1882cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh			OSD_ERR("OSD Target error: OSD_SYSTEM_ID too long(%d). "
1892cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh				"device idetification might not work\n", len);
1902cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh			len = sizeof(odi->systemid);
1912cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh		}
1922cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh		odi->systemid_len = len;
1932cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh		memcpy(odi->systemid, get_attrs[a].val_ptr, len);
1941b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		a++;
1951b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	}
1961b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harroshout:
1971b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_end_request(or);
1981b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	return ret;
1991b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh}
2001b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
2012cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harroshint osd_auto_detect_ver(struct osd_dev *od,
2022cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	void *caps, struct osd_dev_info *odi)
2031b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh{
2041b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	int ret;
2051b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
2061b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	/* Auto-detect the osd version */
2072cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh	ret = _osd_get_print_system_info(od, caps, odi);
2081b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (ret) {
2091b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		osd_dev_set_ver(od, OSD_VER1);
2101b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		OSD_DEBUG("converting to OSD1\n");
2112cdd6410e5a1665823f2a048fc7f8f6a8384be1dBoaz Harrosh		ret = _osd_get_print_system_info(od, caps, odi);
2121b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	}
2131b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
2141b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	return ret;
2151b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh}
2161b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz HarroshEXPORT_SYMBOL(osd_auto_detect_ver);
2171b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
21802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic unsigned _osd_req_cdb_len(struct osd_request *or)
21902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
220c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
22102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
22202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
2234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
2244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
225c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ?
226c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv1_attr_list_elem_size(len) :
227c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv2_attr_list_elem_size(len);
2284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
2294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
23071f32e31e5638df37904697e2d04182935add85dBoaz Harroshstatic void _osd_req_alist_elem_encode(struct osd_request *or,
23171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	void *attr_last, const struct osd_attr *oa)
23271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh{
23371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	if (osd_req_is_ver1(or)) {
23471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv1_attributes_list_element *attr = attr_last;
23571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
23671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_page = cpu_to_be32(oa->attr_page);
23771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_id = cpu_to_be32(oa->attr_id);
23871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_bytes = cpu_to_be16(oa->len);
23971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		memcpy(attr->attr_val, oa->val_ptr, oa->len);
24071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	} else {
24171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv2_attributes_list_element *attr = attr_last;
24271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
24371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_page = cpu_to_be32(oa->attr_page);
24471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_id = cpu_to_be32(oa->attr_id);
24571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_bytes = cpu_to_be16(oa->len);
24671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		memcpy(attr->attr_val, oa->val_ptr, oa->len);
24771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	}
24871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh}
24971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
25071f32e31e5638df37904697e2d04182935add85dBoaz Harroshstatic int _osd_req_alist_elem_decode(struct osd_request *or,
25171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	void *cur_p, struct osd_attr *oa, unsigned max_bytes)
25271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh{
25371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	unsigned inc;
25471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	if (osd_req_is_ver1(or)) {
25571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv1_attributes_list_element *attr = cur_p;
25671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
25771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (max_bytes < sizeof(*attr))
25871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
25971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
26071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->len = be16_to_cpu(attr->attr_bytes);
26171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		inc = _osd_req_alist_elem_size(or, oa->len);
26271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (inc > max_bytes)
26371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
26471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
26571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_page = be32_to_cpu(attr->attr_page);
26671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_id = be32_to_cpu(attr->attr_id);
26771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
26871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		/* OSD1: On empty attributes we return a pointer to 2 bytes
26971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		 * of zeros. This keeps similar behaviour with OSD2.
27071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		 * (See below)
27171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		 */
27271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->val_ptr = likely(oa->len) ? attr->attr_val :
27371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh						(u8 *)&attr->attr_bytes;
27471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	} else {
27571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv2_attributes_list_element *attr = cur_p;
27671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
27771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (max_bytes < sizeof(*attr))
27871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
27971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
28071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->len = be16_to_cpu(attr->attr_bytes);
28171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		inc = _osd_req_alist_elem_size(or, oa->len);
28271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (inc > max_bytes)
28371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
28471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
28571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_page = be32_to_cpu(attr->attr_page);
28671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_id = be32_to_cpu(attr->attr_id);
28771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
288e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		/* OSD2: For convenience, on empty attributes, we return 8 bytes
289e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 * of zeros here. This keeps the same behaviour with OSD2r04,
290e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 * and is nice with null terminating ASCII fields.
291e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 * oa->val_ptr == NULL marks the end-of-list, or error.
292e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 */
293e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		oa->val_ptr = likely(oa->len) ? attr->attr_val : attr->reserved;
29471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	}
29571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	return inc;
29671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh}
29771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
2984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
2994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
300c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ?
301c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv1_list_size(list_head) :
302c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv2_list_size(list_head);
3034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
3064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
307c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ?
308c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		sizeof(struct osdv1_attributes_list_header) :
309c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		sizeof(struct osdv2_attributes_list_header);
3104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic void _osd_req_set_alist_type(struct osd_request *or,
3134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *list, int list_type)
3144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
315c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or)) {
316c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		struct osdv1_attributes_list_header *attr_list = list;
317c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
318c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		memset(attr_list, 0, sizeof(*attr_list));
319c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		attr_list->type = list_type;
320c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	} else {
321c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		struct osdv2_attributes_list_header *attr_list = list;
3224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
323c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		memset(attr_list, 0, sizeof(*attr_list));
324c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		attr_list->type = list_type;
325c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	}
3264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic bool _osd_req_is_alist_type(struct osd_request *or,
3294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *list, int list_type)
3304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
3314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!list)
3324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return false;
3334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
334c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or)) {
3354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		struct osdv1_attributes_list_header *attr_list = list;
3364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return attr_list->type == list_type;
338c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	} else {
339c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		struct osdv2_attributes_list_header *attr_list = list;
340c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
341c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		return attr_list->type == list_type;
3424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
3434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3453e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh/* This is for List-objects not Attributes-Lists */
3463e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshstatic void _osd_req_encode_olist(struct osd_request *or,
3473e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id_list *list)
3483e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
3493e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
3503e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
351c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or)) {
352c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v1.list_identifier = list->list_identifier;
353c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v1.start_address = list->continuation_id;
354c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	} else {
355c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v2.list_identifier = list->list_identifier;
356c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v2.start_address = list->continuation_id;
357c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	}
3583e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
3593e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
3604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
3614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u64 offset, unsigned *padding)
3624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
3634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return __osd_encode_offset(offset, padding,
364c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh			osd_req_is_ver1(or) ?
365c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
366c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh			OSD_OFFSET_MAX_SHIFT);
3674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
369345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshstatic struct osd_security_parameters *
370345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh_osd_req_sec_params(struct osd_request *or)
371345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
372345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	struct osd_cdb *ocdb = &or->cdb;
373345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
374c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or))
375f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		return (struct osd_security_parameters *)&ocdb->v1.sec_params;
376c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	else
377f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		return (struct osd_security_parameters *)&ocdb->v2.sec_params;
378345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
379345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
38002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
38102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
38202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	memset(osdd, 0, sizeof(*osdd));
38302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osdd->scsi_device = scsi_device;
38402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
385c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh#ifdef OSD_VER1_SUPPORT
386c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	osdd->version = OSD_VER2;
387c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh#endif
38802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* TODO: Allocate pools for osd_request attributes ... */
38902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
39002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_dev_init);
39102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
39202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_dev_fini(struct osd_dev *osdd)
39302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
39402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* TODO: De-allocate pools */
39502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
39602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osdd->scsi_device = NULL;
39702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
39802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_dev_fini);
39902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
40002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic struct osd_request *_osd_request_alloc(gfp_t gfp)
40102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
40202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_request *or;
40302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
40402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* TODO: Use mempool with one saved request */
40502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or = kzalloc(sizeof(*or), gfp);
40602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return or;
40702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
40802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
40902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osd_request_free(struct osd_request *or)
41002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
41102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	kfree(or);
41202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
41302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
41402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstruct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
41502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
41602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_request *or;
41702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
41802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or = _osd_request_alloc(gfp);
41902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (!or)
42002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		return NULL;
42102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
42202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->osd_dev = dev;
42302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->alloc_flags = gfp;
42402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->timeout = dev->def_timeout;
42502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->retries = OSD_REQ_RETRIES;
42602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
42702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return or;
42802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
42902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_start_request);
43002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic void _osd_free_seg(struct osd_request *or __unused,
4324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct _osd_req_data_segment *seg)
4334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
4344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!seg->buff || !seg->alloc_size)
4354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return;
4364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
4374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	kfree(seg->buff);
4384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->buff = NULL;
4394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->alloc_size = 0;
4404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
4414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
4425d0961fd1f25e117f907f3af3aaa870637049252Boaz Harroshstatic void _put_request(struct request *rq)
4438c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh{
4445d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	/*
4455d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	 * If osd_finalize_request() was called but the request was not
4465d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	 * executed through the block layer, then we must release BIOs.
4475d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	 * TODO: Keep error code in or->async_error. Need to audit all
4485d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	 *       code paths.
4495d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	 */
4505d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	if (unlikely(rq->bio))
4515d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
4525d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	else
4535d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		blk_put_request(rq);
4548c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh}
4558c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh
45602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_end_request(struct osd_request *or)
45702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
45802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct request *rq = or->request;
45902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
46002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (rq) {
46102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (rq->next_rq) {
4625d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh			_put_request(rq->next_rq);
4638c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh			rq->next_rq = NULL;
46402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
46502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4665d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		_put_request(rq);
46702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
468c4df46c49d8677158c7fb070a08e0d386c80205fBoaz Harrosh
469c4df46c49d8677158c7fb070a08e0d386c80205fBoaz Harrosh	_osd_free_seg(or, &or->get_attr);
470c4df46c49d8677158c7fb070a08e0d386c80205fBoaz Harrosh	_osd_free_seg(or, &or->enc_get_attr);
471c4df46c49d8677158c7fb070a08e0d386c80205fBoaz Harrosh	_osd_free_seg(or, &or->set_attr);
472e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	_osd_free_seg(or, &or->cdb_cont);
473c4df46c49d8677158c7fb070a08e0d386c80205fBoaz Harrosh
47402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_request_free(or);
47502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
47602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_end_request);
47702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4785d0961fd1f25e117f907f3af3aaa870637049252Boaz Harroshstatic void _set_error_resid(struct osd_request *or, struct request *req,
4795d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh			     int error)
4805d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh{
4815d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	or->async_error = error;
4825d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	or->req_errors = req->errors ? : error;
4835d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	or->sense_len = req->sense_len;
4845d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	if (or->out.req)
4855d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		or->out.residual = or->out.req->resid_len;
4865d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	if (or->in.req)
4875d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		or->in.residual = or->in.req->resid_len;
4885d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh}
4895d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh
49002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshint osd_execute_request(struct osd_request *or)
49102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
4925d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	int error = blk_execute_rq(or->request->q, NULL, or->request, 0);
4935d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh
4945d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	_set_error_resid(or, or->request, error);
4955d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	return error;
49602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
49702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_execute_request);
49802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
49902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void osd_request_async_done(struct request *req, int error)
50002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
50102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_request *or = req->end_io_data;
50202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
5035d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	_set_error_resid(or, req, error);
5045d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	if (req->next_rq) {
5055d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		__blk_put_request(req->q, req->next_rq);
5065d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		req->next_rq = NULL;
507aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	}
50802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
5095d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	__blk_put_request(req->q, req);
5105d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	or->request = NULL;
5115d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	or->in.req = NULL;
5125d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	or->out.req = NULL;
5135d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh
51402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (or->async_done)
51502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->async_done(or, or->async_private);
51602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	else
51702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		osd_end_request(or);
51802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
51902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
52002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshint osd_execute_request_async(struct osd_request *or,
52102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osd_req_done_fn *done, void *private)
52202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
52302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request->end_io_data = or;
52402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->async_private = private;
52502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->async_done = done;
52602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
52702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
52802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			      osd_request_async_done);
52902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return 0;
53002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
53102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_execute_request_async);
53202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
5334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshu8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
5344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshu8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
5354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_realloc_seg(struct osd_request *or,
5374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct _osd_req_data_segment *seg, unsigned max_bytes)
5384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *buff;
5404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (seg->alloc_size >= max_bytes)
5424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
5434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
5454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!buff) {
5464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
5474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			seg->alloc_size);
5484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -ENOMEM;
5494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
5504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
5524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->buff = buff;
5534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->alloc_size = max_bytes;
5544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
5554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
557e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harroshstatic int _alloc_cdb_cont(struct osd_request *or, unsigned total_bytes)
558e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh{
559e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	OSD_DEBUG("total_bytes=%d\n", total_bytes);
560e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	return _osd_realloc_seg(or, &or->cdb_cont, total_bytes);
561e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh}
562e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
5634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _alloc_set_attr_list(struct osd_request *or,
5644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
5654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned total_bytes = add_bytes;
5674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (; nelem; --nelem, ++oa)
5694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes += _osd_req_alist_elem_size(or, oa->len);
5704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("total_bytes=%d\n", total_bytes);
5724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
5734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
5764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("total_bytes=%d\n", max_bytes);
5784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
5794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _alloc_get_attr_list(struct osd_request *or)
5824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
5844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
5854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
58702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
58802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Common to all OSD commands
58902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
59002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
59102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osdv1_req_encode_common(struct osd_request *or,
59202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
59302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
59402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osdv1_cdb *ocdb = &or->cdb.v1;
59502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
59602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/*
59702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 * For speed, the commands
59802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
59902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
60002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 * are not supported here. Should pass zero and set after the call
60102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 */
60202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	act &= cpu_to_be16(~0x0080); /* V1 action code */
60302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
60402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
60502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
60602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
60702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
60802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.varlen_cdb.service_action = act;
60902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
61002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.partition = cpu_to_be64(obj->partition);
61102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.object = cpu_to_be64(obj->id);
61202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.v1.length = cpu_to_be64(len);
61302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.v1.start_address = cpu_to_be64(offset);
61402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
61502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
616c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harroshstatic void _osdv2_req_encode_common(struct osd_request *or,
617c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
618c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh{
619c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	struct osdv2_cdb *ocdb = &or->cdb.v2;
620c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
621c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
622c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
623c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
624c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
625c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.varlen_cdb.service_action = act;
626c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
627c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.partition = cpu_to_be64(obj->partition);
628c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.object = cpu_to_be64(obj->id);
629c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.v2.length = cpu_to_be64(len);
630c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.v2.start_address = cpu_to_be64(offset);
631c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh}
632c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
63302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osd_req_encode_common(struct osd_request *or,
63402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
63502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
636c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or))
637c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		_osdv1_req_encode_common(or, act, obj, offset, len);
638c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	else
639c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		_osdv2_req_encode_common(or, act, obj, offset, len);
64002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
64102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
64202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
64302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Device commands
64402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
645ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
646ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
647ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
64802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_format(struct osd_request *or, u64 tot_capacity)
64902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
65002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
65102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh				tot_capacity);
65202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
65302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_format);
65402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
6553e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_dev_partitions(struct osd_request *or,
6563e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
6573e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6583e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
6593e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
6603e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_dev_partitions);
6613e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6623e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshstatic void _osd_req_encode_flush(struct osd_request *or,
6633e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	enum osd_options_flush_scope_values op)
6643e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6653e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
6663e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6673e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	ocdb->command_specific_options = op;
6683e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
6693e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6703e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_obsd(struct osd_request *or,
6713e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	enum osd_options_flush_scope_values op)
6723e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6733e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
6743e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
6753e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
6763e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_obsd);
6773e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
678ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
679ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const u8 *cdb, ...); */
680ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_task_management(struct osd_request *, ...); */
681ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
68202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
68302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Partition commands
68402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
68502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osd_req_encode_partition(struct osd_request *or,
68602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	__be16 act, osd_id partition)
68702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
68802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_obj_id par = {
68902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		.partition = partition,
69002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		.id = 0,
69102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	};
69202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
69302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, act, &par, 0, 0);
69402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
69502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
69602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_create_partition(struct osd_request *or, osd_id partition)
69702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
69802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
69902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
70002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_create_partition);
70102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
70202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_remove_partition(struct osd_request *or, osd_id partition)
70302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
70402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
70502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
70602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_remove_partition);
70702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
708ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_set_partition_key(struct osd_request *,
709ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
710ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
711ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
7123e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshstatic int _osd_req_list_objects(struct osd_request *or,
7133e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
7143e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id_list *list, unsigned nelem)
7153e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
716fc2fac5b5f11e2bee3bf37215c8746236f5ea188Boaz Harrosh	struct request_queue *q = osd_request_queue(or->osd_dev);
7173e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
7183e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct bio *bio;
7193e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7203e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
7213e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7223e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	if (list->list_identifier)
7233e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		_osd_req_encode_olist(or, list);
7243e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7253e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	WARN_ON(or->in.bio);
7263e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	bio = bio_map_kern(q, list, len, or->alloc_flags);
727bf5e84f69618f416e89a5a53434a8c865e70252eDan Carpenter	if (IS_ERR(bio)) {
7283e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
729bf5e84f69618f416e89a5a53434a8c865e70252eDan Carpenter		return PTR_ERR(bio);
7303e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	}
7313e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7327b6d91daee5cac6402186ff224c3af39d79f4a0eChristoph Hellwig	bio->bi_rw &= ~REQ_WRITE;
7333e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	or->in.bio = bio;
7344f024f3797c43cb4b73cd2c50cec728842d0e49eKent Overstreet	or->in.total_bytes = bio->bi_iter.bi_size;
7353e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return 0;
7363e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7373e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7383e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_partition_collections(struct osd_request *or,
7393e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
7403e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	unsigned nelem)
7413e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7423e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id par = {
7433e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.partition = partition,
7443e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.id = 0,
7453e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	};
7463e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7473e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return osd_req_list_collection_objects(or, &par, initial_id, list,
7483e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh					       nelem);
7493e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7503e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_partition_collections);
7513e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7523e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_partition_objects(struct osd_request *or,
7533e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
7543e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	unsigned nelem)
7553e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7563e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id par = {
7573e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.partition = partition,
7583e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.id = 0,
7593e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	};
7603e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7613e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
7623e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh				     nelem);
7633e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7643e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_partition_objects);
7653e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7663e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_partition(struct osd_request *or,
7673e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id partition, enum osd_options_flush_scope_values op)
7683e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7693e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
7703e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
7713e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7723e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_partition);
7733e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7743e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh/*
7753e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh * Collection commands
7763e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh */
777ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_create_collection(struct osd_request *,
778ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *); */
779ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_remove_collection(struct osd_request *,
780ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *); */
781ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
7823e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_collection_objects(struct osd_request *or,
7833e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	const struct osd_obj_id *obj, osd_id initial_id,
7843e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id_list *list, unsigned nelem)
7853e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7863e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
7873e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh				     initial_id, list, nelem);
7883e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7893e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_collection_objects);
7903e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
791ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void query(struct osd_request *, ...); V2 */
792ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
7933e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_collection(struct osd_request *or,
7943e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
7953e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7963e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
7973e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
7983e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7993e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_collection);
8003e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
801ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
802ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
803ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
80402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
80502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Object commands
80602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
80702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
80802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
80902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
81002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
81102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_create_object);
81202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
81302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
81402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
81502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
81602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
81702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_remove_object);
81802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
819ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
820ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_create_multi(struct osd_request *or,
821ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
822ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh*/
823ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
82402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_write(struct osd_request *or,
82562f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	const struct osd_obj_id *obj, u64 offset,
82662f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	struct bio *bio, u64 len)
82702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
82862f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, len);
82902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	WARN_ON(or->out.bio || or->out.total_bytes);
8307b6d91daee5cac6402186ff224c3af39d79f4a0eChristoph Hellwig	WARN_ON(0 == (bio->bi_rw & REQ_WRITE));
83102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->out.bio = bio;
83262f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	or->out.total_bytes = len;
83302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
83402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_write);
83502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
8360e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harroshint osd_req_write_kern(struct osd_request *or,
8370e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	const struct osd_obj_id *obj, u64 offset, void* buff, u64 len)
8380e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh{
839fc2fac5b5f11e2bee3bf37215c8746236f5ea188Boaz Harrosh	struct request_queue *req_q = osd_request_queue(or->osd_dev);
8400e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL);
8410e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh
8420e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	if (IS_ERR(bio))
8430e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh		return PTR_ERR(bio);
8440e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh
8457b6d91daee5cac6402186ff224c3af39d79f4a0eChristoph Hellwig	bio->bi_rw |= REQ_WRITE; /* FIXME: bio_set_dir() */
84662f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	osd_req_write(or, obj, offset, bio, len);
8470e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	return 0;
8480e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh}
8490e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz HarroshEXPORT_SYMBOL(osd_req_write_kern);
8500e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh
851ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_append(struct osd_request *,
852ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, struct bio *data_out); */
853ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_create_write(struct osd_request *,
854ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
855ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_clear(struct osd_request *,
856ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, u64 offset, u64 len); */
857ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_punch(struct osd_request *,
858ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, u64 offset, u64 len); V2 */
859ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
8603e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_object(struct osd_request *or,
8613e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
8623e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	/*V2*/ u64 offset, /*V2*/ u64 len)
8633e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
864c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
865c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
866c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		offset = 0;
867c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		len = 0;
868c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	}
869c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
8703e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
8713e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
8723e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
8733e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_object);
8743e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
87502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_read(struct osd_request *or,
87662f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	const struct osd_obj_id *obj, u64 offset,
87762f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	struct bio *bio, u64 len)
87802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
87962f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len);
88002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	WARN_ON(or->in.bio || or->in.total_bytes);
881d842a93c4b3a20d31f4fb97357e0964210d6066fJiri Slaby	WARN_ON(bio->bi_rw & REQ_WRITE);
88202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->in.bio = bio;
88362f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	or->in.total_bytes = len;
88402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
88502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_read);
88602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
8870e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harroshint osd_req_read_kern(struct osd_request *or,
8880e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	const struct osd_obj_id *obj, u64 offset, void* buff, u64 len)
8890e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh{
890fc2fac5b5f11e2bee3bf37215c8746236f5ea188Boaz Harrosh	struct request_queue *req_q = osd_request_queue(or->osd_dev);
8910e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL);
8920e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh
8930e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	if (IS_ERR(bio))
8940e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh		return PTR_ERR(bio);
8950e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh
89662f469b596dd0aadf046a69027087c18db43734eBoaz Harrosh	osd_req_read(or, obj, offset, bio, len);
8970e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh	return 0;
8980e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh}
8990e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz HarroshEXPORT_SYMBOL(osd_req_read_kern);
9000e35afbc8b054e04a35faa796c72abb3b82bd33bBoaz Harrosh
901e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harroshstatic int _add_sg_continuation_descriptor(struct osd_request *or,
902e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	const struct osd_sg_entry *sglist, unsigned numentries, u64 *len)
903e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh{
904e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	struct osd_sg_continuation_descriptor *oscd;
905e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	u32 oscd_size;
906e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	unsigned i;
907e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	int ret;
908e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
909e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	oscd_size = sizeof(*oscd) + numentries * sizeof(oscd->entries[0]);
910e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
911e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	if (!or->cdb_cont.total_bytes) {
912e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		/* First time, jump over the header, we will write to:
913e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		 *	cdb_cont.buff + cdb_cont.total_bytes
914e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		 */
915e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		or->cdb_cont.total_bytes =
916e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh				sizeof(struct osd_continuation_segment_header);
917e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	}
918e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
919e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	ret = _alloc_cdb_cont(or, or->cdb_cont.total_bytes + oscd_size);
920e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	if (unlikely(ret))
921e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		return ret;
922e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
923e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	oscd = or->cdb_cont.buff + or->cdb_cont.total_bytes;
924e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	oscd->hdr.type = cpu_to_be16(SCATTER_GATHER_LIST);
925e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	oscd->hdr.pad_length = 0;
926e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	oscd->hdr.length = cpu_to_be32(oscd_size - sizeof(*oscd));
927e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
928e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	*len = 0;
929e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	/* copy the sg entries and convert to network byte order */
930e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	for (i = 0; i < numentries; i++) {
931e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		oscd->entries[i].offset = cpu_to_be64(sglist[i].offset);
932e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		oscd->entries[i].len    = cpu_to_be64(sglist[i].len);
933e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		*len += sglist[i].len;
934e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	}
935e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
936e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	or->cdb_cont.total_bytes += oscd_size;
937e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	OSD_DEBUG("total_bytes=%d oscd_size=%d numentries=%d\n",
938e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		  or->cdb_cont.total_bytes, oscd_size, numentries);
939e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	return 0;
940e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh}
941e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
942e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harroshstatic int _osd_req_finalize_cdb_cont(struct osd_request *or, const u8 *cap_key)
943e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh{
944e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	struct request_queue *req_q = osd_request_queue(or->osd_dev);
945e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	struct bio *bio;
946e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
947e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	struct osd_continuation_segment_header *cont_seg_hdr;
948e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
949e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	if (!or->cdb_cont.total_bytes)
950e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		return 0;
951e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
952e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	cont_seg_hdr = or->cdb_cont.buff;
953e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	cont_seg_hdr->format = CDB_CONTINUATION_FORMAT_V2;
954e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	cont_seg_hdr->service_action = cdbh->varlen_cdb.service_action;
955e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
956e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	/* create a bio for continuation segment */
957e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	bio = bio_map_kern(req_q, or->cdb_cont.buff, or->cdb_cont.total_bytes,
958e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh			   GFP_KERNEL);
959057f02a38e67a944a2d0b89bb0111efb9dbe6e6eDan Carpenter	if (IS_ERR(bio))
960057f02a38e67a944a2d0b89bb0111efb9dbe6e6eDan Carpenter		return PTR_ERR(bio);
961e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
962e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	bio->bi_rw |= REQ_WRITE;
963e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
964e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	/* integrity check the continuation before the bio is linked
965e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 * with the other data segments since the continuation
966e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 * integrity is separate from the other data segments.
967e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 */
968e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	osd_sec_sign_data(cont_seg_hdr->integrity_check, bio, cap_key);
969e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
970e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	cdbh->v2.cdb_continuation_length = cpu_to_be32(or->cdb_cont.total_bytes);
971e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
972e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	/* we can't use _req_append_segment, because we need to link in the
973e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 * continuation bio to the head of the bio list - the
974e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 * continuation segment (if it exists) is always the first segment in
975e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 * the out data buffer.
976e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 */
977e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	bio->bi_next = or->out.bio;
978e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	or->out.bio = bio;
979e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	or->out.total_bytes += or->cdb_cont.total_bytes;
980e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
981e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	return 0;
982e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh}
983e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
984e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh/* osd_req_write_sg: Takes a @bio that points to the data out buffer and an
985e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh * @sglist that has the scatter gather entries. Scatter-gather enables a write
986e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh * of multiple none-contiguous areas of an object, in a single call. The extents
987e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh * may overlap and/or be in any order. The only constrain is that:
988e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh *	total_bytes(sglist) >= total_bytes(bio)
989e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh */
990e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harroshint osd_req_write_sg(struct osd_request *or,
991e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	const struct osd_obj_id *obj, struct bio *bio,
992e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	const struct osd_sg_entry *sglist, unsigned numentries)
993e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh{
994e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	u64 len;
995e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	int ret = _add_sg_continuation_descriptor(or, sglist, numentries, &len);
996e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
997e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	if (ret)
998e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		return ret;
999e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	osd_req_write(or, obj, 0, bio, len);
1000e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
1001e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	return 0;
1002e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh}
1003e96e72c45a1e78e9266dd70113b851395a440ef3Boaz HarroshEXPORT_SYMBOL(osd_req_write_sg);
1004e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
1005e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh/* osd_req_read_sg: Read multiple extents of an object into @bio
1006e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh * See osd_req_write_sg
1007e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh */
1008e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harroshint osd_req_read_sg(struct osd_request *or,
1009e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	const struct osd_obj_id *obj, struct bio *bio,
1010e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	const struct osd_sg_entry *sglist, unsigned numentries)
1011e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh{
1012e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	u64 len;
10134977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh	u64 off;
10144977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh	int ret;
1015e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
10164977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh	if (numentries > 1) {
10174977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		off = 0;
10184977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		ret = _add_sg_continuation_descriptor(or, sglist, numentries,
10194977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh						      &len);
10204977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		if (ret)
10214977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh			return ret;
10224977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh	} else {
10234977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		/* Optimize the case of single segment, read_sg is a
10244977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		 * bidi operation.
10254977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		 */
10264977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		len = sglist->len;
10274977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh		off = sglist->offset;
10284977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh	}
10294977c82504f58d7579acabd21688183eaa8768fbBoaz Harrosh	osd_req_read(or, obj, off, bio, len);
1030e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
1031e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	return 0;
1032e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh}
1033e96e72c45a1e78e9266dd70113b851395a440ef3Boaz HarroshEXPORT_SYMBOL(osd_req_read_sg);
1034e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh
10356dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh/* SG-list write/read Kern API
10366dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh *
10376dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh * osd_req_{write,read}_sg_kern takes an array of @buff pointers and an array
10386dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh * of sg_entries. @numentries indicates how many pointers and sg_entries there
10396dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh * are.  By requiring an array of buff pointers. This allows a caller to do a
10406dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh * single write/read and scatter into multiple buffers.
10416dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh * NOTE: Each buffer + len should not cross a page boundary.
10426dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh */
10436dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harroshstatic struct bio *_create_sg_bios(struct osd_request *or,
10446dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	void **buff, const struct osd_sg_entry *sglist, unsigned numentries)
10456dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh{
10466dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	struct request_queue *q = osd_request_queue(or->osd_dev);
10476dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	struct bio *bio;
10486dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	unsigned i;
10496dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10506dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	bio = bio_kmalloc(GFP_KERNEL, numentries);
10516dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	if (unlikely(!bio)) {
10521051e9b33bbf550be52bdd674b519f3dc99f0dd9Masanari Iida		OSD_DEBUG("Failed to allocate BIO size=%u\n", numentries);
10536dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		return ERR_PTR(-ENOMEM);
10546dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	}
10556dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10566dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	for (i = 0; i < numentries; i++) {
10576dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		unsigned offset = offset_in_page(buff[i]);
10586dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		struct page *page = virt_to_page(buff[i]);
10596dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		unsigned len = sglist[i].len;
10606dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		unsigned added_len;
10616dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10626dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		BUG_ON(offset + len > PAGE_SIZE);
10636dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		added_len = bio_add_pc_page(q, bio, page, len, offset);
10646dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		if (unlikely(len != added_len)) {
10656dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh			OSD_DEBUG("bio_add_pc_page len(%d) != added_len(%d)\n",
10666dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh				  len, added_len);
10676dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh			bio_put(bio);
10686dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh			return ERR_PTR(-ENOMEM);
10696dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		}
10706dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	}
10716dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10726dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	return bio;
10736dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh}
10746dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10756dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harroshint osd_req_write_sg_kern(struct osd_request *or,
10766dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	const struct osd_obj_id *obj, void **buff,
10776dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	const struct osd_sg_entry *sglist, unsigned numentries)
10786dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh{
10796dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	struct bio *bio = _create_sg_bios(or, buff, sglist, numentries);
10806dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	if (IS_ERR(bio))
10816dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		return PTR_ERR(bio);
10826dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10836dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	bio->bi_rw |= REQ_WRITE;
10846dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	osd_req_write_sg(or, obj, bio, sglist, numentries);
10856dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10866dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	return 0;
10876dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh}
10886dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz HarroshEXPORT_SYMBOL(osd_req_write_sg_kern);
10896dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10906dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harroshint osd_req_read_sg_kern(struct osd_request *or,
10916dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	const struct osd_obj_id *obj, void **buff,
10926dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	const struct osd_sg_entry *sglist, unsigned numentries)
10936dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh{
10946dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	struct bio *bio = _create_sg_bios(or, buff, sglist, numentries);
10956dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	if (IS_ERR(bio))
10966dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh		return PTR_ERR(bio);
10976dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
10986dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	osd_req_read_sg(or, obj, bio, sglist, numentries);
10996dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
11006dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh	return 0;
11016dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh}
11026dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz HarroshEXPORT_SYMBOL(osd_req_read_sg_kern);
11036dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
11046dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
11056dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9daBoaz Harrosh
11064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshvoid osd_req_get_attributes(struct osd_request *or,
11074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_obj_id *obj)
11084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
11094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
11104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
11114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_get_attributes);
11124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshvoid osd_req_set_attributes(struct osd_request *or,
11144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_obj_id *obj)
11154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
11164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
11174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
11184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_set_attributes);
11194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh/*
11214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Attributes List-mode
11224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh */
11234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_add_set_attr_list(struct osd_request *or,
11254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *oa, unsigned nelem)
11264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
11274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned total_bytes = or->set_attr.total_bytes;
11284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *attr_last;
11294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
11304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode &&
11324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
11334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		WARN_ON(1);
11344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -EINVAL;
11354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
11374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!total_bytes) { /* first-time: allocate and put list header */
11394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes = _osd_req_sizeof_alist_header(or);
11404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
11414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret)
11424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
11434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		_osd_req_set_alist_type(or, or->set_attr.buff,
11444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					OSD_ATTR_LIST_SET_RETRIEVE);
11454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	attr_last = or->set_attr.buff + total_bytes;
11474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (; nelem; --nelem) {
11494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
11504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes += elem_size;
11524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
11534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			or->set_attr.total_bytes = total_bytes - elem_size;
11544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
11554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			if (ret)
11564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				return ret;
11574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			attr_last =
11584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				or->set_attr.buff + or->set_attr.total_bytes;
11594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
11604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
116171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		_osd_req_alist_elem_encode(or, attr_last, oa);
11624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attr_last += elem_size;
11644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		++oa;
11654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->set_attr.total_bytes = total_bytes;
11684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
11694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
11704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_add_set_attr_list);
11714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _req_append_segment(struct osd_request *or,
11734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned padding, struct _osd_req_data_segment *seg,
11744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
11754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
11764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *pad_buff;
11774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
11784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (padding) {
11804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		/* check if we can just add it to last buffer */
11814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (last_seg &&
11824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
11834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			pad_buff = last_seg->buff + last_seg->total_bytes;
11844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		else
11854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			pad_buff = io->pad_buff;
11864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
1187bc38bf106c967389a465d926be22c7371abba69dBoaz Harrosh		ret = blk_rq_map_kern(io->req->q, io->req, pad_buff, padding,
11884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				       or->alloc_flags);
11894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret)
11904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
11914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		io->total_bytes += padding;
11924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
1194bc38bf106c967389a465d926be22c7371abba69dBoaz Harrosh	ret = blk_rq_map_kern(io->req->q, io->req, seg->buff, seg->total_bytes,
11954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			       or->alloc_flags);
11964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
11974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
11984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	io->total_bytes += seg->total_bytes;
12004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
12014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		  seg->total_bytes);
12024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
12034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
12044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_req_finalize_set_attr_list(struct osd_request *or)
12064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
12074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
12084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned padding;
12094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
12104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!or->set_attr.total_bytes) {
12124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
12134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
12144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
12154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
12174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.set_attr_offset =
12184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->out.total_bytes, &padding);
12194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, padding, &or->set_attr,
12214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  or->out.last_seg, &or->out);
12224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
12234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
12244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->out.last_seg = &or->set_attr;
12264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
12274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
12284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_add_get_attr_list(struct osd_request *or,
12304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *oa, unsigned nelem)
12314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
12324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned total_bytes = or->enc_get_attr.total_bytes;
12334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *attr_last;
12344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
12354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode &&
12374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
12384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		WARN_ON(1);
12394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -EINVAL;
12404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
12414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
12424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* first time calc data-in list header size */
12444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!or->get_attr.total_bytes)
12454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
12464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* calc data-out info */
12484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!total_bytes) { /* first-time: allocate and put list header */
12494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		unsigned max_bytes;
12504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes = _osd_req_sizeof_alist_header(or);
12524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		max_bytes = total_bytes +
12534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			nelem * sizeof(struct osd_attributes_list_attrid);
12544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _alloc_get_attr_desc(or, max_bytes);
12554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret)
12564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
12574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
12594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					OSD_ATTR_LIST_GET);
12604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
12614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	attr_last = or->enc_get_attr.buff + total_bytes;
12624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (; nelem; --nelem) {
12644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		struct osd_attributes_list_attrid *attrid;
12654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		const unsigned cur_size = sizeof(*attrid);
12664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes += cur_size;
12684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
12694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			or->enc_get_attr.total_bytes = total_bytes - cur_size;
12704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			ret = _alloc_get_attr_desc(or,
12714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					total_bytes + nelem * sizeof(*attrid));
12724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			if (ret)
12734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				return ret;
12744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			attr_last = or->enc_get_attr.buff +
12754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				or->enc_get_attr.total_bytes;
12764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
12774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attrid = attr_last;
12794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attrid->attr_page = cpu_to_be32(oa->attr_page);
12804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attrid->attr_id = cpu_to_be32(oa->attr_id);
12814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attr_last += cur_size;
12834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		/* calc data-in size */
12854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		or->get_attr.total_bytes +=
12864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			_osd_req_alist_elem_size(or, oa->len);
12874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		++oa;
12884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
12894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->enc_get_attr.total_bytes = total_bytes;
12914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG(
12934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
12944ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       or->get_attr.total_bytes,
12954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
12964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       or->enc_get_attr.total_bytes,
12974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
12984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			/ sizeof(struct osd_attributes_list_attrid));
12994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
13014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
13024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_add_get_attr_list);
13034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_req_finalize_get_attr_list(struct osd_request *or)
13054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
13064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
13074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned out_padding;
13084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned in_padding;
13094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
13104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!or->enc_get_attr.total_bytes) {
13124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
13134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
13144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
13154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
13164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _alloc_get_attr_list(or);
13184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
13194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
13204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* The out-going buffer info update */
13224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("out-going\n");
13234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_desc_bytes =
13244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cpu_to_be32(or->enc_get_attr.total_bytes);
13254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_desc_offset =
13274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
13284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
13304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  or->out.last_seg, &or->out);
13314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
13324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
13334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->out.last_seg = &or->enc_get_attr;
13344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* The incoming buffer info update */
13364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("in-coming\n");
13374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_alloc_length =
13384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cpu_to_be32(or->get_attr.total_bytes);
13394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_offset =
13414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
13424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
13444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  &or->in);
13454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
13464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
13474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->in.last_seg = &or->get_attr;
13484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
13504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
13514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_decode_get_attr_list(struct osd_request *or,
13534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_attr *oa, int *nelem, void **iterator)
13544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
13554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned cur_bytes, returned_bytes;
13564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int n;
13574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
13584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *cur_p;
13594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
13614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				    OSD_ATTR_LIST_SET_RETRIEVE)) {
13624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->attr_page = 0;
13634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->attr_id = 0;
13644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->val_ptr = NULL;
13654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->len = 0;
13664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		*iterator = NULL;
13674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
13684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
13694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (*iterator) {
13714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		BUG_ON((*iterator < or->get_attr.buff) ||
13724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
13734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_p = *iterator;
13744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
13754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		returned_bytes = or->get_attr.total_bytes;
13764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	} else { /* first time decode the list header */
13774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_bytes = sizeof_attr_list;
13784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
13794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					sizeof_attr_list;
13804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_p = or->get_attr.buff + sizeof_attr_list;
13824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (returned_bytes > or->get_attr.alloc_size) {
13844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_DEBUG("target report: space was not big enough! "
13854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  "Allocate=%u Needed=%u\n",
13864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  or->get_attr.alloc_size,
13874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  returned_bytes + sizeof_attr_list);
13884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			returned_bytes =
13904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				or->get_attr.alloc_size - sizeof_attr_list;
13914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
13924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		or->get_attr.total_bytes = returned_bytes;
13934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
13944ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
13954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
139671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
139771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh						 returned_bytes - cur_bytes);
13984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
139971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (inc < 0) {
14004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_ERR("BAD FOOD from target. list not valid!"
14014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				"c=%d r=%d n=%d\n",
14024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				cur_bytes, returned_bytes, n);
14034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			oa->val_ptr = NULL;
1404eff21490c91f981126f0ead3c081dde4f425d387Boaz Harrosh			cur_bytes = returned_bytes; /* break the caller loop */
14054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			break;
14064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
14074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
140871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		cur_bytes += inc;
14094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_p += inc;
14104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		++oa;
14114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
14124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
14144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	*nelem = n;
14154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return returned_bytes - cur_bytes;
14164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
14174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_decode_get_attr_list);
14184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh/*
14204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Attributes Page-mode
14214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh */
14224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_add_get_attr_page(struct osd_request *or,
14244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u32 page_id, void *attar_page, unsigned max_page_len,
14254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *set_one_attr)
14264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
14274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
14284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode &&
14304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
14314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		WARN_ON(1);
14324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -EINVAL;
14334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
14344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
14354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->get_attr.buff = attar_page;
14374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->get_attr.total_bytes = max_page_len;
14384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
14404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
1441ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh
1442ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh	if (!set_one_attr || !set_one_attr->attr_page)
1443ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh		return 0; /* The set is optional */
1444ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh
1445ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh	or->set_attr.buff = set_one_attr->val_ptr;
1446ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh	or->set_attr.total_bytes = set_one_attr->len;
14474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page);
14494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
14504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
14514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
14524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
14534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_add_get_attr_page);
14544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_req_finalize_attr_page(struct osd_request *or)
14564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
14574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
14584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned in_padding, out_padding;
14594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
14604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* returned page */
14624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.get_attr_offset =
14634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
14644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
14664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  &or->in);
14674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
14684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
14694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
1470ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh	if (or->set_attr.total_bytes == 0)
1471ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh		return 0;
1472ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh
14734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* set one value */
14744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_offset =
14754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
14764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
1477ec6a0a41b57feb54b3830918a8fb07147c2ee778Boaz Harrosh	ret = _req_append_segment(or, out_padding, &or->set_attr, NULL,
14784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  &or->out);
14794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return ret;
14804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
14814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
1482f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harroshstatic inline void osd_sec_parms_set_out_offset(bool is_v1,
1483f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
1484f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh{
1485f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	if (is_v1)
1486f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v1.data_out_integrity_check_offset = offset;
1487f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	else
1488f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v2.data_out_integrity_check_offset = offset;
1489f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh}
1490f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh
1491f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harroshstatic inline void osd_sec_parms_set_in_offset(bool is_v1,
1492f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
1493f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh{
1494f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	if (is_v1)
1495f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v1.data_in_integrity_check_offset = offset;
1496f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	else
1497f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v2.data_in_integrity_check_offset = offset;
1498f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh}
1499f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh
1500345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshstatic int _osd_req_finalize_data_integrity(struct osd_request *or,
1501e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	bool has_in, bool has_out, struct bio *out_data_bio, u64 out_data_bytes,
1502e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	const u8 *cap_key)
1503345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
1504345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
1505345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	int ret;
1506345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1507345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (!osd_is_sec_alldata(sec_parms))
1508345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		return 0;
1509345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1510345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (has_out) {
1511345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		struct _osd_req_data_segment seg = {
1512345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.buff = &or->out_data_integ,
1513345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.total_bytes = sizeof(or->out_data_integ),
1514345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		};
1515345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		unsigned pad;
1516345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1517546881aea9787ed5c626ac99ab80158ea9ae0515Boaz Harrosh		or->out_data_integ.data_bytes = cpu_to_be64(out_data_bytes);
1518345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
1519345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			or->set_attr.total_bytes);
1520345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
1521345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			or->enc_get_attr.total_bytes);
1522345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1523f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		osd_sec_parms_set_out_offset(osd_req_is_ver1(or), sec_parms,
1524f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh			osd_req_encode_offset(or, or->out.total_bytes, &pad));
1525345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1526345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
1527345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh					  &or->out);
1528345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		if (ret)
1529345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			return ret;
1530345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->out.last_seg = NULL;
1531345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1532345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		/* they are now all chained to request sign them all together */
1533e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		osd_sec_sign_data(&or->out_data_integ, out_data_bio,
1534345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh				  cap_key);
1535345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	}
1536345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1537345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (has_in) {
1538345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		struct _osd_req_data_segment seg = {
1539345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.buff = &or->in_data_integ,
1540345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.total_bytes = sizeof(or->in_data_integ),
1541345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		};
1542345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		unsigned pad;
1543345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1544f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		osd_sec_parms_set_in_offset(osd_req_is_ver1(or), sec_parms,
1545f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh			osd_req_encode_offset(or, or->in.total_bytes, &pad));
1546345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1547345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
1548345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh					  &or->in);
1549345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		if (ret)
1550345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			return ret;
1551345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1552345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->in.last_seg = NULL;
1553345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	}
1554345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1555345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	return 0;
1556345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
1557345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
155802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
155902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * osd_finalize_request and helpers
156002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
1561c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harroshstatic struct request *_make_request(struct request_queue *q, bool has_write,
1562c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh			      struct _osd_io_info *oii, gfp_t flags)
1563c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh{
1564c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh	if (oii->bio)
1565c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh		return blk_make_request(q, oii->bio, flags);
1566c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh	else {
1567c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh		struct request *req;
1568c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh
1569c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh		req = blk_get_request(q, has_write ? WRITE : READ, flags);
1570a492f075450f3ba87de36e5ffe92a9d0c7af9723Joe Lawrence		if (IS_ERR(req))
1571a492f075450f3ba87de36e5ffe92a9d0c7af9723Joe Lawrence			return req;
1572c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh
1573f27b087b81b70513b8c61ec20596c868f7b93474Jens Axboe		blk_rq_set_block_pc(req);
1574c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh		return req;
1575c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh	}
1576c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh}
157702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
157802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic int _init_blk_request(struct osd_request *or,
157902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	bool has_in, bool has_out)
158002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
158102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	gfp_t flags = or->alloc_flags;
158202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct scsi_device *scsi_device = or->osd_dev->scsi_device;
158302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct request_queue *q = scsi_device->request_queue;
158402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct request *req;
1585c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh	int ret;
158602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1587c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh	req = _make_request(q, has_out, has_out ? &or->out : &or->in, flags);
1588c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh	if (IS_ERR(req)) {
1589c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh		ret = PTR_ERR(req);
159002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		goto out;
1591c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh	}
159202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
159302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request = req;
159403306793e686fd895ab8fa095bb9ec33658ea53aBoaz Harrosh	req->cmd_flags |= REQ_QUIET;
159503306793e686fd895ab8fa095bb9ec33658ea53aBoaz Harrosh
159602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->timeout = or->timeout;
159702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->retries = or->retries;
159802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->sense = or->sense;
159902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->sense_len = 0;
160002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
160102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (has_out) {
160202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->out.req = req;
160302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (has_in) {
160402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			/* allocate bidi request */
1605c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh			req = _make_request(q, false, &or->in, flags);
1606c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh			if (IS_ERR(req)) {
160702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh				OSD_DEBUG("blk_get_request for bidi failed\n");
1608c29b70f6ee4f2fa3ef07f55bc9082945861e5391Boaz Harrosh				ret = PTR_ERR(req);
160902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh				goto out;
161002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			}
1611f27b087b81b70513b8c61ec20596c868f7b93474Jens Axboe			blk_rq_set_block_pc(req);
161202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			or->in.req = or->request->next_rq = req;
161302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
161402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	} else if (has_in)
161502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->in.req = req;
161602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
161702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ret = 0;
161802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshout:
161902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
162002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			or, has_in, has_out, ret, or->request);
162102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return ret;
162202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
162302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
162402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshint osd_finalize_request(struct osd_request *or,
162502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	u8 options, const void *cap, const u8 *cap_key)
162602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
162702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
162802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	bool has_in, has_out;
1629e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	 /* Save for data_integrity without the cdb_continuation */
1630e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	struct bio *out_data_bio = or->out.bio;
1631546881aea9787ed5c626ac99ab80158ea9ae0515Boaz Harrosh	u64 out_data_bytes = or->out.total_bytes;
163202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	int ret;
163302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
163402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (options & OSD_REQ_FUA)
163502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		cdbh->options |= OSD_CDB_FUA;
163602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
163702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (options & OSD_REQ_DPO)
163802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		cdbh->options |= OSD_CDB_DPO;
163902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
164002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
164102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
164202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
164302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osd_set_caps(&or->cdb, cap);
164402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
164502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	has_in = or->in.bio || or->get_attr.total_bytes;
1646e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	has_out = or->out.bio || or->cdb_cont.total_bytes ||
1647e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		or->set_attr.total_bytes || or->enc_get_attr.total_bytes;
164802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1649e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	ret = _osd_req_finalize_cdb_cont(or, cap_key);
1650e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	if (ret) {
1651e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		OSD_DEBUG("_osd_req_finalize_cdb_cont failed\n");
1652e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh		return ret;
1653e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh	}
165402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ret = _init_blk_request(or, has_in, has_out);
165502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (ret) {
165602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		OSD_DEBUG("_init_blk_request failed\n");
165702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		return ret;
165802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
165902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
16604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->out.pad_buff = sg_out_pad_buffer;
16614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->in.pad_buff = sg_in_pad_buffer;
16624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
166302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (!or->attributes_mode)
166402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
166502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cdbh->command_specific_options |= or->attributes_mode;
16664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
16674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _osd_req_finalize_attr_page(or);
166898e1e0f07c3f1820b8ac424569ee9e9916d3665bBoaz Harrosh		if (ret) {
166998e1e0f07c3f1820b8ac424569ee9e9916d3665bBoaz Harrosh			OSD_DEBUG("_osd_req_finalize_attr_page failed\n");
167098e1e0f07c3f1820b8ac424569ee9e9916d3665bBoaz Harrosh			return ret;
167198e1e0f07c3f1820b8ac424569ee9e9916d3665bBoaz Harrosh		}
16724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	} else {
16734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		/* TODO: I think that for the GET_ATTR command these 2 should
16744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 * be reversed to keep them in execution order (for embeded
16754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 * targets with low memory footprint)
16764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 */
16774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _osd_req_finalize_set_attr_list(or);
16784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret) {
16794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
16804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
16814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
16824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
16834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _osd_req_finalize_get_attr_list(or);
16844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret) {
16854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
16864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
16874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
16884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
168902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1690546881aea9787ed5c626ac99ab80158ea9ae0515Boaz Harrosh	ret = _osd_req_finalize_data_integrity(or, has_in, has_out,
1691e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh					       out_data_bio, out_data_bytes,
1692e96e72c45a1e78e9266dd70113b851395a440ef3Boaz Harrosh					       cap_key);
1693345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (ret)
1694345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		return ret;
1695345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1696345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	osd_sec_sign_cdb(&or->cdb, cap_key);
1697345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
169802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request->cmd = or->cdb.buff;
169902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request->cmd_len = _osd_req_cdb_len(or);
170002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
170102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return 0;
170202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
170302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_finalize_request);
170402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1705aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harroshstatic bool _is_osd_security_code(int code)
1706aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh{
1707aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	return	(code == osd_security_audit_value_frozen) ||
1708aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		(code == osd_security_working_key_frozen) ||
1709aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		(code == osd_nonce_not_unique) ||
1710aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		(code == osd_nonce_timestamp_out_of_range) ||
1711aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		(code == osd_invalid_dataout_buffer_integrity_check_value);
1712aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh}
1713aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh
171498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#define OSD_SENSE_PRINT1(fmt, a...) \
171598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	do { \
171698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		if (__cur_sense_need_output) \
171798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_ERR(fmt, ##a); \
171898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	} while (0)
171998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
172098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1("    " fmt, ##a)
172198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
172298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harroshint osd_req_decode_sense_full(struct osd_request *or,
172398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_sense_info *osi, bool silent,
172498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_obj_id *bad_obj_list __unused, int max_obj __unused,
172598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_attr *bad_attr_list, int max_attr)
172698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh{
172798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	int sense_len, original_sense_len;
172898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_sense_info local_osi;
172998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct scsi_sense_descriptor_based *ssdb;
173098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	void *cur_descriptor;
173198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0)
173298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	const bool __cur_sense_need_output = false;
173398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#else
173498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	bool __cur_sense_need_output = !silent;
173598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#endif
1736aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	int ret;
173798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
17385d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	if (likely(!or->req_errors))
173998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		return 0;
1740aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh
1741aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	osi = osi ? : &local_osi;
1742aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	memset(osi, 0, sizeof(*osi));
174398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
17445d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	ssdb = (typeof(ssdb))or->sense;
17455d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	sense_len = or->sense_len;
174698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) {
174798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		OSD_ERR("Block-layer returned error(0x%x) but "
174898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			"sense_len(%u) || key(%d) is empty\n",
17495d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh			or->req_errors, sense_len, ssdb->sense_key);
1750aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		goto analyze;
175198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	}
175298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
175398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
175498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
175598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			ssdb->response_code, sense_len);
1756aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		goto analyze;
175798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	}
175898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
175998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	osi->key = ssdb->sense_key;
176098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
176198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	original_sense_len = ssdb->additional_sense_length + 8;
176298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
176398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1)
176498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if (__cur_sense_need_output)
176598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		__cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
176698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#endif
176798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
1768aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			"additional_code=0x%x async_error=%d errors=0x%x\n",
176998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->key, original_sense_len, sense_len,
1770aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			osi->additional_code, or->async_error,
17715d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh			or->req_errors);
177298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
177398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if (original_sense_len < sense_len)
177498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		sense_len = original_sense_len;
177598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
177698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	cur_descriptor = ssdb->ssd;
177798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	sense_len -= sizeof(*ssdb);
177898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	while (sense_len > 0) {
177998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		struct scsi_sense_descriptor *ssd = cur_descriptor;
178098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		int cur_len = ssd->additional_length + 2;
178198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
178298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		sense_len -= cur_len;
178398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
178498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		if (sense_len < 0)
178598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break; /* sense was truncated */
178698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
178798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		switch (ssd->descriptor_type) {
178898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_information:
178998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_command_specific_information:
179098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
179198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct scsi_sense_command_specific_data_descriptor
179298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*sscd = cur_descriptor;
179398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
179498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->command_info =
179598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				get_unaligned_be64(&sscd->information) ;
179698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
179798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"command_specific_information 0x%llx \n",
179898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				_LLU(osi->command_info));
179998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
180098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
180198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_key_specific:
180298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
180398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct scsi_sense_key_specific_data_descriptor
180498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*ssks = cur_descriptor;
180598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
180698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->sense_info = get_unaligned_be16(&ssks->value);
180798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
180898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"sense_key_specific_information %u"
180998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"sksv_cd_bpv_bp (0x%x)\n",
181098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				osi->sense_info, ssks->sksv_cd_bpv_bp);
181198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
181298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
181398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case osd_sense_object_identification:
181498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{ /*FIXME: Keep first not last, Store in array*/
181598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_identification_data_descriptor
181698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*osidd = cur_descriptor;
181798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
181898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->not_initiated_command_functions =
181998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				le32_to_cpu(osidd->not_initiated_functions);
182098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->completed_command_functions =
182198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				le32_to_cpu(osidd->completed_functions);
182298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->obj.partition = be64_to_cpu(osidd->partition_id);
182398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->obj.id = be64_to_cpu(osidd->object_id);
182498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
182598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"object_identification pid=0x%llx oid=0x%llx\n",
182698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				_LLU(osi->obj.partition), _LLU(osi->obj.id));
182798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
182898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"not_initiated_bits(%x) "
182998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"completed_command_bits(%x)\n",
183098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				osi->not_initiated_command_functions,
183198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				osi->completed_command_functions);
183298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
183398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
183498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case osd_sense_response_integrity_check:
183598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
183698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_response_integrity_check_descriptor
183798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*osricd = cur_descriptor;
183898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			const unsigned len =
183998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					  sizeof(osricd->integrity_check_value);
184098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			char key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
184198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
184298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			hex_dump_to_buffer(osricd->integrity_check_value, len,
184398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				       32, 1, key_dump, sizeof(key_dump), true);
184498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
184598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
184698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case osd_sense_attribute_identification:
184798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
184898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_attributes_data_descriptor
184998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*osadd = cur_descriptor;
185071ecb74b15377a6c0e0e6ea95d4b549580fb4d48Boaz Harrosh			unsigned len = min(cur_len, sense_len);
185198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_attr *pattr = osadd->sense_attrs;
185298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
185371ecb74b15377a6c0e0e6ea95d4b549580fb4d48Boaz Harrosh			while (len >= sizeof(*pattr)) {
185498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				u32 attr_page = be32_to_cpu(pattr->attr_page);
185598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				u32 attr_id = be32_to_cpu(pattr->attr_id);
185698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
185771ecb74b15377a6c0e0e6ea95d4b549580fb4d48Boaz Harrosh				if (!osi->attr.attr_page) {
185898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					osi->attr.attr_page = attr_page;
185998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					osi->attr.attr_id = attr_id;
186098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				}
186198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
186298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				if (bad_attr_list && max_attr) {
186398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					bad_attr_list->attr_page = attr_page;
186498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					bad_attr_list->attr_id = attr_id;
186598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					bad_attr_list++;
186698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					max_attr--;
186798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				}
186871ecb74b15377a6c0e0e6ea95d4b549580fb4d48Boaz Harrosh
186971ecb74b15377a6c0e0e6ea95d4b549580fb4d48Boaz Harrosh				len -= sizeof(*pattr);
187098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				OSD_SENSE_PRINT2(
187198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"osd_sense_attribute_identification"
187298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"attr_page=0x%x attr_id=0x%x\n",
187398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					attr_page, attr_id);
187498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			}
187598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
187698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		/*These are not legal for OSD*/
187798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_field_replaceable_unit:
187898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n");
187998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
188098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_stream_commands:
188198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_stream_commands\n");
188298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
188398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_block_commands:
188498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_block_commands\n");
188598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
188698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_ata_return:
188798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_ata_return\n");
188898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
188998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		default:
189098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			if (ssd->descriptor_type <= scsi_sense_Reserved_last)
189198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				OSD_SENSE_PRINT2(
189298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"scsi_sense Reserved descriptor (0x%x)",
189398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					ssd->descriptor_type);
189498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			else
189598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				OSD_SENSE_PRINT2(
189698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"scsi_sense Vendor descriptor (0x%x)",
189798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					ssd->descriptor_type);
189898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
189998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
190098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		cur_descriptor += cur_len;
190198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	}
190298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
1903aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harroshanalyze:
1904aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	if (!osi->key) {
1905aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		/* scsi sense is Empty, the request was never issued to target
1906aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		 * linux return code might tell us what happened.
1907aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		 */
1908aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		if (or->async_error == -ENOMEM)
1909aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			osi->osd_err_pri = OSD_ERR_PRI_RESOURCE;
1910aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		else
1911aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			osi->osd_err_pri = OSD_ERR_PRI_UNREACHABLE;
1912aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		ret = or->async_error;
1913aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	} else if (osi->key <= scsi_sk_recovered_error) {
1914aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		osi->osd_err_pri = 0;
1915aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		ret = 0;
1916aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	} else if (osi->additional_code == scsi_invalid_field_in_cdb) {
1917aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		if (osi->cdb_field_offset == OSD_CFO_STARTING_BYTE) {
1918aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			osi->osd_err_pri = OSD_ERR_PRI_CLEAR_PAGES;
1919aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			ret = -EFAULT; /* caller should recover from this */
1920aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		} else if (osi->cdb_field_offset == OSD_CFO_OBJECT_ID) {
1921aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			osi->osd_err_pri = OSD_ERR_PRI_NOT_FOUND;
1922aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			ret = -ENOENT;
1923aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		} else if (osi->cdb_field_offset == OSD_CFO_PERMISSIONS) {
1924aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			osi->osd_err_pri = OSD_ERR_PRI_NO_ACCESS;
1925aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			ret = -EACCES;
1926aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		} else {
1927aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			osi->osd_err_pri = OSD_ERR_PRI_BAD_CRED;
1928aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh			ret = -EINVAL;
1929aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		}
1930aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	} else if (osi->additional_code == osd_quota_error) {
1931aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		osi->osd_err_pri = OSD_ERR_PRI_NO_SPACE;
1932aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		ret = -ENOSPC;
1933aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	} else if (_is_osd_security_code(osi->additional_code)) {
1934aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		osi->osd_err_pri = OSD_ERR_PRI_BAD_CRED;
1935aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		ret = -EINVAL;
1936aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	} else {
1937aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		osi->osd_err_pri = OSD_ERR_PRI_EIO;
1938aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh		ret = -EIO;
1939aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	}
1940aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh
19415d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	if (!or->out.residual)
19425d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		or->out.residual = or->out.total_bytes;
19435d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh	if (!or->in.residual)
19445d0961fd1f25e117f907f3af3aaa870637049252Boaz Harrosh		or->in.residual = or->in.total_bytes;
1945aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh
1946aa9fffbe2c4db4557248c5c626a85bf3c7867044Boaz Harrosh	return ret;
194798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh}
194898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz HarroshEXPORT_SYMBOL(osd_req_decode_sense_full);
194998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
195002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
195102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Implementation of osd_sec.h API
195202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * TODO: Move to a separate osd_sec.c file at a later stage.
195302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
195402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
195502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshenum { OSD_SEC_CAP_V1_ALL_CAPS =
195602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
195702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
195802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
195902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
196002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh};
196102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1962c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harroshenum { OSD_SEC_CAP_V2_ALL_CAPS =
1963c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
1964c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh};
1965c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
196602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_sec_init_nosec_doall_caps(void *caps,
196702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
196802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
196902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_capability *cap = caps;
197002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	u8 type;
197102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	u8 descriptor_type;
197202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
197302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (likely(obj->id)) {
197402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (unlikely(is_collection)) {
197502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			type = OSD_SEC_OBJ_COLLECTION;
197602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
197702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh						  OSD_SEC_OBJ_DESC_COL;
197802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		} else {
197902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			type = OSD_SEC_OBJ_USER;
198002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
198102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
198202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		WARN_ON(!obj->partition);
198302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	} else {
198402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
198502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh					OSD_SEC_OBJ_ROOT;
198602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
198702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
198802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
198902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	memset(cap, 0, sizeof(*cap));
199002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
199102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
199202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
199302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.security_method = OSD_SEC_NOSEC;
199402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*	cap->expiration_time;
199502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->AUDIT[30-10];
199602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->discriminator[42-30];
199702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->object_created_time; */
199802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.object_type = type;
199902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
200002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.object_descriptor_type = descriptor_type;
200102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->od.obj_desc.policy_access_tag = 0;
200202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
200302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
200402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
200502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
200602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
2007c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh/* FIXME: Extract version from caps pointer.
2008c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh *        Also Pete's target only supports caps from OSDv1 for now
2009c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh */
201002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_set_caps(struct osd_cdb *cdb, const void *caps)
201102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
2012c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	bool is_ver1 = true;
2013c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	/* NOTE: They start at same address */
2014c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
201502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
20164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
2017345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshbool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused)
2018345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
2019345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	return false;
2020345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
2021345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
2022345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshvoid osd_sec_sign_cdb(struct osd_cdb *ocdb __unused, const u8 *cap_key __unused)
2023345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
2024345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
2025345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
2026345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshvoid osd_sec_sign_data(void *data_integ __unused,
2027345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		       struct bio *bio __unused, const u8 *cap_key __unused)
2028345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
2029345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
2030345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
20314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh/*
20324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Declared in osd_protocol.h
20334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * 4.12.5 Data-In and Data-Out buffer offsets
20344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * byte offset = mantissa * (2^(exponent+8))
20354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Returns the smallest allowed encoded offset that contains given @offset
20364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * The actual encoded offset returned is @offset + *@padding.
20374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh */
20384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshosd_cdb_offset __osd_encode_offset(
20394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u64 offset, unsigned *padding, int min_shift, int max_shift)
20404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
20414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u64 try_offset = -1, mod, align;
20424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	osd_cdb_offset be32_offset;
20434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int shift;
20444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
20454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	*padding = 0;
20464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!offset)
20474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
20484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
20494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (shift = min_shift; shift < max_shift; ++shift) {
20504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		try_offset = offset >> shift;
20514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
20524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			break;
20534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
20544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
20554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	BUG_ON(shift == max_shift);
20564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
20574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	align = 1 << shift;
20584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	mod = offset & (align - 1);
20594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (mod) {
20604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		*padding = align - mod;
20614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		try_offset += 1;
20624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
20634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
20644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	try_offset |= ((shift - 8) & 0xf) << 28;
20654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	be32_offset = cpu_to_be32((u32)try_offset);
20664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
20674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
20684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
20694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 be32_offset, *padding);
20704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return be32_offset;
20714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
2072