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_REMOTE_DEVICE
62 * object.
63 */
64
65
66 #include <dev/isci/scil/scic_remote_device.h>
67 #include <dev/isci/scil/scic_port.h>
68 #include <dev/isci/scil/scic_user_callback.h>
69
70 #include <dev/isci/scil/scif_sas_logger.h>
71 #include <dev/isci/scil/scif_sas_remote_device.h>
72 #include <dev/isci/scil/scif_sas_stp_remote_device.h>
73 #include <dev/isci/scil/scif_sas_domain.h>
74 #include <dev/isci/scil/scif_sas_controller.h>
75 #include <dev/isci/scil/sci_controller.h>
76 #include <dev/isci/scil/sci_util.h>
77
78
79 //******************************************************************************
80 //* P U B L I C M E T H O D S
81 //******************************************************************************
82
83 U32 scif_remote_device_get_object_size(
84 void
85 )
86 {
87 return ( sizeof(SCIF_SAS_REMOTE_DEVICE_T)
88 + scic_remote_device_get_object_size() );
89 }
90
91 // ---------------------------------------------------------------------------
92
93 void scif_remote_device_construct(
94 SCI_DOMAIN_HANDLE_T domain,
95 void * remote_device_memory,
96 SCI_REMOTE_DEVICE_HANDLE_T * new_scif_remote_device_handle
97 )
98 {
99 SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *) domain;
100 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
101 remote_device_memory;
102
103 SCIF_LOG_TRACE((
104 sci_base_object_get_logger(fw_domain),
105 SCIF_LOG_OBJECT_REMOTE_DEVICE,
106 "scif_remote_device_construct(0x%x, 0x%x, 0x%x) enter\n",
107 domain, remote_device_memory, new_scif_remote_device_handle
108 ));
109
110 memset(remote_device_memory, 0, sizeof(SCIF_SAS_REMOTE_DEVICE_T));
111
112 // The user's handle to the remote device evaluates to the memory
113 // address where the remote device object is stored.
114 *new_scif_remote_device_handle = remote_device_memory;
115
116 fw_device->domain = fw_domain;
117 fw_device->destruct_when_stopped = FALSE;
118 //fw_device->parent.is_failed = FALSE;
119 fw_device->operation_status = SCI_SUCCESS;
120 fw_device->request_count = 0;
121 fw_device->task_request_count = 0;
122 fw_device->is_currently_discovered = TRUE;
123 fw_device->containing_device = NULL;
124 fw_device->device_port_width = 1;
125 fw_device->expander_phy_identifier = 0;
126 fw_device->destination_state =
127 SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UNSPECIFIED;
128 fw_device->ea_target_reset_request_scheduled = NULL;
129
130 // Construct the base object first in order to ensure logging can
131 // function.
132 sci_base_remote_device_construct(
133 &fw_device->parent,
134 sci_base_object_get_logger(fw_domain),
135 scif_sas_remote_device_state_table
136 );
137
138 sci_base_state_machine_construct(
139 &fw_device->starting_substate_machine,
140 &fw_device->parent.parent,
141 scif_sas_remote_device_starting_substate_table,
142 SCIF_SAS_REMOTE_DEVICE_STARTING_SUBSTATE_AWAIT_COMPLETE
143 );
144
145 sci_base_state_machine_construct(
146 &fw_device->ready_substate_machine,
147 &fw_device->parent.parent,
148 scif_sas_remote_device_ready_substate_table,
149 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
150 );
151
152 scif_sas_remote_device_initialize_state_logging(fw_device);
153
154 scic_remote_device_construct(
155 fw_domain->core_object,
156 ((U8*) remote_device_memory) + sizeof(SCIF_SAS_REMOTE_DEVICE_T),
157 &fw_device->core_object
158 );
159
160 // Set the association in the core object, so that we are able to
161 // determine our framework remote device object from the core remote
162 // device.
163 sci_object_set_association(fw_device->core_object, fw_device);
164 }
165
166 // ---------------------------------------------------------------------------
167
168 SCI_STATUS scif_remote_device_da_construct(
169 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
170 SCI_SAS_ADDRESS_T * sas_address,
171 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols
172 )
173 {
174 SCI_STATUS status = SCI_SUCCESS;
175 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
176 remote_device;
177
178 SCIF_LOG_TRACE((
179 sci_base_object_get_logger(fw_device),
180 SCIF_LOG_OBJECT_REMOTE_DEVICE,
181 "scif_remote_device_da_construct(0x%x, 0x%x, 0x%x) enter\n",
182 remote_device, sas_address, protocols
183 ));
184
185 // Make sure the device hasn't already been constructed and added
186 // to the domain.
187 if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address)
188 == SCI_INVALID_HANDLE)
189 {
190 SCIC_PORT_PROPERTIES_T properties;
191
192 scic_port_get_properties(fw_device->domain->core_object, &properties);
193
194 // Check to see if this is the direct attached device.
195 if ( (sas_address->low == properties.remote.sas_address.low)
196 && (sas_address->high == properties.remote.sas_address.high) )
197 {
198 //Get accurate port width from port's phy mask for a DA device.
199 SCI_GET_BITS_SET_COUNT(properties.phy_mask, fw_device->device_port_width);
200
201 status = scic_remote_device_da_construct(fw_device->core_object);
202 }
203 else
204 // Don't allow the user to construct a direct attached device
205 // if it's not a direct attached device.
206 status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
207 }
208 else
209 status = SCI_FAILURE_DEVICE_EXISTS;
210
211 if (status == SCI_SUCCESS)
212 {
213 // Add the device to the domain list.
214 sci_abstract_list_pushback(
215 &fw_device->domain->remote_device_list, fw_device
216 );
217
218 // If a SATA/STP device is connected, then construct it.
219 if (protocols->u.bits.stp_target)
220 scif_sas_stp_remote_device_construct(fw_device);
221 else if (protocols->u.bits.smp_target)
222 scif_sas_smp_remote_device_construct(fw_device);
223
224 SCIF_LOG_INFO((
225 sci_base_object_get_logger(fw_device),
226 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
227 "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n",
228 fw_device->domain, sas_address->low, sas_address->high
229 ));
230
231 status = fw_device->state_handlers->parent.start_handler(
232 &fw_device->parent
233 );
234 }
235 else
236 {
237 SCIF_LOG_WARNING((
238 sci_base_object_get_logger(fw_device),
239 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
240 "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n",
241 fw_device->domain, sas_address->low, sas_address->high, status
242 ));
243 }
244
245 return status;
246 }
247
248 // ---------------------------------------------------------------------------
249
250 SCI_STATUS scif_remote_device_ea_construct(
251 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
252 SCI_REMOTE_DEVICE_HANDLE_T containing_device,
253 SMP_RESPONSE_DISCOVER_T * smp_response
254 )
255 {
256 SCI_SAS_ADDRESS_T * sas_address;
257 SCI_STATUS status = SCI_SUCCESS;
258 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
259 remote_device;
260 SCIF_SAS_REMOTE_DEVICE_T * fw_smp_device = (SCIF_SAS_REMOTE_DEVICE_T *)
261 containing_device;
262
263 fw_device->containing_device = fw_smp_device;
264 fw_device->expander_phy_identifier =
265 fw_smp_device->protocol_device.smp_device.current_activity_phy_index;
266
267 sas_address = &smp_response->attached_sas_address;
268
269 SCIF_LOG_TRACE((
270 sci_base_object_get_logger(fw_device),
271 SCIF_LOG_OBJECT_REMOTE_DEVICE,
272 "scif_remote_device_ea_construct(0x%x, 0x%x) enter\n",
273 remote_device, smp_response
274 ));
275
276 // Make sure the device hasn't already been constructed and added
277 // to the domain.
278 if (scif_domain_get_device_by_sas_address(fw_device->domain, sas_address)
279 == SCI_INVALID_HANDLE)
280 {
281 //for sata device, we need another routine. likely
282 //scif_remote_device_ea_sata_construct.
283 status = scic_remote_device_ea_construct(fw_device->core_object, smp_response);
284 }
285 else
286 status = SCI_FAILURE_DEVICE_EXISTS;
287
288 if (status == SCI_SUCCESS)
289 {
290 // Add the device to the domain list.
291 sci_abstract_list_pushback(
292 &fw_device->domain->remote_device_list, fw_device
293 );
294
295 if (smp_response->protocols.u.bits.attached_smp_target)
296 scif_sas_smp_remote_device_construct(fw_device);
297 else if (smp_response->protocols.u.bits.attached_stp_target)
298 scif_sas_stp_remote_device_construct(fw_device);
299
300 SCIF_LOG_INFO((
301 sci_base_object_get_logger(fw_device),
302 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
303 "Domain:0x%x SasAddress:0x%x,0x%x remote device constructed\n",
304 fw_device->domain, sas_address->low, sas_address->high
305 ));
306
307 //only start the device if the device is not a SATA disk on SPINUP_HOLD state.
308 if ( scic_remote_device_get_connection_rate(fw_device->core_object) !=
309 SCI_SATA_SPINUP_HOLD )
310 {
311 status = fw_device->state_handlers->parent.start_handler(
312 &fw_device->parent
313 );
314 }
315 }
316 else
317 {
318 SCIF_LOG_WARNING((
319 sci_base_object_get_logger(fw_device),
320 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
321 "Domain:0x%x SasAddress:0x%x,0x%x Status:0x%x remote device construct failure\n",
322 fw_device->domain, sas_address->low, sas_address->high, status
323 ));
324 }
325
326 return status;
327 }
328
329 // ---------------------------------------------------------------------------
330
331 SCI_STATUS scif_remote_device_destruct(
332 SCI_REMOTE_DEVICE_HANDLE_T remote_device
333 )
334 {
335 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
336 remote_device;
337
338 SCIF_LOG_TRACE((
339 sci_base_object_get_logger(fw_device),
340 SCIF_LOG_OBJECT_REMOTE_DEVICE,
341 "scif_remote_device_destruct(0x%x) enter\n",
342 remote_device
343 ));
344
345 //remove the device from domain's remote_device_list
346 fw_device->domain->state_handlers->device_destruct_handler(
347 &fw_device->domain->parent, &fw_device->parent
348 );
349
350 // The destruct process may not complete immediately, since the core
351 // remote device likely needs to be stopped first. However, the user
352 // is not given a callback notification for destruction.
353 return fw_device->state_handlers->parent.destruct_handler(
354 &fw_device->parent
355 );
356 }
357
358 // ---------------------------------------------------------------------------
359
360 SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle(
361 SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device
362 )
363 {
364 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
365 scif_remote_device;
366
367 if ( (fw_device == NULL) || (fw_device->core_object == SCI_INVALID_HANDLE) )
368 return SCI_INVALID_HANDLE;
369
370 SCIF_LOG_WARNING((
371 sci_base_object_get_logger(fw_device),
372 SCIF_LOG_OBJECT_REMOTE_DEVICE,
373 "RemoteDevice:0x%x no associated core device found\n",
374 fw_device
375 ));
376
377 return fw_device->core_object;
378 }
379
380 // ---------------------------------------------------------------------------
381
382 void scic_cb_remote_device_start_complete(
383 SCI_CONTROLLER_HANDLE_T controller,
384 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
385 SCI_STATUS completion_status
386 )
387 {
388 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
389 sci_object_get_association(remote_device);
390
391 SCIF_LOG_TRACE((
392 sci_base_object_get_logger(fw_device),
393 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
394 "scic_cb_remote_device_start_complete(0x%x, 0x%x, 0x%x) enter\n",
395 controller, remote_device, completion_status
396 ));
397
398 fw_device->state_handlers->start_complete_handler(
399 fw_device, completion_status
400 );
401 }
402
403 // ---------------------------------------------------------------------------
404
405 void scic_cb_remote_device_stop_complete(
406 SCI_CONTROLLER_HANDLE_T controller,
407 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
408 SCI_STATUS completion_status
409 )
410 {
411 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
412 sci_object_get_association(remote_device);
413
414 SCIF_LOG_TRACE((
415 sci_base_object_get_logger(fw_device),
416 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
417 "scic_cb_remote_device_stop_complete(0x%x, 0x%x, 0x%x) enter\n",
418 controller, remote_device, completion_status
419 ));
420
421 fw_device->state_handlers->stop_complete_handler(
422 fw_device, completion_status
423 );
424 }
425
426 // ---------------------------------------------------------------------------
427
428 void scic_cb_remote_device_ready(
429 SCI_CONTROLLER_HANDLE_T controller,
430 SCI_REMOTE_DEVICE_HANDLE_T remote_device
431 )
432 {
433 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
434 sci_object_get_association(remote_device);
435
436 fw_device->state_handlers->ready_handler(fw_device);
437 }
438
439 // ---------------------------------------------------------------------------
440
441 void scic_cb_remote_device_not_ready(
442 SCI_CONTROLLER_HANDLE_T controller,
443 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
444 U32 reason_code
445 )
446 {
447 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
448 sci_object_get_association(remote_device);
449
450 fw_device->state_handlers->not_ready_handler(fw_device,reason_code);
451 }
452
453 // ---------------------------------------------------------------------------
454
455 U16 scif_remote_device_get_max_queue_depth(
456 SCI_REMOTE_DEVICE_HANDLE_T remote_device
457 )
458 {
459 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
460 remote_device;
461 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
462
463 scic_remote_device_get_protocols(fw_device->core_object, &protocols);
464
465 // If the target is a SATA/STP target, then determine the queue depth
466 // for either NCQ or for UDMA.
467 if (protocols.u.bits.attached_stp_target)
468 {
469 if (fw_device->protocol_device.stp_device.sati_device.capabilities
470 & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE)
471 {
472 return fw_device->protocol_device.stp_device.sati_device.ncq_depth;
473 }
474 else
475 {
476 // At the moment, we only allow a single UDMA request to be queued.
477 return 1;
478 }
479 }
480
481 // For SSP devices return a no maximum queue depth supported.
482 return SCIF_REMOTE_DEVICE_NO_MAX_QUEUE_DEPTH;
483 }
484
485 // ---------------------------------------------------------------------------
486
487 SCI_STATUS scif_remote_device_get_containing_device(
488 SCI_REMOTE_DEVICE_HANDLE_T remote_device,
489 SCI_REMOTE_DEVICE_HANDLE_T * containing_device
490 )
491 {
492 SCI_STATUS status = SCI_FAILURE;
493 SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *)
494 remote_device;
495
496 if ( (this_device != NULL) && (containing_device != NULL) )
497 {
498 *containing_device = (SCI_REMOTE_DEVICE_HANDLE_T)(this_device->containing_device);
499 if (*containing_device != NULL)
500 {
501 status = SCI_SUCCESS;
502 }
503 }
504
505 return status;
506 }
507
508 // ---------------------------------------------------------------------------
509
510 U32 scif_remote_device_get_started_io_count(
511 SCI_REMOTE_DEVICE_HANDLE_T remote_device
512 )
513 {
514 SCIF_SAS_REMOTE_DEVICE_T * this_device = (SCIF_SAS_REMOTE_DEVICE_T *)
515 remote_device;
516
517 return this_device->request_count - this_device->task_request_count;
518 }
519 //******************************************************************************
520 //* P R O T E C T E D M E T H O D S
521 //******************************************************************************
522
523 /*
524 void scif_sas_remote_device_failure(
525 SCIF_SAS_REMOTE_DEVICE_T * fw_device
526 )
527 {
528 fw_device->parent.is_failed = TRUE;
529 sci_base_state_machine_change_state(
530 &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
531 );
532 }
533 */
534
535
536 /**
537 * @brief This method retrieves info from Report Phy Sata response and
538 * save the additional data for a SATA remote device, if necessary.
539 *
540 * @param[in] report_phy_sata_response SMP Report Phy Sata response
541 *
542 * @return none
543 */
544 void scif_sas_remote_device_save_report_phy_sata_information(
545 SMP_RESPONSE_REPORT_PHY_SATA_T * report_phy_sata_response
546 )
547 {
548 //do nothing currently. Later, if needed, we will search the existed
549 //remote device by stp_sas_address, then save more information for
550 //that device off the report_phy_sata_response. This assumes the
551 //stp_sas_address from report_phy_sata response is the same sas address
552 //from discover response.
553
554 return;
555 }
556
557 /**
558 * @brief This method does target reset for DA or EA remote device.
559 *
560 * @param[in] fw_controller, the controller object the target device belongs
561 * to.
562 * @param[in] fw_device, the target device to be hard reset.
563 * @param[in] fw_request, the scif task request object that asked for this
564 * target reset.
565 */
566 void scif_sas_remote_device_target_reset(
567 SCIF_SAS_REMOTE_DEVICE_T * fw_device,
568 SCIF_SAS_REQUEST_T * fw_request
569 )
570 {
571 SCIF_LOG_INFO((
572 sci_base_object_get_logger(fw_device),
573 SCIF_LOG_OBJECT_REMOTE_DEVICE,
574 "scif_sas_remote_device_target_reset! fw_device:0x%x fw_request:0x%x\n",
575 fw_device, fw_request
576 ));
577
578 if (fw_device->containing_device == NULL)
579 {
580 SCI_PORT_HANDLE_T port;
581
582 port = scif_domain_get_scic_port_handle(fw_device->domain);
583
584 //Direct attached device target reset.
585 //calling core to do port reset. The fw_request will not be used here.
586 scic_port_hard_reset(
587 port,
588 scic_remote_device_get_suggested_reset_timeout(fw_device->core_object)
589 );
590 }
591 else
592 { //Expander attached device target reset.
593
594 if ( fw_device->containing_device->protocol_device.smp_device.current_activity
595 == SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET )
596 {
597 //The containing expander is in the middle of target resetting other of its
598 //remote disks. Flag this remote device to be target reset later.
599 SCIF_LOG_INFO((
600 sci_base_object_get_logger(fw_device),
601 SCIF_LOG_OBJECT_REMOTE_DEVICE,
602 "scif_sas_remote_device_target_reset DELAYED! fw_device:0x%x fw_request:0x%x\n",
603 fw_device, fw_request
604 ));
605
606 fw_device->ea_target_reset_request_scheduled = fw_request;
607 return;
608 }
609
610 //set current_activity and current_smp_request to expander device.
611 scif_sas_smp_remote_device_start_target_reset(
612 fw_device->containing_device, fw_device, fw_request);
613 }
614
615 scic_remote_device_reset(fw_device->core_object);
616 }
617
618
619 /**
620 * @brief This method completes target reset for DA or EA remote device.
621 *
622 * @param[in] fw_device, the target device to be hard reset.
623 * @param[in] fw_request, the scif task request object that asked for this
624 * target reset.
625 * @param[in] completion_status
626 */
627 void scif_sas_remote_device_target_reset_complete(
628 SCIF_SAS_REMOTE_DEVICE_T * fw_device,
629 SCIF_SAS_REQUEST_T * fw_request,
630 SCI_STATUS completion_status
631 )
632 {
633 SCIF_LOG_INFO((
634 sci_base_object_get_logger(fw_device),
635 SCIF_LOG_OBJECT_REMOTE_DEVICE,
636 "scif_sas_remote_device_target_reset_complete! "
637 "fw_device:0x%x fw_request:0x%x completion_status 0x%x\n",
638 fw_device, fw_request, completion_status
639 ));
640
641 scif_cb_task_request_complete(
642 fw_device->domain->controller,
643 fw_device,
644 fw_request,
645 (SCI_TASK_STATUS) completion_status
646 );
647
648 scic_remote_device_reset_complete(fw_device->core_object);
649
650 //For expander attached device done target reset.
651 if (fw_device->containing_device != NULL)
652 {
653 //search for all the devices in the domain to find other remote devices
654 //needs to be target reset.
655 SCIF_SAS_REMOTE_DEVICE_T * next_device;
656
657 scif_sas_smp_remote_device_clear(fw_device->containing_device);
658
659 if( (next_device = scif_sas_domain_find_next_ea_target_reset(fw_device->domain))
660 != NULL )
661 {
662 scif_sas_smp_remote_device_start_target_reset(
663 next_device->containing_device,
664 next_device,
665 next_device->ea_target_reset_request_scheduled
666 );
667
668 next_device->ea_target_reset_request_scheduled = NULL;
669 }
670 else
671 {
672 //if the domain is in the DISCOVER state, we should resume the DISCOVER.
673 if (fw_device->domain->parent.state_machine.current_state_id ==
674 SCI_BASE_DOMAIN_STATE_DISCOVERING)
675 {
676 SCIF_SAS_REMOTE_DEVICE_T * top_expander = fw_device->containing_device;
677
678 while(top_expander->containing_device != NULL)
679 top_expander = top_expander->containing_device;
680
681 scif_sas_domain_start_smp_discover(fw_device->domain, top_expander);
682 }
683 else
684 {
685 //Tell driver to kick off Discover process. If the domain is already
686 //in Discovery state, this discovery request will not be carried on.
687 scif_cb_domain_change_notification(
688 fw_device->domain->controller, fw_device->domain );
689 }
690 }
691 }
692 else
693 {
694 //Tell driver to kick off Discover process. If the domain is already
695 //in Discovery state, this discovery request will not be carried on.
696 scif_cb_domain_change_notification(
697 fw_device->domain->controller, fw_device->domain );
698 }
699 }
700
701 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
702 SCI_STATUS scif_sas_remote_device_update_port_width(
703 SCIF_SAS_REMOTE_DEVICE_T * fw_device,
704 U8 new_port_width
705 )
706 {
707 SCIF_LOG_INFO((
708 sci_base_object_get_logger(fw_device),
709 SCIF_LOG_OBJECT_REMOTE_DEVICE,
710 "scif_sas_remote_device_update_port_width (0x%x, 0x%x) enter\n",
711 fw_device, new_port_width
712 ));
713
714 fw_device->device_port_width = new_port_width;
715
716 //Don't Start a new update of port width if a device is already in
717 //UPDATING PORT WIDTH state.
718 if (fw_device->parent.state_machine.current_state_id == SCI_BASE_REMOTE_DEVICE_STATE_READY)
719 {
720 if (fw_device->device_port_width != 0)
721 {
722 //Change state to UPDATING_PORT_WIDTH
723 sci_base_state_machine_change_state(
724 &fw_device->parent.state_machine,
725 SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
726 );
727 }
728
729 return SCI_SUCCESS;
730 }
731 else if (fw_device->parent.state_machine.current_state_id ==
732 SCI_BASE_REMOTE_DEVICE_STATE_STARTING)
733 {
734 fw_device->destination_state =
735 SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_UPDATING_PORT_WIDTH;
736 }
737
738 return SCI_FAILURE_INVALID_STATE;
739 }
740 #endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
741
742
743 #ifdef SCI_LOGGING
744 void scif_sas_remote_device_initialize_state_logging(
745 SCIF_SAS_REMOTE_DEVICE_T * remote_device
746 )
747 {
748 sci_base_state_machine_logger_initialize(
749 &remote_device->parent.state_machine_logger,
750 &remote_device->parent.state_machine,
751 &remote_device->parent.parent,
752 scif_cb_logger_log_states,
753 "SCIF_SAS_REMOTE_DEVICE_T", "base_state_machine",
754 SCIF_LOG_OBJECT_REMOTE_DEVICE
755 );
756
757 sci_base_state_machine_logger_initialize(
758 &remote_device->starting_substate_machine_logger,
759 &remote_device->starting_substate_machine,
760 &remote_device->parent.parent,
761 scif_cb_logger_log_states,
762 "SCIF_SAS_REMOTE_DEVICE_T", "starting substate machine",
763 SCIF_LOG_OBJECT_REMOTE_DEVICE
764 );
765
766 sci_base_state_machine_logger_initialize(
767 &remote_device->ready_substate_machine_logger,
768 &remote_device->ready_substate_machine,
769 &remote_device->parent.parent,
770 scif_cb_logger_log_states,
771 "SCIF_SAS_REMOTE_DEVICE_T", "ready substate machine",
772 SCIF_LOG_OBJECT_REMOTE_DEVICE
773 );
774 }
775
776 void scif_sas_remote_device_deinitialize_state_logging(
777 SCIF_SAS_REMOTE_DEVICE_T * remote_device
778 )
779 {
780 sci_base_state_machine_logger_deinitialize(
781 &remote_device->parent.state_machine_logger,
782 &remote_device->parent.state_machine
783 );
784
785 sci_base_state_machine_logger_deinitialize(
786 &remote_device->starting_substate_machine_logger,
787 &remote_device->starting_substate_machine
788 );
789
790 sci_base_state_machine_logger_deinitialize(
791 &remote_device->ready_substate_machine_logger,
792 &remote_device->ready_substate_machine
793 );
794 }
795 #endif // SCI_LOGGING
796
Cache object: adedeea4dd092fcddc68a6c1173eecbf
|