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 #include <dev/isci/isci.h>
35
36 #include <dev/isci/scil/scif_controller.h>
37 #include <dev/isci/scil/scif_user_callback.h>
38
39 /**
40 * @brief This user callback will inform the user that a task management
41 * request completed.
42 *
43 * @param[in] controller This parameter specifies the controller on
44 * which the task management request is completing.
45 * @param[in] remote_device This parameter specifies the remote device on
46 * which this task management request is completing.
47 * @param[in] task_request This parameter specifies the task management
48 * request that has completed.
49 * @param[in] completion_status This parameter specifies the results of
50 * the IO request operation. SCI_TASK_SUCCESS indicates
51 * successful completion.
52 *
53 * @return none
54 */
55 void
scif_cb_task_request_complete(SCI_CONTROLLER_HANDLE_T controller,SCI_REMOTE_DEVICE_HANDLE_T remote_device,SCI_TASK_REQUEST_HANDLE_T task_request,SCI_TASK_STATUS completion_status)56 scif_cb_task_request_complete(SCI_CONTROLLER_HANDLE_T controller,
57 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
58 SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status)
59 {
60
61 scif_controller_complete_task(controller, remote_device, task_request);
62 isci_task_request_complete(controller, remote_device, task_request,
63 completion_status);
64 }
65
66 /**
67 * @brief This method returns the Logical Unit to be utilized for this
68 * task management request.
69 *
70 * @note The contents of the value returned from this callback are defined
71 * by the protocol standard (e.g. T10 SAS specification). Please
72 * refer to the transport task information unit description
73 * in the associated standard.
74 *
75 * @param[in] scif_user_task_request This parameter points to the user's
76 * task request object. It is a cookie that allows the user to
77 * provide the necessary information for this callback.
78 *
79 * @return This method returns the LUN associated with this request.
80 * @todo This should be U64?
81 */
82 uint32_t
scif_cb_task_request_get_lun(void * scif_user_task_request)83 scif_cb_task_request_get_lun(void * scif_user_task_request)
84 {
85
86 /* Currently we are only doing hard resets, not LUN resets. So
87 * always returning 0 is OK here, since LUN doesn't matter for
88 * a hard device reset.
89 */
90 return (0);
91 }
92
93 /**
94 * @brief This method returns the task management function to be utilized
95 * for this task request.
96 *
97 * @note The contents of the value returned from this callback are defined
98 * by the protocol standard (e.g. T10 SAS specification). Please
99 * refer to the transport task information unit description
100 * in the associated standard.
101 *
102 * @param[in] scif_user_task_request This parameter points to the user's
103 * task request object. It is a cookie that allows the user to
104 * provide the necessary information for this callback.
105 *
106 * @return This method returns an unsigned byte representing the task
107 * management function to be performed.
108 */
scif_cb_task_request_get_function(void * scif_user_task_request)109 uint8_t scif_cb_task_request_get_function(void * scif_user_task_request)
110 {
111 /* SCIL supports many types of task management functions, but this
112 * driver only uses HARD_RESET.
113 */
114 return (SCI_SAS_HARD_RESET);
115 }
116
117 /**
118 * @brief This method returns the task management IO tag to be managed.
119 * Depending upon the task management function the value returned
120 * from this method may be ignored.
121 *
122 * @param[in] scif_user_task_request This parameter points to the user's
123 * task request object. It is a cookie that allows the user to
124 * provide the necessary information for this callback.
125 *
126 * @return This method returns an unsigned 16-bit word depicting the IO
127 * tag to be managed.
128 */
129 uint16_t
scif_cb_task_request_get_io_tag_to_manage(void * scif_user_task_request)130 scif_cb_task_request_get_io_tag_to_manage(void * scif_user_task_request)
131 {
132
133 return (0);
134 }
135
136 /**
137 * @brief This callback method asks the user to provide the virtual
138 * address of the response data buffer for the supplied IO request.
139 *
140 * @param[in] scif_user_task_request This parameter points to the user's
141 * task request object. It is a cookie that allows the user to
142 * provide the necessary information for this callback.
143 *
144 * @return This method returns the virtual address for the response data buffer
145 * associated with this IO request.
146 */
147 void *
scif_cb_task_request_get_response_data_address(void * scif_user_task_request)148 scif_cb_task_request_get_response_data_address(void * scif_user_task_request)
149 {
150 struct ISCI_TASK_REQUEST *task_request =
151 (struct ISCI_TASK_REQUEST *)scif_user_task_request;
152
153 return (&task_request->sense_data);
154 }
155
156 /**
157 * @brief This callback method asks the user to provide the length of the
158 * response data buffer for the supplied IO request.
159 *
160 * @param[in] scif_user_task_request This parameter points to the user's
161 * task request object. It is a cookie that allows the user to
162 * provide the necessary information for this callback.
163 *
164 * @return This method returns the length of the response buffer data
165 * associated with this IO request.
166 */
167 uint32_t
scif_cb_task_request_get_response_data_length(void * scif_user_task_request)168 scif_cb_task_request_get_response_data_length(void * scif_user_task_request)
169 {
170
171 return (sizeof(struct scsi_sense_data));
172 }
173
174 void
isci_task_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,SCI_REMOTE_DEVICE_HANDLE_T remote_device,SCI_TASK_REQUEST_HANDLE_T task_request,SCI_TASK_STATUS completion_status)175 isci_task_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
176 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
177 SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status)
178 {
179 struct ISCI_TASK_REQUEST *isci_task_request =
180 (struct ISCI_TASK_REQUEST *)sci_object_get_association(task_request);
181 struct ISCI_CONTROLLER *isci_controller =
182 (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
183 struct ISCI_REMOTE_DEVICE *isci_remote_device =
184 (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device);
185 struct ISCI_REMOTE_DEVICE *pending_remote_device;
186 BOOL retry_task = FALSE;
187 union ccb *ccb = isci_task_request->ccb;
188
189 isci_remote_device->is_resetting = FALSE;
190
191 switch ((int)completion_status) {
192 case SCI_TASK_SUCCESS:
193 case SCI_TASK_FAILURE_RESPONSE_VALID:
194 break;
195
196 case SCI_TASK_FAILURE_INVALID_STATE:
197 retry_task = TRUE;
198 isci_log_message(0, "ISCI",
199 "task failure (invalid state) - retrying\n");
200 break;
201
202 case SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES:
203 retry_task = TRUE;
204 isci_log_message(0, "ISCI",
205 "task failure (insufficient resources) - retrying\n");
206 break;
207
208 case SCI_FAILURE_TIMEOUT:
209 if (isci_controller->fail_on_task_timeout) {
210 retry_task = FALSE;
211 isci_log_message(0, "ISCI",
212 "task timeout - not retrying\n");
213 scif_cb_domain_device_removed(scif_controller,
214 isci_remote_device->domain->sci_object,
215 remote_device);
216 } else {
217 retry_task = TRUE;
218 isci_log_message(0, "ISCI",
219 "task timeout - retrying\n");
220 }
221 break;
222
223 case SCI_TASK_FAILURE:
224 case SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL:
225 case SCI_TASK_FAILURE_INVALID_TAG:
226 case SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR:
227 case SCI_TASK_FAILURE_TERMINATED:
228 case SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE:
229 isci_log_message(0, "ISCI",
230 "unhandled task completion code 0x%x\n", completion_status);
231 break;
232
233 default:
234 isci_log_message(0, "ISCI",
235 "unhandled task completion code 0x%x\n", completion_status);
236 break;
237 }
238
239 if (isci_controller->is_frozen == TRUE) {
240 isci_controller->is_frozen = FALSE;
241 xpt_release_simq(isci_controller->sim, TRUE);
242 }
243
244 sci_pool_put(isci_controller->request_pool,
245 (struct ISCI_REQUEST *)isci_task_request);
246
247 /* Make sure we release the device queue, since it may have been frozen
248 * if someone tried to start an I/O while the task was in progress.
249 */
250 isci_remote_device_release_device_queue(isci_remote_device);
251
252 if (retry_task == TRUE)
253 isci_remote_device_reset(isci_remote_device, ccb);
254 else {
255 pending_remote_device = sci_fast_list_remove_head(
256 &isci_controller->pending_device_reset_list);
257
258 if (pending_remote_device != NULL) {
259 /* Any resets that were triggered from an XPT_RESET_DEV
260 * CCB are never put in the pending list if the request
261 * pool is empty - they are given back to CAM to be
262 * requeued. So we will alawys pass NULL here,
263 * denoting that there is no CCB associated with the
264 * device reset.
265 */
266 isci_remote_device_reset(pending_remote_device, NULL);
267 } else if (ccb != NULL) {
268 /* There was a CCB associated with this reset, so mark
269 * it complete and return it to CAM.
270 */
271 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
272 ccb->ccb_h.status |= CAM_REQ_CMP;
273 xpt_done(ccb);
274 }
275 }
276 }
277
278