1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * BSD LICENSE 5 * 6 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * * Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * * Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <dev/isci/isci.h> 37 38 #include <dev/isci/scil/scif_controller.h> 39 #include <dev/isci/scil/scif_user_callback.h> 40 41 /** 42 * @brief This user callback will inform the user that a task management 43 * request completed. 44 * 45 * @param[in] controller This parameter specifies the controller on 46 * which the task management request is completing. 47 * @param[in] remote_device This parameter specifies the remote device on 48 * which this task management request is completing. 49 * @param[in] task_request This parameter specifies the task management 50 * request that has completed. 51 * @param[in] completion_status This parameter specifies the results of 52 * the IO request operation. SCI_TASK_SUCCESS indicates 53 * successful completion. 54 * 55 * @return none 56 */ 57 void 58 scif_cb_task_request_complete(SCI_CONTROLLER_HANDLE_T controller, 59 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 60 SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status) 61 { 62 63 scif_controller_complete_task(controller, remote_device, task_request); 64 isci_task_request_complete(controller, remote_device, task_request, 65 completion_status); 66 } 67 68 /** 69 * @brief This method returns the Logical Unit to be utilized for this 70 * task management request. 71 * 72 * @note The contents of the value returned from this callback are defined 73 * by the protocol standard (e.g. T10 SAS specification). Please 74 * refer to the transport task information unit description 75 * in the associated standard. 76 * 77 * @param[in] scif_user_task_request This parameter points to the user's 78 * task request object. It is a cookie that allows the user to 79 * provide the necessary information for this callback. 80 * 81 * @return This method returns the LUN associated with this request. 82 * @todo This should be U64? 83 */ 84 uint32_t 85 scif_cb_task_request_get_lun(void * scif_user_task_request) 86 { 87 88 /* Currently we are only doing hard resets, not LUN resets. So 89 * always returning 0 is OK here, since LUN doesn't matter for 90 * a hard device reset. 91 */ 92 return (0); 93 } 94 95 /** 96 * @brief This method returns the task management function to be utilized 97 * for this task request. 98 * 99 * @note The contents of the value returned from this callback are defined 100 * by the protocol standard (e.g. T10 SAS specification). Please 101 * refer to the transport task information unit description 102 * in the associated standard. 103 * 104 * @param[in] scif_user_task_request This parameter points to the user's 105 * task request object. It is a cookie that allows the user to 106 * provide the necessary information for this callback. 107 * 108 * @return This method returns an unsigned byte representing the task 109 * management function to be performed. 110 */ 111 uint8_t scif_cb_task_request_get_function(void * scif_user_task_request) 112 { 113 /* SCIL supports many types of task management functions, but this 114 * driver only uses HARD_RESET. 115 */ 116 return (SCI_SAS_HARD_RESET); 117 } 118 119 /** 120 * @brief This method returns the task management IO tag to be managed. 121 * Depending upon the task management function the value returned 122 * from this method may be ignored. 123 * 124 * @param[in] scif_user_task_request This parameter points to the user's 125 * task request object. It is a cookie that allows the user to 126 * provide the necessary information for this callback. 127 * 128 * @return This method returns an unsigned 16-bit word depicting the IO 129 * tag to be managed. 130 */ 131 uint16_t 132 scif_cb_task_request_get_io_tag_to_manage(void * scif_user_task_request) 133 { 134 135 return (0); 136 } 137 138 /** 139 * @brief This callback method asks the user to provide the virtual 140 * address of the response data buffer for the supplied IO request. 141 * 142 * @param[in] scif_user_task_request This parameter points to the user's 143 * task request object. It is a cookie that allows the user to 144 * provide the necessary information for this callback. 145 * 146 * @return This method returns the virtual address for the response data buffer 147 * associated with this IO request. 148 */ 149 void * 150 scif_cb_task_request_get_response_data_address(void * scif_user_task_request) 151 { 152 struct ISCI_TASK_REQUEST *task_request = 153 (struct ISCI_TASK_REQUEST *)scif_user_task_request; 154 155 return (&task_request->sense_data); 156 } 157 158 /** 159 * @brief This callback method asks the user to provide the length of the 160 * response data buffer for the supplied IO request. 161 * 162 * @param[in] scif_user_task_request This parameter points to the user's 163 * task request object. It is a cookie that allows the user to 164 * provide the necessary information for this callback. 165 * 166 * @return This method returns the length of the response buffer data 167 * associated with this IO request. 168 */ 169 uint32_t 170 scif_cb_task_request_get_response_data_length(void * scif_user_task_request) 171 { 172 173 return (sizeof(struct scsi_sense_data)); 174 } 175 176 void 177 isci_task_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller, 178 SCI_REMOTE_DEVICE_HANDLE_T remote_device, 179 SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status) 180 { 181 struct ISCI_TASK_REQUEST *isci_task_request = 182 (struct ISCI_TASK_REQUEST *)sci_object_get_association(task_request); 183 struct ISCI_CONTROLLER *isci_controller = 184 (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller); 185 struct ISCI_REMOTE_DEVICE *isci_remote_device = 186 (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device); 187 struct ISCI_REMOTE_DEVICE *pending_remote_device; 188 BOOL retry_task = FALSE; 189 union ccb *ccb = isci_task_request->ccb; 190 191 isci_remote_device->is_resetting = FALSE; 192 193 switch ((int)completion_status) { 194 case SCI_TASK_SUCCESS: 195 case SCI_TASK_FAILURE_RESPONSE_VALID: 196 break; 197 198 case SCI_TASK_FAILURE_INVALID_STATE: 199 retry_task = TRUE; 200 isci_log_message(0, "ISCI", 201 "task failure (invalid state) - retrying\n"); 202 break; 203 204 case SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES: 205 retry_task = TRUE; 206 isci_log_message(0, "ISCI", 207 "task failure (insufficient resources) - retrying\n"); 208 break; 209 210 case SCI_FAILURE_TIMEOUT: 211 if (isci_controller->fail_on_task_timeout) { 212 retry_task = FALSE; 213 isci_log_message(0, "ISCI", 214 "task timeout - not retrying\n"); 215 scif_cb_domain_device_removed(scif_controller, 216 isci_remote_device->domain->sci_object, 217 remote_device); 218 } else { 219 retry_task = TRUE; 220 isci_log_message(0, "ISCI", 221 "task timeout - retrying\n"); 222 } 223 break; 224 225 case SCI_TASK_FAILURE: 226 case SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL: 227 case SCI_TASK_FAILURE_INVALID_TAG: 228 case SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR: 229 case SCI_TASK_FAILURE_TERMINATED: 230 case SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE: 231 isci_log_message(0, "ISCI", 232 "unhandled task completion code 0x%x\n", completion_status); 233 break; 234 235 default: 236 isci_log_message(0, "ISCI", 237 "unhandled task completion code 0x%x\n", completion_status); 238 break; 239 } 240 241 if (isci_controller->is_frozen == TRUE) { 242 isci_controller->is_frozen = FALSE; 243 xpt_release_simq(isci_controller->sim, TRUE); 244 } 245 246 sci_pool_put(isci_controller->request_pool, 247 (struct ISCI_REQUEST *)isci_task_request); 248 249 /* Make sure we release the device queue, since it may have been frozen 250 * if someone tried to start an I/O while the task was in progress. 251 */ 252 isci_remote_device_release_device_queue(isci_remote_device); 253 254 if (retry_task == TRUE) 255 isci_remote_device_reset(isci_remote_device, ccb); 256 else { 257 pending_remote_device = sci_fast_list_remove_head( 258 &isci_controller->pending_device_reset_list); 259 260 if (pending_remote_device != NULL) { 261 /* Any resets that were triggered from an XPT_RESET_DEV 262 * CCB are never put in the pending list if the request 263 * pool is empty - they are given back to CAM to be 264 * requeued. So we will alawys pass NULL here, 265 * denoting that there is no CCB associated with the 266 * device reset. 267 */ 268 isci_remote_device_reset(pending_remote_device, NULL); 269 } else if (ccb != NULL) { 270 /* There was a CCB associated with this reset, so mark 271 * it complete and return it to CAM. 272 */ 273 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 274 ccb->ccb_h.status |= CAM_REQ_CMP; 275 xpt_done(ccb); 276 } 277 } 278 } 279 280