mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-19 13:46:25 +00:00
- Version descriptors added
- Multi-transport support added to scst_local - Sysfs attributes "version" and "trace_level" added to scst_local git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2060 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -3746,6 +3746,11 @@ static struct scst_trace_log iscsi_local_trace_tbl[] = {
|
||||
#define ISCSI_TRACE_TBL_HELP ", d_write, conn, conn_dbg, iov, pdu, net_page"
|
||||
#endif
|
||||
|
||||
static uint16_t iscsi_get_scsi_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
return 0x0960; /* iSCSI */
|
||||
}
|
||||
|
||||
struct scst_tgt_template iscsi_template = {
|
||||
.name = "iscsi",
|
||||
.sg_tablesize = 0xFFFF /* no limit */,
|
||||
@@ -3785,6 +3790,7 @@ struct scst_tgt_template iscsi_template = {
|
||||
.task_mgmt_fn_done = iscsi_task_mgmt_fn_done,
|
||||
.report_aen = iscsi_report_aen,
|
||||
.get_initiator_port_transport_id = iscsi_get_initiator_port_transport_id,
|
||||
.get_scsi_transport_version = iscsi_get_scsi_transport_version,
|
||||
};
|
||||
|
||||
static __init int iscsi_run_threads(int count, char *name, int (*fn)(void *))
|
||||
|
||||
+7
-1
@@ -66,7 +66,7 @@ static void mvst_host_action(struct mvs_info *mvi,
|
||||
enum mvst_tgt_host_action_t action, u8 phyid);
|
||||
static int mvst_start_sas_target(struct mvs_info *mvi, u8 id);
|
||||
static int mvst_restart_free_list(struct mvs_info *mvi, u8 slot_id);
|
||||
|
||||
static uint16_t mvst_get_scsi_transport_version(struct scst_cmd *scst_cmd);
|
||||
|
||||
struct kmem_cache *mvst_cmd_cachep;
|
||||
struct mvst_msg_queue tgt_msg_queue;
|
||||
@@ -89,12 +89,18 @@ struct scst_tgt_template tgt_template = {
|
||||
.on_free_cmd = mvst_on_free_cmd,
|
||||
.task_mgmt_fn_done = mvst_task_mgmt_fn_done,
|
||||
.report_aen = mvst_report_event,
|
||||
.get_scsi_transport_version = mvst_get_scsi_transport_version,
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
static uint16_t mvst_get_scsi_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
return 0x0BE0; /* SAS */
|
||||
}
|
||||
|
||||
static u64 mvst_get_be_sas_addr(u8 *sas_addr)
|
||||
{
|
||||
u64 lo = cpu_to_be32((u32)(*(u32 *)&sas_addr[0]));
|
||||
|
||||
@@ -96,6 +96,8 @@ static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset);
|
||||
static void q2t_clear_tgt_db(struct q2t_tgt *tgt, bool local_only);
|
||||
static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd);
|
||||
static int q2t_unreg_sess(struct q2t_sess *sess);
|
||||
static uint16_t q2t_get_scsi_transport_version(struct scst_cmd *scst_cmd);
|
||||
static uint16_t q2t_get_phys_transport_version(struct scst_cmd *scst_cmd);
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
|
||||
@@ -170,6 +172,8 @@ static struct scst_tgt_template tgt2x_template = {
|
||||
.on_free_cmd = q2t_on_free_cmd,
|
||||
.task_mgmt_fn_done = q2t_task_mgmt_fn_done,
|
||||
.get_initiator_port_transport_id = q2t_get_initiator_port_transport_id,
|
||||
.get_scsi_transport_version = q2t_get_scsi_transport_version,
|
||||
.get_phys_transport_version = q2t_get_phys_transport_version,
|
||||
.on_hw_pending_cmd_timeout = q2t_on_hw_pending_cmd_timeout,
|
||||
.enable_target = q2t_enable_tgt,
|
||||
.is_target_enabled = q2t_is_tgt_enabled,
|
||||
@@ -5503,6 +5507,17 @@ static void q2t_proc_log_entry_clean(struct scst_tgt_template *templ)
|
||||
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
static uint16_t q2t_get_scsi_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
/* FCP-2 (speculative, there's no info what FW supports) */
|
||||
return 0x0900;
|
||||
}
|
||||
|
||||
static uint16_t q2t_get_phys_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
return 0x0DA0; /* FC-FS */
|
||||
}
|
||||
|
||||
static int __init q2t_init(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
@@ -1581,6 +1581,11 @@ out:
|
||||
return (res);
|
||||
}
|
||||
|
||||
static uint16_t isp_get_scsi_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
return 0x0900; /* FCP-2 */
|
||||
}
|
||||
|
||||
static struct scst_tgt_template isp_tgt_template =
|
||||
{
|
||||
.sg_tablesize = SG_ALL, /* we set this value lately based on hardware */
|
||||
@@ -1598,6 +1603,7 @@ static struct scst_tgt_template isp_tgt_template =
|
||||
.rdy_to_xfer = isp_rdy_to_xfer,
|
||||
.on_free_cmd = isp_on_free_cmd,
|
||||
.task_mgmt_fn_done = isp_task_mgmt_fn_done,
|
||||
.get_scsi_transport_version = isp_get_scsi_transport_version,
|
||||
|
||||
//.report_aen = isp_report_aen,
|
||||
.get_initiator_port_transport_id = isp_get_initiator_port_transport_id,
|
||||
|
||||
@@ -884,6 +884,22 @@ struct scst_tgt_template {
|
||||
*/
|
||||
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_cmd *cmd);
|
||||
|
||||
/*
|
||||
* 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_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Name of the template. Must be unique to identify
|
||||
* the template. MUST HAVE
|
||||
@@ -2747,6 +2763,12 @@ static inline void scst_cmd_set_ext_cdb(struct scst_cmd *cmd,
|
||||
cmd->ext_cdb_len = ext_cdb_len;
|
||||
}
|
||||
|
||||
/* Returns cmd's target */
|
||||
static inline struct scst_tgt *scst_cmd_get_tgt(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->tgt;
|
||||
}
|
||||
|
||||
/* Returns cmd's session */
|
||||
static inline struct scst_session *scst_cmd_get_session(struct scst_cmd *cmd)
|
||||
{
|
||||
|
||||
@@ -217,6 +217,7 @@ struct scst_vdisk_dev {
|
||||
must be <= SCSI Model + 1 */
|
||||
char *filename; /* File name, protected by
|
||||
scst_mutex and suspended activities */
|
||||
uint16_t command_set_version;
|
||||
unsigned int t10_dev_id_set:1; /* true if t10_dev_id manually set */
|
||||
char t10_dev_id[16+8+2]; /* T10 device ID */
|
||||
char usn[MAX_USN_LEN];
|
||||
@@ -1396,7 +1397,7 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
|
||||
goto out_put;
|
||||
}
|
||||
} else {
|
||||
int len;
|
||||
int len, num;
|
||||
|
||||
if (cmd->cdb[2] != 0) {
|
||||
TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
|
||||
@@ -1433,6 +1434,46 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
|
||||
* aligned.
|
||||
*/
|
||||
memcpy(&buf[32], SCST_FIO_REV, 4);
|
||||
|
||||
/** Version descriptors **/
|
||||
|
||||
buf[4] += 58 - 36;
|
||||
num = 0;
|
||||
|
||||
/* SAM-3 T10/1561-D revision 14 */
|
||||
buf[58 + num] = 0x0;
|
||||
buf[58 + num + 1] = 0x76;
|
||||
num += 2;
|
||||
|
||||
/* Physical transport */
|
||||
if (cmd->tgtt->get_phys_transport_version != NULL) {
|
||||
uint16_t v = cmd->tgtt->get_phys_transport_version(cmd);
|
||||
if (v != 0) {
|
||||
*((uint16_t *)&buf[58 + num]) = cpu_to_be16(v);
|
||||
num += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* SCSI transport */
|
||||
if (cmd->tgtt->get_scsi_transport_version != NULL) {
|
||||
*((uint16_t *)&buf[58 + num]) =
|
||||
cpu_to_be16(cmd->tgtt->get_scsi_transport_version(cmd));
|
||||
num += 2;
|
||||
}
|
||||
|
||||
/* SPC-3 T10/1416-D revision 23 */
|
||||
buf[58 + num] = 0x3;
|
||||
buf[58 + num + 1] = 0x12;
|
||||
num += 2;
|
||||
|
||||
/* Device command set */
|
||||
if (virt_dev->command_set_version != 0) {
|
||||
*((uint16_t *)&buf[58 + num]) =
|
||||
cpu_to_be16(virt_dev->command_set_version);
|
||||
num += 2;
|
||||
}
|
||||
|
||||
buf[4] += num;
|
||||
resp_len = buf[4] + 5;
|
||||
}
|
||||
|
||||
@@ -3216,6 +3257,8 @@ static int vdev_fileio_add_device(const char *device_name, char *params)
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
virt_dev->command_set_version = 0x04C0; /* SBC-3 */
|
||||
|
||||
virt_dev->wt_flag = DEF_WRITE_THROUGH;
|
||||
virt_dev->nv_cache = DEF_NV_CACHE;
|
||||
virt_dev->o_direct_flag = DEF_O_DIRECT;
|
||||
@@ -3277,6 +3320,8 @@ static int vdev_blockio_add_device(const char *device_name, char *params)
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
virt_dev->command_set_version = 0x04C0; /* SBC-3 */
|
||||
|
||||
virt_dev->blockio = 1;
|
||||
|
||||
res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
|
||||
@@ -3329,6 +3374,8 @@ static int vdev_nullio_add_device(const char *device_name, char *params)
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
virt_dev->command_set_version = 0x04C0; /* SBC-3 */
|
||||
|
||||
virt_dev->nullio = 1;
|
||||
|
||||
res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
|
||||
@@ -3486,6 +3533,8 @@ static ssize_t __vcdrom_add_device(const char *device_name, char *params)
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
virt_dev->command_set_version = 0x02A0; /* MMC-3 */
|
||||
|
||||
virt_dev->rd_only = 1;
|
||||
virt_dev->removable = 1;
|
||||
virt_dev->cdrom_empty = 1;
|
||||
|
||||
+354
-44
@@ -59,7 +59,7 @@
|
||||
|
||||
#ifdef CONFIG_SCST_DEBUG
|
||||
#define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_PID | \
|
||||
TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
|
||||
TRACE_LINE | TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
|
||||
TRACE_MINOR | TRACE_SPECIAL)
|
||||
#else
|
||||
# ifdef CONFIG_SCST_TRACING
|
||||
@@ -130,6 +130,8 @@ static int num_aborts;
|
||||
static int num_dev_resets;
|
||||
static int num_target_resets;
|
||||
|
||||
static DEFINE_MUTEX(scst_local_mutex);
|
||||
|
||||
/*
|
||||
* We put AEN items on a list on the scst_local_host_info structure so they
|
||||
* can be processed via a work function. We do not actually need the LUN, since
|
||||
@@ -155,6 +157,16 @@ struct scst_local_host_info {
|
||||
struct work_struct local_work;
|
||||
spinlock_t lock;
|
||||
struct list_head work_list;
|
||||
uint16_t scsi_transport_version, phys_transport_version;
|
||||
uint8_t *transport_id;
|
||||
int transport_id_len;
|
||||
};
|
||||
|
||||
struct scst_local_sess_info {
|
||||
struct scst_local_host_info *host;
|
||||
int number;
|
||||
uint8_t *transport_id;
|
||||
int transport_id_len;
|
||||
};
|
||||
|
||||
#define to_scst_lcl_host(d) \
|
||||
@@ -185,6 +197,8 @@ struct scst_local_tgt_specific {
|
||||
static struct kmem_cache *tgt_specific_pool;
|
||||
#endif
|
||||
|
||||
static atomic_t scst_local_sess_number = ATOMIC_INIT(0);
|
||||
|
||||
static LIST_HEAD(scst_local_host_list);
|
||||
static DEFINE_SPINLOCK(scst_local_host_list_lock);
|
||||
|
||||
@@ -710,14 +724,17 @@ static int scst_local_report_aen(struct scst_aen *aen)
|
||||
{
|
||||
int res = 0;
|
||||
int event_fn = scst_aen_get_event_fn(aen);
|
||||
struct scst_local_host_info *scst_lcl_host = scst_sess_get_tgt_priv(
|
||||
scst_aen_get_sess(aen));
|
||||
/*__be64 lun = scst_aen_get_lun(aen);*/
|
||||
struct scst_local_host_info *scst_lcl_host;
|
||||
struct scst_local_sess_info *sess;
|
||||
struct scst_local_work_item *work_item = NULL;
|
||||
long unsigned flags;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
sess = (struct scst_local_sess_info *)scst_sess_get_tgt_priv(
|
||||
scst_aen_get_sess(aen));
|
||||
scst_lcl_host = sess->host;
|
||||
|
||||
switch (event_fn) {
|
||||
case SCST_AEN_SCSI:
|
||||
/*
|
||||
@@ -749,25 +766,16 @@ static int scst_local_report_aen(struct scst_aen *aen)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int scst_local_get_initiator_port_transport_id(
|
||||
struct scst_session *scst_sess,
|
||||
uint8_t **transport_id)
|
||||
static int scst_local_get_sas_transport_id(
|
||||
struct scst_local_sess_info *sess,
|
||||
uint8_t **transport_id, int *len)
|
||||
{
|
||||
int res = 0;
|
||||
int tr_id_size = 0, sess = -1, i = 0;
|
||||
int tr_id_size = 0;
|
||||
uint8_t *tr_id = NULL;
|
||||
struct scst_local_host_info *scst_lcl_host;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (scst_sess == NULL) {
|
||||
res = SCSI_TRANSPORTID_PROTOCOLID_SAS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
scst_lcl_host = (struct scst_local_host_info *)
|
||||
scst_sess_get_tgt_priv(scst_sess);
|
||||
|
||||
tr_id_size = 24; /* A SAS TransportID */
|
||||
|
||||
tr_id = kzalloc(tr_id_size, GFP_KERNEL);
|
||||
@@ -780,23 +788,6 @@ static int scst_local_get_initiator_port_transport_id(
|
||||
|
||||
tr_id[0] = 0x00 | SCSI_TRANSPORTID_PROTOCOLID_SAS;
|
||||
|
||||
for (i = 0; i < scst_local_num_tgts; i++) {
|
||||
/*
|
||||
* We are called before the session is returned below
|
||||
*/
|
||||
if (scst_lcl_host->session[i] == NULL) {
|
||||
sess = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sess == -1) {
|
||||
printk(KERN_INFO "%s: Unable to find a matching session\n",
|
||||
__func__);
|
||||
res = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assemble a valid SAS address = 0x5OOUUIIR12345678 ... Does SCST
|
||||
* have one?
|
||||
@@ -805,13 +796,14 @@ static int scst_local_get_initiator_port_transport_id(
|
||||
tr_id[4] = 0x5F;
|
||||
tr_id[5] = 0xEE;
|
||||
tr_id[6] = 0xDE;
|
||||
tr_id[7] = 0x40 | ((sess >> 4) & 0x0F);
|
||||
tr_id[8] = 0x0F | (sess & 0xF0);
|
||||
tr_id[7] = 0x40 | ((sess->number >> 4) & 0x0F);
|
||||
tr_id[8] = 0x0F | (sess->number & 0xF0);
|
||||
tr_id[9] = 0xAD;
|
||||
tr_id[10] = 0xE0;
|
||||
tr_id[11] = 0x50;
|
||||
|
||||
*transport_id = tr_id;
|
||||
*len = tr_id_size;
|
||||
|
||||
TRACE_DBG("Created tid '%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'",
|
||||
tr_id[4], tr_id[5], tr_id[6], tr_id[7],
|
||||
@@ -822,6 +814,53 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int scst_local_get_initiator_port_transport_id(
|
||||
struct scst_session *scst_sess,
|
||||
uint8_t **transport_id)
|
||||
{
|
||||
int res = 0;
|
||||
int tr_id_size = 0;
|
||||
uint8_t *tr_id = NULL;
|
||||
struct scst_local_sess_info *sess;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (scst_sess == NULL) {
|
||||
res = SCSI_TRANSPORTID_PROTOCOLID_SAS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sess = (struct scst_local_sess_info *)scst_sess_get_tgt_priv(scst_sess);
|
||||
|
||||
mutex_lock(&scst_local_mutex);
|
||||
|
||||
if (sess->transport_id == NULL) {
|
||||
res = scst_local_get_sas_transport_id(sess,
|
||||
transport_id, &tr_id_size);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
tr_id_size = sess->transport_id_len;
|
||||
sBUG_ON(tr_id_size == 0);
|
||||
|
||||
tr_id = kzalloc(tr_id_size, GFP_KERNEL);
|
||||
if (tr_id == NULL) {
|
||||
PRINT_ERROR("Allocation of TransportID (size %d) failed",
|
||||
tr_id_size);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(tr_id, sess->transport_id, sess->transport_id_len);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_local_mutex);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void scst_local_release_adapter(struct device *dev)
|
||||
{
|
||||
struct scst_local_host_info *scst_lcl_host;
|
||||
@@ -831,9 +870,14 @@ static void scst_local_release_adapter(struct device *dev)
|
||||
scst_lcl_host = to_scst_lcl_host(dev);
|
||||
if (scst_lcl_host) {
|
||||
for (i = 0; i < scst_local_num_tgts; i++)
|
||||
if (scst_lcl_host->session[i])
|
||||
if (scst_lcl_host->session[i]) {
|
||||
struct scst_local_sess_info *sess;
|
||||
sess = scst_sess_get_tgt_priv(
|
||||
scst_lcl_host->session[i]);
|
||||
scst_unregister_session(
|
||||
scst_lcl_host->session[i], TRUE, NULL);
|
||||
kfree(sess);
|
||||
}
|
||||
scst_unregister_target(scst_lcl_host->target);
|
||||
cancel_work_sync(&scst_lcl_host->local_work);
|
||||
kfree(scst_lcl_host);
|
||||
@@ -858,11 +902,10 @@ static int scst_local_add_adapter(void)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
scst_lcl_host = kzalloc(sizeof(struct scst_local_host_info),
|
||||
GFP_KERNEL);
|
||||
scst_lcl_host = kzalloc(sizeof(*scst_lcl_host), GFP_KERNEL);
|
||||
if (NULL == scst_lcl_host) {
|
||||
printk(KERN_ERR "%s out of memory at line %d\n",
|
||||
__func__, __LINE__);
|
||||
PRINT_ERROR("Unable to alloc scst_lcl_host (size %d)",
|
||||
sizeof(*scst_lcl_host));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -882,17 +925,32 @@ static int scst_local_add_adapter(void)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
scst_tgt_set_tgt_priv(scst_lcl_host->target, scst_lcl_host);
|
||||
|
||||
/*
|
||||
* Create a session for each device
|
||||
*/
|
||||
for (i = 0; i < scst_local_num_tgts; i++) {
|
||||
struct scst_local_sess_info *sess;
|
||||
|
||||
sess = kzalloc(sizeof(*sess), GFP_KERNEL);
|
||||
if (NULL == sess) {
|
||||
PRINT_ERROR("Unable to alloc scst_lcl_host (size %d)",
|
||||
sizeof(*sess));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sess->host = scst_lcl_host;
|
||||
sess->number = atomic_inc_return(&scst_local_sess_number);
|
||||
|
||||
sprintf(name, "scstlclhst%d:%d", scst_local_add_host, i);
|
||||
scst_lcl_host->session[i] = scst_register_session(
|
||||
scst_lcl_host->target,
|
||||
0, name, (void *)scst_lcl_host,
|
||||
0, name, (void *)sess,
|
||||
NULL, NULL);
|
||||
if (!scst_lcl_host->session[i]) {
|
||||
printk(KERN_WARNING "scst_register_session failed:\n");
|
||||
kfree(sess);
|
||||
error = -1;
|
||||
goto unregister_target;
|
||||
}
|
||||
@@ -1395,12 +1453,259 @@ static void scst_local_targ_task_mgmt_done(struct scst_mgmt_cmd *mgmt_cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
|
||||
static ssize_t scst_local_version_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
sprintf(buf, "%s/%s\n", SCST_LOCAL_VERSION, scst_local_version_date);
|
||||
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
strcat(buf, "EXTRACHECKS\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_TRACING
|
||||
strcat(buf, "TRACING\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_DEBUG
|
||||
strcat(buf, "DEBUG\n");
|
||||
#endif
|
||||
|
||||
TRACE_EXIT();
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static struct kobj_attribute scst_local_version_attr =
|
||||
__ATTR(version, S_IRUGO, scst_local_version_show, NULL);
|
||||
|
||||
static ssize_t scst_local_scsi_transport_version_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_tgt *scst_tgt;
|
||||
struct scst_local_host_info *host;
|
||||
ssize_t size;
|
||||
|
||||
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
host = (struct scst_local_host_info *)scst_tgt_get_tgt_priv(scst_tgt);
|
||||
|
||||
if (host->scsi_transport_version != 0)
|
||||
size = sprintf(buf, "0x%x\n%s", host->scsi_transport_version,
|
||||
SCST_SYSFS_KEY_MARK "\n");
|
||||
else
|
||||
size = sprintf(buf, "0x%x\n", 0x0BE0); /* SAS */
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t scst_local_scsi_transport_version_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buffer, size_t size)
|
||||
{
|
||||
ssize_t res;
|
||||
struct scst_tgt *scst_tgt;
|
||||
struct scst_local_host_info *host;
|
||||
unsigned long val;
|
||||
|
||||
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
host = (struct scst_local_host_info *)scst_tgt_get_tgt_priv(scst_tgt);
|
||||
|
||||
res = strict_strtoul(buffer, 0, &val);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("strict_strtoul() for %s failed: %d", buffer, res);
|
||||
goto out;
|
||||
}
|
||||
|
||||
host->scsi_transport_version = val;
|
||||
|
||||
res = size;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct kobj_attribute scst_local_scsi_transport_version_attr =
|
||||
__ATTR(scsi_transport_version, S_IRUGO| S_IWUSR,
|
||||
scst_local_scsi_transport_version_show,
|
||||
scst_local_scsi_transport_version_store);
|
||||
|
||||
static ssize_t scst_local_phys_transport_version_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_tgt *scst_tgt;
|
||||
struct scst_local_host_info *host;
|
||||
|
||||
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
host = (struct scst_local_host_info *)scst_tgt_get_tgt_priv(scst_tgt);
|
||||
|
||||
return sprintf(buf, "0x%x\n%s", host->phys_transport_version,
|
||||
(host->phys_transport_version != 0) ?
|
||||
SCST_SYSFS_KEY_MARK "\n" : "");
|
||||
}
|
||||
|
||||
static ssize_t scst_local_phys_transport_version_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buffer, size_t size)
|
||||
{
|
||||
ssize_t res;
|
||||
struct scst_tgt *scst_tgt;
|
||||
struct scst_local_host_info *host;
|
||||
unsigned long val;
|
||||
|
||||
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
host = (struct scst_local_host_info *)scst_tgt_get_tgt_priv(scst_tgt);
|
||||
|
||||
res = strict_strtoul(buffer, 0, &val);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("strict_strtoul() for %s failed: %d", buffer, res);
|
||||
goto out;
|
||||
}
|
||||
|
||||
host->phys_transport_version = val;
|
||||
|
||||
res = size;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct kobj_attribute scst_local_phys_transport_version_attr =
|
||||
__ATTR(phys_transport_version, S_IRUGO| S_IWUSR,
|
||||
scst_local_phys_transport_version_show,
|
||||
scst_local_phys_transport_version_store);
|
||||
|
||||
static ssize_t scst_local_transport_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t res;
|
||||
struct scst_session *scst_sess;
|
||||
struct scst_local_sess_info *sess;
|
||||
uint8_t *tr_id;
|
||||
int tr_id_len, i;
|
||||
|
||||
scst_sess = container_of(kobj, struct scst_session, sess_kobj);
|
||||
sess = (struct scst_local_sess_info *)scst_sess_get_tgt_priv(scst_sess);
|
||||
|
||||
mutex_lock(&scst_local_mutex);
|
||||
|
||||
if (sess->transport_id != NULL) {
|
||||
tr_id = sess->transport_id;
|
||||
tr_id_len = sess->transport_id_len;
|
||||
} else {
|
||||
res = scst_local_get_sas_transport_id(sess, &tr_id, &tr_id_len);
|
||||
if (res != 0)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
res = 0;
|
||||
for (i = 0; i < tr_id_len; i++)
|
||||
res += sprintf(&buf[res], "%c", tr_id[i]);
|
||||
|
||||
if (sess->transport_id != NULL)
|
||||
res += sprintf(&buf[res], "\n%s", SCST_SYSFS_KEY_MARK "\n");
|
||||
else
|
||||
kfree(tr_id);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_local_mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t scst_local_transport_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buffer, size_t size)
|
||||
{
|
||||
ssize_t res;
|
||||
struct scst_session *scst_sess;
|
||||
struct scst_local_sess_info *sess;
|
||||
|
||||
scst_sess = container_of(kobj, struct scst_session, sess_kobj);
|
||||
sess = (struct scst_local_sess_info *)scst_sess_get_tgt_priv(scst_sess);
|
||||
|
||||
mutex_lock(&scst_local_mutex);
|
||||
|
||||
if (sess->transport_id != NULL) {
|
||||
kfree(sess->transport_id);
|
||||
sess->transport_id = NULL;
|
||||
sess->transport_id_len = 0;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
goto out_res;
|
||||
|
||||
sess->transport_id = kzalloc(size, GFP_KERNEL);
|
||||
if (sess->transport_id == NULL) {
|
||||
PRINT_ERROR("Allocation of transport_id (size %d) failed",
|
||||
size);
|
||||
res = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
sess->transport_id_len = size;
|
||||
|
||||
memcpy(sess->transport_id, buffer, sess->transport_id_len);
|
||||
|
||||
out_res:
|
||||
res = size;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_local_mutex);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct kobj_attribute scst_local_transport_id_attr =
|
||||
__ATTR(transport_id, S_IRUGO| S_IWUSR,
|
||||
scst_local_transport_id_show,
|
||||
scst_local_transport_id_store);
|
||||
|
||||
static const struct attribute *scst_local_tgtt_attrs[] = {
|
||||
&scst_local_version_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute *scst_local_tgt_attrs[] = {
|
||||
&scst_local_scsi_transport_version_attr.attr,
|
||||
&scst_local_phys_transport_version_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute *scst_local_sess_attrs[] = {
|
||||
&scst_local_transport_id_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
static uint16_t scst_local_get_scsi_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
struct scst_local_host_info *host;
|
||||
|
||||
host = (struct scst_local_host_info *)scst_tgt_get_tgt_priv(
|
||||
scst_cmd_get_tgt(scst_cmd));
|
||||
|
||||
if (host->scsi_transport_version == 0)
|
||||
return 0x0BE0; /* SAS */
|
||||
else
|
||||
return host->scsi_transport_version;
|
||||
}
|
||||
|
||||
static uint16_t scst_local_get_phys_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
struct scst_local_host_info *host;
|
||||
|
||||
host = (struct scst_local_host_info *)scst_tgt_get_tgt_priv(
|
||||
scst_cmd_get_tgt(scst_cmd));
|
||||
|
||||
return host->phys_transport_version;
|
||||
}
|
||||
|
||||
static struct scst_tgt_template scst_local_targ_tmpl = {
|
||||
.name = "scst_local_tgt",
|
||||
.sg_tablesize = 0xffff,
|
||||
.xmit_response_atomic = 1,
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
.enabled_attr_not_needed = 1,
|
||||
.tgtt_attrs = scst_local_tgtt_attrs,
|
||||
.tgt_attrs = scst_local_tgt_attrs,
|
||||
.sess_attrs = scst_local_sess_attrs,
|
||||
#endif
|
||||
.detect = scst_local_targ_detect,
|
||||
.release = scst_local_targ_release,
|
||||
@@ -1409,8 +1714,13 @@ static struct scst_tgt_template scst_local_targ_tmpl = {
|
||||
.on_free_cmd = scst_local_targ_on_free_cmd,
|
||||
.task_mgmt_fn_done = scst_local_targ_task_mgmt_done,
|
||||
.report_aen = scst_local_report_aen,
|
||||
.get_initiator_port_transport_id
|
||||
= scst_local_get_initiator_port_transport_id,
|
||||
.get_initiator_port_transport_id = scst_local_get_initiator_port_transport_id,
|
||||
.get_scsi_transport_version = scst_local_get_scsi_transport_version,
|
||||
.get_phys_transport_version = scst_local_get_phys_transport_version,
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
.default_trace_flags = SCST_LOCAL_DEFAULT_LOG_FLAGS,
|
||||
.trace_flags = &trace_flag,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -3495,6 +3495,11 @@ static int srpt_release(struct scst_tgt *scst_tgt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t srpt_get_scsi_transport_version(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
return 0x0940; /* SRP */
|
||||
}
|
||||
|
||||
/* SCST target template for the SRP target implementation. */
|
||||
static struct scst_tgt_template srpt_template = {
|
||||
.name = DRV_NAME,
|
||||
@@ -3516,6 +3521,7 @@ static struct scst_tgt_template srpt_template = {
|
||||
.on_free_cmd = srpt_on_free_cmd,
|
||||
.task_mgmt_fn_done = srpt_tsk_mgmt_done,
|
||||
.get_initiator_port_transport_id = srpt_get_initiator_port_transport_id,
|
||||
.get_scsi_transport_version = srpt_get_scsi_transport_version,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user