osd_initiator.c revision e9da4d7f731dafc2b93ce7b31aa09c4d935ef978
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:
1002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh *   Boaz Harrosh <bharrosh@panasas.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
4202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include <scsi/osd_initiator.h>
4302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include <scsi/osd_sec.h>
441b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh#include <scsi/osd_attributes.h>
4598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#include <scsi/osd_sense.h>
4698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
4702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include <scsi/scsi_device.h>
4802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh#include "osd_debug.h"
5002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh#ifndef __unused
524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh#    define __unused			__attribute__((unused))
534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh#endif
544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshenum { OSD_REQ_RETRIES = 1 };
5602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
5702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshMODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
5802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshMODULE_DESCRIPTION("open-osd initiator library libosd.ko");
5902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshMODULE_LICENSE("GPL");
6002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
6102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic inline void build_test(void)
6202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
6302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* structures were not packed */
6402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
65c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
6602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
6702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
6802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
691b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harroshstatic const char *_osd_ver_desc(struct osd_request *or)
701b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh{
711b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
721b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh}
731b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
741b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
751b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
761b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harroshstatic int _osd_print_system_info(struct osd_dev *od, void *caps)
771b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh{
781b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	struct osd_request *or;
791b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	struct osd_attr get_attrs[] = {
801b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
811b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
821b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
831b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
841b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
851b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
861b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
871b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
881b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
891b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
901b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		/* IBM-OSD-SIM Has a bug with this one put it last */
911b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
921b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	};
931b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	void *iter = NULL, *pFirst;
941b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	int nelem = ARRAY_SIZE(get_attrs), a = 0;
951b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	int ret;
961b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
971b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	or = osd_start_request(od, GFP_KERNEL);
981b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (!or)
991b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		return -ENOMEM;
1001b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1011b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	/* get attrs */
1021b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_req_get_attributes(or, &osd_root_object);
1031b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
1041b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1051b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	ret = osd_finalize_request(or, 0, caps, NULL);
1061b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (ret)
1071b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		goto out;
1081b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1091b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	ret = osd_execute_request(or);
1101b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (ret) {
1111b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
1121b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		goto out;
1131b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	}
1141b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1151b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
1161b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1171b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("Detected %s device\n",
1181b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		_osd_ver_desc(or));
1191b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1201b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1211b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
1221b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1231b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1241b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1251b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
1261b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1271b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1281b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1291b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
1301b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1311b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1321b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1331b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
13497218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? get_unaligned_be32(pFirst) : ~0U);
1351b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1361b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1371b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
1381b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		(char *)pFirst);
1391b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1401b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a].val_ptr;
1411b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
1421b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	a++;
1431b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1441b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1451b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
14697218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
1471b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1481b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1491b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
15097218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
1511b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1521b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1531b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n",
15497218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
15597218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh
15697218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh	if (a >= nelem)
15797218a1499391b174ea95e05b7a40fbb73e79813Boaz Harrosh		goto out;
1581b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1591b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	/* FIXME: Where are the time utilities */
1601b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	pFirst = get_attrs[a++].val_ptr;
1611b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
1621b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		((char *)pFirst)[0], ((char *)pFirst)[1],
1631b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		((char *)pFirst)[2], ((char *)pFirst)[3],
1641b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		((char *)pFirst)[4], ((char *)pFirst)[5]);
1651b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1661b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
1671b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		unsigned len = get_attrs[a].len;
1681b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		char sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
1691b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1701b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
1711b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh				   sid_dump, sizeof(sid_dump), true);
1721b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
1731b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		a++;
1741b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	}
1751b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harroshout:
1761b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	osd_end_request(or);
1771b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	return ret;
1781b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh}
1791b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1801b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harroshint osd_auto_detect_ver(struct osd_dev *od, void *caps)
1811b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh{
1821b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	int ret;
1831b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1841b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	/* Auto-detect the osd version */
1851b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	ret = _osd_print_system_info(od, caps);
1861b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	if (ret) {
1871b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		osd_dev_set_ver(od, OSD_VER1);
1881b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		OSD_DEBUG("converting to OSD1\n");
1891b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh		ret = _osd_print_system_info(od, caps);
1901b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	}
1911b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
1921b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh	return ret;
1931b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh}
1941b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz HarroshEXPORT_SYMBOL(osd_auto_detect_ver);
1951b9dce94c8a24a3f1a01fcdf688f2d903b32acdfBoaz Harrosh
19602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic unsigned _osd_req_cdb_len(struct osd_request *or)
19702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
198c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
19902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
20002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
2014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
2024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
203c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ?
204c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv1_attr_list_elem_size(len) :
205c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv2_attr_list_elem_size(len);
2064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
2074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
20871f32e31e5638df37904697e2d04182935add85dBoaz Harroshstatic void _osd_req_alist_elem_encode(struct osd_request *or,
20971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	void *attr_last, const struct osd_attr *oa)
21071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh{
21171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	if (osd_req_is_ver1(or)) {
21271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv1_attributes_list_element *attr = attr_last;
21371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
21471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_page = cpu_to_be32(oa->attr_page);
21571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_id = cpu_to_be32(oa->attr_id);
21671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_bytes = cpu_to_be16(oa->len);
21771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		memcpy(attr->attr_val, oa->val_ptr, oa->len);
21871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	} else {
21971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv2_attributes_list_element *attr = attr_last;
22071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
22171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_page = cpu_to_be32(oa->attr_page);
22271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_id = cpu_to_be32(oa->attr_id);
22371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		attr->attr_bytes = cpu_to_be16(oa->len);
22471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		memcpy(attr->attr_val, oa->val_ptr, oa->len);
22571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	}
22671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh}
22771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
22871f32e31e5638df37904697e2d04182935add85dBoaz Harroshstatic int _osd_req_alist_elem_decode(struct osd_request *or,
22971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	void *cur_p, struct osd_attr *oa, unsigned max_bytes)
23071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh{
23171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	unsigned inc;
23271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	if (osd_req_is_ver1(or)) {
23371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv1_attributes_list_element *attr = cur_p;
23471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
23571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (max_bytes < sizeof(*attr))
23671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
23771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
23871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->len = be16_to_cpu(attr->attr_bytes);
23971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		inc = _osd_req_alist_elem_size(or, oa->len);
24071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (inc > max_bytes)
24171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
24271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
24371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_page = be32_to_cpu(attr->attr_page);
24471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_id = be32_to_cpu(attr->attr_id);
24571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
24671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		/* OSD1: On empty attributes we return a pointer to 2 bytes
24771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		 * of zeros. This keeps similar behaviour with OSD2.
24871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		 * (See below)
24971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		 */
25071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->val_ptr = likely(oa->len) ? attr->attr_val :
25171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh						(u8 *)&attr->attr_bytes;
25271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	} else {
25371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		struct osdv2_attributes_list_element *attr = cur_p;
25471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
25571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (max_bytes < sizeof(*attr))
25671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
25771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
25871f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->len = be16_to_cpu(attr->attr_bytes);
25971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		inc = _osd_req_alist_elem_size(or, oa->len);
26071f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (inc > max_bytes)
26171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh			return -1;
26271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
26371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_page = be32_to_cpu(attr->attr_page);
26471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		oa->attr_id = be32_to_cpu(attr->attr_id);
26571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
266e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		/* OSD2: For convenience, on empty attributes, we return 8 bytes
267e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 * of zeros here. This keeps the same behaviour with OSD2r04,
268e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 * and is nice with null terminating ASCII fields.
269e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 * oa->val_ptr == NULL marks the end-of-list, or error.
270e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		 */
271e9da4d7f731dafc2b93ce7b31aa09c4d935ef978Boaz Harrosh		oa->val_ptr = likely(oa->len) ? attr->attr_val : attr->reserved;
27271f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	}
27371f32e31e5638df37904697e2d04182935add85dBoaz Harrosh	return inc;
27471f32e31e5638df37904697e2d04182935add85dBoaz Harrosh}
27571f32e31e5638df37904697e2d04182935add85dBoaz Harrosh
2764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
2774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
278c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ?
279c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv1_list_size(list_head) :
280c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		osdv2_list_size(list_head);
2814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
2824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
2834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
2844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
285c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	return osd_req_is_ver1(or) ?
286c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		sizeof(struct osdv1_attributes_list_header) :
287c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		sizeof(struct osdv2_attributes_list_header);
2884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
2894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
2904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic void _osd_req_set_alist_type(struct osd_request *or,
2914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *list, int list_type)
2924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
293c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or)) {
294c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		struct osdv1_attributes_list_header *attr_list = list;
295c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
296c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		memset(attr_list, 0, sizeof(*attr_list));
297c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		attr_list->type = list_type;
298c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	} else {
299c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		struct osdv2_attributes_list_header *attr_list = list;
3004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
301c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		memset(attr_list, 0, sizeof(*attr_list));
302c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		attr_list->type = list_type;
303c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	}
3044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic bool _osd_req_is_alist_type(struct osd_request *or,
3074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *list, int list_type)
3084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
3094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!list)
3104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return false;
3114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
312c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or)) {
3134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		struct osdv1_attributes_list_header *attr_list = list;
3144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return attr_list->type == list_type;
316c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	} else {
317c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		struct osdv2_attributes_list_header *attr_list = list;
318c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
319c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		return attr_list->type == list_type;
3204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
3214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
3233e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh/* This is for List-objects not Attributes-Lists */
3243e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshstatic void _osd_req_encode_olist(struct osd_request *or,
3253e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id_list *list)
3263e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
3273e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
3283e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
329c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or)) {
330c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v1.list_identifier = list->list_identifier;
331c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v1.start_address = list->continuation_id;
332c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	} else {
333c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v2.list_identifier = list->list_identifier;
334c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		cdbh->v2.start_address = list->continuation_id;
335c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	}
3363e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
3373e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
3384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
3394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u64 offset, unsigned *padding)
3404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
3414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return __osd_encode_offset(offset, padding,
342c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh			osd_req_is_ver1(or) ?
343c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh				OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
344c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh			OSD_OFFSET_MAX_SHIFT);
3454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
3464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
347345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshstatic struct osd_security_parameters *
348345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh_osd_req_sec_params(struct osd_request *or)
349345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
350345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	struct osd_cdb *ocdb = &or->cdb;
351345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
352c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or))
353f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		return (struct osd_security_parameters *)&ocdb->v1.sec_params;
354c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	else
355f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		return (struct osd_security_parameters *)&ocdb->v2.sec_params;
356345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
357345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
35802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
35902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
36002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	memset(osdd, 0, sizeof(*osdd));
36102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osdd->scsi_device = scsi_device;
36202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
363c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh#ifdef OSD_VER1_SUPPORT
364c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	osdd->version = OSD_VER2;
365c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh#endif
36602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* TODO: Allocate pools for osd_request attributes ... */
36702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
36802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_dev_init);
36902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
37002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_dev_fini(struct osd_dev *osdd)
37102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
37202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* TODO: De-allocate pools */
37302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
37402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osdd->scsi_device = NULL;
37502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
37602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_dev_fini);
37702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
37802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic struct osd_request *_osd_request_alloc(gfp_t gfp)
37902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
38002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_request *or;
38102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
38202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/* TODO: Use mempool with one saved request */
38302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or = kzalloc(sizeof(*or), gfp);
38402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return or;
38502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
38602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
38702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osd_request_free(struct osd_request *or)
38802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
38902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	kfree(or);
39002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
39102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
39202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstruct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
39302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
39402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_request *or;
39502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
39602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or = _osd_request_alloc(gfp);
39702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (!or)
39802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		return NULL;
39902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
40002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->osd_dev = dev;
40102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->alloc_flags = gfp;
40202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->timeout = dev->def_timeout;
40302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->retries = OSD_REQ_RETRIES;
40402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
40502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return or;
40602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
40702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_start_request);
40802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic void _osd_free_seg(struct osd_request *or __unused,
4104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct _osd_req_data_segment *seg)
4114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
4124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!seg->buff || !seg->alloc_size)
4134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return;
4144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
4154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	kfree(seg->buff);
4164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->buff = NULL;
4174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->alloc_size = 0;
4184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
4194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
4208c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harroshstatic void _put_request(struct request *rq , bool is_async)
4218c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh{
4228c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh	if (is_async) {
4238c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		WARN_ON(rq->bio);
4248c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		__blk_put_request(rq->q, rq);
4258c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh	} else {
4268c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		/*
4278c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		 * If osd_finalize_request() was called but the request was not
4288c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		 * executed through the block layer, then we must release BIOs.
4298c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		 * TODO: Keep error code in or->async_error. Need to audit all
4308c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		 *       code paths.
4318c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		 */
4328c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		if (unlikely(rq->bio))
4338c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh			blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
4348c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		else
4358c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh			blk_put_request(rq);
4368c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh	}
4378c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh}
4388c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh
43902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_end_request(struct osd_request *or)
44002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
44102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct request *rq = or->request;
4428c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh	/* IMPORTANT: make sure this agrees with osd_execute_request_async */
4438c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh	bool is_async = (or->request->end_io_data == or);
44402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	_osd_free_seg(or, &or->set_attr);
4464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	_osd_free_seg(or, &or->enc_get_attr);
4474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	_osd_free_seg(or, &or->get_attr);
4484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
44902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (rq) {
45002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (rq->next_rq) {
4518c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh			_put_request(rq->next_rq, is_async);
4528c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh			rq->next_rq = NULL;
45302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
45402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4558c0baccadc86d9f07e663dd255751dd70e461ba3Boaz Harrosh		_put_request(rq, is_async);
45602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
45702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_request_free(or);
45802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
45902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_end_request);
46002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
46102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshint osd_execute_request(struct osd_request *or)
46202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
46302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return blk_execute_rq(or->request->q, NULL, or->request, 0);
46402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
46502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_execute_request);
46602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
46702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void osd_request_async_done(struct request *req, int error)
46802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
46902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_request *or = req->end_io_data;
47002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
47102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->async_error = error;
47202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
47302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (error)
47402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
47502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
47602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (or->async_done)
47702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->async_done(or, or->async_private);
47802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	else
47902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		osd_end_request(or);
48002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
48102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
48202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshint osd_execute_request_async(struct osd_request *or,
48302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osd_req_done_fn *done, void *private)
48402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
48502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request->end_io_data = or;
48602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->async_private = private;
48702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->async_done = done;
48802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
48902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
49002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			      osd_request_async_done);
49102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return 0;
49202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
49302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_execute_request_async);
49402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
4954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshu8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
4964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshu8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
4974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
4984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_realloc_seg(struct osd_request *or,
4994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct _osd_req_data_segment *seg, unsigned max_bytes)
5004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *buff;
5024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (seg->alloc_size >= max_bytes)
5044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
5054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
5074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!buff) {
5084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
5094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			seg->alloc_size);
5104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -ENOMEM;
5114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
5124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
5144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->buff = buff;
5154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	seg->alloc_size = max_bytes;
5164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
5174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _alloc_set_attr_list(struct osd_request *or,
5204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
5214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned total_bytes = add_bytes;
5234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (; nelem; --nelem, ++oa)
5254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes += _osd_req_alist_elem_size(or, oa->len);
5264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("total_bytes=%d\n", total_bytes);
5284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return _osd_realloc_seg(or, &or->set_attr, total_bytes);
5294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
5324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("total_bytes=%d\n", max_bytes);
5344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
5354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
5374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _alloc_get_attr_list(struct osd_request *or)
5384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
5394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
5404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
5414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
5424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
54302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
54402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Common to all OSD commands
54502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
54602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
54702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osdv1_req_encode_common(struct osd_request *or,
54802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
54902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
55002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osdv1_cdb *ocdb = &or->cdb.v1;
55102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
55202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	/*
55302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 * For speed, the commands
55402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 *	OSD_ACT_PERFORM_SCSI_COMMAND	, V1 0x8F7E, V2 0x8F7C
55502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 *	OSD_ACT_SCSI_TASK_MANAGEMENT	, V1 0x8F7F, V2 0x8F7D
55602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 * are not supported here. Should pass zero and set after the call
55702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	 */
55802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	act &= cpu_to_be16(~0x0080); /* V1 action code */
55902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
56002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
56102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
56202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
56302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
56402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.varlen_cdb.service_action = act;
56502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
56602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.partition = cpu_to_be64(obj->partition);
56702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.object = cpu_to_be64(obj->id);
56802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.v1.length = cpu_to_be64(len);
56902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ocdb->h.v1.start_address = cpu_to_be64(offset);
57002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
57102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
572c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harroshstatic void _osdv2_req_encode_common(struct osd_request *or,
573c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
574c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh{
575c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	struct osdv2_cdb *ocdb = &or->cdb.v2;
576c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
577c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
578c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
579c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
580c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
581c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.varlen_cdb.service_action = act;
582c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
583c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.partition = cpu_to_be64(obj->partition);
584c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.object = cpu_to_be64(obj->id);
585c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.v2.length = cpu_to_be64(len);
586c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	ocdb->h.v2.start_address = cpu_to_be64(offset);
587c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh}
588c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
58902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osd_req_encode_common(struct osd_request *or,
59002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	__be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
59102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
592c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (osd_req_is_ver1(or))
593c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		_osdv1_req_encode_common(or, act, obj, offset, len);
594c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	else
595c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		_osdv2_req_encode_common(or, act, obj, offset, len);
59602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
59702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
59802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
59902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Device commands
60002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
601ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
602ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
603ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
60402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_format(struct osd_request *or, u64 tot_capacity)
60502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
60602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
60702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh				tot_capacity);
60802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
60902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_format);
61002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
6113e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_dev_partitions(struct osd_request *or,
6123e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
6133e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6143e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
6153e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
6163e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_dev_partitions);
6173e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6183e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshstatic void _osd_req_encode_flush(struct osd_request *or,
6193e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	enum osd_options_flush_scope_values op)
6203e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6213e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
6223e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6233e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	ocdb->command_specific_options = op;
6243e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
6253e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6263e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_obsd(struct osd_request *or,
6273e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	enum osd_options_flush_scope_values op)
6283e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6293e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
6303e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
6313e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
6323e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_obsd);
6333e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
634ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
635ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const u8 *cdb, ...); */
636ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_task_management(struct osd_request *, ...); */
637ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
63802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
63902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Partition commands
64002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
64102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic void _osd_req_encode_partition(struct osd_request *or,
64202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	__be16 act, osd_id partition)
64302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
64402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_obj_id par = {
64502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		.partition = partition,
64602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		.id = 0,
64702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	};
64802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
64902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, act, &par, 0, 0);
65002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
65102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
65202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_create_partition(struct osd_request *or, osd_id partition)
65302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
65402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
65502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
65602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_create_partition);
65702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
65802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_remove_partition(struct osd_request *or, osd_id partition)
65902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
66002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
66102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
66202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_remove_partition);
66302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
664ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_set_partition_key(struct osd_request *,
665ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
666ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	u8 seed[OSD_CRYPTO_SEED_SIZE]); */
667ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
6683e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshstatic int _osd_req_list_objects(struct osd_request *or,
6693e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	__be16 action, const struct osd_obj_id *obj, osd_id initial_id,
6703e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id_list *list, unsigned nelem)
6713e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6723e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct request_queue *q = or->osd_dev->scsi_device->request_queue;
6733e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	u64 len = nelem * sizeof(osd_id) + sizeof(*list);
6743e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct bio *bio;
6753e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6763e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, action, obj, (u64)initial_id, len);
6773e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6783e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	if (list->list_identifier)
6793e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		_osd_req_encode_olist(or, list);
6803e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6813e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	WARN_ON(or->in.bio);
6823e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	bio = bio_map_kern(q, list, len, or->alloc_flags);
683bf5e84f69618f416e89a5a53434a8c865e70252eDan Carpenter	if (IS_ERR(bio)) {
6843e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		OSD_ERR("!!! Failed to allocate list_objects BIO\n");
685bf5e84f69618f416e89a5a53434a8c865e70252eDan Carpenter		return PTR_ERR(bio);
6863e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	}
6873e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6883e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	bio->bi_rw &= ~(1 << BIO_RW);
6893e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	or->in.bio = bio;
6903e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	or->in.total_bytes = bio->bi_size;
6913e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return 0;
6923e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
6933e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
6943e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_partition_collections(struct osd_request *or,
6953e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
6963e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	unsigned nelem)
6973e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
6983e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id par = {
6993e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.partition = partition,
7003e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.id = 0,
7013e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	};
7023e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7033e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return osd_req_list_collection_objects(or, &par, initial_id, list,
7043e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh					       nelem);
7053e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7063e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_partition_collections);
7073e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7083e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_partition_objects(struct osd_request *or,
7093e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
7103e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	unsigned nelem)
7113e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7123e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id par = {
7133e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.partition = partition,
7143e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh		.id = 0,
7153e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	};
7163e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7173e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
7183e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh				     nelem);
7193e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7203e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_partition_objects);
7213e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7223e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_partition(struct osd_request *or,
7233e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	osd_id partition, enum osd_options_flush_scope_values op)
7243e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7253e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
7263e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
7273e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7283e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_partition);
7293e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
7303e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh/*
7313e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh * Collection commands
7323e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh */
733ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_create_collection(struct osd_request *,
734ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *); */
735ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_remove_collection(struct osd_request *,
736ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *); */
737ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
7383e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshint osd_req_list_collection_objects(struct osd_request *or,
7393e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	const struct osd_obj_id *obj, osd_id initial_id,
7403e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	struct osd_obj_id_list *list, unsigned nelem)
7413e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7423e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
7433e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh				     initial_id, list, nelem);
7443e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7453e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_list_collection_objects);
7463e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
747ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void query(struct osd_request *, ...); V2 */
748ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
7493e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_collection(struct osd_request *or,
7503e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
7513e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
7523e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
7533e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
7543e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
7553e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_collection);
7563e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
757ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
758ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
759ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
76002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
76102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Object commands
76202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
76302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
76402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
76502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
76602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
76702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_create_object);
76802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
76902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
77002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
77102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
77202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
77302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_remove_object);
77402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
775ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
776ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_create_multi(struct osd_request *or,
777ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
778ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh*/
779ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
78002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_write(struct osd_request *or,
78102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
78202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
78302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
78402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	WARN_ON(or->out.bio || or->out.total_bytes);
78502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	bio->bi_rw |= (1 << BIO_RW);
78602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->out.bio = bio;
78702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->out.total_bytes = bio->bi_size;
78802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
78902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_write);
79002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
791ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_append(struct osd_request *,
792ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, struct bio *data_out); */
793ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_create_write(struct osd_request *,
794ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, struct bio *data_out, u64 offset); */
795ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_clear(struct osd_request *,
796ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, u64 offset, u64 len); */
797ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh/*TODO: void osd_req_punch(struct osd_request *,
798ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh	const struct osd_obj_id *, u64 offset, u64 len); V2 */
799ae30c994a4bb70510fdcb9e7223805bb2a8bc9eeBoaz Harrosh
8003e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harroshvoid osd_req_flush_object(struct osd_request *or,
8013e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
8023e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	/*V2*/ u64 offset, /*V2*/ u64 len)
8033e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh{
804c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
805c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
806c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		offset = 0;
807c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh		len = 0;
808c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	}
809c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
8103e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
8113e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh	_osd_req_encode_flush(or, op);
8123e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh}
8133e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz HarroshEXPORT_SYMBOL(osd_req_flush_object);
8143e08613037fd4ec0b716a215602c4bdb3d0d9171Boaz Harrosh
81502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_req_read(struct osd_request *or,
81602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	const struct osd_obj_id *obj, struct bio *bio, u64 offset)
81702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
81802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
81902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	WARN_ON(or->in.bio || or->in.total_bytes);
82002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	bio->bi_rw &= ~(1 << BIO_RW);
82102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->in.bio = bio;
82202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->in.total_bytes = bio->bi_size;
82302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
82402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_req_read);
82502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
8264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshvoid osd_req_get_attributes(struct osd_request *or,
8274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_obj_id *obj)
8284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
8294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
8304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
8314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_get_attributes);
8324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshvoid osd_req_set_attributes(struct osd_request *or,
8344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_obj_id *obj)
8354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
8364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	_osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
8374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
8384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_set_attributes);
8394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh/*
8414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Attributes List-mode
8424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh */
8434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_add_set_attr_list(struct osd_request *or,
8454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *oa, unsigned nelem)
8464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
8474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned total_bytes = or->set_attr.total_bytes;
8484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *attr_last;
8494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
8504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode &&
8524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
8534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		WARN_ON(1);
8544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -EINVAL;
8554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
8564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
8574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!total_bytes) { /* first-time: allocate and put list header */
8594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes = _osd_req_sizeof_alist_header(or);
8604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
8614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret)
8624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
8634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		_osd_req_set_alist_type(or, or->set_attr.buff,
8644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					OSD_ATTR_LIST_SET_RETRIEVE);
8654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
8664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	attr_last = or->set_attr.buff + total_bytes;
8674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (; nelem; --nelem) {
8694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
8704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes += elem_size;
8724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (unlikely(or->set_attr.alloc_size < total_bytes)) {
8734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			or->set_attr.total_bytes = total_bytes - elem_size;
8744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
8754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			if (ret)
8764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				return ret;
8774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			attr_last =
8784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				or->set_attr.buff + or->set_attr.total_bytes;
8794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
8804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
88171f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		_osd_req_alist_elem_encode(or, attr_last, oa);
8824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attr_last += elem_size;
8844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		++oa;
8854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
8864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->set_attr.total_bytes = total_bytes;
8884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
8894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
8904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_add_set_attr_list);
8914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _append_map_kern(struct request *req,
8934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *buff, unsigned len, gfp_t flags)
8944ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
8954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct bio *bio;
8964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
8974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
8984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	bio = bio_map_kern(req->q, buff, len, flags);
8994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (IS_ERR(bio)) {
9004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
9014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			PTR_ERR(bio));
9024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return PTR_ERR(bio);
9034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
9044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = blk_rq_append_bio(req->q, req, bio);
9054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret) {
9064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
9074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		bio_put(bio);
9084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
9094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return ret;
9104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
9114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _req_append_segment(struct osd_request *or,
9134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned padding, struct _osd_req_data_segment *seg,
9144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
9154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
9164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *pad_buff;
9174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
9184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (padding) {
9204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		/* check if we can just add it to last buffer */
9214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (last_seg &&
9224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		    (padding <= last_seg->alloc_size - last_seg->total_bytes))
9234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			pad_buff = last_seg->buff + last_seg->total_bytes;
9244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		else
9254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			pad_buff = io->pad_buff;
9264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _append_map_kern(io->req, pad_buff, padding,
9284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				       or->alloc_flags);
9294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret)
9304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
9314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		io->total_bytes += padding;
9324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
9334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
9354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			       or->alloc_flags);
9364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
9374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
9384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	io->total_bytes += seg->total_bytes;
9404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
9414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		  seg->total_bytes);
9424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
9434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
9444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_req_finalize_set_attr_list(struct osd_request *or)
9464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
9474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
9484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned padding;
9494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
9504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!or->set_attr.total_bytes) {
9524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
9534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
9544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
9554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
9574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.set_attr_offset =
9584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->out.total_bytes, &padding);
9594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, padding, &or->set_attr,
9614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  or->out.last_seg, &or->out);
9624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
9634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
9644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->out.last_seg = &or->set_attr;
9664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
9674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
9684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_add_get_attr_list(struct osd_request *or,
9704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *oa, unsigned nelem)
9714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
9724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned total_bytes = or->enc_get_attr.total_bytes;
9734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *attr_last;
9744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
9754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode &&
9774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	    or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
9784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		WARN_ON(1);
9794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -EINVAL;
9804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
9814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
9824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* first time calc data-in list header size */
9844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!or->get_attr.total_bytes)
9854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
9864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* calc data-out info */
9884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!total_bytes) { /* first-time: allocate and put list header */
9894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		unsigned max_bytes;
9904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes = _osd_req_sizeof_alist_header(or);
9924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		max_bytes = total_bytes +
9934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			nelem * sizeof(struct osd_attributes_list_attrid);
9944ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _alloc_get_attr_desc(or, max_bytes);
9954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret)
9964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
9974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
9984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		_osd_req_set_alist_type(or, or->enc_get_attr.buff,
9994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					OSD_ATTR_LIST_GET);
10004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
10014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	attr_last = or->enc_get_attr.buff + total_bytes;
10024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (; nelem; --nelem) {
10044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		struct osd_attributes_list_attrid *attrid;
10054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		const unsigned cur_size = sizeof(*attrid);
10064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		total_bytes += cur_size;
10084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
10094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			or->enc_get_attr.total_bytes = total_bytes - cur_size;
10104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			ret = _alloc_get_attr_desc(or,
10114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					total_bytes + nelem * sizeof(*attrid));
10124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			if (ret)
10134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				return ret;
10144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			attr_last = or->enc_get_attr.buff +
10154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				or->enc_get_attr.total_bytes;
10164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
10174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attrid = attr_last;
10194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attrid->attr_page = cpu_to_be32(oa->attr_page);
10204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attrid->attr_id = cpu_to_be32(oa->attr_id);
10214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		attr_last += cur_size;
10234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		/* calc data-in size */
10254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		or->get_attr.total_bytes +=
10264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			_osd_req_alist_elem_size(or, oa->len);
10274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		++oa;
10284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
10294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->enc_get_attr.total_bytes = total_bytes;
10314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG(
10334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
10344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       or->get_attr.total_bytes,
10354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
10364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       or->enc_get_attr.total_bytes,
10374ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	       (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
10384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			/ sizeof(struct osd_attributes_list_attrid));
10394ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
10414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
10424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_add_get_attr_list);
10434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_req_finalize_get_attr_list(struct osd_request *or)
10454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
10464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
10474ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned out_padding;
10484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned in_padding;
10494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
10504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!or->enc_get_attr.total_bytes) {
10524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
10534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
10544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
10554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
10564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _alloc_get_attr_list(or);
10584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
10594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
10604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* The out-going buffer info update */
10624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("out-going\n");
10634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_desc_bytes =
10644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cpu_to_be32(or->enc_get_attr.total_bytes);
10654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_desc_offset =
10674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
10684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
10704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  or->out.last_seg, &or->out);
10714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
10724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
10734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->out.last_seg = &or->enc_get_attr;
10744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* The incoming buffer info update */
10764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("in-coming\n");
10774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_alloc_length =
10784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cpu_to_be32(or->get_attr.total_bytes);
10794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_list.get_attr_offset =
10814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
10824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
10844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  &or->in);
10854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
10864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
10874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->in.last_seg = &or->get_attr;
10884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
10904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
10914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
10924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_decode_get_attr_list(struct osd_request *or,
10934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_attr *oa, int *nelem, void **iterator)
10944ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
10954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned cur_bytes, returned_bytes;
10964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int n;
10974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
10984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	void *cur_p;
10994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!_osd_req_is_alist_type(or, or->get_attr.buff,
11014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				    OSD_ATTR_LIST_SET_RETRIEVE)) {
11024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->attr_page = 0;
11034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->attr_id = 0;
11044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->val_ptr = NULL;
11054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		oa->len = 0;
11064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		*iterator = NULL;
11074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
11084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (*iterator) {
11114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		BUG_ON((*iterator < or->get_attr.buff) ||
11124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		     (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
11134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_p = *iterator;
11144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
11154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		returned_bytes = or->get_attr.total_bytes;
11164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	} else { /* first time decode the list header */
11174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_bytes = sizeof_attr_list;
11184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
11194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh					sizeof_attr_list;
11204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_p = or->get_attr.buff + sizeof_attr_list;
11224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (returned_bytes > or->get_attr.alloc_size) {
11244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_DEBUG("target report: space was not big enough! "
11254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  "Allocate=%u Needed=%u\n",
11264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  or->get_attr.alloc_size,
11274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  returned_bytes + sizeof_attr_list);
11284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			returned_bytes =
11304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				or->get_attr.alloc_size - sizeof_attr_list;
11314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
11324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		or->get_attr.total_bytes = returned_bytes;
11334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
113671f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
113771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh						 returned_bytes - cur_bytes);
11384ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
113971f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		if (inc < 0) {
11404ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_ERR("BAD FOOD from target. list not valid!"
11414ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				"c=%d r=%d n=%d\n",
11424ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				cur_bytes, returned_bytes, n);
11434ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			oa->val_ptr = NULL;
11444ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			break;
11454ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
11464ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
114771f32e31e5638df37904697e2d04182935add85dBoaz Harrosh		cur_bytes += inc;
11484ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		cur_p += inc;
11494ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		++oa;
11504ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11514ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11524ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	*iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
11534ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	*nelem = n;
11544ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return returned_bytes - cur_bytes;
11554ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
11564ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_decode_get_attr_list);
11574ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11584ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh/*
11594ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Attributes Page-mode
11604ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh */
11614ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11624ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshint osd_req_add_get_attr_page(struct osd_request *or,
11634ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u32 page_id, void *attar_page, unsigned max_page_len,
11644ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	const struct osd_attr *set_one_attr)
11654ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
11664ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
11674ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11684ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode &&
11694ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	    or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
11704ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		WARN_ON(1);
11714ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return -EINVAL;
11724ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
11734ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
11744ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11754ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->get_attr.buff = attar_page;
11764ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->get_attr.total_bytes = max_page_len;
11774ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11784ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->set_attr.buff = set_one_attr->val_ptr;
11794ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->set_attr.total_bytes = set_one_attr->len;
11804ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
11824ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
11834ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* ocdb->attrs_page.get_attr_offset; */
11844ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11854ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page);
11864ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
11874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
11884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* ocdb->attrs_page.set_attr_offset; */
11894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return 0;
11904ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
11914ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz HarroshEXPORT_SYMBOL(osd_req_add_get_attr_page);
11924ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshstatic int _osd_req_finalize_attr_page(struct osd_request *or)
11944ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
11954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
11964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	unsigned in_padding, out_padding;
11974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int ret;
11984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
11994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* returned page */
12004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.get_attr_offset =
12014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
12024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
12044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  &or->in);
12054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (ret)
12064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return ret;
12074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	/* set one value */
12094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	cdbh->attrs_page.set_attr_offset =
12104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
12114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
12124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
12134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh				  &or->out);
12144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return ret;
12154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
12164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
1217f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harroshstatic inline void osd_sec_parms_set_out_offset(bool is_v1,
1218f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
1219f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh{
1220f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	if (is_v1)
1221f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v1.data_out_integrity_check_offset = offset;
1222f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	else
1223f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v2.data_out_integrity_check_offset = offset;
1224f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh}
1225f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh
1226f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harroshstatic inline void osd_sec_parms_set_in_offset(bool is_v1,
1227f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
1228f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh{
1229f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	if (is_v1)
1230f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v1.data_in_integrity_check_offset = offset;
1231f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh	else
1232f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		sec_parms->v2.data_in_integrity_check_offset = offset;
1233f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh}
1234f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh
1235345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshstatic int _osd_req_finalize_data_integrity(struct osd_request *or,
1236345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	bool has_in, bool has_out, const u8 *cap_key)
1237345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
1238345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
1239345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	int ret;
1240345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1241345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (!osd_is_sec_alldata(sec_parms))
1242345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		return 0;
1243345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1244345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (has_out) {
1245345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		struct _osd_req_data_segment seg = {
1246345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.buff = &or->out_data_integ,
1247345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.total_bytes = sizeof(or->out_data_integ),
1248345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		};
1249345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		unsigned pad;
1250345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1251345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->out_data_integ.data_bytes = cpu_to_be64(
1252345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			or->out.bio ? or->out.bio->bi_size : 0);
1253345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->out_data_integ.set_attributes_bytes = cpu_to_be64(
1254345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			or->set_attr.total_bytes);
1255345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->out_data_integ.get_attributes_bytes = cpu_to_be64(
1256345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			or->enc_get_attr.total_bytes);
1257345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1258f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		osd_sec_parms_set_out_offset(osd_req_is_ver1(or), sec_parms,
1259f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh			osd_req_encode_offset(or, or->out.total_bytes, &pad));
1260345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1261345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
1262345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh					  &or->out);
1263345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		if (ret)
1264345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			return ret;
1265345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->out.last_seg = NULL;
1266345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1267345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		/* they are now all chained to request sign them all together */
1268345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
1269345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh				  cap_key);
1270345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	}
1271345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1272345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (has_in) {
1273345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		struct _osd_req_data_segment seg = {
1274345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.buff = &or->in_data_integ,
1275345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			.total_bytes = sizeof(or->in_data_integ),
1276345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		};
1277345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		unsigned pad;
1278345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1279f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh		osd_sec_parms_set_in_offset(osd_req_is_ver1(or), sec_parms,
1280f8d3a644bec74fd55dbfb11f95af7bf98fa963dcBoaz Harrosh			osd_req_encode_offset(or, or->in.total_bytes, &pad));
1281345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1282345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
1283345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh					  &or->in);
1284345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		if (ret)
1285345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh			return ret;
1286345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1287345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		or->in.last_seg = NULL;
1288345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	}
1289345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1290345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	return 0;
1291345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
1292345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
129302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
129402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * osd_finalize_request and helpers
129502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
129602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
129702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshstatic int _init_blk_request(struct osd_request *or,
129802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	bool has_in, bool has_out)
129902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
130002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	gfp_t flags = or->alloc_flags;
130102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct scsi_device *scsi_device = or->osd_dev->scsi_device;
130202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct request_queue *q = scsi_device->request_queue;
130302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct request *req;
130402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	int ret = -ENOMEM;
130502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
130602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req = blk_get_request(q, has_out, flags);
130702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (!req)
130802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		goto out;
130902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
131002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request = req;
131102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->cmd_type = REQ_TYPE_BLOCK_PC;
131202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->timeout = or->timeout;
131302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->retries = or->retries;
131402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->sense = or->sense;
131502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	req->sense_len = 0;
131602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
131702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (has_out) {
131802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->out.req = req;
131902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (has_in) {
132002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			/* allocate bidi request */
132102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			req = blk_get_request(q, READ, flags);
132202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			if (!req) {
132302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh				OSD_DEBUG("blk_get_request for bidi failed\n");
132402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh				goto out;
132502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			}
132602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			req->cmd_type = REQ_TYPE_BLOCK_PC;
132702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			or->in.req = or->request->next_rq = req;
132802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
132902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	} else if (has_in)
133002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->in.req = req;
133102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
133202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ret = 0;
133302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshout:
133402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
133502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			or, has_in, has_out, ret, or->request);
133602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return ret;
133702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
133802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
133902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshint osd_finalize_request(struct osd_request *or,
134002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	u8 options, const void *cap, const u8 *cap_key)
134102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
134202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
134302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	bool has_in, has_out;
134402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	int ret;
134502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
134602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (options & OSD_REQ_FUA)
134702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		cdbh->options |= OSD_CDB_FUA;
134802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
134902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (options & OSD_REQ_DPO)
135002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		cdbh->options |= OSD_CDB_DPO;
135102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
135202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (options & OSD_REQ_BYPASS_TIMESTAMPS)
135302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
135402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
135502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osd_set_caps(&or->cdb, cap);
135602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
135702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	has_in = or->in.bio || or->get_attr.total_bytes;
135802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	has_out = or->out.bio || or->set_attr.total_bytes ||
135902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->enc_get_attr.total_bytes;
136002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
136102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	ret = _init_blk_request(or, has_in, has_out);
136202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (ret) {
136302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		OSD_DEBUG("_init_blk_request failed\n");
136402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		return ret;
136502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
136602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
136702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (or->out.bio) {
136802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		ret = blk_rq_append_bio(or->request->q, or->out.req,
136902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh					or->out.bio);
137002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (ret) {
137102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			OSD_DEBUG("blk_rq_append_bio out failed\n");
137202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			return ret;
137302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
137402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
137502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			_LLU(or->out.total_bytes), or->out.req->data_len);
137602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
137702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (or->in.bio) {
137802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
137902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (ret) {
138002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			OSD_DEBUG("blk_rq_append_bio in failed\n");
138102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			return ret;
138202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
138302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
138402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			_LLU(or->in.total_bytes), or->in.req->data_len);
138502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
138602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
13874ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->out.pad_buff = sg_out_pad_buffer;
13884ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	or->in.pad_buff = sg_in_pad_buffer;
13894ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
139002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (!or->attributes_mode)
139102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
139202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cdbh->command_specific_options |= or->attributes_mode;
13934ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
13944ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _osd_req_finalize_attr_page(or);
13954ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	} else {
13964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		/* TODO: I think that for the GET_ATTR command these 2 should
13974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 * be reversed to keep them in execution order (for embeded
13984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 * targets with low memory footprint)
13994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 */
14004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _osd_req_finalize_set_attr_list(or);
14014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret) {
14024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
14034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
14044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
14054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
14064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		ret = _osd_req_finalize_get_attr_list(or);
14074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (ret) {
14084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
14094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			return ret;
14104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		}
14114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
141202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1413345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
1414345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	if (ret)
1415345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		return ret;
1416345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1417345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	osd_sec_sign_cdb(&or->cdb, cap_key);
1418345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
141902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request->cmd = or->cdb.buff;
142002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	or->request->cmd_len = _osd_req_cdb_len(or);
142102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
142202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	return 0;
142302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
142402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_finalize_request);
142502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
142698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#define OSD_SENSE_PRINT1(fmt, a...) \
142798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	do { \
142898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		if (__cur_sense_need_output) \
142998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_ERR(fmt, ##a); \
143098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	} while (0)
143198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
143298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1("    " fmt, ##a)
143398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
143498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harroshint osd_req_decode_sense_full(struct osd_request *or,
143598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_sense_info *osi, bool silent,
143698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_obj_id *bad_obj_list __unused, int max_obj __unused,
143798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_attr *bad_attr_list, int max_attr)
143898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh{
143998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	int sense_len, original_sense_len;
144098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct osd_sense_info local_osi;
144198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	struct scsi_sense_descriptor_based *ssdb;
144298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	void *cur_descriptor;
144398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0)
144498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	const bool __cur_sense_need_output = false;
144598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#else
144698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	bool __cur_sense_need_output = !silent;
144798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#endif
144898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
144998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if (!or->request->errors)
145098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		return 0;
145198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
145298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	ssdb = or->request->sense;
145398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	sense_len = or->request->sense_len;
145498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) {
145598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		OSD_ERR("Block-layer returned error(0x%x) but "
145698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			"sense_len(%u) || key(%d) is empty\n",
145798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			or->request->errors, sense_len, ssdb->sense_key);
145898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		return -EIO;
145998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	}
146098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
146198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
146298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
146398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			ssdb->response_code, sense_len);
146498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		return -EIO;
146598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	}
146698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
146798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	osi = osi ? : &local_osi;
146898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	memset(osi, 0, sizeof(*osi));
146998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	osi->key = ssdb->sense_key;
147098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
147198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	original_sense_len = ssdb->additional_sense_length + 8;
147298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
147398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1)
147498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if (__cur_sense_need_output)
147598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		__cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
147698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh#endif
147798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
147898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			"additional_code=0x%x\n",
147998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->key, original_sense_len, sense_len,
148098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->additional_code);
148198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
148298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	if (original_sense_len < sense_len)
148398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		sense_len = original_sense_len;
148498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
148598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	cur_descriptor = ssdb->ssd;
148698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	sense_len -= sizeof(*ssdb);
148798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	while (sense_len > 0) {
148898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		struct scsi_sense_descriptor *ssd = cur_descriptor;
148998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		int cur_len = ssd->additional_length + 2;
149098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
149198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		sense_len -= cur_len;
149298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
149398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		if (sense_len < 0)
149498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break; /* sense was truncated */
149598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
149698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		switch (ssd->descriptor_type) {
149798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_information:
149898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_command_specific_information:
149998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
150098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct scsi_sense_command_specific_data_descriptor
150198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*sscd = cur_descriptor;
150298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
150398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->command_info =
150498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				get_unaligned_be64(&sscd->information) ;
150598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
150698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"command_specific_information 0x%llx \n",
150798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				_LLU(osi->command_info));
150898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
150998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
151098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_key_specific:
151198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
151298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct scsi_sense_key_specific_data_descriptor
151398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*ssks = cur_descriptor;
151498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
151598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->sense_info = get_unaligned_be16(&ssks->value);
151698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
151798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"sense_key_specific_information %u"
151898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"sksv_cd_bpv_bp (0x%x)\n",
151998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				osi->sense_info, ssks->sksv_cd_bpv_bp);
152098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
152198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
152298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case osd_sense_object_identification:
152398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{ /*FIXME: Keep first not last, Store in array*/
152498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_identification_data_descriptor
152598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*osidd = cur_descriptor;
152698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
152798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->not_initiated_command_functions =
152898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				le32_to_cpu(osidd->not_initiated_functions);
152998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->completed_command_functions =
153098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				le32_to_cpu(osidd->completed_functions);
153198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->obj.partition = be64_to_cpu(osidd->partition_id);
153298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			osi->obj.id = be64_to_cpu(osidd->object_id);
153398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
153498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"object_identification pid=0x%llx oid=0x%llx\n",
153598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				_LLU(osi->obj.partition), _LLU(osi->obj.id));
153698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2(
153798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"not_initiated_bits(%x) "
153898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				"completed_command_bits(%x)\n",
153998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				osi->not_initiated_command_functions,
154098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				osi->completed_command_functions);
154198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
154298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
154398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case osd_sense_response_integrity_check:
154498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
154598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_response_integrity_check_descriptor
154698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*osricd = cur_descriptor;
154798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			const unsigned len =
154898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					  sizeof(osricd->integrity_check_value);
154998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			char key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
155098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
155198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			hex_dump_to_buffer(osricd->integrity_check_value, len,
155298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				       32, 1, key_dump, sizeof(key_dump), true);
155398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
155498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
155598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case osd_sense_attribute_identification:
155698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		{
155798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_attributes_data_descriptor
155898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				*osadd = cur_descriptor;
155998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			int len = min(cur_len, sense_len);
156098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			int i = 0;
156198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			struct osd_sense_attr *pattr = osadd->sense_attrs;
156298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
156398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			while (len < 0) {
156498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				u32 attr_page = be32_to_cpu(pattr->attr_page);
156598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				u32 attr_id = be32_to_cpu(pattr->attr_id);
156698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
156798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				if (i++ == 0) {
156898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					osi->attr.attr_page = attr_page;
156998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					osi->attr.attr_id = attr_id;
157098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				}
157198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
157298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				if (bad_attr_list && max_attr) {
157398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					bad_attr_list->attr_page = attr_page;
157498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					bad_attr_list->attr_id = attr_id;
157598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					bad_attr_list++;
157698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					max_attr--;
157798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				}
157898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				OSD_SENSE_PRINT2(
157998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"osd_sense_attribute_identification"
158098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"attr_page=0x%x attr_id=0x%x\n",
158198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					attr_page, attr_id);
158298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			}
158398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
158498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		/*These are not legal for OSD*/
158598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_field_replaceable_unit:
158698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n");
158798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
158898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_stream_commands:
158998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_stream_commands\n");
159098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
159198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_block_commands:
159298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_block_commands\n");
159398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
159498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		case scsi_sense_ata_return:
159598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			OSD_SENSE_PRINT2("scsi_sense_ata_return\n");
159698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			break;
159798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		default:
159898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			if (ssd->descriptor_type <= scsi_sense_Reserved_last)
159998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				OSD_SENSE_PRINT2(
160098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"scsi_sense Reserved descriptor (0x%x)",
160198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					ssd->descriptor_type);
160298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh			else
160398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh				OSD_SENSE_PRINT2(
160498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					"scsi_sense Vendor descriptor (0x%x)",
160598f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh					ssd->descriptor_type);
160698f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		}
160798f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
160898f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh		cur_descriptor += cur_len;
160998f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	}
161098f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
161198f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh	return (osi->key > scsi_sk_recovered_error) ? -EIO : 0;
161298f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh}
161398f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz HarroshEXPORT_SYMBOL(osd_req_decode_sense_full);
161498f3aea2bd4b4f9cd7a6a6479ed9410787f756fdBoaz Harrosh
161502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*
161602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * Implementation of osd_sec.h API
161702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh * TODO: Move to a separate osd_sec.c file at a later stage.
161802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh */
161902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
162002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshenum { OSD_SEC_CAP_V1_ALL_CAPS =
162102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
162202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
162302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
162402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
162502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh};
162602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1627c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harroshenum { OSD_SEC_CAP_V2_ALL_CAPS =
1628c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
1629c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh};
1630c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh
163102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_sec_init_nosec_doall_caps(void *caps,
163202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
163302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
163402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	struct osd_capability *cap = caps;
163502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	u8 type;
163602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	u8 descriptor_type;
163702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
163802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	if (likely(obj->id)) {
163902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		if (unlikely(is_collection)) {
164002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			type = OSD_SEC_OBJ_COLLECTION;
164102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
164202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh						  OSD_SEC_OBJ_DESC_COL;
164302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		} else {
164402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			type = OSD_SEC_OBJ_USER;
164502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh			descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
164602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		}
164702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		WARN_ON(!obj->partition);
164802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	} else {
164902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		type = obj->partition ? OSD_SEC_OBJ_PARTITION :
165002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh					OSD_SEC_OBJ_ROOT;
165102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh		descriptor_type = OSD_SEC_OBJ_DESC_PAR;
165202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	}
165302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
165402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	memset(cap, 0, sizeof(*cap));
165502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
165602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
165702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
165802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.security_method = OSD_SEC_NOSEC;
165902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh/*	cap->expiration_time;
166002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->AUDIT[30-10];
166102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->discriminator[42-30];
166202941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->object_created_time; */
166302941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.object_type = type;
166402941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
166502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->h.object_descriptor_type = descriptor_type;
166602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->od.obj_desc.policy_access_tag = 0;
166702941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
166802941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh	cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
166902941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
167002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz HarroshEXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
167102941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh
1672c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh/* FIXME: Extract version from caps pointer.
1673c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh *        Also Pete's target only supports caps from OSDv1 for now
1674c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh */
167502941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harroshvoid osd_set_caps(struct osd_cdb *cdb, const void *caps)
167602941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh{
1677c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	bool is_ver1 = true;
1678c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	/* NOTE: They start at same address */
1679c6572c983726fe3f3bb5f07e9afe3a9b8e402d1bBoaz Harrosh	memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
168002941a530ef736210b4cf8b24dd34c238d5d5a40Boaz Harrosh}
16814ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
1682345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshbool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused)
1683345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
1684345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh	return false;
1685345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
1686345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1687345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshvoid osd_sec_sign_cdb(struct osd_cdb *ocdb __unused, const u8 *cap_key __unused)
1688345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
1689345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
1690345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
1691345c435dbb0b77b00ffe73801102533e24c647afBoaz Harroshvoid osd_sec_sign_data(void *data_integ __unused,
1692345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh		       struct bio *bio __unused, const u8 *cap_key __unused)
1693345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh{
1694345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh}
1695345c435dbb0b77b00ffe73801102533e24c647afBoaz Harrosh
16964ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh/*
16974ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Declared in osd_protocol.h
16984ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * 4.12.5 Data-In and Data-Out buffer offsets
16994ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * byte offset = mantissa * (2^(exponent+8))
17004ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * Returns the smallest allowed encoded offset that contains given @offset
17014ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh * The actual encoded offset returned is @offset + *@padding.
17024ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh */
17034ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harroshosd_cdb_offset __osd_encode_offset(
17044ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u64 offset, unsigned *padding, int min_shift, int max_shift)
17054ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh{
17064ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	u64 try_offset = -1, mod, align;
17074ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	osd_cdb_offset be32_offset;
17084ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	int shift;
17094ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
17104ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	*padding = 0;
17114ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (!offset)
17124ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		return 0;
17134ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
17144ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	for (shift = min_shift; shift < max_shift; ++shift) {
17154ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		try_offset = offset >> shift;
17164ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
17174ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh			break;
17184ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
17194ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
17204ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	BUG_ON(shift == max_shift);
17214ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
17224ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	align = 1 << shift;
17234ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	mod = offset & (align - 1);
17244ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	if (mod) {
17254ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		*padding = align - mod;
17264ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		try_offset += 1;
17274ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	}
17284ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
17294ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	try_offset |= ((shift - 8) & 0xf) << 28;
17304ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	be32_offset = cpu_to_be32((u32)try_offset);
17314ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh
17324ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
17334ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
17344ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh		 be32_offset, *padding);
17354ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh	return be32_offset;
17364ef1a3d70d02663f6bfe901db629e8e608da15b1Boaz Harrosh}
1737