1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /******************************************************************************* 3 * Filename: target_core_ua.c 4 * 5 * This file contains logic for SPC-3 Unit Attention emulation 6 * 7 * (c) Copyright 2009-2013 Datera, Inc. 8 * 9 * Nicholas A. Bellinger <nab@kernel.org> 10 * 11 ******************************************************************************/ 12 13 #include <linux/slab.h> 14 #include <linux/spinlock.h> 15 #include <scsi/scsi_proto.h> 16 17 #include <target/target_core_base.h> 18 #include <target/target_core_fabric.h> 19 20 #include "target_core_internal.h" 21 #include "target_core_alua.h" 22 #include "target_core_pr.h" 23 #include "target_core_ua.h" 24 25 sense_reason_t 26 target_scsi3_ua_check(struct se_cmd *cmd) 27 { 28 struct se_dev_entry *deve; 29 struct se_session *sess = cmd->se_sess; 30 struct se_node_acl *nacl; 31 32 if (!sess) 33 return 0; 34 35 nacl = sess->se_node_acl; 36 if (!nacl) 37 return 0; 38 39 rcu_read_lock(); 40 deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun); 41 if (!deve) { 42 rcu_read_unlock(); 43 return 0; 44 } 45 if (list_empty_careful(&deve->ua_list)) { 46 rcu_read_unlock(); 47 return 0; 48 } 49 rcu_read_unlock(); 50 /* 51 * From sam4r14, section 5.14 Unit attention condition: 52 * 53 * a) if an INQUIRY command enters the enabled command state, the 54 * device server shall process the INQUIRY command and shall neither 55 * report nor clear any unit attention condition; 56 * b) if a REPORT LUNS command enters the enabled command state, the 57 * device server shall process the REPORT LUNS command and shall not 58 * report any unit attention condition; 59 * e) if a REQUEST SENSE command enters the enabled command state while 60 * a unit attention condition exists for the SCSI initiator port 61 * associated with the I_T nexus on which the REQUEST SENSE command 62 * was received, then the device server shall process the command 63 * and either: 64 */ 65 switch (cmd->t_task_cdb[0]) { 66 case INQUIRY: 67 case REPORT_LUNS: 68 case REQUEST_SENSE: 69 return 0; 70 default: 71 return TCM_CHECK_CONDITION_UNIT_ATTENTION; 72 } 73 } 74 75 int core_scsi3_ua_allocate( 76 struct se_dev_entry *deve, 77 u8 asc, 78 u8 ascq) 79 { 80 struct se_ua *ua, *ua_p, *ua_tmp; 81 82 ua = kmem_cache_zalloc(se_ua_cache, GFP_ATOMIC); 83 if (!ua) { 84 pr_err("Unable to allocate struct se_ua\n"); 85 return -ENOMEM; 86 } 87 INIT_LIST_HEAD(&ua->ua_nacl_list); 88 89 ua->ua_asc = asc; 90 ua->ua_ascq = ascq; 91 92 spin_lock(&deve->ua_lock); 93 list_for_each_entry_safe(ua_p, ua_tmp, &deve->ua_list, ua_nacl_list) { 94 /* 95 * Do not report the same UNIT ATTENTION twice.. 96 */ 97 if ((ua_p->ua_asc == asc) && (ua_p->ua_ascq == ascq)) { 98 spin_unlock(&deve->ua_lock); 99 kmem_cache_free(se_ua_cache, ua); 100 return 0; 101 } 102 /* 103 * Attach the highest priority Unit Attention to 104 * the head of the list following sam4r14, 105 * Section 5.14 Unit Attention Condition: 106 * 107 * POWER ON, RESET, OR BUS DEVICE RESET OCCURRED highest 108 * POWER ON OCCURRED or 109 * DEVICE INTERNAL RESET 110 * SCSI BUS RESET OCCURRED or 111 * MICROCODE HAS BEEN CHANGED or 112 * protocol specific 113 * BUS DEVICE RESET FUNCTION OCCURRED 114 * I_T NEXUS LOSS OCCURRED 115 * COMMANDS CLEARED BY POWER LOSS NOTIFICATION 116 * all others Lowest 117 * 118 * Each of the ASCQ codes listed above are defined in 119 * the 29h ASC family, see spc4r17 Table D.1 120 */ 121 if (ua_p->ua_asc == 0x29) { 122 if ((asc == 0x29) && (ascq > ua_p->ua_ascq)) 123 list_add(&ua->ua_nacl_list, 124 &deve->ua_list); 125 else 126 list_add_tail(&ua->ua_nacl_list, 127 &deve->ua_list); 128 } else if (ua_p->ua_asc == 0x2a) { 129 /* 130 * Incoming Family 29h ASCQ codes will override 131 * Family 2AHh ASCQ codes for Unit Attention condition. 132 */ 133 if ((asc == 0x29) || (ascq > ua_p->ua_asc)) 134 list_add(&ua->ua_nacl_list, 135 &deve->ua_list); 136 else 137 list_add_tail(&ua->ua_nacl_list, 138 &deve->ua_list); 139 } else 140 list_add_tail(&ua->ua_nacl_list, 141 &deve->ua_list); 142 spin_unlock(&deve->ua_lock); 143 144 return 0; 145 } 146 list_add_tail(&ua->ua_nacl_list, &deve->ua_list); 147 spin_unlock(&deve->ua_lock); 148 149 pr_debug("Allocated UNIT ATTENTION, mapped LUN: %llu, ASC:" 150 " 0x%02x, ASCQ: 0x%02x\n", deve->mapped_lun, 151 asc, ascq); 152 153 return 0; 154 } 155 156 void target_ua_allocate_lun(struct se_node_acl *nacl, 157 u32 unpacked_lun, u8 asc, u8 ascq) 158 { 159 struct se_dev_entry *deve; 160 161 if (!nacl) 162 return; 163 164 rcu_read_lock(); 165 deve = target_nacl_find_deve(nacl, unpacked_lun); 166 if (!deve) { 167 rcu_read_unlock(); 168 return; 169 } 170 171 core_scsi3_ua_allocate(deve, asc, ascq); 172 rcu_read_unlock(); 173 } 174 175 void core_scsi3_ua_release_all( 176 struct se_dev_entry *deve) 177 { 178 struct se_ua *ua, *ua_p; 179 180 spin_lock(&deve->ua_lock); 181 list_for_each_entry_safe(ua, ua_p, &deve->ua_list, ua_nacl_list) { 182 list_del(&ua->ua_nacl_list); 183 kmem_cache_free(se_ua_cache, ua); 184 } 185 spin_unlock(&deve->ua_lock); 186 } 187 188 /* 189 * Dequeue a unit attention from the unit attention list. This function 190 * returns true if the dequeuing succeeded and if *@key, *@asc and *@ascq have 191 * been set. 192 */ 193 bool core_scsi3_ua_for_check_condition(struct se_cmd *cmd, u8 *key, u8 *asc, 194 u8 *ascq) 195 { 196 struct se_device *dev = cmd->se_dev; 197 struct se_dev_entry *deve; 198 struct se_session *sess = cmd->se_sess; 199 struct se_node_acl *nacl; 200 struct se_ua *ua = NULL, *ua_p; 201 int head = 1; 202 203 if (WARN_ON_ONCE(!sess)) 204 return false; 205 206 nacl = sess->se_node_acl; 207 if (WARN_ON_ONCE(!nacl)) 208 return false; 209 210 rcu_read_lock(); 211 deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun); 212 if (!deve) { 213 rcu_read_unlock(); 214 *key = ILLEGAL_REQUEST; 215 *asc = 0x25; /* LOGICAL UNIT NOT SUPPORTED */ 216 *ascq = 0; 217 return true; 218 } 219 *key = UNIT_ATTENTION; 220 /* 221 * The highest priority Unit Attentions are placed at the head of the 222 * struct se_dev_entry->ua_list, and will be returned in CHECK_CONDITION + 223 * sense data for the received CDB. 224 */ 225 spin_lock(&deve->ua_lock); 226 list_for_each_entry_safe(ua, ua_p, &deve->ua_list, ua_nacl_list) { 227 /* 228 * For ua_intlck_ctrl code not equal to 00b, only report the 229 * highest priority UNIT_ATTENTION and ASC/ASCQ without 230 * clearing it. 231 */ 232 if (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) { 233 *asc = ua->ua_asc; 234 *ascq = ua->ua_ascq; 235 break; 236 } 237 /* 238 * Otherwise for the default 00b, release the UNIT ATTENTION 239 * condition. Return the ASC/ASCQ of the highest priority UA 240 * (head of the list) in the outgoing CHECK_CONDITION + sense. 241 */ 242 if (head) { 243 *asc = ua->ua_asc; 244 *ascq = ua->ua_ascq; 245 head = 0; 246 } 247 list_del(&ua->ua_nacl_list); 248 kmem_cache_free(se_ua_cache, ua); 249 } 250 spin_unlock(&deve->ua_lock); 251 rcu_read_unlock(); 252 253 pr_debug("[%s]: %s UNIT ATTENTION condition with" 254 " INTLCK_CTRL: %d, mapped LUN: %llu, got CDB: 0x%02x" 255 " reported ASC: 0x%02x, ASCQ: 0x%02x\n", 256 nacl->se_tpg->se_tpg_tfo->fabric_name, 257 (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : 258 "Releasing", dev->dev_attrib.emulate_ua_intlck_ctrl, 259 cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq); 260 261 return head == 0; 262 } 263 264 int core_scsi3_ua_clear_for_request_sense( 265 struct se_cmd *cmd, 266 u8 *asc, 267 u8 *ascq) 268 { 269 struct se_dev_entry *deve; 270 struct se_session *sess = cmd->se_sess; 271 struct se_node_acl *nacl; 272 struct se_ua *ua = NULL, *ua_p; 273 int head = 1; 274 275 if (!sess) 276 return -EINVAL; 277 278 nacl = sess->se_node_acl; 279 if (!nacl) 280 return -EINVAL; 281 282 rcu_read_lock(); 283 deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun); 284 if (!deve) { 285 rcu_read_unlock(); 286 return -EINVAL; 287 } 288 if (list_empty_careful(&deve->ua_list)) { 289 rcu_read_unlock(); 290 return -EPERM; 291 } 292 /* 293 * The highest priority Unit Attentions are placed at the head of the 294 * struct se_dev_entry->ua_list. The First (and hence highest priority) 295 * ASC/ASCQ will be returned in REQUEST_SENSE payload data for the 296 * matching struct se_lun. 297 * 298 * Once the returning ASC/ASCQ values are set, we go ahead and 299 * release all of the Unit Attention conditions for the associated 300 * struct se_lun. 301 */ 302 spin_lock(&deve->ua_lock); 303 list_for_each_entry_safe(ua, ua_p, &deve->ua_list, ua_nacl_list) { 304 if (head) { 305 *asc = ua->ua_asc; 306 *ascq = ua->ua_ascq; 307 head = 0; 308 } 309 list_del(&ua->ua_nacl_list); 310 kmem_cache_free(se_ua_cache, ua); 311 } 312 spin_unlock(&deve->ua_lock); 313 rcu_read_unlock(); 314 315 pr_debug("[%s]: Released UNIT ATTENTION condition, mapped" 316 " LUN: %llu, got REQUEST_SENSE reported ASC: 0x%02x," 317 " ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->fabric_name, 318 cmd->orig_fe_lun, *asc, *ascq); 319 320 return (head) ? -EPERM : 0; 321 } 322