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