]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/isci/scil/scif_sas_task_request.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / isci / scil / scif_sas_task_request.c
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  *
40  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51  */
52
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
55
56 /**
57  * @file
58  *
59  * @brief This file contains the task management request object
60  *        (SCIF_SAS_TASK_REQUEST) method implementations.
61  */
62
63
64 #include <dev/isci/scil/intel_sas.h>
65
66 #include <dev/isci/scil/scic_task_request.h>
67 #include <dev/isci/scil/scic_remote_device.h>
68 #include <dev/isci/scil/scic_user_callback.h>
69 #include <dev/isci/scil/scic_controller.h>
70 #include <dev/isci/scil/scif_user_callback.h>
71
72 #include <dev/isci/scil/scif_sas_request.h>
73 #include <dev/isci/scil/scif_sas_task_request.h>
74 #include <dev/isci/scil/scif_sas_stp_task_request.h>
75 #include <dev/isci/scil/scif_sas_logger.h>
76 #include <dev/isci/scil/scif_sas_controller.h>
77 #include <dev/isci/scil/scif_sas_domain.h>
78 #include <dev/isci/scil/scif_sas_remote_device.h>
79 #include <dev/isci/scil/scif_sas_smp_io_request.h>
80
81 //******************************************************************************
82 //* P U B L I C   M E T H O D S
83 //******************************************************************************
84
85 U32 scif_task_request_get_object_size(
86    void
87 )
88 {
89    return (sizeof(SCIF_SAS_TASK_REQUEST_T) + scic_task_request_get_object_size());
90 }
91
92 // ---------------------------------------------------------------------------
93
94 U8 scif_sas_task_request_get_function(
95    SCIF_SAS_TASK_REQUEST_T *fw_task
96 )
97 {
98    return fw_task->function;
99 }
100
101 // ---------------------------------------------------------------------------
102
103 static
104 SCI_STATUS scif_sas_task_request_generic_construct(
105    SCI_CONTROLLER_HANDLE_T      scif_controller,
106    SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
107    U16                          io_tag,
108    void                       * user_task_request_object,
109    void                       * task_request_memory,
110    SCI_TASK_REQUEST_HANDLE_T  * scif_task_request,
111    U8                           task_function
112 )
113 {
114    SCI_STATUS                 status;
115    SCIF_SAS_CONTROLLER_T    * fw_controller   = (SCIF_SAS_CONTROLLER_T*)
116                                                 scif_controller;
117    SCIF_SAS_TASK_REQUEST_T  * fw_task         = (SCIF_SAS_TASK_REQUEST_T*)
118                                                 task_request_memory;
119    SCIF_SAS_REMOTE_DEVICE_T * fw_device       = (SCIF_SAS_REMOTE_DEVICE_T*)
120                                                 scif_remote_device;
121    U8                       * core_request_memory;
122
123    SCIF_LOG_TRACE((
124       sci_base_object_get_logger(fw_controller),
125       SCIF_LOG_OBJECT_TASK_MANAGEMENT,
126       "scif_task_request_construct(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) enter\n",
127       scif_controller, scif_remote_device, io_tag, user_task_request_object,
128       task_request_memory, scif_task_request
129    ));
130
131    // Initialize the user's handle to the framework task request.
132    *scif_task_request = fw_task;
133
134    // initialize affected request count
135    fw_task->affected_request_count = 0;
136    fw_task->io_tag_to_manage = SCI_CONTROLLER_INVALID_IO_TAG;
137    fw_task->function = task_function;
138
139    if (task_function == SCI_SAS_HARD_RESET )
140    {
141       if (fw_device->containing_device != NULL )
142       {// Target Reset is for an expander attached device,
143        // go down to construct smp Phy Control request.
144          scif_sas_smp_request_construct_phy_control(
145             fw_controller,
146             fw_device->containing_device,
147             PHY_OPERATION_HARD_RESET,
148             fw_device->expander_phy_identifier,
149             user_task_request_object,
150             task_request_memory
151          );
152       }
153       else
154       {
155          scif_sas_request_construct(
156             &fw_task->parent,
157             fw_device,
158             sci_base_object_get_logger(fw_controller),
159             scif_sas_task_request_state_table
160          );
161
162          // If target reset is for a DA device, don't build task at all.
163          // Just set object association.
164          sci_object_set_association(fw_task, user_task_request_object);
165       }
166
167       return SCI_SUCCESS;
168    }
169
170    // Construct the parent object first in order to ensure logging can
171    // function.
172    scif_sas_request_construct(
173       &fw_task->parent,
174       fw_device,
175       sci_base_object_get_logger(fw_controller),
176       scif_sas_task_request_state_table
177    );
178
179    core_request_memory = (U8 *)task_request_memory + sizeof(SCIF_SAS_TASK_REQUEST_T);
180
181    status = scic_task_request_construct(
182                fw_controller->core_object,
183                fw_device->core_object,
184                io_tag,
185                fw_task,
186                core_request_memory,
187                &fw_task->parent.core_object
188             );
189
190    if (status == SCI_SUCCESS)
191    {
192       SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
193
194       // These associations must be set early for the core io request
195       // object construction to complete correctly as there will be
196       // callbacks into the user driver framework during core construction
197       sci_object_set_association(fw_task, user_task_request_object);
198       sci_object_set_association(fw_task->parent.core_object, fw_task);
199
200       // Perform protocol specific core IO request construction.
201       scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
202       if (dev_protocols.u.bits.attached_ssp_target)
203          status = scic_task_request_construct_ssp(fw_task->parent.core_object);
204       else if (dev_protocols.u.bits.attached_stp_target)
205          status = scif_sas_stp_task_request_construct(fw_task);
206       else
207          status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
208
209       if (status == SCI_SUCCESS)
210       {
211          sci_base_state_machine_logger_initialize(
212             &fw_task->parent.parent.state_machine_logger,
213             &fw_task->parent.parent.state_machine,
214             &fw_task->parent.parent.parent,
215             scif_cb_logger_log_states,
216             "SCIF_SAS_TASK_REQUEST_T", "base_state_machine",
217             SCIF_LOG_OBJECT_TASK_MANAGEMENT
218          );
219       }
220       else
221       {
222          SCIF_LOG_WARNING((
223             sci_base_object_get_logger(fw_task),
224             SCIF_LOG_OBJECT_TASK_MANAGEMENT,
225             "Device:0x%x TaskRequest:0x%x Function:0x%x construct failed\n",
226             fw_device, fw_task, scif_sas_task_request_get_function(fw_task)
227          ));
228       }
229    }
230
231    return status;
232 }
233
234 // ---------------------------------------------------------------------------
235
236 SCI_STATUS scif_sas_internal_task_request_construct(
237    SCI_CONTROLLER_HANDLE_T      scif_controller,
238    SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
239    U16                          io_tag,
240    void                       * task_request_memory,
241    SCI_TASK_REQUEST_HANDLE_T  * scif_task_request,
242    U8                           task_function
243 )
244 {
245    SCI_STATUS                 status;
246    SCIF_SAS_TASK_REQUEST_T *  fw_task;
247
248    status = scif_sas_task_request_generic_construct(
249                scif_controller,
250                scif_remote_device,
251                io_tag,
252                NULL,
253                task_request_memory,
254                scif_task_request,
255                task_function
256             );
257
258    fw_task = (SCIF_SAS_TASK_REQUEST_T *)task_request_memory;
259
260    fw_task->parent.is_internal = TRUE;
261
262    return status;
263 }
264
265 // ---------------------------------------------------------------------------
266
267 SCI_STATUS scif_task_request_construct(
268    SCI_CONTROLLER_HANDLE_T      scif_controller,
269    SCI_REMOTE_DEVICE_HANDLE_T   scif_remote_device,
270    U16                          io_tag,
271    void                       * user_task_request_object,
272    void                       * task_request_memory,
273    SCI_TASK_REQUEST_HANDLE_T  * scif_task_request
274 )
275 {
276    SCI_STATUS  status;
277    U8          task_function =
278                 scif_cb_task_request_get_function(user_task_request_object);
279
280    status = scif_sas_task_request_generic_construct(
281                scif_controller,
282                scif_remote_device,
283                io_tag,
284                user_task_request_object,
285                task_request_memory,
286                scif_task_request,
287                task_function
288             );
289
290    return status;
291 }
292
293 // ---------------------------------------------------------------------------
294
295 void scif_sas_internal_task_request_destruct(
296    SCIF_SAS_TASK_REQUEST_T * fw_internal_task
297 )
298 {
299    SCIF_SAS_CONTROLLER_T * fw_controller =
300       fw_internal_task->parent.device->domain->controller;
301    scif_sas_controller_free_internal_request(fw_controller, fw_internal_task);
302 }
303
304 // ---------------------------------------------------------------------------
305
306 void scic_cb_task_request_complete(
307    SCI_CONTROLLER_HANDLE_T     controller,
308    SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
309    SCI_TASK_REQUEST_HANDLE_T   task_request,
310    SCI_TASK_STATUS             completion_status
311 )
312 {
313    SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
314                                          sci_object_get_association(controller);
315    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
316                                       sci_object_get_association(remote_device);
317    SCIF_SAS_TASK_REQUEST_T  * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
318                                        sci_object_get_association(task_request);
319    SCI_STATUS                 status;
320
321    SCIF_LOG_TRACE((
322       sci_base_object_get_logger(fw_controller),
323       SCIF_LOG_OBJECT_TASK_MANAGEMENT,
324       "scic_cb_task_request_complete(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
325       controller, remote_device, task_request, completion_status
326    ));
327
328    status = fw_task->parent.state_handlers->complete_handler(
329                &fw_task->parent.parent
330             );
331
332    if (status == SCI_SUCCESS)
333    {
334       if (fw_task->parent.protocol_complete_handler != NULL)
335       {
336          status = fw_task->parent.protocol_complete_handler(
337             fw_controller, fw_device, &fw_task->parent, (SCI_STATUS *)&completion_status
338          );
339       }
340
341       if (status == SCI_SUCCESS)
342       {
343          SCIF_LOG_WARNING((
344             sci_base_object_get_logger(fw_task),
345             SCIF_LOG_OBJECT_TASK_MANAGEMENT,
346             "RemoteDevice:0x%x TaskRequest:0x%x Function:0x%x CompletionStatus:0x%x "
347             "completed\n",
348             fw_device, fw_task,
349             scif_sas_task_request_get_function(fw_task),
350             completion_status
351          ));
352
353          // If this isn't an internal framework IO request, then simply pass the
354          // notification up to the SCIF user.  Otherwise, immediately complete the
355          // task since there is no SCIF user to notify.
356          if (fw_task->parent.is_internal == FALSE)
357          {
358             scif_cb_task_request_complete(
359                fw_controller, fw_device, fw_task, completion_status
360             );
361          }
362          else
363          {
364             scif_controller_complete_task(
365                fw_controller,
366                fw_device,
367                fw_task
368             );
369          }
370       }
371    }
372 }
373
374 // ---------------------------------------------------------------------------
375
376 U32 scic_cb_ssp_task_request_get_lun(
377    void * scic_user_task_request
378 )
379 {
380    SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
381                                        scic_user_task_request;
382
383    fw_task->parent.lun = scif_cb_task_request_get_lun(
384                             fw_task->parent.parent.parent.associated_object
385                          );
386
387    return fw_task->parent.lun;
388 }
389
390 // ---------------------------------------------------------------------------
391
392 U8 scic_cb_ssp_task_request_get_function(
393    void * scic_user_task_request
394 )
395 {
396    SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
397                                        scic_user_task_request;
398
399    return scif_sas_task_request_get_function(fw_task);
400 }
401
402 // ---------------------------------------------------------------------------
403
404 U16 scic_cb_ssp_task_request_get_io_tag_to_manage(
405    void * scic_user_task_request
406 )
407 {
408    SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
409                                        scic_user_task_request;
410
411    fw_task->io_tag_to_manage
412       = scif_cb_task_request_get_io_tag_to_manage(
413            fw_task->parent.parent.parent.associated_object
414         );
415
416    return fw_task->io_tag_to_manage;
417 }
418
419 // ---------------------------------------------------------------------------
420
421 void * scic_cb_ssp_task_request_get_response_data_address(
422    void * scic_user_task_request
423 )
424 {
425    SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
426                                        scic_user_task_request;
427
428    return scif_cb_task_request_get_response_data_address(
429                 fw_task->parent.parent.parent.associated_object
430           );
431 }
432
433 // ---------------------------------------------------------------------------
434
435 U32 scic_cb_ssp_task_request_get_response_data_length(
436    void * scic_user_task_request
437 )
438 {
439    SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)
440                                        scic_user_task_request;
441
442    return scif_cb_task_request_get_response_data_length(
443              fw_task->parent.parent.parent.associated_object
444           );
445 }
446
447 //******************************************************************************
448 //* P R O T E C T E D   M E T H O D S
449 //******************************************************************************
450
451 /**
452  * @brief This method performs functionality required after a task management
453  *        operation (either a task management request or a silicon task
454  *        termination) has finished.
455  *
456  * @param[in]  fw_task This parameter specifies the request that has
457  *             the operation completing.
458  *
459  * @return none
460  */
461 void scif_sas_task_request_operation_complete(
462    SCIF_SAS_TASK_REQUEST_T * fw_task
463 )
464 {
465    SCIF_LOG_TRACE((
466       sci_base_object_get_logger(fw_task),
467       SCIF_LOG_OBJECT_TASK_MANAGEMENT,
468       "scif_sas_task_request_operation_complete(0x%x) enter\n",
469       fw_task
470    ));
471
472    fw_task->affected_request_count--;
473
474    SCIF_LOG_INFO((
475       sci_base_object_get_logger(fw_task),
476       SCIF_LOG_OBJECT_TASK_MANAGEMENT,
477       "TaskRequest:0x%x current affected request count:0x%x\n",
478       fw_task, fw_task->affected_request_count
479    ));
480 }
481