Skip to contentSkip to conversation

: Add support for UNIT_ATTENTION conditions

PATCH New Nicholas A. Bellinger 1 participant 1 message Mar 25, 2009 SCSI

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 : Add support for UNIT_ATTENTION conditions

Quoted 1 line

From 2fed7603d2b4b8f0fb7a6bd1f3087eb6cbe0d21a Mon Sep 17 00:00:00 2001

From: Nicholas Bellinger <[email protected]>
Date: Tue, 24 Mar 2009 22:14:27 -0700
Subject: [PATCH 1/2] [Target_Core_Mod]: Add support for UNIT_ATTENTION conditions

This patch adds support for UNIT_ATTENTION and ua_intlck_ctrl emulation following spc4r17, section 7.4.6 Control Mode Page, Table 349.

Upon reception of a REQUEST_SENSE, this patch will report and release a UNIT_ATTENTION condition for a given I_T Nexus. It adds a se_ua_t structure defs, and new UA related structure members to se_dev_entry_t in se_node_acl->device_list[] coming from se_lun_acl_t mapped se_lun_t objects. Upon release of mapped target_core_mod LUN ACL, this patch will release all associated UNIT ATTENTION conditions.

By default, this patch uses ua_intlck_ctrl code 00b, and clears UNIT ATTENTION conditions by sending CHECK_CONDITION with a SENSE KEY of UNIT ATTENTION + the associated highest priority ASC+ASCQ when a UNIT ATTENTION condition has been established. Note that this is the current behaviour of Linux/SCSI and linux/drivers/scsi midlayer code for ua_intlck_ctrl.

This patch also supports the optional 2nd and 3rd modes of ua_intlck_ctrl (code 10b and 11b), with the latter using:
target_core_ua.h:ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS.
Both of these modes have been tested with this code and require manual intervention with sg_requests and REQUEST_SENSE for Linux/SCSI Initiator ports to explictly release a target_core_mod established UNIT ATTENTION condition.

---
 drivers/lio-core/Makefile                |    1 +
 drivers/lio-core/target_core_base.h      |   13 ++
 drivers/lio-core/target_core_configfs.c  |    4 +
 drivers/lio-core/target_core_device.c    |   27 +++-
 drivers/lio-core/target_core_device.h    |    1 +
 drivers/lio-core/target_core_tpg.c       |   10 +
 drivers/lio-core/target_core_transport.c |  127 ++++++++++--
 drivers/lio-core/target_core_transport.h |    2 +
 drivers/lio-core/target_core_ua.c        |  333 ++++++++++++++++++++++++++++++
 drivers/lio-core/target_core_ua.h        |   36 ++++
 10 files changed, 534 insertions(+), 20 deletions(-)
 create mode 100644 drivers/lio-core/target_core_ua.c
 create mode 100644 drivers/lio-core/target_core_ua.h
drivers/lio-core/Makefile +1 -0
index a171db3..66eba19 100644
@@ -40,6 +40,7 @@ target_core_mod-objs			:=	target_core_configfs.o \
 						target_core_tmr.o \
 						target_core_tpg.o \
 						target_core_transport.o \
+						target_core_ua.o \
 						div64.o
 
 ifeq ($(LINUX_IBLOCK), 1)
drivers/lio-core/target_core_base.h +13 -0
index cab978f..cb56d6a 100644
@@ -197,6 +197,7 @@
 #define UNKNOWN_MODE_PAGE			0xb
 #define WRITE_PROTECTED				0xc
 #define CHECK_CONDITION_ABORT_CMD		0xd
+#define CHECK_CONDITION_UNIT_ATTENTION		0xe
 
 typedef struct se_obj_s {
 	atomic_t obj_access_count;
@@ -539,6 +540,14 @@ typedef struct se_tmr_req_s {
 	struct list_head	tmr_list;
 } ____cacheline_aligned se_tmr_req_t;
 
+typedef struct se_ua_s {
+	u8			ua_asc;
+	u8			ua_ascq;
+	struct se_node_acl_s	*ua_nacl;
+	struct list_head	ua_dev_list;
+	struct list_head	ua_nacl_list;
+} ____cacheline_aligned se_ua_t;
+
 typedef struct se_node_acl_s {
 	char			initiatorname[TRANSPORT_IQN_LEN];
 	int			nodeacl_flags;
@@ -600,12 +609,16 @@ typedef struct se_dev_entry_s {
 	u64			read_bytes;
 	u64			write_bytes;
 #endif /* SNMP_SUPPORT */
+	atomic_t		ua_count;
+	spinlock_t		ua_lock;
 	struct se_lun_s		*se_lun;
+	struct list_head	ua_list;
 }  ____cacheline_aligned se_dev_entry_t;
 
 typedef struct se_dev_attrib_s {
 	int		status_thread;
 	int		status_thread_tur;
+	int		emulate_ua_intlck_ctrl;
 	int		emulate_tas;
 	int		emulate_reservations;
 	int		emulate_alua;
drivers/lio-core/target_core_configfs.c +4 -0
index 5473d4c..975ecb8 100644
@@ -478,6 +478,9 @@ SE_DEV_ATTR(status_thread, S_IRUGO | S_IWUSR);
 DEF_DEV_ATTRIB(status_thread_tur);
 SE_DEV_ATTR(status_thread_tur, S_IRUGO | S_IWUSR);
 
+DEF_DEV_ATTRIB(emulate_ua_intlck_ctrl);
+SE_DEV_ATTR(emulate_ua_intlck_ctrl, S_IRUGO | S_IWUSR);
+
 DEF_DEV_ATTRIB(emulate_tas);
 SE_DEV_ATTR(emulate_tas, S_IRUGO | S_IWUSR);
 
@@ -507,6 +510,7 @@ CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib_s, da_group);
 static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
 	&target_core_dev_attrib_status_thread.attr,
 	&target_core_dev_attrib_status_thread_tur.attr,
+	&target_core_dev_attrib_emulate_ua_intlck_ctrl.attr,
 	&target_core_dev_attrib_emulate_tas.attr,
 	&target_core_dev_attrib_hw_block_size.attr,
 	&target_core_dev_attrib_block_size.attr,
drivers/lio-core/target_core_device.c +25 -2
index a1c5c95..95ab18d 100644
@@ -49,6 +49,7 @@
 #include <target_core_pr.h>
 #include <target_core_tpg.h>
 #include <target_core_transport.h>
+#include <target_core_ua.h>
 #include <target_core_fabric_ops.h>
 #include <target_core_plugin.h>
 #include <target_core_seobj.h>
@@ -483,12 +484,12 @@ void core_update_device_list_for_node(
 		deve->attach_count++;
 #endif /* SNMP_SUPPORT */
 		spin_unlock_bh(&nacl->device_list_lock);
-
 		return;
 	}
 	/*
 	 * Disable se_dev_entry_t LUN ACL mapping
 	 */
+	core_scsi3_ua_release_all(deve);
 	deve->se_lun = NULL;
 	deve->lun_flags = 0;
 	deve->creation_time = 0;
@@ -869,6 +870,7 @@ void se_dev_set_default_attribs(se_device_t *dev)
 {
 	DEV_ATTRIB(dev)->status_thread = DA_STATUS_THREAD;
 	DEV_ATTRIB(dev)->status_thread_tur = DA_STATUS_THREAD_TUR;
+	DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL;
 	DEV_ATTRIB(dev)->emulate_tas = DA_EMULATE_TAS;
 	DEV_ATTRIB(dev)->emulate_reservations = DA_EMULATE_RESERVATIONS;
 	DEV_ATTRIB(dev)->emulate_alua = DA_EMULATE_ALUA;
@@ -970,11 +972,32 @@ int se_dev_set_status_thread_tur(se_device_t *dev, int flag)
 	return 0;
 }
 
+int se_dev_set_emulate_ua_intlck_ctrl(se_device_t *dev, int flag)
+{
+	if ((flag != 0) && (flag != 1) && (flag != 2)) {
+		printk(KERN_ERR "Illegal value %d\n", flag);
+		return -1;
+	}
+
+	if (DEV_OBJ_API(dev)->check_count(&dev->dev_export_obj)) {
+		printk(KERN_ERR "dev[%p]: Unable to change SE Device"
+			" UA_INTRLCK_CTRL while dev_export_obj: %d count"
+			" exists\n", dev,
+			DEV_OBJ_API(dev)->check_count(&dev->dev_export_obj));
+		return -1;
+	}
+	DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl = flag;
+	printk(KERN_INFO "dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n",
+		dev, DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl);
+
+	return 0;
+}
+
 int se_dev_set_emulate_tas(se_device_t *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
 		printk(KERN_ERR "Illegal value %d\n", flag);
-		return 1;
+		return -1;
 	}
 
 	if (DEV_OBJ_API(dev)->check_count(&dev->dev_export_obj)) {
drivers/lio-core/target_core_device.h +1 -0
index 3b46ef1..2877d01 100644
@@ -62,6 +62,7 @@ extern void se_dev_set_default_attribs(se_device_t *);
 extern int se_dev_set_task_timeout(se_device_t *, u32);
 extern int se_dev_set_status_thread(se_device_t *, int);
 extern int se_dev_set_status_thread_tur(se_device_t *, int);
+extern int se_dev_set_emulate_ua_intlck_ctrl(se_device_t *, int);
 extern int se_dev_set_emulate_tas(se_device_t *, int);
 extern int se_dev_set_queue_depth(se_device_t *, u32);
 extern int se_dev_set_max_sectors(se_device_t *, u32);
drivers/lio-core/target_core_tpg.c +10 -0
index 406cbae..e406022 100644
@@ -235,6 +235,9 @@ static int core_set_queue_depth_for_node(
  */
 static int core_create_device_list_for_node(se_node_acl_t *nacl)
 {
+	se_dev_entry_t *deve;
+	int i;
+
 	nacl->device_list = kzalloc(sizeof(se_dev_entry_t) *
 				TRANSPORT_MAX_LUNS_PER_TPG, GFP_KERNEL);
 	if (!(nacl->device_list)) {
@@ -242,6 +245,13 @@ static int core_create_device_list_for_node(se_node_acl_t *nacl)
 			" se_node_acl_t->device_list\n");
 		return -1;
 	}
+	for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
+		deve = &nacl->device_list[i];
+
+		atomic_set(&deve->ua_count, 0);
+		spin_lock_init(&deve->ua_lock);
+		INIT_LIST_HEAD(&deve->ua_list);
+	}
 
 	return 0;
 }
drivers/lio-core/target_core_transport.c +109 -18

207 lines not on this page · raw message

drivers/lio-core/target_core_transport.h +2 -0
index f3637ec..d207462 100644
@@ -102,6 +102,8 @@
 #define DA_STATUS_THREAD			0
 /* Disabled by default */
 #define DA_STATUS_THREAD_TUR			0
+/* Emulation for UNIT ATTENTION Interlock Control */
+#define DA_EMULATE_UA_INTLLCK_CTRL		0
 /* Emulation for TASK_ABORTED status (TAS) by default */
 #define DA_EMULATE_TAS				1
 /* No Emulation for PSCSI by default */
drivers/lio-core/target_core_ua.c new file +333 -0

333 lines not on this page · raw message

drivers/lio-core/target_core_ua.h new file +36 -0
new file mode 100644
index 0000000..9e600d0
@@ -0,0 +1,36 @@
+#ifndef TARGET_CORE_UA_H
+
+/*
+ * From spc4r17, Table D.1: ASC and ASCQ Assignement
+ */
+#define ASCQ_29H_POWER_ON_RESET_OR_BUS_DEVICE_RESET_OCCURED	0x00
+#define ASCQ_29H_POWER_ON_OCCURRED				0x01
+#define ASCQ_29H_SCSI_BUS_RESET_OCCURED				0x02
+#define ASCQ_29H_BUS_DEVICE_RESET_FUNCTION_OCCURRED		0x03
+#define ASCQ_29H_DEVICE_INTERNAL_RESET				0x04
+#define ASCQ_29H_TRANSCEIVER_MODE_CHANGED_TO_SINGLE_ENDED	0x05
+#define ASCQ_29H_TRANSCEIVER_MODE_CHANGED_TO_LVD		0x06
+#define ASCQ_29H_NEXUS_LOSS_OCCURRED				0x07
+
+#define ASCQ_2AH_PARAMETERS_CHANGED				0x00
+#define ASCQ_2AH_MODE_PARAMETERS_CHANGED			0x01
+#define ASCQ_2AH_LOG_PARAMETERS_CHANGED				0x02
+#define ASCQ_2AH_RESERVATIONS_PREEMPTED				0x03
+#define ASCQ_2AH_RESERVATIONS_RELEASED				0x04
+#define ASCQ_2AH_REGISTRATIONS_PREEMPTED			0x05
+#define ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED		0x06
+#define ASCQ_2AH_IMPLICT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED 0x07
+#define ASCQ_2AH_PRIORITY_CHANGED				0x08
+
+#define ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS		0x09
+
+extern struct kmem_cache *se_ua_cache;
+
+extern int core_scsi3_ua_check(struct se_cmd_s *, unsigned char *);
+extern int core_scsi3_ua_allocate(struct se_node_acl_s *, u32, u8, u8);
+extern void core_scsi3_ua_release_all(struct se_dev_entry_s *);
+extern void core_scsi3_ua_for_check_condition(struct se_cmd_s *, u8 *, u8 *);
+extern int core_scsi3_ua_clear_for_request_sense(struct se_cmd_s *,
+						u8 *, u8 *);
+
+#endif /* TARGET_CORE_UA_H */
Signature · 1 line
1.5.4.1