From: Vladislav Bolkhovitin <vst@vlnb.net>
To: linux-scsi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
scst-devel <scst-devel@lists.sourceforge.net>,
James Bottomley <James.Bottomley@HansenPartnership.com>,
Andrew Morton <akpm@linux-foundation.org>,
FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>,
Mike Christie <michaelc@cs.wisc.edu>,
Vu Pham <vuhuong@mellanox.com>,
Bart Van Assche <bart.vanassche@gmail.com>,
James Smart <James.Smart@Emulex.Com>,
Joe Eykholt <jeykholt@cisco.com>, Andy Yan <ayan@marvell.com>,
Chetan Loke <generationgnu@yahoo.com>,
Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Hannes Reinecke <hare@suse.de>,
Richard Sharpe <realrichardsharpe@gmail.com>
Subject: [PATCH 3/19]: SCST public headers
Date: Sat, 02 Oct 2010 01:38:14 +0400 [thread overview]
Message-ID: <4CA654C6.2070902@vlnb.net> (raw)
In-Reply-To: <4CA653F0.1010008@vlnb.net>
This patch contains declarations of all externally visible SCST
constants, types and functions prototypes.
Particularly, it has definitions of all core SCST structures:
- scst_tgt_template - defines SCST target driver, its callbacks
and SCST core behavior dealing with it.
- scst_dev_type - defines SCST backend driver, its callbacks and
SCST core behavior dealing with it.
- scst_tgt - defines SCST target (SCSI target port). Analog of Scsi_Host on
the initiator side.
- scst_session - defines SCST session (SCSI I_T nexus)
- scst_cmd - defines SCST command (SCSI I_T_L_Q nexus)
- scst_device - defines SCST device (SCSI device)
- scst_tgt_dev - defines SCSI I_T_L nexus
- scst_acg - defines SCST access control group. Such groups define
which initiators see which LUNs.
as well as prototypes for all the functions to manage those objects.
Signed-off-by: Vladislav Bolkhovitin <vst@vlnb.net>
---
scst.h | 3642 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
scst_const.h | 376 ++++++
2 files changed, 4018 insertions(+)
diff -uprN orig/linux-2.6.35/include/scst/scst_const.h linux-2.6.35/include/scst/scst_const.h
--- orig/linux-2.6.35/include/scst/scst_const.h
+++ linux-2.6.35/include/scst/scst_const.h
@@ -0,0 +1,376 @@
+/*
+ * include/scst_const.h
+ *
+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
+ * Copyright (C) 2007 - 2010 ID7 Ltd.
+ *
+ * Contains common SCST constants.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SCST_CONST_H
+#define __SCST_CONST_H
+
+#include <scsi/scsi.h>
+
+#define SCST_CONST_VERSION "$Revision: 2272 $"
+
+/*** Shared constants between user and kernel spaces ***/
+
+/* Max size of CDB */
+#define SCST_MAX_CDB_SIZE 16
+
+/* Max size of various names */
+#define SCST_MAX_NAME 50
+
+/* Max size of external names, like initiator name */
+#define SCST_MAX_EXTERNAL_NAME 256
+
+/*
+ * Size of sense sufficient to carry standard sense data.
+ * Warning! It's allocated on stack!
+ */
+#define SCST_STANDARD_SENSE_LEN 18
+
+/* Max size of sense */
+#define SCST_SENSE_BUFFERSIZE 96
+
+/*************************************************************
+ ** Allowed delivery statuses for cmd's delivery_status
+ *************************************************************/
+
+#define SCST_CMD_DELIVERY_SUCCESS 0
+#define SCST_CMD_DELIVERY_FAILED -1
+#define SCST_CMD_DELIVERY_ABORTED -2
+
+/*************************************************************
+ ** Values for task management functions
+ *************************************************************/
+#define SCST_ABORT_TASK 0
+#define SCST_ABORT_TASK_SET 1
+#define SCST_CLEAR_ACA 2
+#define SCST_CLEAR_TASK_SET 3
+#define SCST_LUN_RESET 4
+#define SCST_TARGET_RESET 5
+
+/** SCST extensions **/
+
+/*
+ * Notifies about I_T nexus loss event in the corresponding session.
+ * Aborts all tasks there, resets the reservation, if any, and sets
+ * up the I_T Nexus loss UA.
+ */
+#define SCST_NEXUS_LOSS_SESS 6
+
+/* Aborts all tasks in the corresponding session */
+#define SCST_ABORT_ALL_TASKS_SESS 7
+
+/*
+ * Notifies about I_T nexus loss event. Aborts all tasks in all sessions
+ * of the tgt, resets the reservations, if any, and sets up the I_T Nexus
+ * loss UA.
+ */
+#define SCST_NEXUS_LOSS 8
+
+/* Aborts all tasks in all sessions of the tgt */
+#define SCST_ABORT_ALL_TASKS 9
+
+/*
+ * Internal TM command issued by SCST in scst_unregister_session(). It is the
+ * same as SCST_NEXUS_LOSS_SESS, except:
+ * - it doesn't call task_mgmt_affected_cmds_done()
+ * - it doesn't call task_mgmt_fn_done()
+ * - it doesn't queue NEXUS LOSS UA.
+ *
+ * Target drivers must NEVER use it!!
+ */
+#define SCST_UNREG_SESS_TM 10
+
+/*
+ * Internal TM command issued by SCST in scst_pr_abort_reg(). It aborts all
+ * tasks from mcmd->origin_pr_cmd->tgt_dev, except mcmd->origin_pr_cmd.
+ * Additionally:
+ * - it signals pr_aborting_cmpl completion when all affected
+ * commands marked as aborted.
+ * - it doesn't call task_mgmt_affected_cmds_done()
+ * - it doesn't call task_mgmt_fn_done()
+ * - it calls mcmd->origin_pr_cmd->scst_cmd_done() when all affected
+ * commands aborted.
+ *
+ * Target drivers must NEVER use it!!
+ */
+#define SCST_PR_ABORT_ALL 11
+
+/*************************************************************
+ ** Values for mgmt cmd's status field. Codes taken from iSCSI
+ *************************************************************/
+#define SCST_MGMT_STATUS_SUCCESS 0
+#define SCST_MGMT_STATUS_TASK_NOT_EXIST -1
+#define SCST_MGMT_STATUS_LUN_NOT_EXIST -2
+#define SCST_MGMT_STATUS_FN_NOT_SUPPORTED -5
+#define SCST_MGMT_STATUS_REJECTED -255
+#define SCST_MGMT_STATUS_FAILED -129
+
+/*************************************************************
+ ** SCSI task attribute queue types
+ *************************************************************/
+enum scst_cmd_queue_type {
+ SCST_CMD_QUEUE_UNTAGGED = 0,
+ SCST_CMD_QUEUE_SIMPLE,
+ SCST_CMD_QUEUE_ORDERED,
+ SCST_CMD_QUEUE_HEAD_OF_QUEUE,
+ SCST_CMD_QUEUE_ACA
+};
+
+/*************************************************************
+ ** CDB flags
+ **
+ ** Implicit ordered used for commands which need calm environment
+ ** without any simultaneous activities. For instance, for MODE
+ ** SELECT it is needed to correctly generate its UA.
+ *************************************************************/
+enum scst_cdb_flags {
+ SCST_TRANSFER_LEN_TYPE_FIXED = 0x0001,
+ SCST_SMALL_TIMEOUT = 0x0002,
+ SCST_LONG_TIMEOUT = 0x0004,
+ SCST_UNKNOWN_LENGTH = 0x0008,
+ SCST_INFO_VALID = 0x0010, /* must be single bit */
+ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x0020,
+ SCST_IMPLICIT_HQ = 0x0040,
+ SCST_IMPLICIT_ORDERED = 0x0080,
+ SCST_SKIP_UA = 0x0100,
+ SCST_WRITE_MEDIUM = 0x0200,
+ SCST_LOCAL_CMD = 0x0400,
+ SCST_FULLY_LOCAL_CMD = 0x0800,
+ SCST_REG_RESERVE_ALLOWED = 0x1000,
+ SCST_WRITE_EXCL_ALLOWED = 0x2000,
+ SCST_EXCL_ACCESS_ALLOWED = 0x4000,
+#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
+ SCST_TEST_IO_IN_SIRQ_ALLOWED = 0x8000,
+#endif
+};
+
+/*************************************************************
+ ** Data direction aliases. Changing it don't forget to change
+ ** scst_to_tgt_dma_dir as well!!
+ *************************************************************/
+#define SCST_DATA_UNKNOWN 0
+#define SCST_DATA_WRITE 1
+#define SCST_DATA_READ 2
+#define SCST_DATA_BIDI (SCST_DATA_WRITE | SCST_DATA_READ)
+#define SCST_DATA_NONE 4
+
+/*************************************************************
+ ** Default suffix for targets with NULL names
+ *************************************************************/
+#define SCST_DEFAULT_TGT_NAME_SUFFIX "_target_"
+
+/*************************************************************
+ ** Sense manipulation and examination
+ *************************************************************/
+#define SCST_LOAD_SENSE(key_asc_ascq) key_asc_ascq
+
+#define SCST_SENSE_VALID(sense) ((sense != NULL) && \
+ ((((const uint8_t *)(sense))[0] & 0x70) == 0x70))
+
+#define SCST_NO_SENSE(sense) ((sense != NULL) && \
+ (((const uint8_t *)(sense))[2] == 0))
+
+/*************************************************************
+ ** Sense data for the appropriate errors. Can be used with
+ ** scst_set_cmd_error()
+ *************************************************************/
+#define scst_sense_no_sense NO_SENSE, 0x00, 0
+#define scst_sense_hardw_error HARDWARE_ERROR, 0x44, 0
+#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0
+#define scst_sense_invalid_opcode ILLEGAL_REQUEST, 0x20, 0
+#define scst_sense_invalid_field_in_cdb ILLEGAL_REQUEST, 0x24, 0
+#define scst_sense_invalid_field_in_parm_list ILLEGAL_REQUEST, 0x26, 0
+#define scst_sense_parameter_value_invalid ILLEGAL_REQUEST, 0x26, 2
+#define scst_sense_invalid_release ILLEGAL_REQUEST, 0x26, 4
+#define scst_sense_parameter_list_length_invalid \
+ ILLEGAL_REQUEST, 0x1A, 0
+#define scst_sense_reset_UA UNIT_ATTENTION, 0x29, 0
+#define scst_sense_nexus_loss_UA UNIT_ATTENTION, 0x29, 0x7
+#define scst_sense_saving_params_unsup ILLEGAL_REQUEST, 0x39, 0
+#define scst_sense_lun_not_supported ILLEGAL_REQUEST, 0x25, 0
+#define scst_sense_data_protect DATA_PROTECT, 0x00, 0
+#define scst_sense_miscompare_error MISCOMPARE, 0x1D, 0
+#define scst_sense_block_out_range_error ILLEGAL_REQUEST, 0x21, 0
+#define scst_sense_medium_changed_UA UNIT_ATTENTION, 0x28, 0
+#define scst_sense_read_error MEDIUM_ERROR, 0x11, 0
+#define scst_sense_write_error MEDIUM_ERROR, 0x03, 0
+#define scst_sense_not_ready NOT_READY, 0x04, 0x10
+#define scst_sense_invalid_message ILLEGAL_REQUEST, 0x49, 0
+#define scst_sense_cleared_by_another_ini_UA UNIT_ATTENTION, 0x2F, 0
+#define scst_sense_capacity_data_changed UNIT_ATTENTION, 0x2A, 0x9
+#define scst_sense_reservation_preempted UNIT_ATTENTION, 0x2A, 0x03
+#define scst_sense_reservation_released UNIT_ATTENTION, 0x2A, 0x04
+#define scst_sense_registrations_preempted UNIT_ATTENTION, 0x2A, 0x05
+#define scst_sense_reported_luns_data_changed UNIT_ATTENTION, 0x3F, 0xE
+#define scst_sense_inquery_data_changed UNIT_ATTENTION, 0x3F, 0x3
+
+/*************************************************************
+ * SCSI opcodes not listed anywhere else
+ *************************************************************/
+#define REPORT_DEVICE_IDENTIFIER 0xA3
+#define INIT_ELEMENT_STATUS 0x07
+#define INIT_ELEMENT_STATUS_RANGE 0x37
+#define PREVENT_ALLOW_MEDIUM 0x1E
+#define READ_ATTRIBUTE 0x8C
+#define REQUEST_VOLUME_ADDRESS 0xB5
+#define WRITE_ATTRIBUTE 0x8D
+#define WRITE_VERIFY_16 0x8E
+#define VERIFY_6 0x13
+#ifndef VERIFY_12
+#define VERIFY_12 0xAF
+#endif
+
+
+/*************************************************************
+ ** SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
+ ** T10/1561-D Revision 4 Draft dated 7th November 2002.
+ *************************************************************/
+#define SAM_STAT_GOOD 0x00
+#define SAM_STAT_CHECK_CONDITION 0x02
+#define SAM_STAT_CONDITION_MET 0x04
+#define SAM_STAT_BUSY 0x08
+#define SAM_STAT_INTERMEDIATE 0x10
+#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14
+#define SAM_STAT_RESERVATION_CONFLICT 0x18
+#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */
+#define SAM_STAT_TASK_SET_FULL 0x28
+#define SAM_STAT_ACA_ACTIVE 0x30
+#define SAM_STAT_TASK_ABORTED 0x40
+
+/*************************************************************
+ ** Control byte field in CDB
+ *************************************************************/
+#define CONTROL_BYTE_LINK_BIT 0x01
+#define CONTROL_BYTE_NACA_BIT 0x04
+
+/*************************************************************
+ ** Byte 1 in INQUIRY CDB
+ *************************************************************/
+#define SCST_INQ_EVPD 0x01
+
+/*************************************************************
+ ** Byte 3 in Standard INQUIRY data
+ *************************************************************/
+#define SCST_INQ_BYTE3 3
+
+#define SCST_INQ_NORMACA_BIT 0x20
+
+/*************************************************************
+ ** Byte 2 in RESERVE_10 CDB
+ *************************************************************/
+#define SCST_RES_3RDPTY 0x10
+#define SCST_RES_LONGID 0x02
+
+/*************************************************************
+ ** Values for the control mode page TST field
+ *************************************************************/
+#define SCST_CONTR_MODE_ONE_TASK_SET 0
+#define SCST_CONTR_MODE_SEP_TASK_SETS 1
+
+/*******************************************************************
+ ** Values for the control mode page QUEUE ALGORITHM MODIFIER field
+ *******************************************************************/
+#define SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER 0
+#define SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER 1
+
+/*************************************************************
+ ** Values for the control mode page D_SENSE field
+ *************************************************************/
+#define SCST_CONTR_MODE_FIXED_SENSE 0
+#define SCST_CONTR_MODE_DESCR_SENSE 1
+
+/*************************************************************
+ ** TransportID protocol identifiers
+ *************************************************************/
+
+#define SCSI_TRANSPORTID_PROTOCOLID_FCP2 0
+#define SCSI_TRANSPORTID_PROTOCOLID_SPI5 1
+#define SCSI_TRANSPORTID_PROTOCOLID_SRP 4
+#define SCSI_TRANSPORTID_PROTOCOLID_ISCSI 5
+#define SCSI_TRANSPORTID_PROTOCOLID_SAS 6
+
+/*************************************************************
+ ** Misc SCSI constants
+ *************************************************************/
+#define SCST_SENSE_ASC_UA_RESET 0x29
+#define BYTCHK 0x02
+#define POSITION_LEN_SHORT 20
+#define POSITION_LEN_LONG 32
+
+/*************************************************************
+ ** Various timeouts
+ *************************************************************/
+#define SCST_DEFAULT_TIMEOUT (60 * HZ)
+
+#define SCST_GENERIC_CHANGER_TIMEOUT (3 * HZ)
+#define SCST_GENERIC_CHANGER_LONG_TIMEOUT (14000 * HZ)
+
+#define SCST_GENERIC_PROCESSOR_TIMEOUT (3 * HZ)
+#define SCST_GENERIC_PROCESSOR_LONG_TIMEOUT (14000 * HZ)
+
+#define SCST_GENERIC_TAPE_SMALL_TIMEOUT (3 * HZ)
+#define SCST_GENERIC_TAPE_REG_TIMEOUT (900 * HZ)
+#define SCST_GENERIC_TAPE_LONG_TIMEOUT (14000 * HZ)
+
+#define SCST_GENERIC_MODISK_SMALL_TIMEOUT (3 * HZ)
+#define SCST_GENERIC_MODISK_REG_TIMEOUT (900 * HZ)
+#define SCST_GENERIC_MODISK_LONG_TIMEOUT (14000 * HZ)
+
+#define SCST_GENERIC_DISK_SMALL_TIMEOUT (3 * HZ)
+#define SCST_GENERIC_DISK_REG_TIMEOUT (60 * HZ)
+#define SCST_GENERIC_DISK_LONG_TIMEOUT (3600 * HZ)
+
+#define SCST_GENERIC_RAID_TIMEOUT (3 * HZ)
+#define SCST_GENERIC_RAID_LONG_TIMEOUT (14000 * HZ)
+
+#define SCST_GENERIC_CDROM_SMALL_TIMEOUT (3 * HZ)
+#define SCST_GENERIC_CDROM_REG_TIMEOUT (900 * HZ)
+#define SCST_GENERIC_CDROM_LONG_TIMEOUT (14000 * HZ)
+
+#define SCST_MAX_OTHER_TIMEOUT (14000 * HZ)
+
+/*************************************************************
+ ** I/O grouping attribute string values. Must match constants
+ ** w/o '_STR' suffix!
+ *************************************************************/
+#define SCST_IO_GROUPING_AUTO_STR "auto"
+#define SCST_IO_GROUPING_THIS_GROUP_ONLY_STR "this_group_only"
+#define SCST_IO_GROUPING_NEVER_STR "never"
+
+/*************************************************************
+ ** Threads pool type attribute string values.
+ ** Must match scst_dev_type_threads_pool_type!
+ *************************************************************/
+#define SCST_THREADS_POOL_PER_INITIATOR_STR "per_initiator"
+#define SCST_THREADS_POOL_SHARED_STR "shared"
+
+/*************************************************************
+ ** Misc constants
+ *************************************************************/
+#define SCST_SYSFS_BLOCK_SIZE PAGE_SIZE
+
+#define SCST_PR_DIR "/var/lib/scst/pr"
+
+#define TID_COMMON_SIZE 24
+
+#define SCST_SYSFS_KEY_MARK "[key]"
+
+#define SCST_MIN_REL_TGT_ID 1
+#define SCST_MAX_REL_TGT_ID 65535
+
+#endif /* __SCST_CONST_H */
diff -uprN orig/linux-2.6.35/include/scst/scst.h linux-2.6.35/include/scst/scst.h
--- orig/linux-2.6.35/include/scst/scst.h
+++ linux-2.6.35/include/scst/scst.h
@@ -0,0 +1,3642 @@
+/*
+ * include/scst.h
+ *
+ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
+ * Copyright (C) 2004 - 2005 Leonid Stoljar
+ * Copyright (C) 2007 - 2010 ID7 Ltd.
+ *
+ * Main SCSI target mid-level include file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SCST_H
+#define __SCST_H
+
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/blkdev.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/cpumask.h>
+
+
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi.h>
+
+#include <scst/scst_const.h>
+
+#include <scst/scst_sgv.h>
+
+/*
+ * Version numbers, the same as for the kernel.
+ *
+ * Changing it don't forget to change SCST_FIO_REV in scst_vdisk.c
+ * and FIO_REV in usr/fileio/common.h as well.
+ */
+#define SCST_VERSION(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + d)
+#define SCST_VERSION_CODE SCST_VERSION(2, 0, 0, 0)
+#define SCST_VERSION_STRING_SUFFIX
+#define SCST_VERSION_STRING "2.1.0-pre1" SCST_VERSION_STRING_SUFFIX
+#define SCST_INTERFACE_VERSION \
+ SCST_VERSION_STRING "$Revision: 2324 $" SCST_CONST_VERSION
+
+#define SCST_LOCAL_NAME "scst_local"
+
+/*************************************************************
+ ** States of command processing state machine. At first,
+ ** "active" states, then - "passive" ones. This is to have
+ ** more efficient generated code of the corresponding
+ ** "switch" statements.
+ *************************************************************/
+
+/* Internal parsing */
+#define SCST_CMD_STATE_PRE_PARSE 0
+
+/* Dev handler's parse() is going to be called */
+#define SCST_CMD_STATE_DEV_PARSE 1
+
+/* Allocation of the cmd's data buffer */
+#define SCST_CMD_STATE_PREPARE_SPACE 2
+
+/* Calling preprocessing_done() */
+#define SCST_CMD_STATE_PREPROCESSING_DONE 3
+
+/* Target driver's rdy_to_xfer() is going to be called */
+#define SCST_CMD_STATE_RDY_TO_XFER 4
+
+/* Target driver's pre_exec() is going to be called */
+#define SCST_CMD_STATE_TGT_PRE_EXEC 5
+
+/* Cmd is going to be sent for execution */
+#define SCST_CMD_STATE_SEND_FOR_EXEC 6
+
+/* Cmd is being checked if it should be executed locally */
+#define SCST_CMD_STATE_LOCAL_EXEC 7
+
+/* Cmd is ready for execution */
+#define SCST_CMD_STATE_REAL_EXEC 8
+
+/* Internal post-exec checks */
+#define SCST_CMD_STATE_PRE_DEV_DONE 9
+
+/* Internal MODE SELECT pages related checks */
+#define SCST_CMD_STATE_MODE_SELECT_CHECKS 10
+
+/* Dev handler's dev_done() is going to be called */
+#define SCST_CMD_STATE_DEV_DONE 11
+
+/* Target driver's xmit_response() is going to be called */
+#define SCST_CMD_STATE_PRE_XMIT_RESP 12
+
+/* Target driver's xmit_response() is going to be called */
+#define SCST_CMD_STATE_XMIT_RESP 13
+
+/* Cmd finished */
+#define SCST_CMD_STATE_FINISHED 14
+
+/* Internal cmd finished */
+#define SCST_CMD_STATE_FINISHED_INTERNAL 15
+
+#define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED_INTERNAL+100)
+
+/* A cmd is created, but scst_cmd_init_done() not called */
+#define SCST_CMD_STATE_INIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+1)
+
+/* LUN translation (cmd->tgt_dev assignment) */
+#define SCST_CMD_STATE_INIT (SCST_CMD_STATE_LAST_ACTIVE+2)
+
+/* Waiting for scst_restart_cmd() */
+#define SCST_CMD_STATE_PREPROCESSING_DONE_CALLED (SCST_CMD_STATE_LAST_ACTIVE+3)
+
+/* Waiting for data from the initiator (until scst_rx_data() called) */
+#define SCST_CMD_STATE_DATA_WAIT (SCST_CMD_STATE_LAST_ACTIVE+4)
+
+/* Waiting for CDB's execution finish */
+#define SCST_CMD_STATE_REAL_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+5)
+
+/* Waiting for response's transmission finish */
+#define SCST_CMD_STATE_XMIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+6)
+
+/*************************************************************
+ * Can be retuned instead of cmd's state by dev handlers'
+ * functions, if the command's state should be set by default
+ *************************************************************/
+#define SCST_CMD_STATE_DEFAULT 500
+
+/*************************************************************
+ * Can be retuned instead of cmd's state by dev handlers'
+ * functions, if it is impossible to complete requested
+ * task in atomic context. The cmd will be restarted in thread
+ * context.
+ *************************************************************/
+#define SCST_CMD_STATE_NEED_THREAD_CTX 1000
+
+/*************************************************************
+ * Can be retuned instead of cmd's state by dev handlers'
+ * parse function, if the cmd processing should be stopped
+ * for now. The cmd will be restarted by dev handlers itself.
+ *************************************************************/
+#define SCST_CMD_STATE_STOP 1001
+
+/*************************************************************
+ ** States of mgmt command processing state machine
+ *************************************************************/
+
+/* LUN translation (mcmd->tgt_dev assignment) */
+#define SCST_MCMD_STATE_INIT 0
+
+/* Mgmt cmd is being processed */
+#define SCST_MCMD_STATE_EXEC 1
+
+/* Waiting for affected commands done */
+#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE 2
+
+/* Post actions when affected commands done */
+#define SCST_MCMD_STATE_AFFECTED_CMDS_DONE 3
+
+/* Waiting for affected local commands finished */
+#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED 4
+
+/* Target driver's task_mgmt_fn_done() is going to be called */
+#define SCST_MCMD_STATE_DONE 5
+
+/* The mcmd finished */
+#define SCST_MCMD_STATE_FINISHED 6
+
+/*************************************************************
+ ** Constants for "atomic" parameter of SCST's functions
+ *************************************************************/
+#define SCST_NON_ATOMIC 0
+#define SCST_ATOMIC 1
+
+/*************************************************************
+ ** Values for pref_context parameter of scst_cmd_init_done(),
+ ** scst_rx_data(), scst_restart_cmd(), scst_tgt_cmd_done()
+ ** and scst_cmd_done()
+ *************************************************************/
+
+enum scst_exec_context {
+ /*
+ * Direct cmd's processing (i.e. regular function calls in the current
+ * context) sleeping is not allowed
+ */
+ SCST_CONTEXT_DIRECT_ATOMIC,
+
+ /*
+ * Direct cmd's processing (i.e. regular function calls in the current
+ * context), sleeping is allowed, no restrictions
+ */
+ SCST_CONTEXT_DIRECT,
+
+ /* Tasklet or thread context required for cmd's processing */
+ SCST_CONTEXT_TASKLET,
+
+ /* Thread context required for cmd's processing */
+ SCST_CONTEXT_THREAD,
+
+ /*
+ * Context is the same as it was in previous call of the corresponding
+ * callback. For example, if dev handler's exec() does sync. data
+ * reading this value should be used for scst_cmd_done(). The same is
+ * true if scst_tgt_cmd_done() called directly from target driver's
+ * xmit_response(). Not allowed in scst_cmd_init_done() and
+ * scst_cmd_init_stage1_done().
+ */
+ SCST_CONTEXT_SAME
+};
+
+/*************************************************************
+ ** Values for status parameter of scst_rx_data()
+ *************************************************************/
+
+/* Success */
+#define SCST_RX_STATUS_SUCCESS 0
+
+/*
+ * Data receiving finished with error, so set the sense and
+ * finish the command, including xmit_response() call
+ */
+#define SCST_RX_STATUS_ERROR 1
+
+/*
+ * Data receiving finished with error and the sense is set,
+ * so finish the command, including xmit_response() call
+ */
+#define SCST_RX_STATUS_ERROR_SENSE_SET 2
+
+/*
+ * Data receiving finished with fatal error, so finish the command,
+ * but don't call xmit_response()
+ */
+#define SCST_RX_STATUS_ERROR_FATAL 3
+
+/*************************************************************
+ ** Values for status parameter of scst_restart_cmd()
+ *************************************************************/
+
+/* Success */
+#define SCST_PREPROCESS_STATUS_SUCCESS 0
+
+/*
+ * Command's processing finished with error, so set the sense and
+ * finish the command, including xmit_response() call
+ */
+#define SCST_PREPROCESS_STATUS_ERROR 1
+
+/*
+ * Command's processing finished with error and the sense is set,
+ * so finish the command, including xmit_response() call
+ */
+#define SCST_PREPROCESS_STATUS_ERROR_SENSE_SET 2
+
+/*
+ * Command's processing finished with fatal error, so finish the command,
+ * but don't call xmit_response()
+ */
+#define SCST_PREPROCESS_STATUS_ERROR_FATAL 3
+
+/*************************************************************
+ ** Values for AEN functions
+ *************************************************************/
+
+/*
+ * SCSI Asynchronous Event. Parameter contains SCSI sense
+ * (Unit Attention). AENs generated only for 2 the following UAs:
+ * CAPACITY DATA HAS CHANGED and REPORTED LUNS DATA HAS CHANGED.
+ * Other UAs reported regularly as CHECK CONDITION status,
+ * because it doesn't look safe to report them using AENs, since
+ * reporting using AENs opens delivery race windows even in case of
+ * untagged commands.
+ */
+#define SCST_AEN_SCSI 0
+
+/*
+ * Notifies that CPU affinity mask on the corresponding session changed
+ */
+#define SCST_AEN_CPU_MASK_CHANGED 1
+
+/*************************************************************
+ ** Allowed return/status codes for report_aen() callback and
+ ** scst_set_aen_delivery_status() function
+ *************************************************************/
+
+/* Success */
+#define SCST_AEN_RES_SUCCESS 0
+
+/* Not supported */
+#define SCST_AEN_RES_NOT_SUPPORTED -1
+
+/* Failure */
+#define SCST_AEN_RES_FAILED -2
+
+/*************************************************************
+ ** Allowed return codes for xmit_response(), rdy_to_xfer()
+ *************************************************************/
+
+/* Success */
+#define SCST_TGT_RES_SUCCESS 0
+
+/* Internal device queue is full, retry again later */
+#define SCST_TGT_RES_QUEUE_FULL -1
+
+/*
+ * It is impossible to complete requested task in atomic context.
+ * The cmd will be restarted in thread context.
+ */
+#define SCST_TGT_RES_NEED_THREAD_CTX -2
+
+/*
+ * Fatal error, if returned by xmit_response() the cmd will
+ * be destroyed, if by any other function, xmit_response()
+ * will be called with HARDWARE ERROR sense data
+ */
+#define SCST_TGT_RES_FATAL_ERROR -3
+
+/*************************************************************
+ ** Allowed return codes for dev handler's exec()
+ *************************************************************/
+
+/* The cmd is done, go to other ones */
+#define SCST_EXEC_COMPLETED 0
+
+/* The cmd should be sent to SCSI mid-level */
+#define SCST_EXEC_NOT_COMPLETED 1
+
+/*
+ * Set if cmd is finished and there is status/sense to be sent.
+ * The status should be not sent (i.e. the flag not set) if the
+ * possibility to perform a command in "chunks" (i.e. with multiple
+ * xmit_response()/rdy_to_xfer()) is used (not implemented yet).
+ * Obsolete, use scst_cmd_get_is_send_status() instead.
+ */
+#define SCST_TSC_FLAG_STATUS 0x2
+
+/*************************************************************
+ ** Additional return code for dev handler's task_mgmt_fn()
+ *************************************************************/
+
+/* Regular standard actions for the command should be done */
+#define SCST_DEV_TM_NOT_COMPLETED 1
+
+/*************************************************************
+ ** Session initialization phases
+ *************************************************************/
+
+/* Set if session is being initialized */
+#define SCST_SESS_IPH_INITING 0
+
+/* Set if the session is successfully initialized */
+#define SCST_SESS_IPH_SUCCESS 1
+
+/* Set if the session initialization failed */
+#define SCST_SESS_IPH_FAILED 2
+
+/* Set if session is initialized and ready */
+#define SCST_SESS_IPH_READY 3
+
+/*************************************************************
+ ** Session shutdown phases
+ *************************************************************/
+
+/* Set if session is initialized and ready */
+#define SCST_SESS_SPH_READY 0
+
+/* Set if session is shutting down */
+#define SCST_SESS_SPH_SHUTDOWN 1
+
+/* Set if session is shutting down */
+#define SCST_SESS_SPH_UNREG_DONE_CALLING 2
+
+/*************************************************************
+ ** Session's async (atomic) flags
+ *************************************************************/
+
+/* Set if the sess's hw pending work is scheduled */
+#define SCST_SESS_HW_PENDING_WORK_SCHEDULED 0
+
+/*************************************************************
+ ** Cmd's async (atomic) flags
+ *************************************************************/
+
+/* Set if the cmd is aborted and ABORTED sense will be sent as the result */
+#define SCST_CMD_ABORTED 0
+
+/* Set if the cmd is aborted by other initiator */
+#define SCST_CMD_ABORTED_OTHER 1
+
+/* Set if no response should be sent to the target about this cmd */
+#define SCST_CMD_NO_RESP 2
+
+/* Set if the cmd is dead and can be destroyed at any time */
+#define SCST_CMD_CAN_BE_DESTROYED 3
+
+/*
+ * Set if the cmd's device has TAS flag set. Used only when aborted by
+ * other initiator.
+ */
+#define SCST_CMD_DEVICE_TAS 4
+
+/*************************************************************
+ ** Tgt_dev's async. flags (tgt_dev_flags)
+ *************************************************************/
+
+/* Set if tgt_dev has Unit Attention sense */
+#define SCST_TGT_DEV_UA_PENDING 0
+
+/* Set if tgt_dev is RESERVED by another session */
+#define SCST_TGT_DEV_RESERVED 1
+
+/* Set if the corresponding context is atomic */
+#define SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC 5
+#define SCST_TGT_DEV_AFTER_EXEC_ATOMIC 6
+
+#define SCST_TGT_DEV_CLUST_POOL 11
+
+/*************************************************************
+ ** I/O groupping types. Changing them don't forget to change
+ ** the corresponding *_STR values in scst_const.h!
+ *************************************************************/
+
+/*
+ * All initiators with the same name connected to this group will have
+ * shared IO context, for each name own context. All initiators with
+ * different names will have own IO context.
+ */
+#define SCST_IO_GROUPING_AUTO 0
+
+/* All initiators connected to this group will have shared IO context */
+#define SCST_IO_GROUPING_THIS_GROUP_ONLY -1
+
+/* Each initiator connected to this group will have own IO context */
+#define SCST_IO_GROUPING_NEVER -2
+
+/*************************************************************
+ ** Kernel cache creation helper
+ *************************************************************/
+#ifndef KMEM_CACHE
+#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
+ sizeof(struct __struct), __alignof__(struct __struct),\
+ (__flags), NULL, NULL)
+#endif
+
+/*************************************************************
+ ** Vlaid_mask constants for scst_analyze_sense()
+ *************************************************************/
+
+#define SCST_SENSE_KEY_VALID 1
+#define SCST_SENSE_ASC_VALID 2
+#define SCST_SENSE_ASCQ_VALID 4
+
+#define SCST_SENSE_ASCx_VALID (SCST_SENSE_ASC_VALID | \
+ SCST_SENSE_ASCQ_VALID)
+
+#define SCST_SENSE_ALL_VALID (SCST_SENSE_KEY_VALID | \
+ SCST_SENSE_ASC_VALID | \
+ SCST_SENSE_ASCQ_VALID)
+
+/*************************************************************
+ * TYPES
+ *************************************************************/
+
+struct scst_tgt;
+struct scst_session;
+struct scst_cmd;
+struct scst_mgmt_cmd;
+struct scst_device;
+struct scst_tgt_dev;
+struct scst_dev_type;
+struct scst_acg;
+struct scst_acg_dev;
+struct scst_acn;
+struct scst_aen;
+
+/*
+ * SCST uses 64-bit numbers to represent LUN's internally. The value
+ * NO_SUCH_LUN is guaranteed to be different of every valid LUN.
+ */
+#define NO_SUCH_LUN ((uint64_t)-1)
+
+typedef enum dma_data_direction scst_data_direction;
+
+/*
+ * SCST target template: defines target driver's parameters and callback
+ * functions.
+ *
+ * MUST HAVEs define functions that are expected to be defined in order to
+ * work. OPTIONAL says that there is a choice.
+ */
+struct scst_tgt_template {
+ /* public: */
+
+ /*
+ * SG tablesize allows to check whether scatter/gather can be used
+ * or not.
+ */
+ int sg_tablesize;
+
+ /*
+ * True, if this target adapter uses unchecked DMA onto an ISA bus.
+ */
+ unsigned unchecked_isa_dma:1;
+
+ /*
+ * True, if this target adapter can benefit from using SG-vector
+ * clustering (i.e. smaller number of segments).
+ */
+ unsigned use_clustering:1;
+
+ /*
+ * True, if this target adapter doesn't support SG-vector clustering
+ */
+ unsigned no_clustering:1;
+
+ /*
+ * True, if corresponding function supports execution in
+ * the atomic (non-sleeping) context
+ */
+ unsigned xmit_response_atomic:1;
+ unsigned rdy_to_xfer_atomic:1;
+
+ /* True, if this target doesn't need "enabled" attribute */
+ unsigned enabled_attr_not_needed:1;
+
+ /*
+ * The maximum time in seconds cmd can stay inside the target
+ * hardware, i.e. after rdy_to_xfer() and xmit_response(), before
+ * on_hw_pending_cmd_timeout() will be called, if defined.
+ *
+ * In the current implementation a cmd will be aborted in time t
+ * max_hw_pending_time <= t < 2*max_hw_pending_time.
+ */
+ int max_hw_pending_time;
+
+ /*
+ * This function is equivalent to the SCSI
+ * queuecommand. The target should transmit the response
+ * buffer and the status in the scst_cmd struct.
+ * The expectation is that this executing this command is NON-BLOCKING.
+ * If it is blocking, consider to set threads_num to some none 0 number.
+ *
+ * After the response is actually transmitted, the target
+ * should call the scst_tgt_cmd_done() function of the
+ * mid-level, which will allow it to free up the command.
+ * Returns one of the SCST_TGT_RES_* constants.
+ *
+ * Pay attention to "atomic" attribute of the cmd, which can be get
+ * by scst_cmd_atomic(): it is true if the function called in the
+ * atomic (non-sleeping) context.
+ *
+ * MUST HAVE
+ */
+ int (*xmit_response) (struct scst_cmd *cmd);
+
+ /*
+ * This function informs the driver that data
+ * buffer corresponding to the said command have now been
+ * allocated and it is OK to receive data for this command.
+ * This function is necessary because a SCSI target does not
+ * have any control over the commands it receives. Most lower
+ * level protocols have a corresponding function which informs
+ * the initiator that buffers have been allocated e.g., XFER_
+ * RDY in Fibre Channel. After the data is actually received
+ * the low-level driver needs to call scst_rx_data() in order to
+ * continue processing this command.
+ * Returns one of the SCST_TGT_RES_* constants.
+ *
+ * This command is expected to be NON-BLOCKING.
+ * If it is blocking, consider to set threads_num to some none 0 number.
+ *
+ * Pay attention to "atomic" attribute of the cmd, which can be get
+ * by scst_cmd_atomic(): it is true if the function called in the
+ * atomic (non-sleeping) context.
+ *
+ * OPTIONAL
+ */
+ int (*rdy_to_xfer) (struct scst_cmd *cmd);
+
+ /*
+ * Called if cmd stays inside the target hardware, i.e. after
+ * rdy_to_xfer() and xmit_response(), more than max_hw_pending_time
+ * time. The target driver supposed to cleanup this command and
+ * resume cmd's processing.
+ *
+ * OPTIONAL
+ */
+ void (*on_hw_pending_cmd_timeout) (struct scst_cmd *cmd);
+
+ /*
+ * Called to notify the driver that the command is about to be freed.
+ * Necessary, because for aborted commands xmit_response() could not
+ * be called. Could be called on IRQ context.
+ *
+ * OPTIONAL
+ */
+ void (*on_free_cmd) (struct scst_cmd *cmd);
+
+ /*
+ * This function allows target driver to handle data buffer
+ * allocations on its own.
+ *
+ * Target driver doesn't have to always allocate buffer in this
+ * function, but if it decide to do it, it must check that
+ * scst_cmd_get_data_buff_alloced() returns 0, otherwise to avoid
+ * double buffer allocation and memory leaks alloc_data_buf() shall
+ * fail.
+ *
+ * Shall return 0 in case of success or < 0 (preferrably -ENOMEM)
+ * in case of error, or > 0 if the regular SCST allocation should be
+ * done. In case of returning successfully,
+ * scst_cmd->tgt_data_buf_alloced will be set by SCST.
+ *
+ * It is possible that both target driver and dev handler request own
+ * memory allocation. In this case, data will be memcpy() between
+ * buffers, where necessary.
+ *
+ * If allocation in atomic context - cf. scst_cmd_atomic() - is not
+ * desired or fails and consequently < 0 is returned, this function
+ * will be re-called in thread context.
+ *
+ * Please note that the driver will have to handle itself all relevant
+ * details such as scatterlist setup, highmem, freeing the allocated
+ * memory, etc.
+ *
+ * OPTIONAL.
+ */
+ int (*alloc_data_buf) (struct scst_cmd *cmd);
+
+ /*
+ * This function informs the driver that data
+ * buffer corresponding to the said command have now been
+ * allocated and other preprocessing tasks have been done.
+ * A target driver could need to do some actions at this stage.
+ * After the target driver done the needed actions, it shall call
+ * scst_restart_cmd() in order to continue processing this command.
+ * In case of preliminary the command completion, this function will
+ * also be called before xmit_response().
+ *
+ * Called only if the cmd is queued using scst_cmd_init_stage1_done()
+ * instead of scst_cmd_init_done().
+ *
+ * Returns void, the result is expected to be returned using
+ * scst_restart_cmd().
+ *
+ * This command is expected to be NON-BLOCKING.
+ * If it is blocking, consider to set threads_num to some none 0 number.
+ *
+ * Pay attention to "atomic" attribute of the cmd, which can be get
+ * by scst_cmd_atomic(): it is true if the function called in the
+ * atomic (non-sleeping) context.
+ *
+ * OPTIONAL.
+ */
+ void (*preprocessing_done) (struct scst_cmd *cmd);
+
+ /*
+ * This function informs the driver that the said command is about
+ * to be executed.
+ *
+ * Returns one of the SCST_PREPROCESS_* constants.
+ *
+ * This command is expected to be NON-BLOCKING.
+ * If it is blocking, consider to set threads_num to some none 0 number.
+ *
+ * OPTIONAL
+ */
+ int (*pre_exec) (struct scst_cmd *cmd);
+
+ /*
+ * This function informs the driver that all affected by the
+ * corresponding task management function commands have beed completed.
+ * No return value expected.
+ *
+ * This function is expected to be NON-BLOCKING.
+ *
+ * Called without any locks held from a thread context.
+ *
+ * OPTIONAL
+ */
+ void (*task_mgmt_affected_cmds_done) (struct scst_mgmt_cmd *mgmt_cmd);
+
+ /*
+ * This function informs the driver that the corresponding task
+ * management function has been completed, i.e. all the corresponding
+ * commands completed and freed. No return value expected.
+ *
+ * This function is expected to be NON-BLOCKING.
+ *
+ * Called without any locks held from a thread context.
+ *
+ * MUST HAVE if the target supports task management.
+ */
+ void (*task_mgmt_fn_done) (struct scst_mgmt_cmd *mgmt_cmd);
+
+ /*
+ * This function should detect the target adapters that
+ * are present in the system. The function should return a value
+ * >= 0 to signify the number of detected target adapters.
+ * A negative value should be returned whenever there is
+ * an error.
+ *
+ * MUST HAVE
+ */
+ int (*detect) (struct scst_tgt_template *tgt_template);
+
+ /*
+ * This function should free up the resources allocated to the device.
+ * The function should return 0 to indicate successful release
+ * or a negative value if there are some issues with the release.
+ * In the current version the return value is ignored.
+ *
+ * MUST HAVE
+ */
+ int (*release) (struct scst_tgt *tgt);
+
+ /*
+ * This function is used for Asynchronous Event Notifications.
+ *
+ * Returns one of the SCST_AEN_RES_* constants.
+ * After AEN is sent, target driver must call scst_aen_done() and,
+ * optionally, scst_set_aen_delivery_status().
+ *
+ * This function is expected to be NON-BLOCKING, but can sleep.
+ *
+ * This function must be prepared to handle AENs between calls for the
+ * corresponding session of scst_unregister_session() and
+ * unreg_done_fn() callback called or before scst_unregister_session()
+ * returned, if its called in the blocking mode. AENs for such sessions
+ * should be ignored.
+ *
+ * MUST HAVE, if low-level protocol supports AENs.
+ */
+ int (*report_aen) (struct scst_aen *aen);
+
+ /*
+ * This function returns in tr_id the corresponding to sess initiator
+ * port TransporID in the form as it's used by PR commands, see
+ * "Transport Identifiers" in SPC. Space for the initiator port
+ * TransporID must be allocated via kmalloc(). Caller supposed to
+ * kfree() it, when it isn't needed anymore.
+ *
+ * If sess is NULL, this function must return TransportID PROTOCOL
+ * IDENTIFIER of this transport.
+ *
+ * Returns 0 on success or negative error code otherwise.
+ *
+ * SHOULD HAVE, because it's required for Persistent Reservations.
+ */
+ int (*get_initiator_port_transport_id) (struct scst_session *sess,
+ uint8_t **transport_id);
+
+ /*
+ * This function allows to enable or disable particular target.
+ * A disabled target doesn't receive and process any SCSI commands.
+ *
+ * SHOULD HAVE to avoid race when there are connected initiators,
+ * while target not yet completed the initial configuration. In this
+ * case the too early connected initiators would see not those devices,
+ * which they intended to see.
+ *
+ * If you are sure your target driver doesn't need enabling target,
+ * you should set enabled_attr_not_needed in 1.
+ */
+ int (*enable_target) (struct scst_tgt *tgt, bool enable);
+
+ /*
+ * This function shows if particular target is enabled or not.
+ *
+ * SHOULD HAVE, see above why.
+ */
+ bool (*is_target_enabled) (struct scst_tgt *tgt);
+
+ /*
+ * This function adds a virtual target.
+ *
+ * If both add_target and del_target callbacks defined, then this
+ * target driver supposed to support virtual targets. In this case
+ * an "mgmt" entry will be created in the sysfs root for this driver.
+ * The "mgmt" entry will support 2 commands: "add_target" and
+ * "del_target", for which the corresponding callbacks will be called.
+ * Also target driver can define own commands for the "mgmt" entry, see
+ * mgmt_cmd and mgmt_cmd_help below.
+ *
+ * This approach allows uniform targets management to simplify external
+ * management tools like scstadmin. See README for more details.
+ *
+ * Either both add_target and del_target must be defined, or none.
+ *
+ * MUST HAVE if virtual targets are supported.
+ */
+ ssize_t (*add_target) (const char *target_name, char *params);
+
+ /*
+ * This function deletes a virtual target. See comment for add_target
+ * above.
+ *
+ * MUST HAVE if virtual targets are supported.
+ */
+ ssize_t (*del_target) (const char *target_name);
+
+ /*
+ * This function called if not "add_target" or "del_target" command is
+ * sent to the mgmt entry (see comment for add_target above). In this
+ * case the command passed to this function as is in a string form.
+ *
+ * OPTIONAL.
+ */
+ ssize_t (*mgmt_cmd) (char *cmd);
+
+ /*
+ * Should return physical transport version. Used in the corresponding
+ * INQUIRY version descriptor. See SPC for the list of available codes.
+ *
+ * OPTIONAL
+ */
+ uint16_t (*get_phys_transport_version) (struct scst_tgt *tgt);
+
+ /*
+ * Should return SCSI transport version. Used in the corresponding
+ * INQUIRY version descriptor. See SPC for the list of available codes.
+ *
+ * OPTIONAL
+ */
+ uint16_t (*get_scsi_transport_version) (struct scst_tgt *tgt);
+
+ /*
+ * Name of the template. Must be unique to identify
+ * the template. MUST HAVE
+ */
+ const char name[SCST_MAX_NAME];
+
+ /*
+ * Number of additional threads to the pool of dedicated threads.
+ * Used if xmit_response() or rdy_to_xfer() is blocking.
+ * It is the target driver's duty to ensure that not more, than that
+ * number of threads, are blocked in those functions at any time.
+ */
+ int threads_num;
+
+ /* Optional default log flags */
+ const unsigned long default_trace_flags;
+
+ /* Optional pointer to trace flags */
+ unsigned long *trace_flags;
+
+ /* Optional local trace table */
+ struct scst_trace_log *trace_tbl;
+
+ /* Optional local trace table help string */
+ const char *trace_tbl_help;
+
+ /* sysfs attributes, if any */
+ const struct attribute **tgtt_attrs;
+
+ /* sysfs target attributes, if any */
+ const struct attribute **tgt_attrs;
+
+ /* sysfs session attributes, if any */
+ const struct attribute **sess_attrs;
+
+ /* Optional help string for mgmt_cmd commands */
+ const char *mgmt_cmd_help;
+
+ /* List of parameters for add_target command, if any */
+ const char *add_target_parameters;
+
+ /*
+ * List of optional, i.e. which could be added by add_attribute command
+ * and deleted by del_attribute command, sysfs attributes, if any.
+ * Helpful for scstadmin to work correctly.
+ */
+ const char *tgtt_optional_attributes;
+
+ /*
+ * List of optional, i.e. which could be added by add_target_attribute
+ * command and deleted by del_target_attribute command, sysfs
+ * attributes, if any. Helpful for scstadmin to work correctly.
+ */
+ const char *tgt_optional_attributes;
+
+ /** Private, must be inited to 0 by memset() **/
+
+ /* List of targets per template, protected by scst_mutex */
+ struct list_head tgt_list;
+
+ /* List entry of global templates list */
+ struct list_head scst_template_list_entry;
+
+ struct kobject tgtt_kobj; /* kobject for this struct */
+
+ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
+ int tgtt_active_sysfs_works_count;
+
+ /* sysfs release completion */
+ struct completion tgtt_kobj_release_cmpl;
+
+};
+
+/*
+ * Threads pool types. Changing them don't forget to change
+ * the corresponding *_STR values in scst_const.h!
+ */
+enum scst_dev_type_threads_pool_type {
+ /* Each initiator will have dedicated threads pool. */
+ SCST_THREADS_POOL_PER_INITIATOR = 0,
+
+ /* All connected initiators will use shared threads pool */
+ SCST_THREADS_POOL_SHARED,
+
+ /* Invalid value for scst_parse_threads_pool_type() */
+ SCST_THREADS_POOL_TYPE_INVALID,
+};
+
+/*
+ * SCST dev handler template: defines dev handler's parameters and callback
+ * functions.
+ *
+ * MUST HAVEs define functions that are expected to be defined in order to
+ * work. OPTIONAL says that there is a choice.
+ */
+struct scst_dev_type {
+ /* SCSI type of the supported device. MUST HAVE */
+ int type;
+
+ /*
+ * True, if corresponding function supports execution in
+ * the atomic (non-sleeping) context
+ */
+ unsigned parse_atomic:1;
+ unsigned alloc_data_buf_atomic:1;
+ unsigned dev_done_atomic:1;
+
+ /*
+ * Should be true, if exec() is synchronous. This is a hint to SCST core
+ * to optimize commands order management.
+ */
+ unsigned exec_sync:1;
+
+ /*
+ * Should be set if the device wants to receive notification of
+ * Persistent Reservation commands (PR OUT only)
+ * Note: The notification will not be send if the command failed
+ */
+ unsigned pr_cmds_notifications:1;
+
+ /*
+ * Called to parse CDB from the cmd and initialize
+ * cmd->bufflen and cmd->data_direction (both - REQUIRED).
+ *
+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
+ * if the next default state should be used, or
+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
+ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the
+ * command should not be further processed for now. In the
+ * SCST_CMD_STATE_NEED_THREAD_CTX case the function
+ * will be recalled in the thread context, where sleeping is allowed.
+ *
+ * Pay attention to "atomic" attribute of the cmd, which can be get
+ * by scst_cmd_atomic(): it is true if the function called in the
+ * atomic (non-sleeping) context.
+ *
+ * MUST HAVE
+ */
+ int (*parse) (struct scst_cmd *cmd);
+
+ /*
+ * This function allows dev handler to handle data buffer
+ * allocations on its own.
+ *
+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
+ * if the next default state should be used, or
+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
+ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the
+ * command should not be further processed for now. In the
+ * SCST_CMD_STATE_NEED_THREAD_CTX case the function
+ * will be recalled in the thread context, where sleeping is allowed.
+ *
+ * Pay attention to "atomic" attribute of the cmd, which can be get
+ * by scst_cmd_atomic(): it is true if the function called in the
+ * atomic (non-sleeping) context.
+ *
+ * OPTIONAL
+ */
+ int (*alloc_data_buf) (struct scst_cmd *cmd);
+
+ /*
+ * Called to execute CDB. Useful, for instance, to implement
+ * data caching. The result of CDB execution is reported via
+ * cmd->scst_cmd_done() callback.
+ * Returns:
+ * - SCST_EXEC_COMPLETED - the cmd is done, go to other ones
+ * - SCST_EXEC_NOT_COMPLETED - the cmd should be sent to SCSI
+ * mid-level.
+ *
+ * If this function provides sync execution, you should set
+ * exec_sync flag and consider to setup dedicated threads by
+ * setting threads_num > 0.
+ *
+ * !! If this function is implemented, scst_check_local_events() !!
+ * !! shall be called inside it just before the actual command's !!
+ * !! execution. !!
+ *
+ * OPTIONAL, if not set, the commands will be sent directly to SCSI
+ * device.
+ */
+ int (*exec) (struct scst_cmd *cmd);
+
+ /*
+ * Called to notify dev handler about the result of cmd execution
+ * and perform some post processing. Cmd's fields is_send_status and
+ * resp_data_len should be set by this function, but SCST offers good
+ * defaults.
+ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
+ * if the next default state should be used, or
+ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
+ * context, but requires sleeping. In the last case, the function
+ * will be recalled in the thread context, where sleeping is allowed.
+ *
+ * Pay attention to "atomic" attribute of the cmd, which can be get
+ * by scst_cmd_atomic(): it is true if the function called in the
+ * atomic (non-sleeping) context.
+ *
+ * OPTIONAL
+ */
+ int (*dev_done) (struct scst_cmd *cmd);
+
+ /*
+ * Called to notify dev hander that the command is about to be freed.
+ *
+ * Could be called on IRQ context.
+ *
+ * OPTIONAL
+ */
+ void (*on_free_cmd) (struct scst_cmd *cmd);
+
+ /*
+ * Called to execute a task management command.
+ * Returns:
+ * - SCST_MGMT_STATUS_SUCCESS - the command is done with success,
+ * no firther actions required
+ * - The SCST_MGMT_STATUS_* error code if the command is failed and
+ * no further actions required
+ * - SCST_DEV_TM_NOT_COMPLETED - regular standard actions for the
+ * command should be done
+ *
+ * Called without any locks held from a thread context.
+ *
+ * OPTIONAL
+ */
+ int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd,
+ struct scst_tgt_dev *tgt_dev);
+
+ /*
+ * Called to notify dev handler that its sg_tablesize is too low to
+ * satisfy this command's data transfer requirements. Should return
+ * true if exec() callback will split this command's CDB on smaller
+ * transfers, false otherwise.
+ *
+ * Could be called on SIRQ context.
+ *
+ * MUST HAVE, if dev handler supports CDB splitting.
+ */
+ bool (*on_sg_tablesize_low) (struct scst_cmd *cmd);
+
+ /*
+ * Called when new device is attaching to the dev handler
+ * Returns 0 on success, error code otherwise.
+ *
+ * OPTIONAL
+ */
+ int (*attach) (struct scst_device *dev);
+
+ /*
+ * Called when a device is detaching from the dev handler.
+ *
+ * OPTIONAL
+ */
+ void (*detach) (struct scst_device *dev);
+
+ /*
+ * Called when new tgt_dev (session) is attaching to the dev handler.
+ * Returns 0 on success, error code otherwise.
+ *
+ * OPTIONAL
+ */
+ int (*attach_tgt) (struct scst_tgt_dev *tgt_dev);
+
+ /*
+ * Called when tgt_dev (session) is detaching from the dev handler.
+ *
+ * OPTIONAL
+ */
+ void (*detach_tgt) (struct scst_tgt_dev *tgt_dev);
+
+ /*
+ * This function adds a virtual device.
+ *
+ * If both add_device and del_device callbacks defined, then this
+ * dev handler supposed to support adding/deleting virtual devices.
+ * In this case an "mgmt" entry will be created in the sysfs root for
+ * this handler. The "mgmt" entry will support 2 commands: "add_device"
+ * and "del_device", for which the corresponding callbacks will be called.
+ * Also dev handler can define own commands for the "mgmt" entry, see
+ * mgmt_cmd and mgmt_cmd_help below.
+ *
+ * This approach allows uniform devices management to simplify external
+ * management tools like scstadmin. See README for more details.
+ *
+ * Either both add_device and del_device must be defined, or none.
+ *
+ * MUST HAVE if virtual devices are supported.
+ */
+ ssize_t (*add_device) (const char *device_name, char *params);
+
+ /*
+ * This function deletes a virtual device. See comment for add_device
+ * above.
+ *
+ * MUST HAVE if virtual devices are supported.
+ */
+ ssize_t (*del_device) (const char *device_name);
+
+ /*
+ * This function called if not "add_device" or "del_device" command is
+ * sent to the mgmt entry (see comment for add_device above). In this
+ * case the command passed to this function as is in a string form.
+ *
+ * OPTIONAL.
+ */
+ ssize_t (*mgmt_cmd) (char *cmd);
+
+ /*
+ * Name of the dev handler. Must be unique. MUST HAVE.
+ *
+ * It's SCST_MAX_NAME + few more bytes to match scst_user expectations.
+ */
+ char name[SCST_MAX_NAME + 10];
+
+ /*
+ * Number of threads in this handler's devices' threads pools.
+ * If 0 - no threads will be created, if <0 - creation of the threads
+ * pools is prohibited. Also pay attention to threads_pool_type below.
+ */
+ int threads_num;
+
+ /* Threads pool type. Valid only if threads_num > 0. */
+ enum scst_dev_type_threads_pool_type threads_pool_type;
+
+ /* Optional default log flags */
+ const unsigned long default_trace_flags;
+
+ /* Optional pointer to trace flags */
+ unsigned long *trace_flags;
+
+ /* Optional local trace table */
+ struct scst_trace_log *trace_tbl;
+
+ /* Optional local trace table help string */
+ const char *trace_tbl_help;
+
+ /* Optional help string for mgmt_cmd commands */
+ const char *mgmt_cmd_help;
+
+ /* List of parameters for add_device command, if any */
+ const char *add_device_parameters;
+
+ /*
+ * List of optional, i.e. which could be added by add_attribute command
+ * and deleted by del_attribute command, sysfs attributes, if any.
+ * Helpful for scstadmin to work correctly.
+ */
+ const char *devt_optional_attributes;
+
+ /*
+ * List of optional, i.e. which could be added by add_device_attribute
+ * command and deleted by del_device_attribute command, sysfs
+ * attributes, if any. Helpful for scstadmin to work correctly.
+ */
+ const char *dev_optional_attributes;
+
+ /* sysfs attributes, if any */
+ const struct attribute **devt_attrs;
+
+ /* sysfs device attributes, if any */
+ const struct attribute **dev_attrs;
+
+ /* Pointer to dev handler's private data */
+ void *devt_priv;
+
+ /* Pointer to parent dev type in the sysfs hierarchy */
+ struct scst_dev_type *parent;
+
+ struct module *module;
+
+ /** Private, must be inited to 0 by memset() **/
+
+ /* list entry in scst_(virtual_)dev_type_list */
+ struct list_head dev_type_list_entry;
+
+ struct kobject devt_kobj; /* main handlers/driver */
+
+ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
+ int devt_active_sysfs_works_count;
+
+ /* To wait until devt_kobj released */
+ struct completion devt_kobj_release_compl;
+};
+
+/*
+ * An SCST target, analog of SCSI target port.
+ */
+struct scst_tgt {
+ /* List of remote sessions per target, protected by scst_mutex */
+ struct list_head sess_list;
+
+ /* List entry of targets per template (tgts_list) */
+ struct list_head tgt_list_entry;
+
+ struct scst_tgt_template *tgtt; /* corresponding target template */
+
+ struct scst_acg *default_acg; /* default acg for this target */
+
+ struct list_head tgt_acg_list; /* target ACG groups */
+
+ /*
+ * Maximum SG table size. Needed here, since different cards on the
+ * same target template can have different SG table limitations.
+ */
+ int sg_tablesize;
+
+ /* Used for storage of target driver private stuff */
+ void *tgt_priv;
+
+ /*
+ * The following fields used to store and retry cmds if target's
+ * internal queue is full, so the target is unable to accept
+ * the cmd returning QUEUE FULL.
+ * They protected by tgt_lock, where necessary.
+ */
+ bool retry_timer_active;
+ struct timer_list retry_timer;
+ atomic_t finished_cmds;
+ int retry_cmds;
+ spinlock_t tgt_lock;
+ struct list_head retry_cmd_list;
+
+ /* Used to wait until session finished to unregister */
+ wait_queue_head_t unreg_waitQ;
+
+ /* Name of the target */
+ char *tgt_name;
+
+ uint16_t rel_tgt_id;
+
+ /* sysfs release completion */
+ struct completion tgt_kobj_release_cmpl;
+
+ struct kobject tgt_kobj; /* main targets/target kobject */
+ struct kobject *tgt_sess_kobj; /* target/sessions/ */
+ struct kobject *tgt_luns_kobj; /* target/luns/ */
+ struct kobject *tgt_ini_grp_kobj; /* target/ini_groups/ */
+};
+
+#ifdef CONFIG_SCST_MEASURE_LATENCY
+
+/* Defines extended latency statistics */
+struct scst_ext_latency_stat {
+ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
+ unsigned int processed_cmds_rd;
+ uint64_t min_scst_time_rd, min_tgt_time_rd, min_dev_time_rd;
+ uint64_t max_scst_time_rd, max_tgt_time_rd, max_dev_time_rd;
+
+ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
+ unsigned int processed_cmds_wr;
+ uint64_t min_scst_time_wr, min_tgt_time_wr, min_dev_time_wr;
+ uint64_t max_scst_time_wr, max_tgt_time_wr, max_dev_time_wr;
+};
+
+#define SCST_IO_SIZE_THRESHOLD_SMALL (8*1024)
+#define SCST_IO_SIZE_THRESHOLD_MEDIUM (32*1024)
+#define SCST_IO_SIZE_THRESHOLD_LARGE (128*1024)
+#define SCST_IO_SIZE_THRESHOLD_VERY_LARGE (512*1024)
+
+#define SCST_LATENCY_STAT_INDEX_SMALL 0
+#define SCST_LATENCY_STAT_INDEX_MEDIUM 1
+#define SCST_LATENCY_STAT_INDEX_LARGE 2
+#define SCST_LATENCY_STAT_INDEX_VERY_LARGE 3
+#define SCST_LATENCY_STAT_INDEX_OTHER 4
+#define SCST_LATENCY_STATS_NUM (SCST_LATENCY_STAT_INDEX_OTHER + 1)
+
+#endif /* CONFIG_SCST_MEASURE_LATENCY */
+
+/*
+ * SCST session, analog of SCSI I_T nexus
+ */
+struct scst_session {
+ /*
+ * Initialization phase, one of SCST_SESS_IPH_* constants, protected by
+ * sess_list_lock
+ */
+ int init_phase;
+
+ struct scst_tgt *tgt; /* corresponding target */
+
+ /* Used for storage of target driver private stuff */
+ void *tgt_priv;
+
+ /* session's async flags */
+ unsigned long sess_aflags;
+
+ /*
+ * Hash list for tgt_dev's for this session with size and fn. It isn't
+ * hlist_entry, because we need ability to go over the list in the
+ * reverse order. Protected by scst_mutex and suspended activity.
+ */
+#define SESS_TGT_DEV_LIST_HASH_SIZE (1 << 5)
+#define SESS_TGT_DEV_LIST_HASH_FN(val) ((val) & (SESS_TGT_DEV_LIST_HASH_SIZE - 1))
+ struct list_head sess_tgt_dev_list[SESS_TGT_DEV_LIST_HASH_SIZE];
+
+ /*
+ * List of cmds in this session. Protected by sess_list_lock.
+ *
+ * We must always keep commands in the sess list from the
+ * very beginning, because otherwise they can be missed during
+ * TM processing.
+ */
+ struct list_head sess_cmd_list;
+
+ spinlock_t sess_list_lock; /* protects sess_cmd_list, etc */
+
+ atomic_t refcnt; /* get/put counter */
+
+ /*
+ * Alive commands for this session. ToDo: make it part of the common
+ * IO flow control.
+ */
+ atomic_t sess_cmd_count;
+
+ /* Access control for this session and list entry there */
+ struct scst_acg *acg;
+
+ /* Initiator port transport id */
+ uint8_t *transport_id;
+
+ /* List entry for the sessions list inside ACG */
+ struct list_head acg_sess_list_entry;
+
+ struct delayed_work hw_pending_work;
+
+ /* Name of attached initiator */
+ const char *initiator_name;
+
+ /* List entry of sessions per target */
+ struct list_head sess_list_entry;
+
+ /* List entry for the list that keeps session, waiting for the init */
+ struct list_head sess_init_list_entry;
+
+ /*
+ * List entry for the list that keeps session, waiting for the shutdown
+ */
+ struct list_head sess_shut_list_entry;
+
+ /*
+ * Lists of deferred during session initialization commands.
+ * Protected by sess_list_lock.
+ */
+ struct list_head init_deferred_cmd_list;
+ struct list_head init_deferred_mcmd_list;
+
+ /*
+ * Shutdown phase, one of SCST_SESS_SPH_* constants, unprotected.
+ * Async. relating to init_phase, must be a separate variable, because
+ * session could be unregistered before async. registration is finished.
+ */
+ unsigned long shut_phase;
+
+ /* Used if scst_unregister_session() called in wait mode */
+ struct completion *shutdown_compl;
+
+ /* sysfs release completion */
+ struct completion sess_kobj_release_cmpl;
+
+ unsigned int sess_kobj_ready:1;
+
+ struct kobject sess_kobj; /* kobject for this struct */
+
+ /*
+ * Functions and data for user callbacks from scst_register_session()
+ * and scst_unregister_session()
+ */
+ void *reg_sess_data;
+ void (*init_result_fn) (struct scst_session *sess, void *data,
+ int result);
+ void (*unreg_done_fn) (struct scst_session *sess);
+
+#ifdef CONFIG_SCST_MEASURE_LATENCY
+ /*
+ * Must be the last to allow to work with drivers who don't know
+ * about this config time option.
+ */
+ spinlock_t lat_lock;
+ uint64_t scst_time, tgt_time, dev_time;
+ unsigned int processed_cmds;
+ uint64_t min_scst_time, min_tgt_time, min_dev_time;
+ uint64_t max_scst_time, max_tgt_time, max_dev_time;
+ struct scst_ext_latency_stat sess_latency_stat[SCST_LATENCY_STATS_NUM];
+#endif
+};
+
+/*
+ * SCST_PR_ABORT_ALL TM function helper structure
+ */
+struct scst_pr_abort_all_pending_mgmt_cmds_counter {
+ /*
+ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM
+ * commands.
+ */
+ atomic_t pr_abort_pending_cnt;
+
+ /* Saved completition routine */
+ void (*saved_cmd_done) (struct scst_cmd *cmd, int next_state,
+ enum scst_exec_context pref_context);
+
+ /*
+ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM
+ * commands, which not yet aborted all affected commands and
+ * a completion to signal, when it's done.
+ */
+ atomic_t pr_aborting_cnt;
+ struct completion pr_aborting_cmpl;
+};
+
+/*
+ * Structure to control commands' queuing and threads pool processing the queue
+ */
+struct scst_cmd_threads {
+ spinlock_t cmd_list_lock;
+ struct list_head active_cmd_list; /* commands queue */
+ wait_queue_head_t cmd_list_waitQ;
+
+ struct io_context *io_context; /* IO context of the threads pool */
+
+ bool io_context_ready;
+
+ int nr_threads; /* number of processing threads */
+ struct list_head threads_list; /* processing threads */
+
+ struct list_head lists_list_entry;
+};
+
+/*
+ * SCST command, analog of I_T_L_Q nexus or task
+ */
+struct scst_cmd {
+ /* List entry for below *_cmd_threads */
+ struct list_head cmd_list_entry;
+
+ /* Pointer to lists of commands with the lock */
+ struct scst_cmd_threads *cmd_threads;
+
+ atomic_t cmd_ref;
+
+ struct scst_session *sess; /* corresponding session */
+
+ /* Cmd state, one of SCST_CMD_STATE_* constants */
+ int state;
+
+ /*************************************************************
+ ** Cmd's flags
+ *************************************************************/
+
+ /*
+ * Set if expected_sn should be incremented, i.e. cmd was sent
+ * for execution
+ */
+ unsigned int sent_for_exec:1;
+
+ /* Set if the cmd's action is completed */
+ unsigned int completed:1;
+
+ /* Set if we should ignore Unit Attention in scst_check_sense() */
+ unsigned int ua_ignore:1;
+
+ /* Set if cmd is being processed in atomic context */
+ unsigned int atomic:1;
+
+ /* Set if this command was sent in double UA possible state */
+ unsigned int double_ua_possible:1;
+
+ /* Set if this command contains status */
+ unsigned int is_send_status:1;
+
+ /* Set if cmd is being retried */
+ unsigned int retry:1;
+
+ /* Set if cmd is internally generated */
+ unsigned int internal:1;
+
+ /* Set if the device was blocked by scst_check_blocked_dev() */
+ unsigned int unblock_dev:1;
+
+ /* Set if cmd is queued as hw pending */
+ unsigned int cmd_hw_pending:1;
+
+ /*
+ * Set if the target driver wants to alloc data buffers on its own.
+ * In this case alloc_data_buf() must be provided in the target driver
+ * template.
+ */
+ unsigned int tgt_need_alloc_data_buf:1;
+
+ /*
+ * Set by SCST if the custom data buffer allocation by the target driver
+ * succeeded.
+ */
+ unsigned int tgt_data_buf_alloced:1;
+
+ /* Set if custom data buffer allocated by dev handler */
+ unsigned int dh_data_buf_alloced:1;
+
+ /* Set if the target driver called scst_set_expected() */
+ unsigned int expected_values_set:1;
+
+ /*
+ * Set if the SG buffer was modified by scst_adjust_sg()
+ */
+ unsigned int sg_buff_modified:1;
+
+ /*
+ * Set if cmd buffer was vmallocated and copied from more
+ * then one sg chunk
+ */
+ unsigned int sg_buff_vmallocated:1;
+
+ /*
+ * Set if scst_cmd_init_stage1_done() called and the target
+ * want that preprocessing_done() will be called
+ */
+ unsigned int preprocessing_only:1;
+
+ /* Set if cmd's SN was set */
+ unsigned int sn_set:1;
+
+ /* Set if hq_cmd_count was incremented */
+ unsigned int hq_cmd_inced:1;
+
+ /*
+ * Set if scst_cmd_init_stage1_done() called and the target wants
+ * that the SN for the cmd won't be assigned until scst_restart_cmd()
+ */
+ unsigned int set_sn_on_restart_cmd:1;
+
+ /* Set if the cmd's must not use sgv cache for data buffer */
+ unsigned int no_sgv:1;
+
+ /*
+ * Set if target driver may need to call dma_sync_sg() or similar
+ * function before transferring cmd' data to the target device
+ * via DMA.
+ */
+ unsigned int may_need_dma_sync:1;
+
+ /* Set if the cmd was done or aborted out of its SN */
+ unsigned int out_of_sn:1;
+
+ /* Set if increment expected_sn in cmd->scst_cmd_done() */
+ unsigned int inc_expected_sn_on_done:1;
+
+ /* Set if tgt_sn field is valid */
+ unsigned int tgt_sn_set:1;
+
+ /* Set if any direction residual is possible */
+ unsigned int resid_possible:1;
+
+ /* Set if cmd is done */
+ unsigned int done:1;
+
+ /* Set if cmd is finished */
+ unsigned int finished:1;
+
+#ifdef CONFIG_SCST_DEBUG_TM
+ /* Set if the cmd was delayed by task management debugging code */
+ unsigned int tm_dbg_delayed:1;
+
+ /* Set if the cmd must be ignored by task management debugging code */
+ unsigned int tm_dbg_immut:1;
+#endif
+
+ /**************************************************************/
+
+ /* cmd's async flags */
+ unsigned long cmd_flags;
+
+ /* Keeps status of cmd's status/data delivery to remote initiator */
+ int delivery_status;
+
+ struct scst_tgt_template *tgtt; /* to save extra dereferences */
+ struct scst_tgt *tgt; /* to save extra dereferences */
+ struct scst_device *dev; /* to save extra dereferences */
+
+ struct scst_tgt_dev *tgt_dev; /* corresponding device for this cmd */
+
+ uint64_t lun; /* LUN for this cmd */
+
+ unsigned long start_time;
+
+ /* List entry for tgt_dev's SN related lists */
+ struct list_head sn_cmd_list_entry;
+
+ /* Cmd's serial number, used to execute cmd's in order of arrival */
+ unsigned int sn;
+
+ /* The corresponding sn_slot in tgt_dev->sn_slots */
+ atomic_t *sn_slot;
+
+ /* List entry for sess's sess_cmd_list */
+ struct list_head sess_cmd_list_entry;
+
+ /*
+ * Used to found the cmd by scst_find_cmd_by_tag(). Set by the
+ * target driver on the cmd's initialization time
+ */
+ uint64_t tag;
+
+ uint32_t tgt_sn; /* SN set by target driver (for TM purposes) */
+
+ uint8_t *cdb; /* Pointer on CDB. Points on cdb_buf for small CDBs. */
+ unsigned short cdb_len;
+ uint8_t cdb_buf[SCST_MAX_CDB_SIZE];
+
+ enum scst_cdb_flags op_flags;
+ const char *op_name;
+
+ enum scst_cmd_queue_type queue_type;
+
+ int timeout; /* CDB execution timeout in seconds */
+ int retries; /* Amount of retries that will be done by SCSI mid-level */
+
+ /* SCSI data direction, one of SCST_DATA_* constants */
+ scst_data_direction data_direction;
+
+ /* Remote initiator supplied values, if any */
+ scst_data_direction expected_data_direction;
+ int expected_transfer_len;
+ int expected_out_transfer_len; /* for bidi writes */
+
+ /*
+ * Cmd data length. Could be different from bufflen for commands like
+ * VERIFY, which transfer different amount of data (if any), than
+ * processed.
+ */
+ int data_len;
+
+ /* Completition routine */
+ void (*scst_cmd_done) (struct scst_cmd *cmd, int next_state,
+ enum scst_exec_context pref_context);
+
+ struct sgv_pool_obj *sgv; /* sgv object */
+ int bufflen; /* cmd buffer length */
+ struct scatterlist *sg; /* cmd data buffer SG vector */
+ int sg_cnt; /* SG segments count */
+
+ /*
+ * Response data length in data buffer. Must not be set
+ * directly, use scst_set_resp_data_len() for that.
+ */
+ int resp_data_len;
+
+ /*
+ * Response data length adjusted on residual, i.e.
+ * min(expected_len, resp_len), if expected len set.
+ */
+ int adjusted_resp_data_len;
+
+ /*
+ * Data length to write, i.e. transfer from the initiator. Might be
+ * different from (out_)bufflen, if the initiator asked too big or too
+ * small expected(_out_)transfer_len.
+ */
+ int write_len;
+
+ /*
+ * Write sg and sg_cnt to point out either on sg/sg_cnt, or on
+ * out_sg/out_sg_cnt.
+ */
+ struct scatterlist **write_sg;
+ int *write_sg_cnt;
+
+ /* scst_get_sg_buf_[first,next]() support */
+ struct scatterlist *get_sg_buf_cur_sg_entry;
+ int get_sg_buf_entry_num;
+
+ /* Bidirectional transfers support */
+ int out_bufflen; /* WRITE buffer length */
+ struct sgv_pool_obj *out_sgv; /* WRITE sgv object */
+ struct scatterlist *out_sg; /* WRITE data buffer SG vector */
+ int out_sg_cnt; /* WRITE SG segments count */
+
+ /*
+ * Used if both target driver and dev handler request own memory
+ * allocation. In other cases, both are equal to sg and sg_cnt
+ * correspondingly.
+ *
+ * If target driver requests own memory allocations, it MUST use
+ * functions scst_cmd_get_tgt_sg*() to get sg and sg_cnt! Otherwise,
+ * it may use functions scst_cmd_get_sg*().
+ */
+ struct scatterlist *tgt_sg;
+ int tgt_sg_cnt;
+ struct scatterlist *tgt_out_sg; /* bidirectional */
+ int tgt_out_sg_cnt; /* bidirectional */
+
+ /*
+ * The status fields in case of errors must be set using
+ * scst_set_cmd_error_status()!
+ */
+ uint8_t status; /* status byte from target device */
+ uint8_t msg_status; /* return status from host adapter itself */
+ uint8_t host_status; /* set by low-level driver to indicate status */
+ uint8_t driver_status; /* set by mid-level */
+
+ uint8_t *sense; /* pointer to sense buffer */
+ unsigned short sense_valid_len; /* length of valid sense data */
+ unsigned short sense_buflen; /* length of the sense buffer, if any */
+
+ /* Start time when cmd was sent to rdy_to_xfer() or xmit_response() */
+ unsigned long hw_pending_start;
+
+ /* Used for storage of target driver private stuff */
+ void *tgt_priv;
+
+ /* Used for storage of dev handler private stuff */
+ void *dh_priv;
+
+ /* Used to restore sg if it was modified by scst_adjust_sg() */
+ struct scatterlist *orig_sg;
+ int *p_orig_sg_cnt;
+ int orig_sg_cnt, orig_sg_entry, orig_entry_len;
+
+ /* Used to retry commands in case of double UA */
+ int dbl_ua_orig_resp_data_len, dbl_ua_orig_data_direction;
+
+ /*
+ * List of the corresponding mgmt cmds, if any. Protected by
+ * sess_list_lock.
+ */
+ struct list_head mgmt_cmd_list;
+
+ /* List entry for dev's blocked_cmd_list */
+ struct list_head blocked_cmd_list_entry;
+
+ /* Counter of the corresponding SCST_PR_ABORT_ALL TM commands */
+ struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_abort_counter;
+
+ struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */
+
+#ifdef CONFIG_SCST_MEASURE_LATENCY
+ /*
+ * Must be the last to allow to work with drivers who don't know
+ * about this config time option.
+ */
+ uint64_t start, curr_start, parse_time, alloc_buf_time;
+ uint64_t restart_waiting_time, rdy_to_xfer_time;
+ uint64_t pre_exec_time, exec_time, dev_done_time;
+ uint64_t xmit_time, tgt_on_free_time, dev_on_free_time;
+#endif
+};
+
+/*
+ * Parameters for SCST management commands
+ */
+struct scst_rx_mgmt_params {
+ int fn;
+ uint64_t tag;
+ const uint8_t *lun;
+ int lun_len;
+ uint32_t cmd_sn;
+ int atomic;
+ void *tgt_priv;
+ unsigned char tag_set;
+ unsigned char lun_set;
+ unsigned char cmd_sn_set;
+};
+
+/*
+ * A stub structure to link an management command and affected regular commands
+ */
+struct scst_mgmt_cmd_stub {
+ struct scst_mgmt_cmd *mcmd;
+
+ /* List entry in cmd->mgmt_cmd_list */
+ struct list_head cmd_mgmt_cmd_list_entry;
+
+ /* Set if the cmd was counted in mcmd->cmd_done_wait_count */
+ unsigned int done_counted:1;
+
+ /* Set if the cmd was counted in mcmd->cmd_finish_wait_count */
+ unsigned int finish_counted:1;
+};
+
+/*
+ * SCST task management structure
+ */
+struct scst_mgmt_cmd {
+ /* List entry for *_mgmt_cmd_list */
+ struct list_head mgmt_cmd_list_entry;
+
+ struct scst_session *sess;
+
+ /* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */
+ int state;
+
+ int fn; /* task management function */
+
+ /* Set if device(s) should be unblocked after mcmd's finish */
+ unsigned int needs_unblocking:1;
+ unsigned int lun_set:1; /* set, if lun field is valid */
+ unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */
+
+ /*
+ * Number of commands to finish before sending response,
+ * protected by scst_mcmd_lock
+ */
+ int cmd_finish_wait_count;
+
+ /*
+ * Number of commands to complete (done) before resetting reservation,
+ * protected by scst_mcmd_lock
+ */
+ int cmd_done_wait_count;
+
+ /* Number of completed commands, protected by scst_mcmd_lock */
+ int completed_cmd_count;
+
+ uint64_t lun; /* LUN for this mgmt cmd */
+ /* or (and for iSCSI) */
+ uint64_t tag; /* tag of the corresponding cmd */
+
+ uint32_t cmd_sn; /* affected command's highest SN */
+
+ /* corresponding cmd (to be aborted, found by tag) */
+ struct scst_cmd *cmd_to_abort;
+
+ /* corresponding device for this mgmt cmd (found by lun) */
+ struct scst_tgt_dev *mcmd_tgt_dev;
+
+ /* completition status, one of the SCST_MGMT_STATUS_* constants */
+ int status;
+
+ /* Used for storage of target driver private stuff or origin PR cmd */
+ union {
+ void *tgt_priv;
+ struct scst_cmd *origin_pr_cmd;
+ };
+};
+
+/*
+ * Persistent reservations registrant
+ */
+struct scst_dev_registrant {
+ uint8_t *transport_id;
+ uint16_t rel_tgt_id;
+ __be64 key;
+
+ /* tgt_dev (I_T nexus) for this registrant, if any */
+ struct scst_tgt_dev *tgt_dev;
+
+ /* List entry for dev_registrants_list */
+ struct list_head dev_registrants_list_entry;
+
+ /* 2 auxiliary fields used to rollback changes for errors, etc. */
+ struct list_head aux_list_entry;
+ __be64 rollback_key;
+};
+
+/*
+ * SCST device
+ */
+struct scst_device {
+ unsigned short type; /* SCSI type of the device */
+
+ /*************************************************************
+ ** Dev's flags. Updates serialized by dev_lock or suspended
+ ** activity
+ *************************************************************/
+
+ /* Set if dev is RESERVED */
+ unsigned short dev_reserved:1;
+
+ /* Set if double reset UA is possible */
+ unsigned short dev_double_ua_possible:1;
+
+ /* If set, dev is read only */
+ unsigned short rd_only:1;
+
+ /**************************************************************/
+
+ /*************************************************************
+ ** Dev's control mode page related values. Updates serialized
+ ** by scst_block_dev(). Modified independently to the above and
+ ** below fields, hence the alignment.
+ *************************************************************/
+
+ unsigned int queue_alg:4 __attribute__((aligned(sizeof(long))));
+ unsigned int tst:3;
+ unsigned int tas:1;
+ unsigned int swp:1;
+ unsigned int d_sense:1;
+
+ /*
+ * Set if device implements own ordered commands management. If not set
+ * and queue_alg is SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER,
+ * expected_sn will be incremented only after commands finished.
+ */
+ unsigned int has_own_order_mgmt:1;
+
+ /**************************************************************/
+
+ /*
+ * How many times device was blocked for new cmds execution.
+ * Protected by dev_lock
+ */
+ int block_count;
+
+ /* How many cmds alive on this dev */
+ atomic_t dev_cmd_count;
+
+ /*
+ * Set if dev is persistently reserved. Protected by dev_pr_mutex.
+ * Modified independently to the above field, hence the alignment.
+ */
+ unsigned int pr_is_set:1 __attribute__((aligned(sizeof(long))));
+
+ /*
+ * Set if there is a thread changing or going to change PR state(s).
+ * Protected by dev_pr_mutex.
+ */
+ unsigned int pr_writer_active:1;
+
+ /*
+ * How many threads are checking commands for PR allowance. Used to
+ * implement lockless read-only fast path.
+ */
+ atomic_t pr_readers_count;
+
+ struct scst_dev_type *handler; /* corresponding dev handler */
+
+ /* Used for storage of dev handler private stuff */
+ void *dh_priv;
+
+ /* Corresponding real SCSI device, could be NULL for virtual devices */
+ struct scsi_device *scsi_dev;
+
+ /* List of commands with lock, if dedicated threads are used */
+ struct scst_cmd_threads dev_cmd_threads;
+
+ /* Memory limits for this device */
+ struct scst_mem_lim dev_mem_lim;
+
+ /* How many write cmds alive on this dev. Temporary, ToDo */
+ atomic_t write_cmd_count;
+
+ /*************************************************************
+ ** Persistent reservation fields. Protected by dev_pr_mutex.
+ *************************************************************/
+
+ /*
+ * True if persist through power loss is activated. Modified
+ * independently to the above field, hence the alignment.
+ */
+ unsigned short pr_aptpl:1 __attribute__((aligned(sizeof(long))));
+
+ /* Persistent reservation type */
+ uint8_t pr_type;
+
+ /* Persistent reservation scope */
+ uint8_t pr_scope;
+
+ /* Mutex to protect PR operations */
+ struct mutex dev_pr_mutex;
+
+ /* Persistent reservation generation value */
+ uint32_t pr_generation;
+
+ /* Reference to registrant - persistent reservation holder */
+ struct scst_dev_registrant *pr_holder;
+
+ /* List of dev's registrants */
+ struct list_head dev_registrants_list;
+
+ /*
+ * Count of connected tgt_devs from transports, which don't support
+ * PRs, i.e. don't have get_initiator_port_transport_id(). Protected
+ * by scst_mutex.
+ */
+ int not_pr_supporting_tgt_devs_num;
+
+ /* Persist through power loss files */
+ char *pr_file_name;
+ char *pr_file_name1;
+
+ /**************************************************************/
+
+ spinlock_t dev_lock; /* device lock */
+
+ struct list_head blocked_cmd_list; /* protected by dev_lock */
+
+ /* A list entry used during TM, protected by scst_mutex */
+ struct list_head tm_dev_list_entry;
+
+ /* Virtual device internal ID */
+ int virt_id;
+
+ /* Pointer to virtual device name, for convenience only */
+ char *virt_name;
+
+ /* List entry in global devices list */
+ struct list_head dev_list_entry;
+
+ /*
+ * List of tgt_dev's, one per session, protected by scst_mutex or
+ * dev_lock for reads and both for writes
+ */
+ struct list_head dev_tgt_dev_list;
+
+ /* List of acg_dev's, one per acg, protected by scst_mutex */
+ struct list_head dev_acg_dev_list;
+
+ /* Number of threads in the device's threads pools */
+ int threads_num;
+
+ /* Threads pool type of the device. Valid only if threads_num > 0. */
+ enum scst_dev_type_threads_pool_type threads_pool_type;
+
+ /* sysfs release completion */
+ struct completion dev_kobj_release_cmpl;
+
+ struct kobject dev_kobj; /* kobject for this struct */
+ struct kobject *dev_exp_kobj; /* exported groups */
+
+ /* Export number in the dev's sysfs list. Protected by scst_mutex */
+ int dev_exported_lun_num;
+};
+
+/*
+ * Used to store threads local tgt_dev specific data
+ */
+struct scst_thr_data_hdr {
+ /* List entry in tgt_dev->thr_data_list */
+ struct list_head thr_data_list_entry;
+ struct task_struct *owner_thr; /* the owner thread */
+ atomic_t ref;
+ /* Function that will be called on the tgt_dev destruction */
+ void (*free_fn) (struct scst_thr_data_hdr *data);
+};
+
+/*
+ * Used to clearly dispose async io_context
+ */
+struct scst_async_io_context_keeper {
+ struct kref aic_keeper_kref;
+ bool aic_ready;
+ struct io_context *aic;
+ struct task_struct *aic_keeper_thr;
+ wait_queue_head_t aic_keeper_waitQ;
+};
+
+/*
+ * Used to store per-session specific device information, analog of
+ * SCSI I_T_L nexus.
+ */
+struct scst_tgt_dev {
+ /* List entry in sess->sess_tgt_dev_list */
+ struct list_head sess_tgt_dev_list_entry;
+
+ struct scst_device *dev; /* to save extra dereferences */
+ uint64_t lun; /* to save extra dereferences */
+
+ gfp_t gfp_mask;
+ struct sgv_pool *pool;
+ int max_sg_cnt;
+
+ /*
+ * Tgt_dev's async flags. Modified independently to the neighbour
+ * fields.
+ */
+ unsigned long tgt_dev_flags;
+
+ /* Used for storage of dev handler private stuff */
+ void *dh_priv;
+
+ /* How many cmds alive on this dev in this session */
+ atomic_t tgt_dev_cmd_count;
+
+ /*
+ * Used to execute cmd's in order of arrival, honoring SCSI task
+ * attributes.
+ *
+ * Protected by sn_lock, except expected_sn, which is protected by
+ * itself. Curr_sn must have the same size as expected_sn to
+ * overflow simultaneously.
+ */
+ int def_cmd_count;
+ spinlock_t sn_lock;
+ unsigned int expected_sn;
+ unsigned int curr_sn;
+ int hq_cmd_count;
+ struct list_head deferred_cmd_list;
+ struct list_head skipped_sn_list;
+
+ /*
+ * Set if the prev cmd was ORDERED. Size and, hence, alignment must
+ * allow unprotected modifications independently to the neighbour fields.
+ */
+ unsigned long prev_cmd_ordered;
+
+ int num_free_sn_slots; /* if it's <0, then all slots are busy */
+ atomic_t *cur_sn_slot;
+ atomic_t sn_slots[15];
+
+ /* List of scst_thr_data_hdr and lock */
+ spinlock_t thr_data_lock;
+ struct list_head thr_data_list;
+
+ /* Pointer to lists of commands with the lock */
+ struct scst_cmd_threads *active_cmd_threads;
+
+ /* Union to save some CPU cache footprint */
+ union {
+ struct {
+ /* Copy to save fast path dereference */
+ struct io_context *async_io_context;
+
+ struct scst_async_io_context_keeper *aic_keeper;
+ };
+
+ /* Lists of commands with lock, if dedicated threads are used */
+ struct scst_cmd_threads tgt_dev_cmd_threads;
+ };
+
+ spinlock_t tgt_dev_lock; /* per-session device lock */
+
+ /* List of UA's for this device, protected by tgt_dev_lock */
+ struct list_head UA_list;
+
+ struct scst_session *sess; /* corresponding session */
+ struct scst_acg_dev *acg_dev; /* corresponding acg_dev */
+
+ /* Reference to registrant to find quicker */
+ struct scst_dev_registrant *registrant;
+
+ /* List entry in dev->dev_tgt_dev_list */
+ struct list_head dev_tgt_dev_list_entry;
+
+ /* Internal tmp list entry */
+ struct list_head extra_tgt_dev_list_entry;
+
+ /* Set if INQUIRY DATA HAS CHANGED UA is needed */
+ unsigned int inq_changed_ua_needed:1;
+
+ /*
+ * Stored Unit Attention sense and its length for possible
+ * subsequent REQUEST SENSE. Both protected by tgt_dev_lock.
+ */
+ unsigned short tgt_dev_valid_sense_len;
+ uint8_t tgt_dev_sense[SCST_SENSE_BUFFERSIZE];
+
+ /* sysfs release completion */
+ struct completion tgt_dev_kobj_release_cmpl;
+
+ struct kobject tgt_dev_kobj; /* kobject for this struct */
+
+#ifdef CONFIG_SCST_MEASURE_LATENCY
+ /*
+ * Must be the last to allow to work with drivers who don't know
+ * about this config time option.
+ *
+ * Protected by sess->lat_lock.
+ */
+ uint64_t scst_time, tgt_time, dev_time;
+ unsigned int processed_cmds;
+ struct scst_ext_latency_stat dev_latency_stat[SCST_LATENCY_STATS_NUM];
+#endif
+};
+
+/*
+ * Used to store ACG-specific device information, like LUN
+ */
+struct scst_acg_dev {
+ struct scst_device *dev; /* corresponding device */
+
+ uint64_t lun; /* device's LUN in this acg */
+
+ /* If set, the corresponding LU is read only */
+ unsigned int rd_only:1;
+
+ struct scst_acg *acg; /* parent acg */
+
+ /* List entry in dev->dev_acg_dev_list */
+ struct list_head dev_acg_dev_list_entry;
+
+ /* List entry in acg->acg_dev_list */
+ struct list_head acg_dev_list_entry;
+
+ /* kobject for this structure */
+ struct kobject acg_dev_kobj;
+
+ /* sysfs release completion */
+ struct completion acg_dev_kobj_release_cmpl;
+
+ /* Name of the link to the corresponding LUN */
+ char acg_dev_link_name[20];
+};
+
+/*
+ * ACG - access control group. Used to store group related
+ * control information.
+ */
+struct scst_acg {
+ /* Owner target */
+ struct scst_tgt *tgt;
+
+ /* List of acg_dev's in this acg, protected by scst_mutex */
+ struct list_head acg_dev_list;
+
+ /* List of attached sessions, protected by scst_mutex */
+ struct list_head acg_sess_list;
+
+ /* List of attached acn's, protected by scst_mutex */
+ struct list_head acn_list;
+
+ /* List entry in acg_lists */
+ struct list_head acg_list_entry;
+
+ /* Name of this acg */
+ const char *acg_name;
+
+ /* Type of I/O initiators groupping */
+ int acg_io_grouping_type;
+
+ /* CPU affinity for threads in this ACG */
+ cpumask_t acg_cpu_mask;
+
+ unsigned int tgt_acg:1;
+
+ /* sysfs release completion */
+ struct completion acg_kobj_release_cmpl;
+
+ /* kobject for this structure */
+ struct kobject acg_kobj;
+
+ struct kobject *luns_kobj;
+ struct kobject *initiators_kobj;
+
+ unsigned int addr_method;
+};
+
+/*
+ * ACN - access control name. Used to store names, by which
+ * incoming sessions will be assigned to appropriate ACG.
+ */
+struct scst_acn {
+ struct scst_acg *acg; /* owner ACG */
+
+ const char *name; /* initiator's name */
+
+ /* List entry in acg->acn_list */
+ struct list_head acn_list_entry;
+
+ /* sysfs file attributes */
+ struct kobj_attribute *acn_attr;
+};
+
+/*
+ * Used to store per-session UNIT ATTENTIONs
+ */
+struct scst_tgt_dev_UA {
+ /* List entry in tgt_dev->UA_list */
+ struct list_head UA_list_entry;
+
+ /* Set if UA is global for session */
+ unsigned short global_UA:1;
+
+ /* Unit Attention valid sense len */
+ unsigned short UA_valid_sense_len;
+ /* Unit Attention sense buf */
+ uint8_t UA_sense_buffer[SCST_SENSE_BUFFERSIZE];
+};
+
+/* Used to deliver AENs */
+struct scst_aen {
+ int event_fn; /* AEN fn */
+
+ struct scst_session *sess; /* corresponding session */
+ __be64 lun; /* corresponding LUN in SCSI form */
+
+ union {
+ /* SCSI AEN data */
+ struct {
+ int aen_sense_len;
+ uint8_t aen_sense[SCST_STANDARD_SENSE_LEN];
+ };
+ };
+
+ /* Keeps status of AEN's delivery to remote initiator */
+ int delivery_status;
+};
+
+#ifndef smp_mb__after_set_bit
+/* There is no smp_mb__after_set_bit() in the kernel */
+#define smp_mb__after_set_bit() smp_mb()
+#endif
+
+/*
+ * Registers target template.
+ * Returns 0 on success or appropriate error code otherwise.
+ */
+int __scst_register_target_template(struct scst_tgt_template *vtt,
+ const char *version);
+static inline int scst_register_target_template(struct scst_tgt_template *vtt)
+{
+ return __scst_register_target_template(vtt, SCST_INTERFACE_VERSION);
+}
+
+/*
+ * Registers target template, non-GPL version.
+ * Returns 0 on success or appropriate error code otherwise.
+ *
+ * Note: *vtt must be static!
+ */
+int __scst_register_target_template_non_gpl(struct scst_tgt_template *vtt,
+ const char *version);
+static inline int scst_register_target_template_non_gpl(
+ struct scst_tgt_template *vtt)
+{
+ return __scst_register_target_template_non_gpl(vtt,
+ SCST_INTERFACE_VERSION);
+}
+
+void scst_unregister_target_template(struct scst_tgt_template *vtt);
+
+struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
+ const char *target_name);
+void scst_unregister_target(struct scst_tgt *tgt);
+
+struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
+ const char *initiator_name, void *tgt_priv, void *result_fn_data,
+ void (*result_fn) (struct scst_session *sess, void *data, int result));
+struct scst_session *scst_register_session_non_gpl(struct scst_tgt *tgt,
+ const char *initiator_name, void *tgt_priv);
+void scst_unregister_session(struct scst_session *sess, int wait,
+ void (*unreg_done_fn) (struct scst_session *sess));
+void scst_unregister_session_non_gpl(struct scst_session *sess);
+
+int __scst_register_dev_driver(struct scst_dev_type *dev_type,
+ const char *version);
+static inline int scst_register_dev_driver(struct scst_dev_type *dev_type)
+{
+ return __scst_register_dev_driver(dev_type, SCST_INTERFACE_VERSION);
+}
+void scst_unregister_dev_driver(struct scst_dev_type *dev_type);
+
+int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
+ const char *version);
+/*
+ * Registers dev handler driver for virtual devices (eg VDISK).
+ * Returns 0 on success or appropriate error code otherwise.
+ */
+static inline int scst_register_virtual_dev_driver(
+ struct scst_dev_type *dev_type)
+{
+ return __scst_register_virtual_dev_driver(dev_type,
+ SCST_INTERFACE_VERSION);
+}
+
+void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type);
+
+bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name);
+
+struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
+ const uint8_t *lun, int lun_len, const uint8_t *cdb,
+ unsigned int cdb_len, int atomic);
+void scst_cmd_init_done(struct scst_cmd *cmd,
+ enum scst_exec_context pref_context);
+
+/*
+ * Notifies SCST that the driver finished the first stage of the command
+ * initialization, and the command is ready for execution, but after
+ * SCST done the command's preprocessing preprocessing_done() function
+ * should be called. The second argument sets preferred command execition
+ * context. See SCST_CONTEXT_* constants for details.
+ *
+ * See comment for scst_cmd_init_done() for the serialization requirements.
+ */
+static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd,
+ enum scst_exec_context pref_context, int set_sn)
+{
+ cmd->preprocessing_only = 1;
+ cmd->set_sn_on_restart_cmd = !set_sn;
+ scst_cmd_init_done(cmd, pref_context);
+}
+
+void scst_restart_cmd(struct scst_cmd *cmd, int status,
+ enum scst_exec_context pref_context);
+
+void scst_rx_data(struct scst_cmd *cmd, int status,
+ enum scst_exec_context pref_context);
+
+void scst_tgt_cmd_done(struct scst_cmd *cmd,
+ enum scst_exec_context pref_context);
+
+int scst_rx_mgmt_fn(struct scst_session *sess,
+ const struct scst_rx_mgmt_params *params);
+
+/*
+ * Creates new management command using tag and sends it for execution.
+ * Can be used for SCST_ABORT_TASK only.
+ * Must not be called in parallel with scst_unregister_session() for the
+ * same sess. Returns 0 for success, error code otherwise.
+ *
+ * Obsolete in favor of scst_rx_mgmt_fn()
+ */
+static inline int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn,
+ uint64_t tag, int atomic, void *tgt_priv)
+{
+ struct scst_rx_mgmt_params params;
+
+ BUG_ON(fn != SCST_ABORT_TASK);
+
+ memset(¶ms, 0, sizeof(params));
+ params.fn = fn;
+ params.tag = tag;
+ params.tag_set = 1;
+ params.atomic = atomic;
+ params.tgt_priv = tgt_priv;
+ return scst_rx_mgmt_fn(sess, ¶ms);
+}
+
+/*
+ * Creates new management command using LUN and sends it for execution.
+ * Currently can be used for any fn, except SCST_ABORT_TASK.
+ * Must not be called in parallel with scst_unregister_session() for the
+ * same sess. Returns 0 for success, error code otherwise.
+ *
+ * Obsolete in favor of scst_rx_mgmt_fn()
+ */
+static inline int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn,
+ const uint8_t *lun, int lun_len, int atomic, void *tgt_priv)
+{
+ struct scst_rx_mgmt_params params;
+
+ BUG_ON(fn == SCST_ABORT_TASK);
+
+ memset(¶ms, 0, sizeof(params));
+ params.fn = fn;
+ params.lun = lun;
+ params.lun_len = lun_len;
+ params.lun_set = 1;
+ params.atomic = atomic;
+ params.tgt_priv = tgt_priv;
+ return scst_rx_mgmt_fn(sess, ¶ms);
+}
+
+int scst_get_cdb_info(struct scst_cmd *cmd);
+
+int scst_set_cmd_error_status(struct scst_cmd *cmd, int status);
+int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq);
+void scst_set_busy(struct scst_cmd *cmd);
+
+void scst_check_convert_sense(struct scst_cmd *cmd);
+
+void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq);
+
+void scst_capacity_data_changed(struct scst_device *dev);
+
+struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag);
+struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data,
+ int (*cmp_fn) (struct scst_cmd *cmd,
+ void *data));
+
+enum dma_data_direction scst_to_dma_dir(int scst_dir);
+enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir);
+
+/*
+ * Returns true, if cmd's CDB is fully locally handled by SCST and false
+ * otherwise. Dev handlers parse() and dev_done() not called for such commands.
+ */
+static inline bool scst_is_cmd_fully_local(struct scst_cmd *cmd)
+{
+ return (cmd->op_flags & SCST_FULLY_LOCAL_CMD) != 0;
+}
+
+/*
+ * Returns true, if cmd's CDB is locally handled by SCST and
+ * false otherwise.
+ */
+static inline bool scst_is_cmd_local(struct scst_cmd *cmd)
+{
+ return (cmd->op_flags & SCST_LOCAL_CMD) != 0;
+}
+
+/* Returns true, if cmd can deliver UA */
+static inline bool scst_is_ua_command(struct scst_cmd *cmd)
+{
+ return (cmd->op_flags & SCST_SKIP_UA) == 0;
+}
+
+int scst_register_virtual_device(struct scst_dev_type *dev_handler,
+ const char *dev_name);
+void scst_unregister_virtual_device(int id);
+
+/*
+ * Get/Set functions for tgt's sg_tablesize
+ */
+static inline int scst_tgt_get_sg_tablesize(struct scst_tgt *tgt)
+{
+ return tgt->sg_tablesize;
+}
+
+static inline void scst_tgt_set_sg_tablesize(struct scst_tgt *tgt, int val)
+{
+ tgt->sg_tablesize = val;
+}
+
+/*
+ * Get/Set functions for tgt's target private data
+ */
+static inline void *scst_tgt_get_tgt_priv(struct scst_tgt *tgt)
+{
+ return tgt->tgt_priv;
+}
+
+static inline void scst_tgt_set_tgt_priv(struct scst_tgt *tgt, void *val)
+{
+ tgt->tgt_priv = val;
+}
+
+void scst_update_hw_pending_start(struct scst_cmd *cmd);
+
+/*
+ * Get/Set functions for session's target private data
+ */
+static inline void *scst_sess_get_tgt_priv(struct scst_session *sess)
+{
+ return sess->tgt_priv;
+}
+
+static inline void scst_sess_set_tgt_priv(struct scst_session *sess,
+ void *val)
+{
+ sess->tgt_priv = val;
+}
+
+/**
+ * Returns TRUE if cmd is being executed in atomic context.
+ *
+ * Note: checkpatch will complain on the use of in_atomic() below. You can
+ * safely ignore this warning since in_atomic() is used here only for debugging
+ * purposes.
+ */
+static inline bool scst_cmd_atomic(struct scst_cmd *cmd)
+{
+ int res = cmd->atomic;
+#ifdef CONFIG_SCST_EXTRACHECKS
+ if (unlikely((in_atomic() || in_interrupt() || irqs_disabled()) &&
+ !res)) {
+ printk(KERN_ERR "ERROR: atomic context and non-atomic cmd\n");
+ dump_stack();
+ cmd->atomic = 1;
+ res = 1;
+ }
+#endif
+ return res;
+}
+
+/*
+ * Returns TRUE if cmd has been preliminary completed, i.e. completed or
+ * aborted.
+ */
+static inline bool scst_cmd_prelim_completed(struct scst_cmd *cmd)
+{
+ return cmd->completed || test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
+}
+
+static inline enum scst_exec_context __scst_estimate_context(bool direct)
+{
+ if (in_irq())
+ return SCST_CONTEXT_TASKLET;
+ else if (irqs_disabled())
+ return SCST_CONTEXT_THREAD;
+ else
+ return direct ? SCST_CONTEXT_DIRECT :
+ SCST_CONTEXT_DIRECT_ATOMIC;
+}
+
+static inline enum scst_exec_context scst_estimate_context(void)
+{
+ return __scst_estimate_context(0);
+}
+
+static inline enum scst_exec_context scst_estimate_context_direct(void)
+{
+ return __scst_estimate_context(1);
+}
+
+/* Returns cmd's CDB */
+static inline const uint8_t *scst_cmd_get_cdb(struct scst_cmd *cmd)
+{
+ return cmd->cdb;
+}
+
+/* Returns cmd's CDB length */
+static inline unsigned int scst_cmd_get_cdb_len(struct scst_cmd *cmd)
+{
+ return cmd->cdb_len;
+}
+
+void scst_cmd_set_ext_cdb(struct scst_cmd *cmd,
+ uint8_t *ext_cdb, unsigned int ext_cdb_len);
+
+/* Returns cmd's session */
+static inline struct scst_session *scst_cmd_get_session(struct scst_cmd *cmd)
+{
+ return cmd->sess;
+}
+
+/* Returns cmd's response data length */
+static inline int scst_cmd_get_resp_data_len(struct scst_cmd *cmd)
+{
+ return cmd->resp_data_len;
+}
+
+/* Returns cmd's adjusted response data length */
+static inline int scst_cmd_get_adjusted_resp_data_len(struct scst_cmd *cmd)
+{
+ return cmd->adjusted_resp_data_len;
+}
+
+/* Returns if status should be sent for cmd */
+static inline int scst_cmd_get_is_send_status(struct scst_cmd *cmd)
+{
+ return cmd->is_send_status;
+}
+
+/*
+ * Returns pointer to cmd's SG data buffer.
+ *
+ * Usage of this function is not recommended, use scst_get_buf_*()
+ * family of functions instead.
+ */
+static inline struct scatterlist *scst_cmd_get_sg(struct scst_cmd *cmd)
+{
+ return cmd->sg;
+}
+
+/*
+ * Returns cmd's sg_cnt.
+ *
+ * Usage of this function is not recommended, use scst_get_buf_*()
+ * family of functions instead.
+ */
+static inline int scst_cmd_get_sg_cnt(struct scst_cmd *cmd)
+{
+ return cmd->sg_cnt;
+}
+
+/*
+ * Returns cmd's data buffer length.
+ *
+ * In case if you need to iterate over data in the buffer, usage of
+ * this function is not recommended, use scst_get_buf_*()
+ * family of functions instead.
+ */
+static inline unsigned int scst_cmd_get_bufflen(struct scst_cmd *cmd)
+{
+ return cmd->bufflen;
+}
+
+/*
+ * Returns pointer to cmd's bidirectional in (WRITE) SG data buffer.
+ *
+ * Usage of this function is not recommended, use scst_get_out_buf_*()
+ * family of functions instead.
+ */
+static inline struct scatterlist *scst_cmd_get_out_sg(struct scst_cmd *cmd)
+{
+ return cmd->out_sg;
+}
+
+/*
+ * Returns cmd's bidirectional in (WRITE) sg_cnt.
+ *
+ * Usage of this function is not recommended, use scst_get_out_buf_*()
+ * family of functions instead.
+ */
+static inline int scst_cmd_get_out_sg_cnt(struct scst_cmd *cmd)
+{
+ return cmd->out_sg_cnt;
+}
+
+void scst_restore_sg_buff(struct scst_cmd *cmd);
+
+/* Restores modified sg buffer in the original state, if necessary */
+static inline void scst_check_restore_sg_buff(struct scst_cmd *cmd)
+{
+ if (unlikely(cmd->sg_buff_modified))
+ scst_restore_sg_buff(cmd);
+}
+
+/*
+ * Returns cmd's bidirectional in (WRITE) data buffer length.
+ *
+ * In case if you need to iterate over data in the buffer, usage of
+ * this function is not recommended, use scst_get_out_buf_*()
+ * family of functions instead.
+ */
+static inline unsigned int scst_cmd_get_out_bufflen(struct scst_cmd *cmd)
+{
+ return cmd->out_bufflen;
+}
+
+/* Returns pointer to cmd's target's SG data buffer */
+static inline struct scatterlist *scst_cmd_get_tgt_sg(struct scst_cmd *cmd)
+{
+ return cmd->tgt_sg;
+}
+
+/* Returns cmd's target's sg_cnt */
+static inline int scst_cmd_get_tgt_sg_cnt(struct scst_cmd *cmd)
+{
+ return cmd->tgt_sg_cnt;
+}
+
+/* Sets cmd's target's SG data buffer */
+static inline void scst_cmd_set_tgt_sg(struct scst_cmd *cmd,
+ struct scatterlist *sg, int sg_cnt)
+{
+ cmd->tgt_sg = sg;
+ cmd->tgt_sg_cnt = sg_cnt;
+ cmd->tgt_data_buf_alloced = 1;
+}
+
+/* Returns pointer to cmd's target's OUT SG data buffer */
+static inline struct scatterlist *scst_cmd_get_out_tgt_sg(struct scst_cmd *cmd)
+{
+ return cmd->tgt_out_sg;
+}
+
+/* Returns cmd's target's OUT sg_cnt */
+static inline int scst_cmd_get_tgt_out_sg_cnt(struct scst_cmd *cmd)
+{
+ return cmd->tgt_out_sg_cnt;
+}
+
+/* Sets cmd's target's OUT SG data buffer */
+static inline void scst_cmd_set_tgt_out_sg(struct scst_cmd *cmd,
+ struct scatterlist *sg, int sg_cnt)
+{
+ WARN_ON(!cmd->tgt_data_buf_alloced);
+
+ cmd->tgt_out_sg = sg;
+ cmd->tgt_out_sg_cnt = sg_cnt;
+}
+
+/* Returns cmd's data direction */
+static inline scst_data_direction scst_cmd_get_data_direction(
+ struct scst_cmd *cmd)
+{
+ return cmd->data_direction;
+}
+
+/* Returns cmd's write len as well as write SG and sg_cnt */
+static inline int scst_cmd_get_write_fields(struct scst_cmd *cmd,
+ struct scatterlist **sg, int *sg_cnt)
+{
+ *sg = *cmd->write_sg;
+ *sg_cnt = *cmd->write_sg_cnt;
+ return cmd->write_len;
+}
+
+void scst_cmd_set_write_not_received_data_len(struct scst_cmd *cmd,
+ int not_received);
+
+bool __scst_get_resid(struct scst_cmd *cmd, int *resid, int *bidi_out_resid);
+
+/*
+ * Returns true if cmd has residual(s) and returns them in the corresponding
+ * parameters(s).
+ */
+static inline bool scst_get_resid(struct scst_cmd *cmd,
+ int *resid, int *bidi_out_resid)
+{
+ if (likely(!cmd->resid_possible))
+ return false;
+ return __scst_get_resid(cmd, resid, bidi_out_resid);
+}
+
+/* Returns cmd's status byte from host device */
+static inline uint8_t scst_cmd_get_status(struct scst_cmd *cmd)
+{
+ return cmd->status;
+}
+
+/* Returns cmd's status from host adapter itself */
+static inline uint8_t scst_cmd_get_msg_status(struct scst_cmd *cmd)
+{
+ return cmd->msg_status;
+}
+
+/* Returns cmd's status set by low-level driver to indicate its status */
+static inline uint8_t scst_cmd_get_host_status(struct scst_cmd *cmd)
+{
+ return cmd->host_status;
+}
+
+/* Returns cmd's status set by SCSI mid-level */
+static inline uint8_t scst_cmd_get_driver_status(struct scst_cmd *cmd)
+{
+ return cmd->driver_status;
+}
+
+/* Returns pointer to cmd's sense buffer */
+static inline uint8_t *scst_cmd_get_sense_buffer(struct scst_cmd *cmd)
+{
+ return cmd->sense;
+}
+
+/* Returns cmd's valid sense length */
+static inline int scst_cmd_get_sense_buffer_len(struct scst_cmd *cmd)
+{
+ return cmd->sense_valid_len;
+}
+
+/*
+ * Get/Set functions for cmd's queue_type
+ */
+static inline enum scst_cmd_queue_type scst_cmd_get_queue_type(
+ struct scst_cmd *cmd)
+{
+ return cmd->queue_type;
+}
+
+static inline void scst_cmd_set_queue_type(struct scst_cmd *cmd,
+ enum scst_cmd_queue_type queue_type)
+{
+ cmd->queue_type = queue_type;
+}
+
+/*
+ * Get/Set functions for cmd's target SN
+ */
+static inline uint64_t scst_cmd_get_tag(struct scst_cmd *cmd)
+{
+ return cmd->tag;
+}
+
+static inline void scst_cmd_set_tag(struct scst_cmd *cmd, uint64_t tag)
+{
+ cmd->tag = tag;
+}
+
+/*
+ * Get/Set functions for cmd's target private data.
+ * Variant with *_lock must be used if target driver uses
+ * scst_find_cmd() to avoid race with it, except inside scst_find_cmd()'s
+ * callback, where lock is already taken.
+ */
+static inline void *scst_cmd_get_tgt_priv(struct scst_cmd *cmd)
+{
+ return cmd->tgt_priv;
+}
+
+static inline void scst_cmd_set_tgt_priv(struct scst_cmd *cmd, void *val)
+{
+ cmd->tgt_priv = val;
+}
+
+/*
+ * Get/Set functions for tgt_need_alloc_data_buf flag
+ */
+static inline int scst_cmd_get_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
+{
+ return cmd->tgt_need_alloc_data_buf;
+}
+
+static inline void scst_cmd_set_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
+{
+ cmd->tgt_need_alloc_data_buf = 1;
+}
+
+/*
+ * Get/Set functions for tgt_data_buf_alloced flag
+ */
+static inline int scst_cmd_get_tgt_data_buff_alloced(struct scst_cmd *cmd)
+{
+ return cmd->tgt_data_buf_alloced;
+}
+
+static inline void scst_cmd_set_tgt_data_buff_alloced(struct scst_cmd *cmd)
+{
+ cmd->tgt_data_buf_alloced = 1;
+}
+
+/*
+ * Get/Set functions for dh_data_buf_alloced flag
+ */
+static inline int scst_cmd_get_dh_data_buff_alloced(struct scst_cmd *cmd)
+{
+ return cmd->dh_data_buf_alloced;
+}
+
+static inline void scst_cmd_set_dh_data_buff_alloced(struct scst_cmd *cmd)
+{
+ cmd->dh_data_buf_alloced = 1;
+}
+
+/*
+ * Get/Set functions for no_sgv flag
+ */
+static inline int scst_cmd_get_no_sgv(struct scst_cmd *cmd)
+{
+ return cmd->no_sgv;
+}
+
+static inline void scst_cmd_set_no_sgv(struct scst_cmd *cmd)
+{
+ cmd->no_sgv = 1;
+}
+
+/*
+ * Get/Set functions for tgt_sn
+ */
+static inline int scst_cmd_get_tgt_sn(struct scst_cmd *cmd)
+{
+ BUG_ON(!cmd->tgt_sn_set);
+ return cmd->tgt_sn;
+}
+
+static inline void scst_cmd_set_tgt_sn(struct scst_cmd *cmd, uint32_t tgt_sn)
+{
+ cmd->tgt_sn_set = 1;
+ cmd->tgt_sn = tgt_sn;
+}
+
+/*
+ * Returns 1 if the cmd was aborted, so its status is invalid and no
+ * reply shall be sent to the remote initiator. A target driver should
+ * only clear internal resources, associated with cmd.
+ */
+static inline int scst_cmd_aborted(struct scst_cmd *cmd)
+{
+ return test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags) &&
+ !test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
+}
+
+/* Returns sense data format for cmd's dev */
+static inline bool scst_get_cmd_dev_d_sense(struct scst_cmd *cmd)
+{
+ return (cmd->dev != NULL) ? cmd->dev->d_sense : 0;
+}
+
+/*
+ * Get/Set functions for expected data direction, transfer length
+ * and its validity flag
+ */
+static inline int scst_cmd_is_expected_set(struct scst_cmd *cmd)
+{
+ return cmd->expected_values_set;
+}
+
+static inline scst_data_direction scst_cmd_get_expected_data_direction(
+ struct scst_cmd *cmd)
+{
+ return cmd->expected_data_direction;
+}
+
+static inline int scst_cmd_get_expected_transfer_len(
+ struct scst_cmd *cmd)
+{
+ return cmd->expected_transfer_len;
+}
+
+static inline int scst_cmd_get_expected_out_transfer_len(
+ struct scst_cmd *cmd)
+{
+ return cmd->expected_out_transfer_len;
+}
+
+static inline void scst_cmd_set_expected(struct scst_cmd *cmd,
+ scst_data_direction expected_data_direction,
+ int expected_transfer_len)
+{
+ cmd->expected_data_direction = expected_data_direction;
+ cmd->expected_transfer_len = expected_transfer_len;
+ cmd->expected_values_set = 1;
+}
+
+static inline void scst_cmd_set_expected_out_transfer_len(struct scst_cmd *cmd,
+ int expected_out_transfer_len)
+{
+ WARN_ON(!cmd->expected_values_set);
+ cmd->expected_out_transfer_len = expected_out_transfer_len;
+}
+
+/*
+ * Get/clear functions for cmd's may_need_dma_sync
+ */
+static inline int scst_get_may_need_dma_sync(struct scst_cmd *cmd)
+{
+ return cmd->may_need_dma_sync;
+}
+
+static inline void scst_clear_may_need_dma_sync(struct scst_cmd *cmd)
+{
+ cmd->may_need_dma_sync = 0;
+}
+
+/*
+ * Get/set functions for cmd's delivery_status. It is one of
+ * SCST_CMD_DELIVERY_* constants. It specifies the status of the
+ * command's delivery to initiator.
+ */
+static inline int scst_get_delivery_status(struct scst_cmd *cmd)
+{
+ return cmd->delivery_status;
+}
+
+static inline void scst_set_delivery_status(struct scst_cmd *cmd,
+ int delivery_status)
+{
+ cmd->delivery_status = delivery_status;
+}
+
+static inline unsigned int scst_get_active_cmd_count(struct scst_cmd *cmd)
+{
+ if (likely(cmd->tgt_dev != NULL))
+ return atomic_read(&cmd->tgt_dev->tgt_dev_cmd_count);
+ else
+ return (unsigned int)-1;
+}
+
+/*
+ * Get/Set function for mgmt cmd's target private data
+ */
+static inline void *scst_mgmt_cmd_get_tgt_priv(struct scst_mgmt_cmd *mcmd)
+{
+ return mcmd->tgt_priv;
+}
+
+static inline void scst_mgmt_cmd_set_tgt_priv(struct scst_mgmt_cmd *mcmd,
+ void *val)
+{
+ mcmd->tgt_priv = val;
+}
+
+/* Returns mgmt cmd's completition status (SCST_MGMT_STATUS_* constants) */
+static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd)
+{
+ return mcmd->status;
+}
+
+/* Returns mgmt cmd's TM fn */
+static inline int scst_mgmt_cmd_get_fn(struct scst_mgmt_cmd *mcmd)
+{
+ return mcmd->fn;
+}
+
+/*
+ * Called by dev handler's task_mgmt_fn() to notify SCST core that mcmd
+ * is going to complete asynchronously.
+ */
+void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd);
+
+/*
+ * Called by dev handler to notify SCST core that async. mcmd is completed
+ * with status "status".
+ */
+void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status);
+
+/* Returns AEN's fn */
+static inline int scst_aen_get_event_fn(struct scst_aen *aen)
+{
+ return aen->event_fn;
+}
+
+/* Returns AEN's session */
+static inline struct scst_session *scst_aen_get_sess(struct scst_aen *aen)
+{
+ return aen->sess;
+}
+
+/* Returns AEN's LUN */
+static inline __be64 scst_aen_get_lun(struct scst_aen *aen)
+{
+ return aen->lun;
+}
+
+/* Returns SCSI AEN's sense */
+static inline const uint8_t *scst_aen_get_sense(struct scst_aen *aen)
+{
+ return aen->aen_sense;
+}
+
+/* Returns SCSI AEN's sense length */
+static inline int scst_aen_get_sense_len(struct scst_aen *aen)
+{
+ return aen->aen_sense_len;
+}
+
+/*
+ * Get/set functions for AEN's delivery_status. It is one of
+ * SCST_AEN_RES_* constants. It specifies the status of the
+ * command's delivery to initiator.
+ */
+static inline int scst_get_aen_delivery_status(struct scst_aen *aen)
+{
+ return aen->delivery_status;
+}
+
+static inline void scst_set_aen_delivery_status(struct scst_aen *aen,
+ int status)
+{
+ aen->delivery_status = status;
+}
+
+void scst_aen_done(struct scst_aen *aen);
+
+static inline void sg_clear(struct scatterlist *sg)
+{
+ memset(sg, 0, sizeof(*sg));
+#ifdef CONFIG_DEBUG_SG
+ sg->sg_magic = SG_MAGIC;
+#endif
+}
+
+enum scst_sg_copy_dir {
+ SCST_SG_COPY_FROM_TARGET,
+ SCST_SG_COPY_TO_TARGET
+};
+
+void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir);
+
+/*
+ * Functions for access to the commands data (SG) buffer. Should be used
+ * instead of direct access. Returns the buffer length for success, 0 for EOD,
+ * negative error code otherwise.
+ *
+ * "Buf" argument returns the mapped buffer
+ *
+ * The "put" function unmaps the buffer.
+ */
+static inline int __scst_get_buf(struct scst_cmd *cmd, int sg_cnt,
+ uint8_t **buf)
+{
+ int res = 0;
+ struct scatterlist *sg = cmd->get_sg_buf_cur_sg_entry;
+
+ if (cmd->get_sg_buf_entry_num >= sg_cnt) {
+ *buf = NULL;
+ goto out;
+ }
+
+ if (unlikely(sg_is_chain(sg)))
+ sg = sg_chain_ptr(sg);
+
+ *buf = page_address(sg_page(sg));
+ *buf += sg->offset;
+
+ res = sg->length;
+
+ cmd->get_sg_buf_entry_num++;
+ cmd->get_sg_buf_cur_sg_entry = ++sg;
+
+out:
+ return res;
+}
+
+static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf)
+{
+ if (unlikely(cmd->sg == NULL)) {
+ *buf = NULL;
+ return 0;
+ }
+ cmd->get_sg_buf_entry_num = 0;
+ cmd->get_sg_buf_cur_sg_entry = cmd->sg;
+ cmd->may_need_dma_sync = 1;
+ return __scst_get_buf(cmd, cmd->sg_cnt, buf);
+}
+
+static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf)
+{
+ return __scst_get_buf(cmd, cmd->sg_cnt, buf);
+}
+
+static inline void scst_put_buf(struct scst_cmd *cmd, void *buf)
+{
+ /* Nothing to do */
+}
+
+static inline int scst_get_out_buf_first(struct scst_cmd *cmd, uint8_t **buf)
+{
+ if (unlikely(cmd->out_sg == NULL)) {
+ *buf = NULL;
+ return 0;
+ }
+ cmd->get_sg_buf_entry_num = 0;
+ cmd->get_sg_buf_cur_sg_entry = cmd->out_sg;
+ cmd->may_need_dma_sync = 1;
+ return __scst_get_buf(cmd, cmd->out_sg_cnt, buf);
+}
+
+static inline int scst_get_out_buf_next(struct scst_cmd *cmd, uint8_t **buf)
+{
+ return __scst_get_buf(cmd, cmd->out_sg_cnt, buf);
+}
+
+static inline void scst_put_out_buf(struct scst_cmd *cmd, void *buf)
+{
+ /* Nothing to do */
+}
+
+static inline int scst_get_sg_buf_first(struct scst_cmd *cmd, uint8_t **buf,
+ struct scatterlist *sg, int sg_cnt)
+{
+ if (unlikely(sg == NULL)) {
+ *buf = NULL;
+ return 0;
+ }
+ cmd->get_sg_buf_entry_num = 0;
+ cmd->get_sg_buf_cur_sg_entry = cmd->sg;
+ cmd->may_need_dma_sync = 1;
+ return __scst_get_buf(cmd, sg_cnt, buf);
+}
+
+static inline int scst_get_sg_buf_next(struct scst_cmd *cmd, uint8_t **buf,
+ struct scatterlist *sg, int sg_cnt)
+{
+ return __scst_get_buf(cmd, sg_cnt, buf);
+}
+
+static inline void scst_put_sg_buf(struct scst_cmd *cmd, void *buf,
+ struct scatterlist *sg, int sg_cnt)
+{
+ /* Nothing to do */
+}
+
+/*
+ * Functions for access to the commands data (SG) page. Should be used
+ * instead of direct access. Returns the buffer length for success, 0 for EOD,
+ * negative error code otherwise.
+ *
+ * "Page" argument returns the starting page, "offset" - offset in it.
+ *
+ * The "put" function "puts" the buffer. It should be always be used, because
+ * in future may need to do some additional operations.
+ */
+static inline int __scst_get_sg_page(struct scst_cmd *cmd, int sg_cnt,
+ struct page **page, int *offset)
+{
+ int res = 0;
+ struct scatterlist *sg = cmd->get_sg_buf_cur_sg_entry;
+
+ if (cmd->get_sg_buf_entry_num >= sg_cnt) {
+ *page = NULL;
+ *offset = 0;
+ goto out;
+ }
+
+ if (unlikely(sg_is_chain(sg)))
+ sg = sg_chain_ptr(sg);
+
+ *page = sg_page(sg);
+ *offset = sg->offset;
+ res = sg->length;
+
+ cmd->get_sg_buf_entry_num++;
+ cmd->get_sg_buf_cur_sg_entry = ++sg;
+
+out:
+ return res;
+}
+
+static inline int scst_get_sg_page_first(struct scst_cmd *cmd,
+ struct page **page, int *offset)
+{
+ if (unlikely(cmd->sg == NULL)) {
+ *page = NULL;
+ *offset = 0;
+ return 0;
+ }
+ cmd->get_sg_buf_entry_num = 0;
+ cmd->get_sg_buf_cur_sg_entry = cmd->sg;
+ return __scst_get_sg_page(cmd, cmd->sg_cnt, page, offset);
+}
+
+static inline int scst_get_sg_page_next(struct scst_cmd *cmd,
+ struct page **page, int *offset)
+{
+ return __scst_get_sg_page(cmd, cmd->sg_cnt, page, offset);
+}
+
+static inline void scst_put_sg_page(struct scst_cmd *cmd,
+ struct page *page, int offset)
+{
+ /* Nothing to do */
+}
+
+static inline int scst_get_out_sg_page_first(struct scst_cmd *cmd,
+ struct page **page, int *offset)
+{
+ if (unlikely(cmd->out_sg == NULL)) {
+ *page = NULL;
+ *offset = 0;
+ return 0;
+ }
+ cmd->get_sg_buf_entry_num = 0;
+ cmd->get_sg_buf_cur_sg_entry = cmd->out_sg;
+ return __scst_get_sg_page(cmd, cmd->out_sg_cnt, page, offset);
+}
+
+static inline int scst_get_out_sg_page_next(struct scst_cmd *cmd,
+ struct page **page, int *offset)
+{
+ return __scst_get_sg_page(cmd, cmd->out_sg_cnt, page, offset);
+}
+
+static inline void scst_put_out_sg_page(struct scst_cmd *cmd,
+ struct page *page, int offset)
+{
+ /* Nothing to do */
+}
+
+/*
+ * Returns approximate higher rounded buffers count that
+ * scst_get_buf_[first|next]() return.
+ */
+static inline int scst_get_buf_count(struct scst_cmd *cmd)
+{
+ return (cmd->sg_cnt == 0) ? 1 : cmd->sg_cnt;
+}
+
+/*
+ * Returns approximate higher rounded buffers count that
+ * scst_get_out_buf_[first|next]() return.
+ */
+static inline int scst_get_out_buf_count(struct scst_cmd *cmd)
+{
+ return (cmd->out_sg_cnt == 0) ? 1 : cmd->out_sg_cnt;
+}
+
+int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf);
+void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf);
+
+int scst_suspend_activity(bool interruptible);
+void scst_resume_activity(void);
+
+void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic);
+
+void scst_post_parse(struct scst_cmd *cmd);
+void scst_post_alloc_data_buf(struct scst_cmd *cmd);
+
+int scst_check_local_events(struct scst_cmd *cmd);
+
+int scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd);
+
+struct scst_trace_log {
+ unsigned int val;
+ const char *token;
+};
+
+extern struct mutex scst_mutex;
+
+const struct sysfs_ops *scst_sysfs_get_sysfs_ops(void);
+
+/*
+ * Returns target driver's root sysfs kobject.
+ * The driver can create own files/directories/links here.
+ */
+static inline struct kobject *scst_sysfs_get_tgtt_kobj(
+ struct scst_tgt_template *tgtt)
+{
+ return &tgtt->tgtt_kobj;
+}
+
+/*
+ * Returns target's root sysfs kobject.
+ * The driver can create own files/directories/links here.
+ */
+static inline struct kobject *scst_sysfs_get_tgt_kobj(
+ struct scst_tgt *tgt)
+{
+ return &tgt->tgt_kobj;
+}
+
+/*
+ * Returns device handler's root sysfs kobject.
+ * The driver can create own files/directories/links here.
+ */
+static inline struct kobject *scst_sysfs_get_devt_kobj(
+ struct scst_dev_type *devt)
+{
+ return &devt->devt_kobj;
+}
+
+/*
+ * Returns device's root sysfs kobject.
+ * The driver can create own files/directories/links here.
+ */
+static inline struct kobject *scst_sysfs_get_dev_kobj(
+ struct scst_device *dev)
+{
+ return &dev->dev_kobj;
+}
+
+/*
+ * Returns session's root sysfs kobject.
+ * The driver can create own files/directories/links here.
+ */
+static inline struct kobject *scst_sysfs_get_sess_kobj(
+ struct scst_session *sess)
+{
+ return &sess->sess_kobj;
+}
+
+/* Returns target name */
+static inline const char *scst_get_tgt_name(const struct scst_tgt *tgt)
+{
+ return tgt->tgt_name;
+}
+
+int scst_alloc_sense(struct scst_cmd *cmd, int atomic);
+int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
+ const uint8_t *sense, unsigned int len);
+
+int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
+ int key, int asc, int ascq);
+
+bool scst_is_ua_sense(const uint8_t *sense, int len);
+
+bool scst_analyze_sense(const uint8_t *sense, int len,
+ unsigned int valid_mask, int key, int asc, int ascq);
+
+unsigned long scst_random(void);
+
+void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len);
+
+void scst_get(void);
+void scst_put(void);
+
+void scst_cmd_get(struct scst_cmd *cmd);
+void scst_cmd_put(struct scst_cmd *cmd);
+
+struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count);
+void scst_free(struct scatterlist *sg, int count);
+
+void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
+ struct scst_thr_data_hdr *data,
+ void (*free_fn) (struct scst_thr_data_hdr *data));
+void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev);
+void scst_dev_del_all_thr_data(struct scst_device *dev);
+struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
+ struct task_struct *tsk);
+
+/* Finds local to the current thread data. Returns NULL, if they not found. */
+static inline struct scst_thr_data_hdr *scst_find_thr_data(
+ struct scst_tgt_dev *tgt_dev)
+{
+ return __scst_find_thr_data(tgt_dev, current);
+}
+
+/* Increase ref counter for the thread data */
+static inline void scst_thr_data_get(struct scst_thr_data_hdr *data)
+{
+ atomic_inc(&data->ref);
+}
+
+/* Decrease ref counter for the thread data */
+static inline void scst_thr_data_put(struct scst_thr_data_hdr *data)
+{
+ if (atomic_dec_and_test(&data->ref))
+ data->free_fn(data);
+}
+
+int scst_calc_block_shift(int sector_size);
+int scst_sbc_generic_parse(struct scst_cmd *cmd,
+ int (*get_block_shift)(struct scst_cmd *cmd));
+int scst_cdrom_generic_parse(struct scst_cmd *cmd,
+ int (*get_block_shift)(struct scst_cmd *cmd));
+int scst_modisk_generic_parse(struct scst_cmd *cmd,
+ int (*get_block_shift)(struct scst_cmd *cmd));
+int scst_tape_generic_parse(struct scst_cmd *cmd,
+ int (*get_block_size)(struct scst_cmd *cmd));
+int scst_changer_generic_parse(struct scst_cmd *cmd,
+ int (*nothing)(struct scst_cmd *cmd));
+int scst_processor_generic_parse(struct scst_cmd *cmd,
+ int (*nothing)(struct scst_cmd *cmd));
+int scst_raid_generic_parse(struct scst_cmd *cmd,
+ int (*nothing)(struct scst_cmd *cmd));
+
+int scst_block_generic_dev_done(struct scst_cmd *cmd,
+ void (*set_block_shift)(struct scst_cmd *cmd, int block_shift));
+int scst_tape_generic_dev_done(struct scst_cmd *cmd,
+ void (*set_block_size)(struct scst_cmd *cmd, int block_size));
+
+int scst_obtain_device_parameters(struct scst_device *dev);
+
+void scst_reassign_persistent_sess_states(struct scst_session *new_sess,
+ struct scst_session *old_sess);
+
+int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun);
+
+/*
+ * Has to be put here open coded, because Linux doesn't have equivalent, which
+ * allows exclusive wake ups of threads in LIFO order. We need it to let (yet)
+ * unneeded threads sleep and not pollute CPU cache by their stacks.
+ */
+static inline void add_wait_queue_exclusive_head(wait_queue_head_t *q,
+ wait_queue_t *wait)
+{
+ unsigned long flags;
+
+ wait->flags |= WQ_FLAG_EXCLUSIVE;
+ spin_lock_irqsave(&q->lock, flags);
+ __add_wait_queue(q, wait);
+ spin_unlock_irqrestore(&q->lock, flags);
+}
+
+/*
+ * Structure to match events to user space and replies on them
+ */
+struct scst_sysfs_user_info {
+ /* Unique cookie to identify request */
+ uint32_t info_cookie;
+
+ /* Entry in the global list */
+ struct list_head info_list_entry;
+
+ /* Set if reply from the user space is being executed */
+ unsigned int info_being_executed:1;
+
+ /* Set if this info is in the info_list */
+ unsigned int info_in_list:1;
+
+ /* Completion to wait on for the request completion */
+ struct completion info_completion;
+
+ /* Request completion status and optional data */
+ int info_status;
+ void *data;
+};
+
+int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info);
+void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info);
+struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie);
+int scst_wait_info_completion(struct scst_sysfs_user_info *info,
+ unsigned long timeout);
+
+unsigned int scst_get_setup_id(void);
+
+/*
+ * Needed to avoid potential circular locking dependency between scst_mutex
+ * and internal sysfs locking (s_active). It could be since most sysfs entries
+ * are created and deleted under scst_mutex AND scst_mutex is taken inside
+ * sysfs functions. So, we push from the sysfs functions all the processing
+ * taking scst_mutex. To avoid deadlock, we return from them with EAGAIN
+ * if processing is taking too long. User space then should poll
+ * last_sysfs_mgmt_res until it returns the result of the processing
+ * (something other than EAGAIN).
+ */
+struct scst_sysfs_work_item {
+ /*
+ * If true, then last_sysfs_mgmt_res will not be updated. This is
+ * needed to allow read only sysfs monitoring during management actions.
+ * All management actions are supposed to be externally serialized,
+ * so then last_sysfs_mgmt_res automatically serialized too.
+ * Othewrwise a monitoring action can overwrite value of simultaneous
+ * management action's last_sysfs_mgmt_res.
+ */
+ bool read_only_action;
+
+ struct list_head sysfs_work_list_entry;
+ struct kref sysfs_work_kref;
+ int (*sysfs_work_fn)(struct scst_sysfs_work_item *work);
+ struct completion sysfs_work_done;
+ char *buf;
+
+ union {
+ struct scst_dev_type *devt;
+ struct scst_tgt_template *tgtt;
+ struct {
+ struct scst_tgt *tgt;
+ struct scst_acg *acg;
+ union {
+ bool is_tgt_kobj;
+ int io_grouping_type;
+ bool enable;
+ cpumask_t cpu_mask;
+ };
+ };
+ struct {
+ struct scst_device *dev;
+ int new_threads_num;
+ enum scst_dev_type_threads_pool_type new_threads_pool_type;
+ };
+ struct scst_session *sess;
+ struct {
+ struct scst_tgt *tgt;
+ unsigned long l;
+ };
+ };
+ int work_res;
+ char *res_buf;
+};
+
+int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
+ bool read_only_action, struct scst_sysfs_work_item **res_work);
+int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work);
+void scst_sysfs_work_get(struct scst_sysfs_work_item *work);
+void scst_sysfs_work_put(struct scst_sysfs_work_item *work);
+
+char *scst_get_next_lexem(char **token_str);
+void scst_restore_token_str(char *prev_lexem, char *token_str);
+char *scst_get_next_token_str(char **input_str);
+
+void scst_init_threads(struct scst_cmd_threads *cmd_threads);
+void scst_deinit_threads(struct scst_cmd_threads *cmd_threads);
+
+void scst_pass_through_cmd_done(void *data, char *sense, int result, int resid);
+int scst_scsi_exec_async(struct scst_cmd *cmd, void *data,
+ void (*done)(void *data, char *sense, int result, int resid));
+
+#endif /* __SCST_H */
next prev parent reply other threads:[~2010-10-01 21:39 UTC|newest]
Thread overview: 98+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-01 21:34 [PATCHv4 0/19]: New SCSI target framework (SCST) with dev handlers and 2 target drivers Vladislav Bolkhovitin
2010-10-01 21:36 ` [PATCH 1/19]: Integration of SCST into the Linux kernel tree Vladislav Bolkhovitin
2010-10-01 21:36 ` [PATCH 2/19]: SCST core's Makefile and Kconfig Vladislav Bolkhovitin
2010-10-01 21:38 ` Vladislav Bolkhovitin [this message]
2010-10-01 21:39 ` [PATCH 4/19]: SCST main management files and private headers Vladislav Bolkhovitin
2010-10-01 21:42 ` [PATCH 5/19]: SCST implementation of the SCSI target state machine Vladislav Bolkhovitin
2010-10-01 21:43 ` [PATCH 6/19]: SCST internal library functions Vladislav Bolkhovitin
2010-10-01 21:44 ` [PATCH 7/19]: SCST Persistent Reservations implementation Vladislav Bolkhovitin
2010-10-01 21:46 ` [PATCH 8/19]: SCST SYSFS interface implementation Vladislav Bolkhovitin
2010-10-09 21:20 ` Greg KH
2010-10-11 19:29 ` Vladislav Bolkhovitin
2010-10-11 21:32 ` Greg KH
2010-10-12 18:53 ` Vladislav Bolkhovitin
2010-10-12 19:03 ` Greg KH
2010-10-14 19:48 ` Vladislav Bolkhovitin
2010-10-14 20:04 ` Greg KH
2010-10-22 17:30 ` Vladislav Bolkhovitin
2010-10-22 17:56 ` Greg KH
2010-10-22 18:40 ` Vladislav Bolkhovitin
2010-10-22 18:54 ` Greg KH
2010-11-08 19:58 ` Vladislav Bolkhovitin
2010-11-09 0:28 ` Greg KH
2010-11-09 20:06 ` Vladislav Bolkhovitin
2010-11-10 9:58 ` Boaz Harrosh
2010-11-10 20:19 ` Vladislav Bolkhovitin
2010-11-10 20:29 ` Joe Eykholt
2010-11-10 20:38 ` Vladislav Bolkhovitin
2010-11-10 20:42 ` Joe Eykholt
2010-11-11 9:59 ` Boaz Harrosh
2010-11-11 12:04 ` Greg KH
2010-11-11 14:05 ` Boaz Harrosh
2010-11-11 14:16 ` Greg KH
2010-11-11 14:19 ` Boaz Harrosh
2010-11-11 20:50 ` Vladislav Bolkhovitin
2010-11-12 1:23 ` Dmitry Torokhov
2010-11-12 12:09 ` Bart Van Assche
2010-11-12 12:09 ` Bart Van Assche
2010-11-12 18:44 ` Dmitry Torokhov
2010-11-13 10:52 ` Bart Van Assche
2010-11-13 10:52 ` Bart Van Assche
2010-11-13 17:20 ` Vladislav Bolkhovitin
2010-11-13 23:59 ` Greg KH
2010-11-15 6:59 ` Dmitry Torokhov
2010-11-15 17:53 ` Bart Van Assche
2010-11-15 20:36 ` Vladislav Bolkhovitin
2010-11-15 9:46 ` Boaz Harrosh
2010-11-15 16:16 ` Greg KH
2010-11-15 17:19 ` Boaz Harrosh
2010-11-15 17:49 ` Bart Van Assche
2010-11-15 20:19 ` Nicholas A. Bellinger
2010-11-16 13:12 ` Vladislav Bolkhovitin
2010-11-16 11:59 ` [Scst-devel] " Richard Williams
2010-11-16 13:17 ` Vladislav Bolkhovitin
2010-11-18 21:02 ` Vladislav Bolkhovitin
2010-11-18 21:46 ` Greg KH
2010-11-19 18:00 ` Vladislav Bolkhovitin
2010-11-19 20:22 ` Dmitry Torokhov
2010-11-19 20:50 ` Vladislav Bolkhovitin
2010-11-19 21:16 ` Greg KH
2010-11-24 20:35 ` Vladislav Bolkhovitin
2010-11-19 21:19 ` Greg KH
2010-12-10 12:06 ` Bart Van Assche
2010-12-10 19:36 ` Greg KH
2010-12-14 14:10 ` Bart Van Assche
2010-11-19 18:01 ` Bart Van Assche
2010-11-19 18:01 ` Bart Van Assche
2010-11-15 20:39 ` Vladislav Bolkhovitin
2010-11-15 20:39 ` Vladislav Bolkhovitin
2010-11-15 17:45 ` Bart Van Assche
2010-11-15 18:44 ` Greg KH
2010-11-15 20:39 ` Vladislav Bolkhovitin
2010-11-15 22:13 ` Greg KH
2010-11-16 5:04 ` Joe Eykholt
2010-11-16 6:03 ` Nicholas A. Bellinger
2010-11-16 8:49 ` Florian Mickler
2010-11-16 13:18 ` Vladislav Bolkhovitin
2010-11-16 7:15 ` Bart Van Assche
2010-11-16 13:19 ` Vladislav Bolkhovitin
2010-11-15 20:36 ` Vladislav Bolkhovitin
2010-11-15 7:04 ` Dmitry Torokhov
2010-11-15 20:37 ` Vladislav Bolkhovitin
2010-11-15 21:14 ` Dmitry Torokhov
2010-11-16 13:13 ` Vladislav Bolkhovitin
2010-10-01 21:46 ` [PATCH 9/19]: SCST debugging support routines Vladislav Bolkhovitin
2010-10-01 21:48 ` [PATCH 10/19]: SCST SGV cache Vladislav Bolkhovitin
2010-10-01 21:48 ` [PATCH 11/19]: SCST core's docs Vladislav Bolkhovitin
2010-10-01 21:48 ` Vladislav Bolkhovitin
2010-10-01 21:49 ` [PATCH 12/19]: SCST dev handlers' Makefile Vladislav Bolkhovitin
2010-10-01 21:50 ` [PATCH 13/19]: SCST vdisk dev handler Vladislav Bolkhovitin
2010-10-01 21:51 ` [PATCH 14/19]: SCST pass-through dev handlers Vladislav Bolkhovitin
2010-10-01 21:53 ` [PATCH 15/19]: Implementation of blk_rq_map_kern_sg() Vladislav Bolkhovitin
2010-10-01 21:57 ` [PATCH 16/19]: scst_local target driver Vladislav Bolkhovitin
2010-10-01 21:58 ` [PATCH 17/19]: SCST InfiniBand SRP " Vladislav Bolkhovitin
2010-10-01 22:04 ` [PATCH 18/19]: ibmvstgt: Port from tgt to SCST Vladislav Bolkhovitin
2010-10-01 22:05 ` [PATCH 19/19]: tgt: Removal Vladislav Bolkhovitin
2010-10-02 7:40 ` [PATCHv4 0/19]: New SCSI target framework (SCST) with dev handlers and 2 target drivers Bart Van Assche
2010-10-02 7:40 ` Bart Van Assche
2010-10-06 20:21 ` [Scst-devel] " Steve Modica
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4CA654C6.2070902@vlnb.net \
--to=vst@vlnb.net \
--cc=James.Bottomley@HansenPartnership.com \
--cc=James.Smart@Emulex.Com \
--cc=akpm@linux-foundation.org \
--cc=ayan@marvell.com \
--cc=bart.vanassche@gmail.com \
--cc=dmitry.torokhov@gmail.com \
--cc=fujita.tomonori@lab.ntt.co.jp \
--cc=generationgnu@yahoo.com \
--cc=hare@suse.de \
--cc=jeykholt@cisco.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=michaelc@cs.wisc.edu \
--cc=realrichardsharpe@gmail.com \
--cc=scst-devel@lists.sourceforge.net \
--cc=vuhuong@mellanox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.