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