1 /* 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * * Neither the name of Intel Corporation nor the names of its 40 * contributors may be used to endorse or promote products derived 41 * from this software without specific prior written permission. 42 * 43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 */ 55 #ifndef _ISCI_TASK_H_ 56 #define _ISCI_TASK_H_ 57 58 #include <scsi/sas_ata.h> 59 #include "host.h" 60 61 #define ISCI_TERMINATION_TIMEOUT_MSEC 500 62 63 struct isci_request; 64 65 /** 66 * enum isci_tmf_cb_state - This enum defines the possible states in which the 67 * TMF callback function is invoked during the TMF execution process. 68 * 69 * 70 */ 71 enum isci_tmf_cb_state { 72 73 isci_tmf_init_state = 0, 74 isci_tmf_started, 75 isci_tmf_timed_out 76 }; 77 78 /** 79 * enum isci_tmf_function_codes - This enum defines the possible preparations 80 * of task management requests. 81 * 82 * 83 */ 84 enum isci_tmf_function_codes { 85 86 isci_tmf_func_none = 0, 87 isci_tmf_ssp_task_abort = TMF_ABORT_TASK, 88 isci_tmf_ssp_lun_reset = TMF_LU_RESET, 89 }; 90 /** 91 * struct isci_tmf - This class represents the task management object which 92 * acts as an interface to libsas for processing task management requests 93 * 94 * 95 */ 96 struct isci_tmf { 97 98 struct completion *complete; 99 enum sas_protocol proto; 100 union { 101 struct ssp_response_iu resp_iu; 102 struct dev_to_host_fis d2h_fis; 103 u8 rsp_buf[SSP_RESP_IU_MAX_SIZE]; 104 } resp; 105 unsigned char lun[8]; 106 u16 io_tag; 107 enum isci_tmf_function_codes tmf_code; 108 int status; 109 110 /* The optional callback function allows the user process to 111 * track the TMF transmit / timeout conditions. 112 */ 113 void (*cb_state_func)( 114 enum isci_tmf_cb_state, 115 struct isci_tmf *, void *); 116 void *cb_data; 117 118 }; 119 120 static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf) 121 { 122 if (SAS_PROTOCOL_SATA == tmf->proto) 123 dev_dbg(&ihost->pdev->dev, 124 "%s: status = %x\n" 125 "tmf->resp.d2h_fis.status = %x\n" 126 "tmf->resp.d2h_fis.error = %x\n", 127 __func__, 128 tmf->status, 129 tmf->resp.d2h_fis.status, 130 tmf->resp.d2h_fis.error); 131 else 132 dev_dbg(&ihost->pdev->dev, 133 "%s: status = %x\n" 134 "tmf->resp.resp_iu.data_present = %x\n" 135 "tmf->resp.resp_iu.status = %x\n" 136 "tmf->resp.resp_iu.data_length = %x\n" 137 "tmf->resp.resp_iu.data[0] = %x\n" 138 "tmf->resp.resp_iu.data[1] = %x\n" 139 "tmf->resp.resp_iu.data[2] = %x\n" 140 "tmf->resp.resp_iu.data[3] = %x\n", 141 __func__, 142 tmf->status, 143 tmf->resp.resp_iu.datapres, 144 tmf->resp.resp_iu.status, 145 be32_to_cpu(tmf->resp.resp_iu.response_data_len), 146 tmf->resp.resp_iu.resp_data[0], 147 tmf->resp.resp_iu.resp_data[1], 148 tmf->resp.resp_iu.resp_data[2], 149 tmf->resp.resp_iu.resp_data[3]); 150 } 151 152 153 int isci_task_execute_task( 154 struct sas_task *task, 155 int num, 156 gfp_t gfp_flags); 157 158 int isci_task_abort_task( 159 struct sas_task *task); 160 161 int isci_task_abort_task_set( 162 struct domain_device *d_device, 163 u8 *lun); 164 165 int isci_task_clear_aca( 166 struct domain_device *d_device, 167 u8 *lun); 168 169 int isci_task_clear_task_set( 170 struct domain_device *d_device, 171 u8 *lun); 172 173 int isci_task_query_task( 174 struct sas_task *task); 175 176 int isci_task_lu_reset( 177 struct domain_device *d_device, 178 u8 *lun); 179 180 int isci_task_clear_nexus_port( 181 struct asd_sas_port *port); 182 183 int isci_task_clear_nexus_ha( 184 struct sas_ha_struct *ha); 185 186 int isci_task_I_T_nexus_reset( 187 struct domain_device *d_device); 188 189 void isci_task_request_complete( 190 struct isci_host *isci_host, 191 struct isci_request *request, 192 enum sci_task_status completion_status); 193 194 u16 isci_task_ssp_request_get_io_tag_to_manage( 195 struct isci_request *request); 196 197 u8 isci_task_ssp_request_get_function( 198 struct isci_request *request); 199 200 201 void *isci_task_ssp_request_get_response_data_address( 202 struct isci_request *request); 203 204 u32 isci_task_ssp_request_get_response_data_length( 205 struct isci_request *request); 206 207 int isci_queuecommand( 208 struct scsi_cmnd *scsi_cmd, 209 void (*donefunc)(struct scsi_cmnd *)); 210 211 /** 212 * enum isci_completion_selection - This enum defines the possible actions to 213 * take with respect to a given request's notification back to libsas. 214 * 215 * 216 */ 217 enum isci_completion_selection { 218 219 isci_perform_normal_io_completion, /* Normal notify (task_done) */ 220 isci_perform_aborted_io_completion, /* No notification. */ 221 isci_perform_error_io_completion /* Use sas_task_abort */ 222 }; 223 224 /** 225 * isci_task_set_completion_status() - This function sets the completion status 226 * for the request. 227 * @task: This parameter is the completed request. 228 * @response: This parameter is the response code for the completed task. 229 * @status: This parameter is the status code for the completed task. 230 * 231 * @return The new notification mode for the request. 232 */ 233 static inline enum isci_completion_selection 234 isci_task_set_completion_status( 235 struct sas_task *task, 236 enum service_response response, 237 enum exec_status status, 238 enum isci_completion_selection task_notification_selection) 239 { 240 unsigned long flags; 241 242 spin_lock_irqsave(&task->task_state_lock, flags); 243 244 /* If a device reset is being indicated, make sure the I/O 245 * is in the error path. 246 */ 247 if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) { 248 /* Fail the I/O to make sure it goes into the error path. */ 249 response = SAS_TASK_UNDELIVERED; 250 status = SAM_STAT_TASK_ABORTED; 251 252 task_notification_selection = isci_perform_error_io_completion; 253 } 254 task->task_status.resp = response; 255 task->task_status.stat = status; 256 257 switch (task->task_proto) { 258 259 case SAS_PROTOCOL_SATA: 260 case SAS_PROTOCOL_STP: 261 case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 262 263 if (task_notification_selection 264 == isci_perform_error_io_completion) { 265 /* SATA/STP I/O has it's own means of scheduling device 266 * error handling on the normal path. 267 */ 268 task_notification_selection 269 = isci_perform_normal_io_completion; 270 } 271 break; 272 default: 273 break; 274 } 275 276 switch (task_notification_selection) { 277 278 case isci_perform_error_io_completion: 279 280 if (task->task_proto == SAS_PROTOCOL_SMP) { 281 /* There is no error escalation in the SMP case. 282 * Convert to a normal completion to avoid the 283 * timeout in the discovery path and to let the 284 * next action take place quickly. 285 */ 286 task_notification_selection 287 = isci_perform_normal_io_completion; 288 289 /* Fall through to the normal case... */ 290 } else { 291 /* Use sas_task_abort */ 292 /* Leave SAS_TASK_STATE_DONE clear 293 * Leave SAS_TASK_AT_INITIATOR set. 294 */ 295 break; 296 } 297 298 case isci_perform_aborted_io_completion: 299 /* This path can occur with task-managed requests as well as 300 * requests terminated because of LUN or device resets. 301 */ 302 /* Fall through to the normal case... */ 303 case isci_perform_normal_io_completion: 304 /* Normal notification (task_done) */ 305 task->task_state_flags |= SAS_TASK_STATE_DONE; 306 task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR | 307 SAS_TASK_STATE_PENDING); 308 break; 309 default: 310 WARN_ONCE(1, "unknown task_notification_selection: %d\n", 311 task_notification_selection); 312 break; 313 } 314 315 spin_unlock_irqrestore(&task->task_state_lock, flags); 316 317 return task_notification_selection; 318 319 } 320 #endif /* !defined(_SCI_TASK_H_) */ 321