1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * The full GNU General Public License is included in this distribution
24 * in the file called LICENSE.GPL.
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 * * Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * * Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in
39 * the documentation and/or other materials provided with the
40 * distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
57
58 /**
59 * @file
60 *
61 * @brief This file contains the implementation of the SCIF_SAS_CONTROLLER
62 * object.
63 */
64
65
66 #include <dev/isci/scil/sci_status.h>
67 #include <dev/isci/scil/sci_util.h>
68 #include <dev/isci/scil/sci_controller.h>
69 #include <dev/isci/scil/scic_controller.h>
70 #include <dev/isci/scil/scic_user_callback.h>
71 #include <dev/isci/scil/scif_user_callback.h>
72
73 #include <dev/isci/scil/scif_sas_controller.h>
74 #include <dev/isci/scil/scif_sas_library.h>
75 #include <dev/isci/scil/scif_sas_logger.h>
76
77
78 //******************************************************************************
79 //* P U B L I C M E T H O D S
80 //******************************************************************************
81
82 SCI_STATUS scif_controller_construct(
83 SCI_LIBRARY_HANDLE_T library,
84 SCI_CONTROLLER_HANDLE_T controller,
85 void * user_object
86 )
87 {
88 SCI_STATUS status = SCI_SUCCESS;
89 SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T*) library;
90 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
91
92 // Validate the user supplied parameters.
93 if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE))
94 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
95
96 SCIF_LOG_TRACE((
97 sci_base_object_get_logger(library),
98 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
99 "scif_controller_construct(0x%x, 0x%x) enter\n",
100 library, controller
101 ));
102
103 // Construct the base controller. As part of constructing the base
104 // controller we ask it to also manage the MDL iteration for the Core.
105 sci_base_controller_construct(
106 &fw_controller->parent,
107 sci_base_object_get_logger(fw_library),
108 scif_sas_controller_state_table,
109 fw_controller->mdes,
110 SCIF_SAS_MAX_MEMORY_DESCRIPTORS,
111 sci_controller_get_memory_descriptor_list_handle(fw_controller->core_object)
112 );
113
114 scif_sas_controller_initialize_state_logging(fw_controller);
115
116 sci_object_set_association(fw_controller, user_object);
117
118 status = scic_controller_construct(
119 fw_library->core_object, fw_controller->core_object, fw_controller
120 );
121
122 // If the core controller was successfully constructed, then
123 // finish construction of the framework controller.
124 if (status == SCI_SUCCESS)
125 {
126 // Set the association in the core controller to this framework
127 // controller.
128 sci_object_set_association(
129 (SCI_OBJECT_HANDLE_T) fw_controller->core_object, fw_controller
130 );
131
132 sci_base_state_machine_change_state(
133 &fw_controller->parent.state_machine,
134 SCI_BASE_CONTROLLER_STATE_RESET
135 );
136 }
137
138 return status;
139 }
140
141 // ---------------------------------------------------------------------------
142
143 SCI_STATUS scif_controller_initialize(
144 SCI_CONTROLLER_HANDLE_T controller
145 )
146 {
147 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
148
149 // Validate the user supplied parameters.
150 if (controller == SCI_INVALID_HANDLE)
151 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
152
153 SCIF_LOG_TRACE((
154 sci_base_object_get_logger(controller),
155 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
156 "scif_controller_initialize(0x%x) enter\n",
157 controller
158 ));
159
160 return fw_controller->state_handlers->initialize_handler(
161 &fw_controller->parent
162 );
163 }
164
165 // ---------------------------------------------------------------------------
166
167 U32 scif_controller_get_suggested_start_timeout(
168 SCI_CONTROLLER_HANDLE_T controller
169 )
170 {
171 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
172
173 // Validate the user supplied parameters.
174 if (controller == SCI_INVALID_HANDLE)
175 return 0;
176
177 // Currently we aren't adding any additional time into the suggested
178 // timeout value for the start operation. Simply utilize the core
179 // value.
180 return scic_controller_get_suggested_start_timeout(fw_controller->core_object);
181 }
182
183 // ---------------------------------------------------------------------------
184
185 SCI_STATUS scif_controller_start(
186 SCI_CONTROLLER_HANDLE_T controller,
187 U32 timeout
188 )
189 {
190 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
191
192 // Validate the user supplied parameters.
193 if (controller == SCI_INVALID_HANDLE)
194 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
195
196 SCIF_LOG_TRACE((
197 sci_base_object_get_logger(controller),
198 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
199 "scif_controller_start(0x%x, 0x%x) enter\n",
200 controller, timeout
201 ));
202
203 return fw_controller->state_handlers->
204 start_handler(&fw_controller->parent, timeout);
205 }
206
207 // ---------------------------------------------------------------------------
208
209 SCI_STATUS scif_controller_stop(
210 SCI_CONTROLLER_HANDLE_T controller,
211 U32 timeout
212 )
213 {
214 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
215
216 // Validate the user supplied parameters.
217 if (controller == SCI_INVALID_HANDLE)
218 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
219
220 SCIF_LOG_TRACE((
221 sci_base_object_get_logger(controller),
222 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
223 "scif_controller_stop(0x%x, 0x%x) enter\n",
224 controller, timeout
225 ));
226
227 return fw_controller->state_handlers->
228 stop_handler(&fw_controller->parent, timeout);
229
230 }
231
232 // ---------------------------------------------------------------------------
233
234 SCI_STATUS scif_controller_reset(
235 SCI_CONTROLLER_HANDLE_T controller
236 )
237 {
238 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
239
240 // Validate the user supplied parameters.
241 if (controller == SCI_INVALID_HANDLE)
242 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
243
244 SCIF_LOG_TRACE((
245 sci_base_object_get_logger(controller),
246 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET,
247 "scif_controller_reset(0x%x) enter\n",
248 controller
249 ));
250
251 return fw_controller->state_handlers->
252 reset_handler(&fw_controller->parent);
253 }
254
255 // ---------------------------------------------------------------------------
256
257 SCI_CONTROLLER_HANDLE_T scif_controller_get_scic_handle(
258 SCI_CONTROLLER_HANDLE_T controller
259 )
260 {
261 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
262
263 return fw_controller->core_object;
264 }
265
266 // ---------------------------------------------------------------------------
267
268 SCI_IO_STATUS scif_controller_start_io(
269 SCI_CONTROLLER_HANDLE_T controller,
270 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
271 SCI_IO_REQUEST_HANDLE_T io_request,
272 U16 io_tag
273 )
274 {
275 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
276 SCI_STATUS status;
277
278 SCIF_LOG_TRACE((
279 sci_base_object_get_logger(controller),
280 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
281 "scif_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
282 controller, remote_device, io_request, io_tag
283 ));
284
285 if (
286 sci_pool_empty(fw_controller->hprq.pool)
287 || scif_sas_controller_sufficient_resource(controller)
288 )
289 {
290 status = fw_controller->state_handlers->start_io_handler(
291 (SCI_BASE_CONTROLLER_T*) controller,
292 (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
293 (SCI_BASE_REQUEST_T*) io_request,
294 io_tag
295 );
296 }
297 else
298 status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
299
300 return (SCI_IO_STATUS)status;
301 }
302
303 // ---------------------------------------------------------------------------
304
305 SCI_TASK_STATUS scif_controller_start_task(
306 SCI_CONTROLLER_HANDLE_T controller,
307 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
308 SCI_TASK_REQUEST_HANDLE_T task_request,
309 U16 io_tag
310 )
311 {
312 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
313 SCI_STATUS status;
314
315 // Validate the user supplied parameters.
316 if ( (controller == SCI_INVALID_HANDLE)
317 || (remote_device == SCI_INVALID_HANDLE)
318 || (task_request == SCI_INVALID_HANDLE) )
319 {
320 return SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE;
321 }
322
323 SCIF_LOG_TRACE((
324 sci_base_object_get_logger(controller),
325 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
326 "scif_controller_start_task(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
327 controller, remote_device, task_request, io_tag
328 ));
329
330 if (scif_sas_controller_sufficient_resource(controller))
331 {
332 status = fw_controller->state_handlers->start_task_handler(
333 (SCI_BASE_CONTROLLER_T*) controller,
334 (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
335 (SCI_BASE_REQUEST_T*) task_request,
336 io_tag
337 );
338 }
339 else
340 status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
341
342 return (SCI_TASK_STATUS)status;
343 }
344
345 // ---------------------------------------------------------------------------
346
347 SCI_STATUS scif_controller_complete_io(
348 SCI_CONTROLLER_HANDLE_T controller,
349 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
350 SCI_IO_REQUEST_HANDLE_T io_request
351 )
352 {
353 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
354
355 SCIF_LOG_TRACE((
356 sci_base_object_get_logger(controller),
357 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
358 "scif_controller_complete_io(0x%x, 0x%x, 0x%x) enter\n",
359 controller, remote_device, io_request
360 ));
361
362 return fw_controller->state_handlers->complete_io_handler(
363 (SCI_BASE_CONTROLLER_T*) controller,
364 (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
365 (SCI_BASE_REQUEST_T*) io_request
366 );
367 }
368
369 // ---------------------------------------------------------------------------
370
371 SCI_STATUS scif_controller_complete_task(
372 SCI_CONTROLLER_HANDLE_T controller,
373 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
374 SCI_TASK_REQUEST_HANDLE_T task_request
375 )
376 {
377 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
378
379 // Validate the user supplied parameters.
380 if ( (controller == SCI_INVALID_HANDLE)
381 || (remote_device == SCI_INVALID_HANDLE)
382 || (task_request == SCI_INVALID_HANDLE) )
383 {
384 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
385 }
386
387 SCIF_LOG_TRACE((
388 sci_base_object_get_logger(controller),
389 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
390 "scif_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n",
391 controller, remote_device, task_request
392 ));
393
394 return fw_controller->state_handlers->complete_task_handler(
395 (SCI_BASE_CONTROLLER_T*) controller,
396 (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
397 (SCI_BASE_REQUEST_T*) task_request
398 );
399 }
400
401 // ---------------------------------------------------------------------------
402
403 SCI_STATUS scif_controller_get_domain_handle(
404 SCI_CONTROLLER_HANDLE_T controller,
405 U8 port_index,
406 SCI_DOMAIN_HANDLE_T * domain_handle
407 )
408 {
409 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
410
411 // Validate the user supplied parameters.
412 if (controller == SCI_INVALID_HANDLE)
413 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
414
415 // Retrieve the domain handle if the supplied index is legitimate.
416 if (port_index < SCI_MAX_PORTS)
417 {
418 *domain_handle = &fw_controller->domains[port_index];
419 return SCI_SUCCESS;
420 }
421
422 return SCI_FAILURE_INVALID_PORT;
423 }
424
425 /**
426 * @brief This method builds the memory descriptor list for this
427 * controller.
428 *
429 * @param[in] fw_controller This parameter specifies the framework
430 * controller object for which to build the MDL.
431 *
432 * @return none
433 */
434 void scif_sas_controller_build_mdl(
435 SCIF_SAS_CONTROLLER_T * fw_controller
436 )
437 {
438 // one internal request for each domain.
439 sci_base_mde_construct(
440 &fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO],
441 4,
442 fw_controller->internal_request_entries *
443 scif_sas_internal_request_get_object_size(),
444 SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
445 );
446 }
447
448 // ---------------------------------------------------------------------------
449
450 SCI_STATUS scif_controller_set_mode(
451 SCI_CONTROLLER_HANDLE_T controller,
452 SCI_CONTROLLER_MODE mode
453 )
454 {
455 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
456 SCI_STATUS status = SCI_SUCCESS;
457
458 if (
459 (fw_controller->parent.state_machine.current_state_id
460 == SCI_BASE_CONTROLLER_STATE_INITIALIZING)
461 || (fw_controller->parent.state_machine.current_state_id
462 == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
463 )
464 {
465 switch (mode)
466 {
467 case SCI_MODE_SPEED:
468 fw_controller->internal_request_entries =
469 MIN(fw_controller->internal_request_entries, SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT);
470 scif_sas_controller_build_mdl(fw_controller);
471 break;
472
473 case SCI_MODE_SIZE:
474 fw_controller->internal_request_entries =
475 MIN(fw_controller->internal_request_entries, SCIF_SAS_MIN_INTERNAL_REQUEST_COUNT);
476 scif_sas_controller_build_mdl(fw_controller);
477 break;
478
479 default:
480 status = SCI_FAILURE_INVALID_PARAMETER_VALUE;
481 break;
482 }
483 }
484 else
485 status = SCI_FAILURE_INVALID_STATE;
486
487 if (status != SCI_SUCCESS)
488 {
489 return status;
490 }
491 else
492 {
493 // Currently, the framework doesn't change any configurations for
494 // speed or size modes. Default to speed mode basically.
495 return scic_controller_set_mode(fw_controller->core_object, mode);
496 }
497 }
498
499 // ---------------------------------------------------------------------------
500
501 U32 scif_controller_get_sat_compliance_version(
502 void
503 )
504 {
505 /// @todo Fix return of SAT compliance version.
506 return 0;
507 }
508
509 // ---------------------------------------------------------------------------
510
511 U32 scif_controller_get_sat_compliance_version_revision(
512 void
513 )
514 {
515 /// @todo Fix return of SAT compliance revision.
516 return 0;
517 }
518
519 // ---------------------------------------------------------------------------
520
521 SCI_STATUS scif_user_parameters_set(
522 SCI_CONTROLLER_HANDLE_T controller,
523 SCIF_USER_PARAMETERS_T * scif_parms
524 )
525 {
526 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
527
528 //validate all the registry entries before overwriting the default parameter
529 //values.
530 if (scif_parms->sas.is_sata_ncq_enabled != 1 && scif_parms->sas.is_sata_ncq_enabled != 0)
531 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
532
533 if (scif_parms->sas.max_ncq_depth < 1 || scif_parms->sas.max_ncq_depth > 32)
534 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
535
536 if (scif_parms->sas.is_sata_standby_timer_enabled != 1
537 && scif_parms->sas.is_sata_standby_timer_enabled != 0)
538 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
539
540 if (scif_parms->sas.is_non_zero_buffer_offsets_enabled != 1
541 && scif_parms->sas.is_non_zero_buffer_offsets_enabled != 0)
542 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
543
544 if (scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK
545 && scif_parms->sas.reset_type != SCI_SAS_ABORT_TASK_SET
546 && scif_parms->sas.reset_type != SCI_SAS_CLEAR_TASK_SET
547 && scif_parms->sas.reset_type != SCI_SAS_LOGICAL_UNIT_RESET
548 && scif_parms->sas.reset_type != SCI_SAS_I_T_NEXUS_RESET
549 && scif_parms->sas.reset_type != SCI_SAS_CLEAR_ACA
550 && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK
551 && scif_parms->sas.reset_type != SCI_SAS_QUERY_TASK_SET
552 && scif_parms->sas.reset_type != SCI_SAS_QUERY_ASYNCHRONOUS_EVENT
553 && scif_parms->sas.reset_type != SCI_SAS_HARD_RESET)
554 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
555
556 if (scif_parms->sas.clear_affiliation_during_controller_stop != 1
557 && scif_parms->sas.clear_affiliation_during_controller_stop !=0)
558 return SCI_FAILURE_INVALID_PARAMETER_VALUE;
559
560 memcpy((&fw_controller->user_parameters), scif_parms, sizeof(*scif_parms));
561
562 // In the future more could be done to prevent setting parameters at the
563 // wrong time, but for now we'll simply set the values even if it is too
564 // late for them to take effect.
565 return SCI_SUCCESS;
566 }
567
568 // ---------------------------------------------------------------------------
569
570 #if !defined(DISABLE_INTERRUPTS)
571
572 /**
573 * @brief This routine check each domain of the controller to see if
574 * any domain is overriding interrupt coalescence.
575 *
576 * @param[in] fw_controller frame controller
577 * @param[in] fw_smp_phy The smp phy to be freed.
578 *
579 * @return none
580 */
581 static
582 BOOL scif_sas_controller_is_overriding_interrupt_coalescence(
583 SCIF_SAS_CONTROLLER_T * fw_controller
584 )
585 {
586 U8 index;
587
588 for(index = 0; index < SCI_MAX_DOMAINS; index++)
589 {
590 if(fw_controller->domains[index].parent.state_machine.current_state_id ==
591 SCI_BASE_DOMAIN_STATE_DISCOVERING)
592 return TRUE;
593 }
594
595 return FALSE;
596 }
597
598 SCI_STATUS scif_controller_set_interrupt_coalescence(
599 SCI_CONTROLLER_HANDLE_T controller,
600 U32 coalesce_number,
601 U32 coalesce_timeout
602 )
603 {
604 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T * )controller;
605
606 ///when framework is in the middle of temporarily overriding the interrupt
607 ///coalescence values, user's request of setting interrupt coalescence
608 ///will be saved. As soon as the framework done the temporary overriding,
609 ///it will serve user's request to set new interrupt coalescence.
610 if (scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
611 {
612 U32 curr_coalesce_number;
613 U32 curr_coalesce_timeout;
614 SCI_STATUS core_status;
615
616 // save current interrupt coalescence info.
617 scic_controller_get_interrupt_coalescence (
618 fw_controller->core_object, &curr_coalesce_number, &curr_coalesce_timeout);
619
620 //try user's request out in the core, but immediately restore core's
621 //current setting.
622 core_status = scic_controller_set_interrupt_coalescence(
623 fw_controller->core_object, coalesce_number, coalesce_timeout);
624
625 if ( core_status == SCI_SUCCESS )
626 {
627 fw_controller->saved_interrupt_coalesce_number = (U16)coalesce_number;
628 fw_controller->saved_interrupt_coalesce_timeout = coalesce_timeout;
629 }
630
631 //restore current interrupt coalescence.
632 scic_controller_set_interrupt_coalescence(
633 fw_controller->core_object, curr_coalesce_number, curr_coalesce_timeout);
634
635 return core_status;
636 }
637 else
638 {
639 ///If framework is not internally overriding the interrupt coalescence,
640 ///serve user's request immediately by passing the reqeust to core.
641 return scic_controller_set_interrupt_coalescence(
642 fw_controller->core_object, coalesce_number, coalesce_timeout);
643 }
644 }
645
646 // ---------------------------------------------------------------------------
647
648 void scif_controller_get_interrupt_coalescence(
649 SCI_CONTROLLER_HANDLE_T controller,
650 U32 * coalesce_number,
651 U32 * coalesce_timeout
652 )
653 {
654 SCIF_SAS_CONTROLLER_T * scif_controller = (SCIF_SAS_CONTROLLER_T * )controller;
655
656 scic_controller_get_interrupt_coalescence(
657 scif_controller->core_object, coalesce_number, coalesce_timeout);
658 }
659
660 /**
661 * @brief This method will save the interrupt coalescence values. If
662 * the interrupt coalescence values have already been saved,
663 * then this method performs no operations.
664 *
665 * @param[in,out] fw_controller This parameter specifies the controller
666 * for which to save the interrupt coalescence values.
667 *
668 * @return none
669 */
670 void scif_sas_controller_save_interrupt_coalescence(
671 SCIF_SAS_CONTROLLER_T * fw_controller
672 )
673 {
674 if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
675 {
676 // Override core's interrupt coalescing settings during SMP
677 // DISCOVER process cause' there is only 1 outstanding SMP
678 // request per domain is allowed.
679 scic_controller_get_interrupt_coalescence(
680 fw_controller->core_object,
681 (U32*)&(fw_controller->saved_interrupt_coalesce_number),
682 &(fw_controller->saved_interrupt_coalesce_timeout)
683 );
684
685 // Temporarily disable the interrupt coalescing.
686 scic_controller_set_interrupt_coalescence(fw_controller->core_object,0,0);
687 }
688 }
689
690 /**
691 * @brief This method will restore the interrupt coalescence values. If
692 * the interrupt coalescence values have not already been saved,
693 * then this method performs no operations.
694 *
695 * @param[in,out] fw_controller This parameter specifies the controller
696 * for which to restore the interrupt coalescence values.
697 *
698 * @return none
699 */
700 void scif_sas_controller_restore_interrupt_coalescence(
701 SCIF_SAS_CONTROLLER_T * fw_controller
702 )
703 {
704 if ( !scif_sas_controller_is_overriding_interrupt_coalescence(fw_controller))
705 scic_controller_set_interrupt_coalescence(
706 fw_controller->core_object,
707 fw_controller->saved_interrupt_coalesce_number,
708 fw_controller->saved_interrupt_coalesce_timeout
709 );
710 }
711
712 #endif // !defined(DISABLE_INTERRUPTS)
713
714 // ---------------------------------------------------------------------------
715
716 void scic_cb_controller_start_complete(
717 SCI_CONTROLLER_HANDLE_T controller,
718 SCI_STATUS completion_status
719 )
720 {
721 SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
722 sci_object_get_association(controller);
723
724 SCIF_LOG_TRACE((
725 sci_base_object_get_logger(controller),
726 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
727 "scic_cb_controller_start_complete(0x%x, 0x%x) enter\n",
728 controller, completion_status
729 ));
730
731 if (completion_status == SCI_SUCCESS
732 || completion_status == SCI_FAILURE_TIMEOUT)
733 {
734 // Even the initialization of the core controller timed out, framework
735 // controller should still transit to READY state.
736 sci_base_state_machine_change_state(
737 &fw_controller->parent.state_machine,
738 SCI_BASE_CONTROLLER_STATE_READY
739 );
740 }
741
742 scif_cb_controller_start_complete(fw_controller, completion_status);
743 }
744
745 // ---------------------------------------------------------------------------
746
747 void scic_cb_controller_stop_complete(
748 SCI_CONTROLLER_HANDLE_T controller,
749 SCI_STATUS completion_status
750 )
751 {
752 SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
753 sci_object_get_association(controller);
754
755 SCIF_LOG_TRACE((
756 sci_base_object_get_logger(controller),
757 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
758 "scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n",
759 controller, completion_status
760 ));
761
762 if (completion_status == SCI_SUCCESS)
763 {
764 sci_base_state_machine_change_state(
765 &fw_controller->parent.state_machine,
766 SCI_BASE_CONTROLLER_STATE_STOPPED
767 );
768 }
769 else
770 {
771 sci_base_state_machine_change_state(
772 &fw_controller->parent.state_machine,
773 SCI_BASE_CONTROLLER_STATE_FAILED
774 );
775 }
776
777 scif_cb_controller_stop_complete(fw_controller, completion_status);
778 }
779
780
781 // ---------------------------------------------------------------------------
782
783 void scic_cb_controller_error(
784 SCI_CONTROLLER_HANDLE_T controller,
785 SCI_CONTROLLER_ERROR error
786 )
787 {
788 SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
789 sci_object_get_association(controller);
790
791 fw_controller->parent.error = error;
792
793 SCIF_LOG_TRACE((
794 sci_base_object_get_logger(controller),
795 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
796 "scic_cb_controller_not_ready(0x%x) enter\n",
797 controller
798 ));
799
800 sci_base_state_machine_change_state(
801 &fw_controller->parent.state_machine,
802 SCI_BASE_CONTROLLER_STATE_FAILED
803 );
804 }
805
806 //******************************************************************************
807 //* P R O T E C T E D M E T H O D S
808 //******************************************************************************
809
810 /**
811 * @brief This method is utilized to continue an internal IO operation
812 * on the controller. This method is utilized for SAT translated
813 * requests that generate multiple ATA commands in order to fulfill
814 * the original SCSI request.
815 *
816 * @param[in] controller This parameter specifies the controller on which
817 * to continue an internal IO request.
818 * @param[in] remote_device This parameter specifies the remote device
819 * on which to continue an internal IO request.
820 * @param[in] io_request This parameter specifies the IO request to be
821 * continue.
822 *
823 * @return Indicate if the continue operation was successful.
824 * @retval SCI_SUCCESS This value is returned if the operation succeeded.
825 */
826 SCI_STATUS scif_sas_controller_continue_io(
827 SCI_CONTROLLER_HANDLE_T controller,
828 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
829 SCI_IO_REQUEST_HANDLE_T io_request
830 )
831 {
832 SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
833
834 return fw_controller->state_handlers->continue_io_handler(
835 (SCI_BASE_CONTROLLER_T*) controller,
836 (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
837 (SCI_BASE_REQUEST_T*) io_request
838 );
839 }
840
841 /**
842 * @brief This method will attempt to destruct a framework controller.
843 * This includes free any resources retreived from the user (e.g.
844 * timers).
845 *
846 * @param[in] fw_controller This parameter specifies the framework
847 * controller to destructed.
848 *
849 * @return none
850 */
851 void scif_sas_controller_destruct(
852 SCIF_SAS_CONTROLLER_T * fw_controller
853 )
854 {
855 SCIF_LOG_TRACE((
856 sci_base_object_get_logger(fw_controller),
857 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
858 "scif_sas_controller_destruct(0x%x) enter\n",
859 fw_controller
860 ));
861 }
862
863 //-----------------------------------------------------------------------------
864 // INTERNAL REQUEST RELATED METHODS
865 //-----------------------------------------------------------------------------
866
867 /**
868 * @brief This routine is to allocate the memory for creating a new internal
869 * request.
870 *
871 * @param[in] scif_controller handle to frame controller
872 *
873 * @return void* address to internal request memory
874 */
875 void * scif_sas_controller_allocate_internal_request(
876 SCIF_SAS_CONTROLLER_T * fw_controller
877 )
878 {
879 POINTER_UINT internal_io_address;
880
881 if( !sci_pool_empty(fw_controller->internal_request_memory_pool) )
882 {
883 sci_pool_get(
884 fw_controller->internal_request_memory_pool, internal_io_address
885 );
886
887 //clean the memory.
888 memset((char*)internal_io_address, 0, scif_sas_internal_request_get_object_size());
889
890 return (void *) internal_io_address;
891 }
892 else
893 return NULL;
894 }
895
896 /**
897 * @brief This routine is to free the memory for a completed internal request.
898 *
899 * @param[in] scif_controller handle to frame controller
900 * @param[in] fw_internal_io The internal IO to be freed.
901 *
902 * @return none
903 */
904 void scif_sas_controller_free_internal_request(
905 SCIF_SAS_CONTROLLER_T * fw_controller,
906 void * fw_internal_request_buffer
907 )
908 {
909 SCIF_LOG_TRACE((
910 sci_base_object_get_logger(fw_controller),
911 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
912 "scif_controller_free_internal_request(0x%x, 0x%x) enter\n",
913 fw_controller, fw_internal_request_buffer
914 ));
915
916 //return the memory to the pool.
917 if( !sci_pool_full(fw_controller->internal_request_memory_pool) )
918 {
919 sci_pool_put(
920 fw_controller->internal_request_memory_pool,
921 (POINTER_UINT) fw_internal_request_buffer
922 );
923 }
924 }
925
926
927 /**
928 * @brief this routine is called by OS' DPC to start io requests from internal
929 * high priority request queue
930 * @param[in] fw_controller The framework controller.
931 *
932 * @return none
933 */
934 void scif_sas_controller_start_high_priority_io(
935 SCIF_SAS_CONTROLLER_T * fw_controller
936 )
937 {
938 POINTER_UINT io_address;
939 SCIF_SAS_IO_REQUEST_T * fw_io;
940 SCI_STATUS status;
941
942 SCIF_LOG_TRACE((
943 sci_base_object_get_logger(fw_controller),
944 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
945 "scif_controller_start_high_priority_io(0x%x) enter\n",
946 fw_controller
947 ));
948
949 while ( !sci_pool_empty(fw_controller->hprq.pool) )
950 {
951 sci_pool_get(fw_controller->hprq.pool, io_address);
952
953 fw_io = (SCIF_SAS_IO_REQUEST_T *)io_address;
954
955 status = fw_controller->state_handlers->start_high_priority_io_handler(
956 (SCI_BASE_CONTROLLER_T*) fw_controller,
957 (SCI_BASE_REMOTE_DEVICE_T*) fw_io->parent.device,
958 (SCI_BASE_REQUEST_T*) fw_io,
959 SCI_CONTROLLER_INVALID_IO_TAG
960 );
961 }
962 }
963
964 /**
965 * @brief This method will check how many outstanding IOs currently and number
966 * of IOs in high priority queue, if the overall number exceeds the max_tc,
967 * return FALSE.
968 *
969 * @param[in] fw_controller The framework controller.
970 *
971 * @return BOOL Indicate whether there is sufficient resource to start an IO.
972 * @retvalue TRUE The controller has sufficient resource.
973 * @retvalue FALSE There is not sufficient resource available.
974 */
975 BOOL scif_sas_controller_sufficient_resource(
976 SCIF_SAS_CONTROLLER_T *fw_controller
977 )
978 {
979 SCIF_SAS_DOMAIN_T * fw_domain;
980 U32 domain_index;
981 U32 outstanding_io_count = 0;
982 U32 high_priority_io_count = 0;
983
984 for(domain_index = 0; domain_index < SCI_MAX_DOMAINS; domain_index++)
985 {
986 fw_domain = &fw_controller->domains[domain_index];
987 outstanding_io_count += fw_domain->request_list.element_count;
988 }
989
990 high_priority_io_count = sci_pool_count(fw_controller->hprq.pool);
991
992 if ( (outstanding_io_count + high_priority_io_count) > SCI_MAX_IO_REQUESTS )
993 return FALSE;
994
995 return TRUE;
996 }
997
998
999 /**
1000 * @brief This method is the starting point to complete high prority io for a
1001 * controller then down to domain, device.
1002 *
1003 * @param[in] fw_controller The framework controller
1004 * @param[in] remote_device The framework remote device.
1005 * @param[in] io_request The high priority io request to be completed.
1006 *
1007 * @return SCI_STATUS indicate the completion status from framework down to the
1008 * core.
1009 */
1010 SCI_STATUS scif_sas_controller_complete_high_priority_io(
1011 SCIF_SAS_CONTROLLER_T *fw_controller,
1012 SCIF_SAS_REMOTE_DEVICE_T *remote_device,
1013 SCIF_SAS_REQUEST_T *io_request
1014 )
1015 {
1016 SCIF_LOG_TRACE((
1017 sci_base_object_get_logger(fw_controller),
1018 SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
1019 "scif_sas_controller_complete_high_priority_io(0x%x, 0x%x, 0x%x) enter\n",
1020 fw_controller, remote_device, io_request
1021 ));
1022
1023 //call controller's new added complete_high_priority_io_handler
1024 return fw_controller->state_handlers->complete_high_priority_io_handler(
1025 (SCI_BASE_CONTROLLER_T*) fw_controller,
1026 (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
1027 (SCI_BASE_REQUEST_T*) io_request
1028 );
1029 }
1030
1031 /**
1032
1033 * @brief This routine is to allocate the memory for creating a smp phy object.
1034 *
1035 * @param[in] scif_controller handle to frame controller
1036 *
1037 * @return SCIF_SAS_SMP_PHY_T * An allocated space for smp phy. If failed to allocate,
1038 * return NULL.
1039 */
1040 SCIF_SAS_SMP_PHY_T * scif_sas_controller_allocate_smp_phy(
1041 SCIF_SAS_CONTROLLER_T * fw_controller
1042 )
1043 {
1044 SCIF_SAS_SMP_PHY_T * smp_phy;
1045
1046 SCIF_LOG_TRACE((
1047 sci_base_object_get_logger(fw_controller),
1048 SCIF_LOG_OBJECT_CONTROLLER,
1049 "scif_controller_allocate_smp_phy(0x%x) enter\n",
1050 fw_controller
1051 ));
1052
1053 if( !sci_fast_list_is_empty(&fw_controller->smp_phy_memory_list) )
1054 {
1055 smp_phy = (SCIF_SAS_SMP_PHY_T *)
1056 sci_fast_list_remove_head(&fw_controller->smp_phy_memory_list);
1057
1058 //clean the memory.
1059 memset((char*)smp_phy,
1060 0,
1061 sizeof(SCIF_SAS_SMP_PHY_T)
1062 );
1063
1064 return smp_phy;
1065 }
1066 else
1067 return NULL;
1068 }
1069
1070 /**
1071 * @brief This routine is to free the memory for a released smp phy.
1072 *
1073 * @param[in] fw_controller The framework controller, a smp phy is released
1074 * to its memory.
1075 * @param[in] fw_smp_phy The smp phy to be freed.
1076 *
1077 * @return none
1078 */
1079 void scif_sas_controller_free_smp_phy(
1080 SCIF_SAS_CONTROLLER_T * fw_controller,
1081 SCIF_SAS_SMP_PHY_T * smp_phy
1082 )
1083 {
1084 SCIF_LOG_TRACE((
1085 sci_base_object_get_logger(fw_controller),
1086 SCIF_LOG_OBJECT_CONTROLLER,
1087 "scif_controller_free_smp_phy(0x%x, 0x%x) enter\n",
1088 fw_controller, smp_phy
1089 ));
1090
1091 //return the memory to the list.
1092 sci_fast_list_insert_tail(
1093 &fw_controller->smp_phy_memory_list,
1094 &smp_phy->list_element
1095 );
1096 }
1097
1098
1099 /**
1100 * @brief This method clear affiliation for all the EA SATA devices associated
1101 * to this controller.
1102 *
1103 * @param[in] fw_controller This parameter specifies the framework
1104 * controller object for whose remote devices are to be stopped.
1105 *
1106 * @return This method returns a value indicating if the operation completed.
1107 * @retval SCI_COMPLETE This value indicates that all the EA SATA devices'
1108 * affiliation was cleared.
1109 * @retval SCI_INCOMPLETE This value indicates clear affiliation activity is
1110 * yet to be completed.
1111 */
1112 SCI_STATUS scif_sas_controller_clear_affiliation(
1113 SCIF_SAS_CONTROLLER_T * fw_controller
1114 )
1115 {
1116 U8 index;
1117 SCI_STATUS status;
1118 SCIF_SAS_DOMAIN_T * fw_domain;
1119
1120 SCIF_LOG_TRACE((
1121 sci_base_object_get_logger(fw_controller),
1122 SCIF_LOG_OBJECT_CONTROLLER,
1123 "scif_sas_controller_clear_affiliation(0x%x) enter\n",
1124 fw_controller
1125 ));
1126
1127 index = fw_controller->current_domain_to_clear_affiliation;
1128
1129 if (index < SCI_MAX_DOMAINS)
1130 {
1131 fw_domain = &fw_controller->domains[index];
1132
1133 //Need to stop all the on-going smp activities before clearing affiliation.
1134 scif_sas_domain_cancel_smp_activities(fw_domain);
1135
1136 scif_sas_domain_start_clear_affiliation(fw_domain);
1137
1138 status = SCI_WARNING_SEQUENCE_INCOMPLETE;
1139 }
1140 else
1141 { //the controller has done clear affiliation work to all its domains.
1142 scif_sas_controller_continue_to_stop(fw_controller);
1143 status = SCI_SUCCESS;
1144 }
1145
1146 return status;
1147 }
1148
1149
1150 /**
1151 * @brief This method sets SCIF user parameters to
1152 * default values. Users can override these values utilizing
1153 * the sciF_user_parameters_set() methods.
1154 *
1155 * @param[in] controller This parameter specifies the controller for
1156 * which to set the configuration parameters to their
1157 * default values.
1158 *
1159 * @return none
1160 */
1161 void scif_sas_controller_set_default_config_parameters(
1162 SCIF_SAS_CONTROLLER_T * this_controller
1163 )
1164 {
1165 SCIF_USER_PARAMETERS_T * scif_parms = &(this_controller->user_parameters);
1166
1167 scif_parms->sas.is_sata_ncq_enabled = TRUE;
1168 scif_parms->sas.max_ncq_depth = 32;
1169 scif_parms->sas.is_sata_standby_timer_enabled = FALSE;
1170 scif_parms->sas.is_non_zero_buffer_offsets_enabled = FALSE;
1171 scif_parms->sas.reset_type = SCI_SAS_LOGICAL_UNIT_RESET;
1172 scif_parms->sas.clear_affiliation_during_controller_stop = TRUE;
1173 scif_parms->sas.ignore_fua = FALSE;
1174
1175 }
1176
1177
1178 /**
1179 * @brief This method releases resource for framework controller and associated
1180 * objects.
1181 *
1182 * @param[in] fw_controller This parameter specifies the framework
1183 * controller and associated objects whose resources are to be released.
1184 *
1185 * @return This method returns a value indicating if the operation succeeded.
1186 * @retval SCI_SUCCESS This value indicates that resource release succeeded.
1187 * @retval SCI_FAILURE This value indicates certain failure during the process
1188 * of resource release.
1189 */
1190 SCI_STATUS scif_sas_controller_release_resource(
1191 SCIF_SAS_CONTROLLER_T * fw_controller
1192 )
1193 {
1194 U8 index;
1195 SCIF_SAS_DOMAIN_T * fw_domain;
1196
1197 SCIF_LOG_TRACE((
1198 sci_base_object_get_logger(fw_controller),
1199 SCIF_LOG_OBJECT_CONTROLLER,
1200 "scif_sas_controller_release_resource(0x%x) enter\n",
1201 fw_controller
1202 ));
1203
1204 //currently the only resource to be released is domain's timer.
1205 for (index = 0; index < SCI_MAX_DOMAINS; index++)
1206 {
1207 fw_domain = &fw_controller->domains[index];
1208
1209 scif_sas_domain_release_resource(fw_controller, fw_domain);
1210 }
1211
1212 return SCI_SUCCESS;
1213 }
1214
1215
1216 #ifdef SCI_LOGGING
1217 /**
1218 * This method will start state transition logging for the framework
1219 * controller object.
1220 *
1221 * @param[in] fw_controller The framework controller object on which to
1222 * observe state changes.
1223 *
1224 * @return none
1225 */
1226 void scif_sas_controller_initialize_state_logging(
1227 SCIF_SAS_CONTROLLER_T * fw_controller
1228 )
1229 {
1230 sci_base_state_machine_logger_initialize(
1231 &fw_controller->parent.state_machine_logger,
1232 &fw_controller->parent.state_machine,
1233 &fw_controller->parent.parent,
1234 scif_cb_logger_log_states,
1235 "SCIF_SAS_CONTROLLER_T", "base state machine",
1236 SCIF_LOG_OBJECT_CONTROLLER
1237 );
1238 }
1239
1240 /**
1241 * This method will remove the logging of state transitions from the framework
1242 * controller object.
1243 *
1244 * @param[in] fw_controller The framework controller to change.
1245 *
1246 * @return none
1247 */
1248 void scif_sas_controller_deinitialize_state_logging(
1249 SCIF_SAS_CONTROLLER_T * fw_controller
1250 )
1251 {
1252 sci_base_state_machine_logger_deinitialize(
1253 &fw_controller->parent.state_machine_logger,
1254 &fw_controller->parent.state_machine
1255 );
1256 }
1257 #endif // SCI_LOGGING
Cache object: 6e627ea3075cba6ee3770d6eea64aac4
|