scif_sas_task_request.c revision 331722
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: stable/11/sys/dev/isci/scil/scif_sas_task_request.c 331722 2018-03-29 02:50:57Z eadler $");
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
85U32 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
94U8 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
103static
104SCI_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
236SCI_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
267SCI_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
295void 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
306void 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
376U32 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
392U8 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
404U16 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
421void * 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
435U32 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 */
461void 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
482