1230557Sjimharris/*- 2230557Sjimharris * BSD LICENSE 3230557Sjimharris * 4230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 5230557Sjimharris * All rights reserved. 6230557Sjimharris * 7230557Sjimharris * Redistribution and use in source and binary forms, with or without 8230557Sjimharris * modification, are permitted provided that the following conditions 9230557Sjimharris * are met: 10230557Sjimharris * 11230557Sjimharris * * Redistributions of source code must retain the above copyright 12230557Sjimharris * notice, this list of conditions and the following disclaimer. 13230557Sjimharris * * Redistributions in binary form must reproduce the above copyright 14230557Sjimharris * notice, this list of conditions and the following disclaimer in 15230557Sjimharris * the documentation and/or other materials provided with the 16230557Sjimharris * distribution. 17230557Sjimharris * 18230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29230557Sjimharris */ 30230557Sjimharris 31230557Sjimharris#include <sys/cdefs.h> 32230557Sjimharris__FBSDID("$FreeBSD$"); 33230557Sjimharris 34230557Sjimharris#include <dev/isci/isci.h> 35230557Sjimharris 36230557Sjimharris#include <dev/isci/scil/scif_controller.h> 37230557Sjimharris#include <dev/isci/scil/scif_user_callback.h> 38230557Sjimharris 39230557Sjimharris/** 40230557Sjimharris * @brief This user callback will inform the user that a task management 41230557Sjimharris * request completed. 42230557Sjimharris * 43230557Sjimharris * @param[in] controller This parameter specifies the controller on 44230557Sjimharris * which the task management request is completing. 45230557Sjimharris * @param[in] remote_device This parameter specifies the remote device on 46230557Sjimharris * which this task management request is completing. 47230557Sjimharris * @param[in] task_request This parameter specifies the task management 48230557Sjimharris * request that has completed. 49230557Sjimharris * @param[in] completion_status This parameter specifies the results of 50230557Sjimharris * the IO request operation. SCI_TASK_SUCCESS indicates 51230557Sjimharris * successful completion. 52230557Sjimharris * 53230557Sjimharris * @return none 54230557Sjimharris */ 55230557Sjimharrisvoid 56230557Sjimharrisscif_cb_task_request_complete(SCI_CONTROLLER_HANDLE_T controller, 57230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 58230557Sjimharris SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status) 59230557Sjimharris{ 60230557Sjimharris 61230557Sjimharris scif_controller_complete_task(controller, remote_device, task_request); 62230557Sjimharris isci_task_request_complete(controller, remote_device, task_request, 63230557Sjimharris completion_status); 64230557Sjimharris} 65230557Sjimharris 66230557Sjimharris/** 67230557Sjimharris * @brief This method returns the Logical Unit to be utilized for this 68230557Sjimharris * task management request. 69230557Sjimharris * 70230557Sjimharris * @note The contents of the value returned from this callback are defined 71230557Sjimharris * by the protocol standard (e.g. T10 SAS specification). Please 72230557Sjimharris * refer to the transport task information unit description 73230557Sjimharris * in the associated standard. 74230557Sjimharris * 75230557Sjimharris * @param[in] scif_user_task_request This parameter points to the user's 76230557Sjimharris * task request object. It is a cookie that allows the user to 77230557Sjimharris * provide the necessary information for this callback. 78230557Sjimharris * 79230557Sjimharris * @return This method returns the LUN associated with this request. 80230557Sjimharris * @todo This should be U64? 81230557Sjimharris */ 82230557Sjimharrisuint32_t 83230557Sjimharrisscif_cb_task_request_get_lun(void * scif_user_task_request) 84230557Sjimharris{ 85230557Sjimharris 86230557Sjimharris /* Currently we are only doing hard resets, not LUN resets. So 87230557Sjimharris * always returning 0 is OK here, since LUN doesn't matter for 88230557Sjimharris * a hard device reset. 89230557Sjimharris */ 90230557Sjimharris return (0); 91230557Sjimharris} 92230557Sjimharris 93230557Sjimharris/** 94230557Sjimharris * @brief This method returns the task management function to be utilized 95230557Sjimharris * for this task request. 96230557Sjimharris * 97230557Sjimharris * @note The contents of the value returned from this callback are defined 98230557Sjimharris * by the protocol standard (e.g. T10 SAS specification). Please 99230557Sjimharris * refer to the transport task information unit description 100230557Sjimharris * in the associated standard. 101230557Sjimharris * 102230557Sjimharris * @param[in] scif_user_task_request This parameter points to the user's 103230557Sjimharris * task request object. It is a cookie that allows the user to 104230557Sjimharris * provide the necessary information for this callback. 105230557Sjimharris * 106230557Sjimharris * @return This method returns an unsigned byte representing the task 107230557Sjimharris * management function to be performed. 108230557Sjimharris */ 109230557Sjimharrisuint8_t scif_cb_task_request_get_function(void * scif_user_task_request) 110230557Sjimharris{ 111230557Sjimharris /* SCIL supports many types of task management functions, but this 112230557Sjimharris * driver only uses HARD_RESET. 113230557Sjimharris */ 114230557Sjimharris return (SCI_SAS_HARD_RESET); 115230557Sjimharris} 116230557Sjimharris 117230557Sjimharris/** 118230557Sjimharris * @brief This method returns the task management IO tag to be managed. 119230557Sjimharris * Depending upon the task management function the value returned 120230557Sjimharris * from this method may be ignored. 121230557Sjimharris * 122230557Sjimharris * @param[in] scif_user_task_request This parameter points to the user's 123230557Sjimharris * task request object. It is a cookie that allows the user to 124230557Sjimharris * provide the necessary information for this callback. 125230557Sjimharris * 126230557Sjimharris * @return This method returns an unsigned 16-bit word depicting the IO 127230557Sjimharris * tag to be managed. 128230557Sjimharris */ 129230557Sjimharrisuint16_t 130230557Sjimharrisscif_cb_task_request_get_io_tag_to_manage(void * scif_user_task_request) 131230557Sjimharris{ 132230557Sjimharris 133230557Sjimharris return (0); 134230557Sjimharris} 135230557Sjimharris 136230557Sjimharris/** 137230557Sjimharris * @brief This callback method asks the user to provide the virtual 138230557Sjimharris * address of the response data buffer for the supplied IO request. 139230557Sjimharris * 140230557Sjimharris * @param[in] scif_user_task_request This parameter points to the user's 141230557Sjimharris * task request object. It is a cookie that allows the user to 142230557Sjimharris * provide the necessary information for this callback. 143230557Sjimharris * 144230557Sjimharris * @return This method returns the virtual address for the response data buffer 145230557Sjimharris * associated with this IO request. 146230557Sjimharris */ 147230557Sjimharrisvoid * 148230557Sjimharrisscif_cb_task_request_get_response_data_address(void * scif_user_task_request) 149230557Sjimharris{ 150230557Sjimharris struct ISCI_TASK_REQUEST *task_request = 151230557Sjimharris (struct ISCI_TASK_REQUEST *)scif_user_task_request; 152230557Sjimharris 153230557Sjimharris return (&task_request->sense_data); 154230557Sjimharris} 155230557Sjimharris 156230557Sjimharris/** 157230557Sjimharris * @brief This callback method asks the user to provide the length of the 158230557Sjimharris * response data buffer for the supplied IO request. 159230557Sjimharris * 160230557Sjimharris * @param[in] scif_user_task_request This parameter points to the user's 161230557Sjimharris * task request object. It is a cookie that allows the user to 162230557Sjimharris * provide the necessary information for this callback. 163230557Sjimharris * 164230557Sjimharris * @return This method returns the length of the response buffer data 165230557Sjimharris * associated with this IO request. 166230557Sjimharris */ 167230557Sjimharrisuint32_t 168230557Sjimharrisscif_cb_task_request_get_response_data_length(void * scif_user_task_request) 169230557Sjimharris{ 170230557Sjimharris 171230557Sjimharris return (sizeof(struct scsi_sense_data)); 172230557Sjimharris} 173230557Sjimharris 174230557Sjimharrisvoid 175230557Sjimharrisisci_task_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller, 176230557Sjimharris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 177230557Sjimharris SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status) 178230557Sjimharris{ 179230557Sjimharris struct ISCI_TASK_REQUEST *isci_task_request = 180230557Sjimharris (struct ISCI_TASK_REQUEST *)sci_object_get_association(task_request); 181230557Sjimharris struct ISCI_CONTROLLER *isci_controller = 182230557Sjimharris (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller); 183230557Sjimharris struct ISCI_REMOTE_DEVICE *isci_remote_device = 184230557Sjimharris (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device); 185230557Sjimharris struct ISCI_REMOTE_DEVICE *pending_remote_device; 186230557Sjimharris BOOL retry_task = FALSE; 187230557Sjimharris union ccb *ccb = isci_task_request->ccb; 188230557Sjimharris 189230557Sjimharris isci_remote_device->is_resetting = FALSE; 190230557Sjimharris 191233710Sdim switch ((int)completion_status) { 192230557Sjimharris case SCI_TASK_SUCCESS: 193230557Sjimharris case SCI_TASK_FAILURE_RESPONSE_VALID: 194230557Sjimharris break; 195230557Sjimharris 196230557Sjimharris case SCI_TASK_FAILURE_INVALID_STATE: 197256231Sjimharris retry_task = TRUE; 198256231Sjimharris isci_log_message(0, "ISCI", 199256231Sjimharris "task failure (invalid state) - retrying\n"); 200256231Sjimharris break; 201256231Sjimharris 202230557Sjimharris case SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES: 203230557Sjimharris retry_task = TRUE; 204230557Sjimharris isci_log_message(0, "ISCI", 205256231Sjimharris "task failure (insufficient resources) - retrying\n"); 206230557Sjimharris break; 207230557Sjimharris 208256231Sjimharris case SCI_FAILURE_TIMEOUT: 209256231Sjimharris retry_task = TRUE; 210256231Sjimharris isci_log_message(0, "ISCI", "task timeout - retrying\n"); 211256231Sjimharris break; 212256231Sjimharris 213230557Sjimharris case SCI_TASK_FAILURE: 214230557Sjimharris case SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL: 215230557Sjimharris case SCI_TASK_FAILURE_INVALID_TAG: 216230557Sjimharris case SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR: 217230557Sjimharris case SCI_TASK_FAILURE_TERMINATED: 218230557Sjimharris case SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE: 219230557Sjimharris isci_log_message(0, "ISCI", 220230557Sjimharris "unhandled task completion code 0x%x\n", completion_status); 221230557Sjimharris break; 222230557Sjimharris 223230557Sjimharris default: 224230557Sjimharris isci_log_message(0, "ISCI", 225230557Sjimharris "unhandled task completion code 0x%x\n", completion_status); 226230557Sjimharris break; 227230557Sjimharris } 228230557Sjimharris 229230557Sjimharris if (isci_controller->is_frozen == TRUE) { 230230557Sjimharris isci_controller->is_frozen = FALSE; 231230557Sjimharris xpt_release_simq(isci_controller->sim, TRUE); 232230557Sjimharris } 233230557Sjimharris 234230557Sjimharris sci_pool_put(isci_controller->request_pool, 235230557Sjimharris (struct ISCI_REQUEST *)isci_task_request); 236230557Sjimharris 237230557Sjimharris /* Make sure we release the device queue, since it may have been frozen 238230557Sjimharris * if someone tried to start an I/O while the task was in progress. 239230557Sjimharris */ 240230557Sjimharris isci_remote_device_release_device_queue(isci_remote_device); 241230557Sjimharris 242230557Sjimharris if (retry_task == TRUE) 243230557Sjimharris isci_remote_device_reset(isci_remote_device, ccb); 244230557Sjimharris else { 245230557Sjimharris pending_remote_device = sci_fast_list_remove_head( 246230557Sjimharris &isci_controller->pending_device_reset_list); 247230557Sjimharris 248230557Sjimharris if (pending_remote_device != NULL) { 249230557Sjimharris /* Any resets that were triggered from an XPT_RESET_DEV 250230557Sjimharris * CCB are never put in the pending list if the request 251230557Sjimharris * pool is empty - they are given back to CAM to be 252230557Sjimharris * requeued. So we will alawys pass NULL here, 253230557Sjimharris * denoting that there is no CCB associated with the 254230557Sjimharris * device reset. 255230557Sjimharris */ 256230557Sjimharris isci_remote_device_reset(pending_remote_device, NULL); 257230557Sjimharris } else if (ccb != NULL) { 258230557Sjimharris /* There was a CCB associated with this reset, so mark 259230557Sjimharris * it complete and return it to CAM. 260230557Sjimharris */ 261230557Sjimharris ccb->ccb_h.status &= ~CAM_STATUS_MASK; 262230557Sjimharris ccb->ccb_h.status |= CAM_REQ_CMP; 263230557Sjimharris xpt_done(ccb); 264230557Sjimharris } 265230557Sjimharris } 266230557Sjimharris} 267230557Sjimharris 268