1230557Sjimharris/*- 2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license. When using or 3230557Sjimharris * redistributing this file, you may do so under either license. 4230557Sjimharris * 5230557Sjimharris * GPL LICENSE SUMMARY 6230557Sjimharris * 7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8230557Sjimharris * 9230557Sjimharris * This program is free software; you can redistribute it and/or modify 10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as 11230557Sjimharris * published by the Free Software Foundation. 12230557Sjimharris * 13230557Sjimharris * This program is distributed in the hope that it will be useful, but 14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of 15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16230557Sjimharris * General Public License for more details. 17230557Sjimharris * 18230557Sjimharris * You should have received a copy of the GNU General Public License 19230557Sjimharris * along with this program; if not, write to the Free Software 20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21230557Sjimharris * The full GNU General Public License is included in this distribution 22230557Sjimharris * in the file called LICENSE.GPL. 23230557Sjimharris * 24230557Sjimharris * BSD LICENSE 25230557Sjimharris * 26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27230557Sjimharris * All rights reserved. 28230557Sjimharris * 29230557Sjimharris * Redistribution and use in source and binary forms, with or without 30230557Sjimharris * modification, are permitted provided that the following conditions 31230557Sjimharris * are met: 32230557Sjimharris * 33230557Sjimharris * * Redistributions of source code must retain the above copyright 34230557Sjimharris * notice, this list of conditions and the following disclaimer. 35230557Sjimharris * * Redistributions in binary form must reproduce the above copyright 36230557Sjimharris * notice, this list of conditions and the following disclaimer in 37230557Sjimharris * the documentation and/or other materials provided with the 38230557Sjimharris * distribution. 39230557Sjimharris * 40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51230557Sjimharris */ 52230557Sjimharris 53230557Sjimharris#include <sys/cdefs.h> 54230557Sjimharris__FBSDID("$FreeBSD$"); 55230557Sjimharris 56230557Sjimharris/** 57230557Sjimharris * @file 58230557Sjimharris * 59230557Sjimharris * @brief This file contains the methods for the SCIF_SAS_SMP_REMOTE_DEVICE object. 60230557Sjimharris */ 61230557Sjimharris#include <dev/isci/scil/sci_controller.h> 62230557Sjimharris#include <dev/isci/scil/scif_sas_controller.h> 63230557Sjimharris#include <dev/isci/scil/scif_sas_remote_device.h> 64230557Sjimharris#include <dev/isci/scil/scif_sas_logger.h> 65230557Sjimharris 66230557Sjimharris#include <dev/isci/scil/scif_sas_smp_remote_device.h> 67230557Sjimharris#include <dev/isci/scil/scif_sas_smp_io_request.h> 68230557Sjimharris#include <dev/isci/scil/intel_sas.h> 69230557Sjimharris#include <dev/isci/scil/scic_io_request.h> 70230557Sjimharris#include <dev/isci/scil/scic_remote_device.h> 71230557Sjimharris#include <dev/isci/scil/scif_sas_smp_phy.h> 72230557Sjimharris 73230557Sjimharris 74230557Sjimharris/** 75230557Sjimharris * @brief This method resets all fields for a smp remote device. This is a 76230557Sjimharris * private method. 77230557Sjimharris * 78230557Sjimharris * @param[in] fw_device the framework SMP device that is being 79230557Sjimharris * constructed. 80230557Sjimharris * 81230557Sjimharris * @return none 82230557Sjimharris */ 83230557Sjimharrisvoid scif_sas_smp_remote_device_clear( 84230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 85230557Sjimharris) 86230557Sjimharris{ 87230557Sjimharris //reset all fields in smp_device, indicate that the smp device is not 88230557Sjimharris //in discovery process. 89230557Sjimharris fw_device->protocol_device.smp_device.current_activity = 90230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE; 91230557Sjimharris 92230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 93230557Sjimharris NOT_IN_SMP_ACTIVITY; 94230557Sjimharris 95230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index = 0; 96230557Sjimharris 97230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index = 0; 98230557Sjimharris 99230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor = NULL; 100230557Sjimharris 101230557Sjimharris fw_device->protocol_device.smp_device.is_route_table_cleaned = FALSE; 102230557Sjimharris 103230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy = NULL; 104230557Sjimharris 105230557Sjimharris fw_device->protocol_device.smp_device.scheduled_activity = 106230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE; 107230557Sjimharris 108230557Sjimharris fw_device->protocol_device.smp_device.io_retry_count = 0; 109230557Sjimharris 110230557Sjimharris fw_device->protocol_device.smp_device.curr_clear_affiliation_phy = NULL; 111230557Sjimharris 112230557Sjimharris if (fw_device->protocol_device.smp_device.smp_activity_timer != NULL) 113230557Sjimharris { 114230557Sjimharris //stop the timer 115230557Sjimharris scif_cb_timer_stop( 116230557Sjimharris fw_device->domain->controller, 117230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer 118230557Sjimharris ); 119230557Sjimharris 120230557Sjimharris //destroy the timer 121230557Sjimharris scif_cb_timer_destroy( 122230557Sjimharris fw_device->domain->controller, 123230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer 124230557Sjimharris ); 125230557Sjimharris 126230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer = NULL; 127230557Sjimharris } 128230557Sjimharris} 129230557Sjimharris 130230557Sjimharris 131230557Sjimharris/** 132230557Sjimharris * @brief This method intializes a smp remote device. 133230557Sjimharris * 134230557Sjimharris * @param[in] fw_device the framework SMP device that is being 135230557Sjimharris * constructed. 136230557Sjimharris * 137230557Sjimharris * @return none 138230557Sjimharris */ 139230557Sjimharrisvoid scif_sas_smp_remote_device_construct( 140230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 141230557Sjimharris) 142230557Sjimharris{ 143230557Sjimharris SCIF_LOG_TRACE(( 144230557Sjimharris sci_base_object_get_logger(fw_device), 145230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 146230557Sjimharris "scif_sas_smp_remote_device_construct(0x%x) enter\n", 147230557Sjimharris fw_device 148230557Sjimharris )); 149230557Sjimharris 150230557Sjimharris fw_device->protocol_device.smp_device.number_of_phys = 0; 151230557Sjimharris fw_device->protocol_device.smp_device.expander_route_indexes = 0; 152230557Sjimharris fw_device->protocol_device.smp_device.is_table_to_table_supported = FALSE; 153230557Sjimharris fw_device->protocol_device.smp_device.is_externally_configurable = FALSE; 154230557Sjimharris fw_device->protocol_device.smp_device.is_able_to_config_others = FALSE; 155230557Sjimharris 156230557Sjimharris sci_fast_list_init(&fw_device->protocol_device.smp_device.smp_phy_list); 157230557Sjimharris 158230557Sjimharris scif_sas_smp_remote_device_clear(fw_device); 159230557Sjimharris} 160230557Sjimharris 161230557Sjimharris 162230557Sjimharris/** 163230557Sjimharris * @brief This method decodes a smp response to this smp device and then 164230557Sjimharris * continue the smp discover process. 165230557Sjimharris * 166230557Sjimharris * @param[in] fw_device The framework device that a SMP response targets to. 167230557Sjimharris * @param[in] fw_request The pointer to an smp request whose response 168230557Sjimharris * is to be decoded. 169230557Sjimharris * @param[in] response_data The response data passed in. 170230557Sjimharris * 171230557Sjimharris * @return none 172230557Sjimharris */ 173230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_smp_response( 174230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 175230557Sjimharris SCIF_SAS_REQUEST_T * fw_request, 176230557Sjimharris void * response_data, 177230557Sjimharris SCI_IO_STATUS completion_status 178230557Sjimharris) 179230557Sjimharris{ 180230557Sjimharris SMP_RESPONSE_T * smp_response = (SMP_RESPONSE_T *)response_data; 181230557Sjimharris SCI_STATUS status = SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE; 182230557Sjimharris 183230557Sjimharris if (fw_device->protocol_device.smp_device.smp_activity_timer != NULL) 184230557Sjimharris { 185230557Sjimharris //if there is a timer being used, recycle it now. Since we may 186230557Sjimharris //use the timer for other purpose next. 187230557Sjimharris scif_cb_timer_destroy( 188230557Sjimharris fw_device->domain->controller, 189230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer 190230557Sjimharris ); 191230557Sjimharris 192230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer = NULL; 193230557Sjimharris } 194230557Sjimharris 195230557Sjimharris //if Core set the status of this io to be RETRY_REQUIRED, we should 196230557Sjimharris //retry the IO without even decode the response. 197230557Sjimharris if (completion_status == SCI_FAILURE_RETRY_REQUIRED) 198230557Sjimharris { 199230557Sjimharris scif_sas_smp_remote_device_continue_current_activity( 200230557Sjimharris fw_device, fw_request, SCI_FAILURE_RETRY_REQUIRED 201230557Sjimharris ); 202230557Sjimharris 203230557Sjimharris return SCI_FAILURE_RETRY_REQUIRED; 204230557Sjimharris } 205230557Sjimharris 206230557Sjimharris //check the current smp request, decide what's next smp request to issue. 207230557Sjimharris switch (fw_device->protocol_device.smp_device.current_smp_request) 208230557Sjimharris { 209230557Sjimharris case SMP_FUNCTION_REPORT_GENERAL: 210230557Sjimharris { 211230557Sjimharris //interpret REPORT GENERAL response. 212230557Sjimharris status = scif_sas_smp_remote_device_decode_report_general_response( 213230557Sjimharris fw_device, smp_response 214230557Sjimharris ); 215230557Sjimharris 216230557Sjimharris break; 217230557Sjimharris } 218230557Sjimharris 219230557Sjimharris case SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION: 220230557Sjimharris { 221230557Sjimharris // No need to perform any parsing. Just want to see 222230557Sjimharris // the information in a trace if necessary. 223230557Sjimharris status = SCI_SUCCESS; 224230557Sjimharris break; 225230557Sjimharris } 226230557Sjimharris 227230557Sjimharris case SMP_FUNCTION_DISCOVER: 228230557Sjimharris { 229230557Sjimharris if (fw_device->protocol_device.smp_device.current_activity == 230230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER) 231230557Sjimharris { 232230557Sjimharris //decode discover response 233230557Sjimharris status = scif_sas_smp_remote_device_decode_initial_discover_response( 234230557Sjimharris fw_device, smp_response 235230557Sjimharris ); 236230557Sjimharris } 237230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 238230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET) 239230557Sjimharris { 240230557Sjimharris //decode discover response as a polling result for a remote device 241230557Sjimharris //target reset. 242230557Sjimharris status = 243230557Sjimharris scif_sas_smp_remote_device_decode_target_reset_discover_response( 244230557Sjimharris fw_device, smp_response 245230557Sjimharris ); 246230557Sjimharris } 247230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 248230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_SATA_SPINUP_HOLD_RELEASE) 249230557Sjimharris { 250230557Sjimharris //decode discover response 251230557Sjimharris status = 252230557Sjimharris scif_sas_smp_remote_device_decode_spinup_hold_release_discover_response( 253230557Sjimharris fw_device, smp_response 254230557Sjimharris ); 255230557Sjimharris } 256230557Sjimharris else 257230557Sjimharris ASSERT(0); 258230557Sjimharris break; 259230557Sjimharris } 260230557Sjimharris 261230557Sjimharris case SMP_FUNCTION_REPORT_PHY_SATA: 262230557Sjimharris { 263230557Sjimharris //decode the report phy sata response. 264230557Sjimharris status = scif_sas_smp_remote_device_decode_report_phy_sata_response( 265230557Sjimharris fw_device, smp_response 266230557Sjimharris ); 267230557Sjimharris 268230557Sjimharris break; 269230557Sjimharris } 270230557Sjimharris 271230557Sjimharris case SMP_FUNCTION_PHY_CONTROL: 272230557Sjimharris { 273230557Sjimharris if (fw_device->protocol_device.smp_device.current_activity == 274230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER) 275230557Sjimharris { 276230557Sjimharris //decode the phy control response. 277230557Sjimharris status = scif_sas_smp_remote_device_decode_discover_phy_control_response( 278230557Sjimharris fw_device, smp_response 279230557Sjimharris ); 280230557Sjimharris } 281230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 282230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET) 283230557Sjimharris { 284230557Sjimharris //decode discover response as a polling result for a remote device 285230557Sjimharris //target reset. 286230557Sjimharris status = scif_sas_smp_remote_device_decode_target_reset_phy_control_response( 287230557Sjimharris fw_device, smp_response 288230557Sjimharris ); 289230557Sjimharris } 290230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 291230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION) 292230557Sjimharris { 293230557Sjimharris //currently don't care about the status. 294230557Sjimharris status = SCI_SUCCESS; 295230557Sjimharris } 296230557Sjimharris else 297230557Sjimharris ASSERT(0); 298230557Sjimharris break; 299230557Sjimharris } 300230557Sjimharris 301230557Sjimharris case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION: 302230557Sjimharris { 303230557Sjimharris //Note, currently we don't expect any abnormal status from config route info response, 304230557Sjimharris //but there is a possibility that we exceed the maximum route index. We will take care 305230557Sjimharris //of errors later. 306230557Sjimharris status = scif_sas_smp_remote_device_decode_config_route_info_response( 307230557Sjimharris fw_device, smp_response 308230557Sjimharris ); 309230557Sjimharris break; 310230557Sjimharris } 311230557Sjimharris 312230557Sjimharris default: 313230557Sjimharris //unsupported case, TBD 314230557Sjimharris status = SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE; 315230557Sjimharris break; 316230557Sjimharris } //end of switch 317230557Sjimharris 318230557Sjimharris //Continue current activity based on response's decoding status. 319230557Sjimharris scif_sas_smp_remote_device_continue_current_activity( 320230557Sjimharris fw_device, fw_request, status 321230557Sjimharris ); 322230557Sjimharris 323230557Sjimharris return status; 324230557Sjimharris} 325230557Sjimharris 326230557Sjimharris 327230557Sjimharris/** 328230557Sjimharris * @brief This method decodes a smp Report Genernal response to this smp device 329230557Sjimharris * and then continue the smp discover process. 330230557Sjimharris * 331230557Sjimharris * @param[in] fw_device The framework device that the REPORT GENERAL command 332230557Sjimharris * targets to. 333230557Sjimharris * @param[in] report_general_response The pointer to a report general response 334230557Sjimharris * 335230557Sjimharris * @return none 336230557Sjimharris */ 337230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_report_general_response( 338230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 339230557Sjimharris SMP_RESPONSE_T * smp_response 340230557Sjimharris) 341230557Sjimharris{ 342230557Sjimharris SMP_RESPONSE_REPORT_GENERAL_T * report_general_response = 343230557Sjimharris &smp_response->response.report_general; 344230557Sjimharris 345230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 346230557Sjimharris 347230557Sjimharris SCIF_LOG_TRACE(( 348230557Sjimharris sci_base_object_get_logger(fw_device), 349230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 350230557Sjimharris "scif_sas_smp_remote_device_decode_report_general_response(0x%x, 0x%x) enter\n", 351230557Sjimharris fw_device, smp_response 352230557Sjimharris )); 353230557Sjimharris 354230557Sjimharris if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 355230557Sjimharris { 356230557Sjimharris /// @todo: more decoding work needed when the function_result is not 357230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 358230557Sjimharris /// function result. 359230557Sjimharris SCIF_LOG_ERROR(( 360230557Sjimharris sci_base_object_get_logger(fw_device), 361230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 362230557Sjimharris "Report General function result(0x%x)\n", 363230557Sjimharris response_header->function_result 364230557Sjimharris )); 365230557Sjimharris 366230557Sjimharris return SCI_FAILURE; 367230557Sjimharris } 368230557Sjimharris 369230557Sjimharris //get info from report general response. 370230557Sjimharris fw_device->protocol_device.smp_device.number_of_phys = 371230557Sjimharris (U8)report_general_response->number_of_phys; 372230557Sjimharris 373230557Sjimharris //currently there is byte swap issue in U16 data. 374230557Sjimharris fw_device->protocol_device.smp_device.expander_route_indexes = 375230557Sjimharris ((report_general_response->expander_route_indexes & 0xff) << 8) | 376230557Sjimharris ((report_general_response->expander_route_indexes & 0xff00) >> 8); 377230557Sjimharris 378230557Sjimharris fw_device->protocol_device.smp_device.is_table_to_table_supported = 379230557Sjimharris (BOOL)report_general_response->table_to_table_supported; 380230557Sjimharris 381230557Sjimharris fw_device->protocol_device.smp_device.is_externally_configurable = 382230557Sjimharris (BOOL)report_general_response->configurable_route_table; 383230557Sjimharris 384230557Sjimharris fw_device->protocol_device.smp_device.is_able_to_config_others = 385230557Sjimharris (BOOL)report_general_response->configures_others; 386230557Sjimharris 387230557Sjimharris //If the top level expander of a domain is able to configure others, 388230557Sjimharris //no config route table is needed in the domain. Or else, 389230557Sjimharris //we'll let all the externally configurable expanders in the damain 390230557Sjimharris //configure route table. 391230557Sjimharris if (fw_device->containing_device == NULL 392230557Sjimharris && ! fw_device->protocol_device.smp_device.is_able_to_config_others) 393230557Sjimharris fw_device->domain->is_config_route_table_needed = TRUE; 394230557Sjimharris 395230557Sjimharris //knowing number of phys this expander has, we can allocate all the smp phys for 396230557Sjimharris //this expander now if it is not done already. 397230557Sjimharris if (fw_device->protocol_device.smp_device.smp_phy_list.element_count == 0) 398230557Sjimharris scif_sas_smp_remote_device_populate_smp_phy_list(fw_device); 399230557Sjimharris 400230557Sjimharris if (report_general_response->configuring) 401230557Sjimharris return SCI_FAILURE_RETRY_REQUIRED; 402230557Sjimharris 403230557Sjimharris return SCI_SUCCESS; 404230557Sjimharris} 405230557Sjimharris 406230557Sjimharris 407230557Sjimharris/** 408230557Sjimharris * @brief This method decodes a smp Discover response to this smp device 409230557Sjimharris * and then continue the smp discover process. This is only ever 410230557Sjimharris * called for the very first discover stage during a given domain 411230557Sjimharris * discovery process. 412230557Sjimharris * 413230557Sjimharris * @param[in] fw_device The framework device that the DISCOVER command 414230557Sjimharris * targets to. 415230557Sjimharris * @param[in] discover_response The pointer to a DISCOVER response 416230557Sjimharris * 417230557Sjimharris * @return none 418230557Sjimharris */ 419230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_initial_discover_response( 420230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 421230557Sjimharris SMP_RESPONSE_T * smp_response 422230557Sjimharris) 423230557Sjimharris{ 424230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain; 425230557Sjimharris SCI_SAS_ADDRESS_T attached_device_address; 426230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * attached_remote_device; 427230557Sjimharris SMP_RESPONSE_DISCOVER_T * discover_response = 428230557Sjimharris &smp_response->response.discover; 429230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 430230557Sjimharris 431230557Sjimharris SCIF_LOG_TRACE(( 432230557Sjimharris sci_base_object_get_logger(fw_device), 433230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 434230557Sjimharris "scif_sas_smp_remote_device_decode_initial_discover_response(0x%x, 0x%x) enter\n", 435230557Sjimharris fw_device, smp_response 436230557Sjimharris )); 437230557Sjimharris 438230557Sjimharris if (response_header->function_result == SMP_RESULT_PHY_VACANT) 439230557Sjimharris { 440230557Sjimharris return SCI_SUCCESS; 441230557Sjimharris } 442230557Sjimharris else if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 443230557Sjimharris { 444230557Sjimharris /// @todo: more decoding work needed when the function_result is not 445230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 446230557Sjimharris /// function result. 447230557Sjimharris SCIF_LOG_ERROR(( 448230557Sjimharris sci_base_object_get_logger(fw_device), 449230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 450230557Sjimharris "Discover function result(0x%x)\n", 451230557Sjimharris response_header->function_result 452230557Sjimharris )); 453230557Sjimharris 454230557Sjimharris return SCI_FAILURE; 455230557Sjimharris } 456230557Sjimharris 457230557Sjimharris //only if there is target device attached. We don't add device that is 458230557Sjimharris //initiator only. 459230557Sjimharris if ( ( discover_response->u2.sas1_1.attached_device_type 460230557Sjimharris != SMP_NO_DEVICE_ATTACHED ) 461230557Sjimharris && ( discover_response->protocols.u.bits.attached_ssp_target 462230557Sjimharris || discover_response->protocols.u.bits.attached_stp_target 463230557Sjimharris || discover_response->protocols.u.bits.attached_smp_target 464230557Sjimharris || discover_response->protocols.u.bits.attached_sata_device ) ) 465230557Sjimharris { 466230557Sjimharris attached_device_address = discover_response->attached_sas_address; 467230557Sjimharris 468230557Sjimharris attached_remote_device = (SCIF_SAS_REMOTE_DEVICE_T *) 469230557Sjimharris scif_domain_get_device_by_sas_address( 470230557Sjimharris fw_domain, &attached_device_address 471230557Sjimharris ); 472230557Sjimharris 473230557Sjimharris //need to check if the device already existed in the domian. 474230557Sjimharris if (attached_remote_device != SCI_INVALID_HANDLE) 475230557Sjimharris { 476230557Sjimharris#if !defined(DISABLE_WIDE_PORTED_TARGETS) 477230557Sjimharris if ( attached_remote_device->is_currently_discovered == TRUE 478230557Sjimharris && attached_remote_device != fw_device->containing_device ) 479230557Sjimharris { 480230557Sjimharris //a downstream wide port target is found. 481230557Sjimharris attached_remote_device->device_port_width++; 482230557Sjimharris } 483230557Sjimharris else 484230557Sjimharris#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS) 485230557Sjimharris { 486230557Sjimharris //The device already existed. Mark the device as discovered. 487230557Sjimharris attached_remote_device->is_currently_discovered = TRUE; 488230557Sjimharris } 489230557Sjimharris 490230557Sjimharris#if !defined(DISABLE_WIDE_PORTED_TARGETS) 491230557Sjimharris if (attached_remote_device->device_port_width != 492230557Sjimharris scic_remote_device_get_port_width(attached_remote_device->core_object) 493230557Sjimharris && discover_response->protocols.u.bits.attached_ssp_target 494230557Sjimharris ) 495230557Sjimharris { 496230557Sjimharris scif_sas_remote_device_update_port_width( 497230557Sjimharris attached_remote_device, attached_remote_device->device_port_width); 498230557Sjimharris } 499230557Sjimharris#endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS) 500230557Sjimharris 501230557Sjimharris if ( discover_response->protocols.u.bits.attached_smp_target 502230557Sjimharris && attached_remote_device != fw_device->containing_device) 503230557Sjimharris { 504230557Sjimharris //another expander device is discovered. Its own smp discover will starts after 505230557Sjimharris //this discover finishes. 506230557Sjimharris attached_remote_device->protocol_device.smp_device.scheduled_activity = 507230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER; 508230557Sjimharris } 509230557Sjimharris } 510230557Sjimharris else 511230557Sjimharris { 512230557Sjimharris //report the discovery of a disk for all types of end device. 513230557Sjimharris scif_cb_domain_ea_device_added( 514230557Sjimharris fw_domain->controller, fw_domain, fw_device, discover_response 515230557Sjimharris ); 516230557Sjimharris 517230557Sjimharris //get info from discover response to see what we found. And do 518230557Sjimharris //extra work according to end device's protocol type. 519230557Sjimharris if ( discover_response->protocols.u.bits.attached_ssp_target 520230557Sjimharris || discover_response->protocols.u.bits.attached_smp_target) 521230557Sjimharris { 522230557Sjimharris //for SSP or SMP target, no extra work. 523230557Sjimharris ; 524230557Sjimharris } 525230557Sjimharris else if ( (discover_response->protocols.u.bits.attached_stp_target) 526230557Sjimharris || (discover_response->protocols.u.bits.attached_sata_device) ) 527230557Sjimharris { 528230557Sjimharris // We treat a SATA Device bit the same as an attached STP 529230557Sjimharris // target. 530230557Sjimharris discover_response->protocols.u.bits.attached_stp_target = 1; 531230557Sjimharris 532230557Sjimharris //kick off REPORT PHY SATA to the same phy. 533230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 534230557Sjimharris SMP_FUNCTION_REPORT_PHY_SATA; 535230557Sjimharris } 536230557Sjimharris } 537230557Sjimharris } 538230557Sjimharris else if( (discover_response->u2.sas1_1.negotiated_physical_link_rate == SCI_SATA_SPINUP_HOLD 539230557Sjimharris || discover_response->u4.sas2.negotiated_physical_link_rate == SCI_SATA_SPINUP_HOLD) 540230557Sjimharris &&(discover_response->protocols.u.bits.attached_stp_target 541230557Sjimharris || discover_response->protocols.u.bits.attached_sata_device) 542230557Sjimharris ) 543230557Sjimharris { 544230557Sjimharris attached_remote_device = scif_sas_domain_get_device_by_containing_device( 545230557Sjimharris fw_domain, 546230557Sjimharris fw_device, 547230557Sjimharris discover_response->phy_identifier 548230557Sjimharris ); 549230557Sjimharris 550230557Sjimharris if (attached_remote_device != SCI_INVALID_HANDLE) 551230557Sjimharris { 552230557Sjimharris //Here, the only reason a device already existed in domain but 553230557Sjimharris //the initial discover rersponse shows it in SPINUP_HOLD, is that 554230557Sjimharris //a device has been removed and coming back in SPINUP_HOLD before 555230557Sjimharris //we detected. The possibility of this situation is very very rare. 556230557Sjimharris //we need to remove the device then add it back using the new 557230557Sjimharris //discover response. 558230557Sjimharris scif_cb_domain_device_removed( 559230557Sjimharris fw_domain->controller, fw_domain, attached_remote_device 560230557Sjimharris ); 561230557Sjimharris } 562230557Sjimharris 563230557Sjimharris discover_response->protocols.u.bits.attached_stp_target = 1; 564230557Sjimharris 565230557Sjimharris //still report ea_device_added(). But this device will not be 566230557Sjimharris //started during scif_remote_device_ea_construct(). 567230557Sjimharris scif_cb_domain_ea_device_added( 568230557Sjimharris fw_domain->controller, fw_domain, fw_device, discover_response 569230557Sjimharris ); 570230557Sjimharris 571230557Sjimharris //need to send Phy Control (RESET) to release the phy from spinup hold 572230557Sjimharris //condition. 573230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 574230557Sjimharris SMP_FUNCTION_PHY_CONTROL; 575230557Sjimharris } 576230557Sjimharris 577230557Sjimharris //update the smp phy info based on this DISCOVER response. 578230557Sjimharris return scif_sas_smp_remote_device_save_smp_phy_info( 579230557Sjimharris fw_device, discover_response); 580230557Sjimharris} 581230557Sjimharris 582230557Sjimharris 583230557Sjimharris/** 584230557Sjimharris * @brief This method decodes a smp Report Phy Sata response to this 585230557Sjimharris * smp device and then continue the smp discover process. 586230557Sjimharris * 587230557Sjimharris * @param[in] fw_device The framework device that the REPORT PHY SATA 588230557Sjimharris * command targets to. 589230557Sjimharris * @param[in] report_phy_sata_response The pointer to a REPORT PHY 590230557Sjimharris * SATA response 591230557Sjimharris * 592230557Sjimharris * @return none 593230557Sjimharris */ 594230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_report_phy_sata_response( 595230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 596230557Sjimharris SMP_RESPONSE_T * smp_response 597230557Sjimharris) 598230557Sjimharris{ 599230557Sjimharris SMP_RESPONSE_REPORT_PHY_SATA_T * report_phy_sata_response = 600230557Sjimharris &smp_response->response.report_phy_sata; 601230557Sjimharris 602230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 603230557Sjimharris 604230557Sjimharris SCIF_LOG_TRACE(( 605230557Sjimharris sci_base_object_get_logger(fw_device), 606230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 607230557Sjimharris "scif_sas_smp_remote_device_decode_report_phy_sata_response(0x%x, 0x%x) enter\n", 608230557Sjimharris fw_device, smp_response 609230557Sjimharris )); 610230557Sjimharris 611230557Sjimharris if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 612230557Sjimharris { 613230557Sjimharris /// @todo: more decoding work needed when the function_result is not 614230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 615230557Sjimharris /// function result. 616230557Sjimharris SCIF_LOG_ERROR(( 617230557Sjimharris sci_base_object_get_logger(fw_device), 618230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 619230557Sjimharris "Report Phy Sata function result(0x%x)\n", 620230557Sjimharris response_header->function_result 621230557Sjimharris )); 622230557Sjimharris 623230557Sjimharris return SCI_FAILURE; 624230557Sjimharris } 625230557Sjimharris 626230557Sjimharris scif_sas_remote_device_save_report_phy_sata_information( 627230557Sjimharris report_phy_sata_response 628230557Sjimharris ); 629230557Sjimharris 630230557Sjimharris // continue the discover process. 631230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 632230557Sjimharris SMP_FUNCTION_DISCOVER; 633230557Sjimharris 634230557Sjimharris return SCI_SUCCESS; 635230557Sjimharris} 636230557Sjimharris 637230557Sjimharris 638230557Sjimharris/** 639230557Sjimharris * @brief This method decodes a smp Phy Control response to this smp device and 640230557Sjimharris * then continue the smp TARGET RESET process. 641230557Sjimharris * 642230557Sjimharris * @param[in] fw_device The framework device that the Phy Control command 643230557Sjimharris * targets to. 644230557Sjimharris * @param[in] smp_response The pointer to a Phy Control response 645230557Sjimharris * @param[in] fw_io The scif IO request that associates to this smp response. 646230557Sjimharris * 647230557Sjimharris * @return none 648230557Sjimharris */ 649230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_target_reset_phy_control_response( 650230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 651230557Sjimharris SMP_RESPONSE_T * smp_response 652230557Sjimharris) 653230557Sjimharris{ 654230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 655230557Sjimharris 656230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 657230557Sjimharris 658230557Sjimharris SCIF_LOG_TRACE(( 659230557Sjimharris sci_base_object_get_logger(fw_device), 660230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 661230557Sjimharris "scif_sas_smp_remote_device_decode_target_reset_phy_control_response(0x%x, 0x%x) enter\n", 662230557Sjimharris fw_device, smp_response 663230557Sjimharris )); 664230557Sjimharris 665230557Sjimharris if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 666230557Sjimharris { 667230557Sjimharris /// @todo: more decoding work needed when the function_result is not 668230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 669230557Sjimharris /// function result. 670230557Sjimharris SCIF_LOG_ERROR(( 671230557Sjimharris sci_base_object_get_logger(fw_device), 672230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 673230557Sjimharris "Phy Control function unaccepted result(0x%x)\n", 674230557Sjimharris response_header->function_result 675230557Sjimharris )); 676230557Sjimharris 677230557Sjimharris status = SCI_FAILURE_RETRY_REQUIRED; 678230557Sjimharris } 679230557Sjimharris 680230557Sjimharris // phy Control succeeded. 681230557Sjimharris return status; 682230557Sjimharris} 683230557Sjimharris 684230557Sjimharris/** 685230557Sjimharris * @brief This method decodes a smp Phy Control response to this smp device and 686230557Sjimharris * then continue the smp DISCOVER process. 687230557Sjimharris * 688230557Sjimharris * @param[in] fw_device The framework device that the Phy Control command 689230557Sjimharris * targets to. 690230557Sjimharris * @param[in] smp_response The pointer to a Phy Control response 691230557Sjimharris * 692230557Sjimharris * @return Almost always SCI_SUCCESS 693230557Sjimharris */ 694230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_discover_phy_control_response( 695230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 696230557Sjimharris SMP_RESPONSE_T * smp_response 697230557Sjimharris) 698230557Sjimharris{ 699230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 700230557Sjimharris 701230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 702230557Sjimharris 703230557Sjimharris SCIF_LOG_TRACE(( 704230557Sjimharris sci_base_object_get_logger(fw_device), 705230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 706230557Sjimharris "scif_sas_smp_remote_device_decode_discover_phy_control_response(0x%x, 0x%x) enter\n", 707230557Sjimharris fw_device, smp_response 708230557Sjimharris )); 709230557Sjimharris 710230557Sjimharris if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 711230557Sjimharris { 712230557Sjimharris /// @todo: more decoding work needed when the function_result is not 713230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 714230557Sjimharris /// function result. 715230557Sjimharris SCIF_LOG_ERROR(( 716230557Sjimharris sci_base_object_get_logger(fw_device), 717230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 718230557Sjimharris "Phy Control function unaccepted result(0x%x)\n", 719230557Sjimharris response_header->function_result 720230557Sjimharris )); 721230557Sjimharris 722230557Sjimharris return SCI_FAILURE_RETRY_REQUIRED; 723230557Sjimharris } 724230557Sjimharris 725230557Sjimharris // continue the discover process. 726230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 727230557Sjimharris SMP_FUNCTION_DISCOVER; 728230557Sjimharris 729230557Sjimharris // phy Control succeeded. 730230557Sjimharris return status; 731230557Sjimharris} 732230557Sjimharris 733230557Sjimharris 734230557Sjimharris/** 735230557Sjimharris * @brief This method decodes a smp Discover response to this smp device 736230557Sjimharris * and then continue the smp discover process. 737230557Sjimharris * 738230557Sjimharris * @param[in] fw_device The framework device that the DISCOVER command 739230557Sjimharris * targets to. 740230557Sjimharris * @param[in] discover_response The pointer to a DISCOVER response 741230557Sjimharris * 742230557Sjimharris * @return none 743230557Sjimharris */ 744230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_target_reset_discover_response( 745230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 746230557Sjimharris SMP_RESPONSE_T * smp_response 747230557Sjimharris) 748230557Sjimharris{ 749230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain; 750230557Sjimharris SCI_SAS_ADDRESS_T attached_device_address; 751230557Sjimharris SMP_RESPONSE_DISCOVER_T * discover_response = 752230557Sjimharris &smp_response->response.discover; 753230557Sjimharris 754230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 755230557Sjimharris 756230557Sjimharris SCIF_LOG_TRACE(( 757230557Sjimharris sci_base_object_get_logger(fw_device), 758230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 759230557Sjimharris "scif_sas_smp_remote_device_decode_target_reset_discover_response(0x%x, 0x%x) enter\n", 760230557Sjimharris fw_device, smp_response 761230557Sjimharris )); 762230557Sjimharris 763230557Sjimharris if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 764230557Sjimharris { 765230557Sjimharris /// @todo: more decoding work needed when the function_result is not 766230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 767230557Sjimharris /// function result. 768230557Sjimharris SCIF_LOG_ERROR(( 769230557Sjimharris sci_base_object_get_logger(fw_device), 770230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 771230557Sjimharris "Discover function result(0x%x)\n", 772230557Sjimharris response_header->function_result 773230557Sjimharris )); 774230557Sjimharris 775230557Sjimharris return SCI_FAILURE_RETRY_REQUIRED; 776230557Sjimharris } 777230557Sjimharris 778230557Sjimharris //only if there is device attached. 779230557Sjimharris if ( discover_response->u2.sas1_1.attached_device_type != SMP_NO_DEVICE_ATTACHED ) 780230557Sjimharris { 781230557Sjimharris fw_domain = fw_device->domain; 782230557Sjimharris attached_device_address = discover_response->attached_sas_address; 783230557Sjimharris 784230557Sjimharris // the device should have already existed in the domian. 785231137Sjimharris ASSERT(scif_domain_get_device_by_sas_address( 786231137Sjimharris fw_domain, 787231137Sjimharris &attached_device_address 788231137Sjimharris ) != SCI_INVALID_HANDLE); 789230557Sjimharris return SCI_SUCCESS; 790230557Sjimharris } 791230557Sjimharris else 792230557Sjimharris return SCI_FAILURE_RETRY_REQUIRED; 793230557Sjimharris} 794230557Sjimharris 795230557Sjimharris/** 796230557Sjimharris * @brief This method decodes a smp Discover response to this smp device 797230557Sjimharris * for SPINUP_HOLD_RELEASE activity. If a DISCOVER response says 798230557Sjimharris * SATA DEVICE ATTACHED and has a valid NPL value, we call fw_device's 799230557Sjimharris * start_handler(). But if a DISCOVER response still shows SPINUP 800230557Sjimharris * in NPL state, we need to return retry_required status 801230557Sjimharris * 802230557Sjimharris * @param[in] fw_device The framework device that the DISCOVER command 803230557Sjimharris * targets to. 804230557Sjimharris * @param[in] discover_response The pointer to a DISCOVER response 805230557Sjimharris * 806230557Sjimharris * @return SCI_SUCCESS 807230557Sjimharris * SCI_FAILURE_RETRY_REQUIRED 808230557Sjimharris */ 809230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_spinup_hold_release_discover_response( 810230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 811230557Sjimharris SMP_RESPONSE_T * smp_response 812230557Sjimharris) 813230557Sjimharris{ 814230557Sjimharris SMP_RESPONSE_DISCOVER_T * discover_response = &smp_response->response.discover; 815230557Sjimharris 816230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 817230557Sjimharris 818230557Sjimharris SCIF_LOG_TRACE(( 819230557Sjimharris sci_base_object_get_logger(fw_device), 820230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 821230557Sjimharris "scif_sas_smp_remote_device_decode_spinup_hold_release_discover_response(0x%x, 0x%x) enter\n", 822230557Sjimharris fw_device, smp_response 823230557Sjimharris )); 824230557Sjimharris 825230557Sjimharris if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 826230557Sjimharris { 827230557Sjimharris /// @todo: more decoding work needed when the function_result is not 828230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 829230557Sjimharris /// function result. 830230557Sjimharris SCIF_LOG_ERROR(( 831230557Sjimharris sci_base_object_get_logger(fw_device), 832230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 833230557Sjimharris "Discover function result(0x%x)\n", 834230557Sjimharris response_header->function_result 835230557Sjimharris )); 836230557Sjimharris 837230557Sjimharris return SCI_FAILURE; 838230557Sjimharris } 839230557Sjimharris 840230557Sjimharris if ( discover_response->u2.sas1_1.attached_device_type != SMP_NO_DEVICE_ATTACHED ) 841230557Sjimharris { 842230557Sjimharris if (discover_response->u2.sas1_1.negotiated_physical_link_rate != SCI_SATA_SPINUP_HOLD 843230557Sjimharris && discover_response->u4.sas2.negotiated_physical_link_rate != SCI_SATA_SPINUP_HOLD 844230557Sjimharris && ( discover_response->protocols.u.bits.attached_stp_target 845230557Sjimharris ||discover_response->protocols.u.bits.attached_sata_device ) 846230557Sjimharris ) 847230557Sjimharris { 848230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * target_device = 849230557Sjimharris scif_sas_domain_get_device_by_containing_device( 850230557Sjimharris fw_device->domain, 851230557Sjimharris fw_device, 852230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index 853230557Sjimharris ); 854230557Sjimharris 855230557Sjimharris //Need to update the device's connection rate. Its connection rate was SPINIP_HOLD. 856230557Sjimharris scic_remote_device_set_max_connection_rate( 857230557Sjimharris target_device->core_object, 858230557Sjimharris discover_response->u2.sas1_1.negotiated_physical_link_rate 859230557Sjimharris ); 860230557Sjimharris 861230557Sjimharris //Need to update the smp phy info too. 862230557Sjimharris scif_sas_smp_remote_device_save_smp_phy_info( 863230557Sjimharris fw_device, discover_response); 864230557Sjimharris 865230557Sjimharris //This device has already constructed, only need to call start_handler 866230557Sjimharris //of this device here. 867230557Sjimharris return target_device->state_handlers->parent.start_handler( 868230557Sjimharris &target_device->parent ); 869230557Sjimharris } 870230557Sjimharris else 871230557Sjimharris return SCI_FAILURE_RETRY_REQUIRED; 872230557Sjimharris } 873230557Sjimharris else 874230557Sjimharris return SCI_FAILURE_RETRY_REQUIRED; 875230557Sjimharris} 876230557Sjimharris 877230557Sjimharris 878230557Sjimharris/** 879230557Sjimharris * @brief This method decodes a smp CONFIG ROUTE INFO response to this smp 880230557Sjimharris * device and then continue to config route table. 881230557Sjimharris * 882230557Sjimharris * @param[in] fw_device The framework device that the CONFIG ROUTE INFO command 883230557Sjimharris * targets to. 884230557Sjimharris * @param[in] smp_response The pointer to a CONFIG ROUTE INFO response 885230557Sjimharris * 886230557Sjimharris * @return none 887230557Sjimharris */ 888230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_decode_config_route_info_response( 889230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 890230557Sjimharris SMP_RESPONSE_T * smp_response 891230557Sjimharris) 892230557Sjimharris{ 893230557Sjimharris SMP_RESPONSE_HEADER_T * response_header = &smp_response->header; 894230557Sjimharris 895230557Sjimharris SCIF_LOG_TRACE(( 896230557Sjimharris sci_base_object_get_logger(fw_device), 897230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 898230557Sjimharris "scif_sas_smp_remote_device_decode_config_route_info_response(0x%x, 0x%x) enter\n", 899230557Sjimharris fw_device, smp_response 900230557Sjimharris )); 901230557Sjimharris 902230557Sjimharris if (response_header->function_result == SMP_RESULT_INDEX_DOES_NOT_EXIST) 903230557Sjimharris { 904230557Sjimharris //case of exceeding max route index. We need to remove the devices that are not 905230557Sjimharris //able to be edit to route table. The destination config route smp phy 906230557Sjimharris //is used to remove devices. 907230557Sjimharris scif_sas_smp_remote_device_cancel_config_route_table_activity(fw_device); 908230557Sjimharris 909230557Sjimharris return SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX; 910230557Sjimharris } 911230557Sjimharris else if (response_header->function_result != SMP_RESULT_FUNCTION_ACCEPTED) 912230557Sjimharris { 913230557Sjimharris /// @todo: more decoding work needed when the function_result is not 914230557Sjimharris /// SMP_RESULT_FUNCTION_ACCEPTED. Retry might be the option for some 915230557Sjimharris /// function result. 916230557Sjimharris SCIF_LOG_ERROR(( 917230557Sjimharris sci_base_object_get_logger(fw_device), 918230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 919230557Sjimharris "Discover function result(0x%x)\n", 920230557Sjimharris response_header->function_result 921230557Sjimharris )); 922230557Sjimharris 923230557Sjimharris return SCI_FAILURE; 924230557Sjimharris } 925230557Sjimharris 926230557Sjimharris return SCI_SUCCESS; 927230557Sjimharris} 928230557Sjimharris 929230557Sjimharris 930230557Sjimharris/** 931230557Sjimharris * @brief This method starts the smp Discover process for an expander by 932230557Sjimharris * sending Report General request. 933230557Sjimharris * 934230557Sjimharris * @param[in] fw_device The framework smp device that a command 935230557Sjimharris * targets to. 936230557Sjimharris * 937230557Sjimharris * @return none 938230557Sjimharris */ 939230557Sjimharrisvoid scif_sas_smp_remote_device_start_discover( 940230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 941230557Sjimharris) 942230557Sjimharris{ 943230557Sjimharris SCIF_SAS_CONTROLLER_T * fw_controller = fw_device->domain->controller; 944230557Sjimharris 945230557Sjimharris SCIF_LOG_TRACE(( 946230557Sjimharris sci_base_object_get_logger(fw_device), 947230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 948230557Sjimharris "scif_sas_smp_remote_device_start_discover(0x%x) enter\n", 949230557Sjimharris fw_device 950230557Sjimharris )); 951230557Sjimharris 952230557Sjimharris //For safety, clear the device again, there may be some config route table 953230557Sjimharris //related info are not cleared yet. 954230557Sjimharris scif_sas_smp_remote_device_clear(fw_device); 955230557Sjimharris 956230557Sjimharris //set current activity 957230557Sjimharris fw_device->protocol_device.smp_device.current_activity = 958230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER; 959230557Sjimharris 960230557Sjimharris //Set current_smp_request to REPORT GENERAL. 961230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 962230557Sjimharris SMP_FUNCTION_REPORT_GENERAL; 963230557Sjimharris 964230557Sjimharris //reset discover_to_start flag. 965230557Sjimharris fw_device->protocol_device.smp_device.scheduled_activity = 966230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE; 967230557Sjimharris 968230557Sjimharris //build the first smp request Report Genernal. 969230557Sjimharris scif_sas_smp_request_construct_report_general(fw_controller, fw_device); 970230557Sjimharris 971230557Sjimharris //issue DPC to start this request. 972230557Sjimharris scif_cb_start_internal_io_task_schedule( 973230557Sjimharris fw_controller, 974230557Sjimharris scif_sas_controller_start_high_priority_io, 975230557Sjimharris fw_controller 976230557Sjimharris ); 977230557Sjimharris} 978230557Sjimharris 979230557Sjimharris 980230557Sjimharris/** 981230557Sjimharris * @brief This method continues the smp Discover process. 982230557Sjimharris * 983230557Sjimharris * @param[in] fw_device The framework smp device that a DISCOVER command 984230557Sjimharris * targets to. 985230557Sjimharris * @param[in] fw_request The pointer to an smp request whose response 986230557Sjimharris * has been decoded. 987230557Sjimharris * @param[in] status The decoding status of the smp request's response 988230557Sjimharris * 989230557Sjimharris * @return none 990230557Sjimharris */ 991230557Sjimharrisvoid scif_sas_smp_remote_device_continue_current_activity( 992230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 993230557Sjimharris SCIF_SAS_REQUEST_T * fw_request, 994230557Sjimharris SCI_STATUS status 995230557Sjimharris) 996230557Sjimharris{ 997230557Sjimharris SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)fw_request; 998230557Sjimharris // save the retry count. 999230557Sjimharris U8 io_retry_count = fw_io->retry_count; 1000230557Sjimharris 1001230557Sjimharris if (fw_request->is_internal) 1002230557Sjimharris { 1003230557Sjimharris // Complete this internal io request now. We want to free this io before 1004230557Sjimharris // we create another SMP request, which is going to happen soon. 1005230557Sjimharris scif_sas_internal_io_request_complete( 1006230557Sjimharris fw_device->domain->controller, 1007230557Sjimharris (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_request, 1008230557Sjimharris SCI_SUCCESS 1009230557Sjimharris ); 1010230557Sjimharris } 1011230557Sjimharris 1012230557Sjimharris if (fw_device->protocol_device.smp_device.current_activity == 1013230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_DISCOVER) 1014230557Sjimharris { 1015230557Sjimharris if (status == SCI_SUCCESS) 1016230557Sjimharris { //continue the discover process. 1017230557Sjimharris scif_sas_smp_remote_device_continue_discover(fw_device); 1018230557Sjimharris } 1019230557Sjimharris else if (status == SCI_FAILURE_RETRY_REQUIRED) 1020230557Sjimharris { 1021230557Sjimharris //Retry the smp request. Since we are in the middle of Discover 1022230557Sjimharris //process, all the smp requests are internal. A new smp request 1023230557Sjimharris //will be created for retry. 1024230557Sjimharris U32 retry_wait_duration = (SCIF_DOMAIN_DISCOVER_TIMEOUT / 2) / SCIF_SAS_IO_RETRY_LIMIT; 1025230557Sjimharris 1026230557Sjimharris if (io_retry_count < SCIF_SAS_IO_RETRY_LIMIT) 1027230557Sjimharris scif_sas_smp_remote_device_retry_internal_io ( 1028230557Sjimharris fw_device, io_retry_count, retry_wait_duration); 1029230557Sjimharris else 1030230557Sjimharris scif_sas_smp_remote_device_fail_discover(fw_device); 1031230557Sjimharris } 1032230557Sjimharris else if (status == SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION) 1033230557Sjimharris { 1034230557Sjimharris //remove this expander device and its child devices. No need to 1035230557Sjimharris //continue the discover on this device. 1036230557Sjimharris scif_sas_domain_remove_expander_device(fw_device->domain, fw_device); 1037230557Sjimharris 1038230557Sjimharris //continue the domain's smp discover. 1039230557Sjimharris scif_sas_domain_continue_discover(fw_device->domain); 1040230557Sjimharris } 1041230557Sjimharris else 1042230557Sjimharris { //terminate the discover process. 1043230557Sjimharris scif_sas_smp_remote_device_fail_discover(fw_device); 1044230557Sjimharris } 1045230557Sjimharris } 1046230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 1047230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET) 1048230557Sjimharris { 1049230557Sjimharris if (status == SCI_SUCCESS) 1050230557Sjimharris { //continue the target reset process. 1051230557Sjimharris scif_sas_smp_remote_device_continue_target_reset( 1052230557Sjimharris fw_device, fw_request); 1053230557Sjimharris } 1054230557Sjimharris else if (status == SCI_FAILURE_RETRY_REQUIRED) 1055230557Sjimharris { 1056230557Sjimharris //Retry the same smp request. Since we are in the middle of Target 1057230557Sjimharris //reset process, all the smp requests are using external resource. 1058230557Sjimharris //We will use the exactly same memory to retry. 1059230557Sjimharris if (io_retry_count < SCIF_SAS_IO_RETRY_LIMIT) 1060230557Sjimharris { 1061230557Sjimharris if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL) 1062230557Sjimharris { 1063230557Sjimharris //create the timer to wait before retry. 1064230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer = 1065230557Sjimharris scif_cb_timer_create( 1066230557Sjimharris (SCI_CONTROLLER_HANDLE_T *)fw_device->domain->controller, 1067230557Sjimharris (SCI_TIMER_CALLBACK_T)scif_sas_smp_external_request_retry, 1068230557Sjimharris (void*)fw_request 1069230557Sjimharris ); 1070230557Sjimharris } 1071230557Sjimharris else 1072230557Sjimharris { 1073230557Sjimharris ASSERT(0); 1074230557Sjimharris } 1075230557Sjimharris 1076230557Sjimharris //start the timer to wait 1077230557Sjimharris scif_cb_timer_start( 1078230557Sjimharris (SCI_CONTROLLER_HANDLE_T)fw_device->domain->controller, 1079230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer, 1080230557Sjimharris SMP_REQUEST_RETRY_WAIT_DURATION //20 miliseconds 1081230557Sjimharris ); 1082230557Sjimharris } 1083230557Sjimharris else 1084230557Sjimharris scif_sas_smp_remote_device_fail_target_reset(fw_device, fw_request); 1085230557Sjimharris } 1086230557Sjimharris else 1087230557Sjimharris //terminate the discover process. 1088230557Sjimharris scif_sas_smp_remote_device_fail_target_reset(fw_device, fw_request); 1089230557Sjimharris } 1090230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 1091230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_SATA_SPINUP_HOLD_RELEASE) 1092230557Sjimharris { 1093230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * target_device = 1094230557Sjimharris scif_sas_domain_get_device_by_containing_device( 1095230557Sjimharris fw_device->domain, 1096230557Sjimharris fw_device, 1097230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index 1098230557Sjimharris ); 1099230557Sjimharris 1100230557Sjimharris if (status == SCI_SUCCESS) 1101230557Sjimharris { 1102230557Sjimharris //move on to next round of SPINUP_HOLD_REALSE activity. 1103230557Sjimharris scif_sas_smp_remote_device_sata_spinup_hold_release(fw_device); 1104230557Sjimharris } 1105230557Sjimharris else if (status == SCI_FAILURE_RETRY_REQUIRED) 1106230557Sjimharris { 1107230557Sjimharris U32 delay = 1108230557Sjimharris (scic_remote_device_get_suggested_reset_timeout(target_device->core_object) / 1109230557Sjimharris SCIF_SAS_IO_RETRY_LIMIT); 1110230557Sjimharris 1111230557Sjimharris //Retry the smp request. Since we are in the middle of Discover 1112230557Sjimharris //process, all the smp requests are internal. A new smp request 1113230557Sjimharris //will be created for retry. 1114230557Sjimharris if (io_retry_count < SCIF_SAS_IO_RETRY_LIMIT) 1115230557Sjimharris { 1116230557Sjimharris scif_sas_smp_remote_device_retry_internal_io( 1117230557Sjimharris fw_device, io_retry_count, delay); 1118230557Sjimharris } 1119230557Sjimharris else //give up on this target device. 1120230557Sjimharris { 1121230557Sjimharris scif_sas_smp_remote_device_fail_target_spinup_hold_release( 1122230557Sjimharris fw_device , target_device); 1123230557Sjimharris } 1124230557Sjimharris } 1125230557Sjimharris else //give up on this target device. 1126230557Sjimharris scif_sas_smp_remote_device_fail_target_spinup_hold_release( 1127230557Sjimharris fw_device, target_device); 1128230557Sjimharris } 1129230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 1130230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE) 1131230557Sjimharris { 1132230557Sjimharris SCI_FAST_LIST_ELEMENT_T * next_phy_element = sci_fast_list_get_next( 1133230557Sjimharris &(fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element) ); 1134230557Sjimharris 1135230557Sjimharris SCI_FAST_LIST_T * destination_smp_phy_list = 1136230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element.owning_list; 1137230557Sjimharris 1138230557Sjimharris SCIF_SAS_SMP_PHY_T * next_phy_in_wide_port = NULL; 1139230557Sjimharris 1140230557Sjimharris if (next_phy_element != NULL 1141230557Sjimharris && status != SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX) 1142230557Sjimharris { 1143230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index++; 1144230557Sjimharris 1145230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy = 1146230557Sjimharris (SCIF_SAS_SMP_PHY_T *)sci_fast_list_get_object(next_phy_element); 1147230557Sjimharris 1148230557Sjimharris // Update the anchor for config route index. 1149230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->config_route_table_index_anchor = 1150230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index; 1151230557Sjimharris 1152230557Sjimharris scif_sas_smp_remote_device_configure_route_table(fw_device); 1153230557Sjimharris } 1154230557Sjimharris else if ( scif_sas_smp_remote_device_get_config_route_table_method(fw_device) 1155230557Sjimharris == SCIF_SAS_CONFIG_ROUTE_TABLE_ALL_PHYS 1156230557Sjimharris && (next_phy_in_wide_port = scif_sas_smp_phy_find_next_phy_in_wide_port( 1157230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor) 1158230557Sjimharris )!= NULL 1159230557Sjimharris ) 1160230557Sjimharris { 1161230557Sjimharris //config the other phy in the same wide port 1162230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor = 1163230557Sjimharris next_phy_in_wide_port; 1164230557Sjimharris 1165230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index = 1166230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier; 1167230557Sjimharris 1168230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy = 1169230557Sjimharris sci_fast_list_get_head(destination_smp_phy_list); 1170230557Sjimharris 1171230557Sjimharris if (fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->config_route_table_index_anchor != 0) 1172230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index = 1173230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->config_route_table_index_anchor + 1; 1174230557Sjimharris else 1175230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index = 0; 1176230557Sjimharris 1177230557Sjimharris scif_sas_smp_remote_device_configure_route_table(fw_device); 1178230557Sjimharris } 1179230557Sjimharris else if ( fw_device->protocol_device.smp_device.is_route_table_cleaned == FALSE) 1180230557Sjimharris { 1181230557Sjimharris fw_device->protocol_device.smp_device.current_activity = 1182230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAN_ROUTE_TABLE; 1183230557Sjimharris 1184230557Sjimharris scif_sas_smp_remote_device_clean_route_table(fw_device); 1185230557Sjimharris } 1186230557Sjimharris else 1187230557Sjimharris { 1188230557Sjimharris //set this device's activity to NON. 1189230557Sjimharris fw_device->protocol_device.smp_device.current_activity = 1190230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE; 1191230557Sjimharris 1192230557Sjimharris //we need to notify domain that this device finished config route table, domain 1193230557Sjimharris //may pick up other activities (i.e. Discover) for other expanders. 1194230557Sjimharris scif_sas_domain_continue_discover(fw_device->domain); 1195230557Sjimharris } 1196230557Sjimharris } 1197230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 1198230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAN_ROUTE_TABLE) 1199230557Sjimharris { 1200230557Sjimharris scif_sas_smp_remote_device_clean_route_table(fw_device); 1201230557Sjimharris } 1202230557Sjimharris else if (fw_device->protocol_device.smp_device.current_activity == 1203230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CLEAR_AFFILIATION) 1204230557Sjimharris { 1205230557Sjimharris scif_sas_smp_remote_device_continue_clear_affiliation(fw_device); 1206230557Sjimharris } 1207230557Sjimharris} 1208230557Sjimharris 1209230557Sjimharris 1210230557Sjimharris/** 1211230557Sjimharris * @brief This method continues the smp Discover process. 1212230557Sjimharris * 1213230557Sjimharris * @param[in] fw_device The framework smp device that a DISCOVER command 1214230557Sjimharris * targets to. 1215230557Sjimharris * 1216230557Sjimharris * @return none 1217230557Sjimharris */ 1218230557Sjimharrisvoid scif_sas_smp_remote_device_continue_discover( 1219230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1220230557Sjimharris) 1221230557Sjimharris{ 1222230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain; 1223230557Sjimharris 1224230557Sjimharris SCIF_LOG_TRACE(( 1225230557Sjimharris sci_base_object_get_logger(fw_device), 1226230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1227230557Sjimharris "scif_sas_smp_remote_device_continue_discover(0x%x) enter\n", 1228230557Sjimharris fw_device 1229230557Sjimharris )); 1230230557Sjimharris 1231230557Sjimharris switch (fw_device->protocol_device.smp_device.current_smp_request) 1232230557Sjimharris { 1233230557Sjimharris case SMP_FUNCTION_REPORT_GENERAL: 1234230557Sjimharris // send the REPORT MANUFACTURER_INFO request 1235230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 1236230557Sjimharris SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION; 1237230557Sjimharris 1238230557Sjimharris scif_sas_smp_request_construct_report_manufacturer_info( 1239230557Sjimharris fw_domain->controller, fw_device 1240230557Sjimharris ); 1241230557Sjimharris 1242230557Sjimharris break; 1243230557Sjimharris 1244230557Sjimharris case SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION: 1245230557Sjimharris //send the first SMP DISCOVER request. 1246230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index = 0; 1247230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 1248230557Sjimharris SMP_FUNCTION_DISCOVER; 1249230557Sjimharris 1250230557Sjimharris scif_sas_smp_request_construct_discover( 1251230557Sjimharris fw_domain->controller, 1252230557Sjimharris fw_device, 1253230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index, 1254230557Sjimharris NULL, NULL 1255230557Sjimharris ); 1256230557Sjimharris break; 1257230557Sjimharris 1258230557Sjimharris 1259230557Sjimharris case SMP_FUNCTION_DISCOVER: 1260230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index++; 1261230557Sjimharris 1262230557Sjimharris if ( (fw_device->protocol_device.smp_device.current_activity_phy_index < 1263230557Sjimharris fw_device->protocol_device.smp_device.number_of_phys) ) 1264230557Sjimharris { 1265230557Sjimharris scif_sas_smp_request_construct_discover( 1266230557Sjimharris fw_domain->controller, 1267230557Sjimharris fw_device, 1268230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index, 1269230557Sjimharris NULL, NULL 1270230557Sjimharris ); 1271230557Sjimharris } 1272230557Sjimharris else 1273230557Sjimharris scif_sas_smp_remote_device_finish_initial_discover(fw_device); 1274230557Sjimharris break; 1275230557Sjimharris 1276230557Sjimharris 1277230557Sjimharris case SMP_FUNCTION_REPORT_PHY_SATA: 1278230557Sjimharris scif_sas_smp_request_construct_report_phy_sata( 1279230557Sjimharris fw_device->domain->controller, 1280230557Sjimharris fw_device, 1281230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index 1282230557Sjimharris ); 1283230557Sjimharris 1284230557Sjimharris break; 1285230557Sjimharris 1286230557Sjimharris 1287230557Sjimharris case SMP_FUNCTION_PHY_CONTROL: 1288230557Sjimharris scif_sas_smp_request_construct_phy_control( 1289230557Sjimharris fw_device->domain->controller, 1290230557Sjimharris fw_device, 1291230557Sjimharris PHY_OPERATION_HARD_RESET, 1292230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index, 1293230557Sjimharris NULL, 1294230557Sjimharris NULL 1295230557Sjimharris ); 1296230557Sjimharris 1297230557Sjimharris break; 1298230557Sjimharris 1299230557Sjimharris default: 1300230557Sjimharris break; 1301230557Sjimharris } 1302230557Sjimharris} 1303230557Sjimharris 1304230557Sjimharris/** 1305230557Sjimharris * @brief This method finishes the initial smp DISCOVER process. There 1306230557Sjimharris * may be a spinup_hold release phase following of initial discover, 1307230557Sjimharris * depending on whether there are SATA device in the domain 1308230557Sjimharris * in SATA_SPINUP_HOLD condition. 1309230557Sjimharris * 1310230557Sjimharris * @param[in] fw_device The framework smp device that finishes all the 1311230557Sjimharris * DISCOVER requests. 1312230557Sjimharris * 1313230557Sjimharris * @return none 1314230557Sjimharris */ 1315230557Sjimharrisvoid scif_sas_smp_remote_device_finish_initial_discover( 1316230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1317230557Sjimharris) 1318230557Sjimharris{ 1319230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * device_in_sata_spinup_hold = 1320230557Sjimharris scif_sas_domain_find_device_in_spinup_hold(fw_device->domain); 1321230557Sjimharris 1322230557Sjimharris SCIF_LOG_TRACE(( 1323230557Sjimharris sci_base_object_get_logger(fw_device), 1324230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1325230557Sjimharris "scif_sas_smp_remote_device_finish_initial_discover(0x%x) enter\n", 1326230557Sjimharris fw_device 1327230557Sjimharris )); 1328230557Sjimharris 1329230557Sjimharris if ( device_in_sata_spinup_hold != NULL ) 1330230557Sjimharris { 1331230557Sjimharris //call the common private routine to reset all fields of this smp device. 1332230557Sjimharris scif_sas_smp_remote_device_clear(fw_device); 1333230557Sjimharris 1334230557Sjimharris //Move on to next activity SPINUP_HOLD_RELEASE 1335230557Sjimharris fw_device->protocol_device.smp_device.current_activity = 1336230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_SATA_SPINUP_HOLD_RELEASE; 1337230557Sjimharris 1338230557Sjimharris //create the timer to delay a little bit before going to 1339230557Sjimharris //sata spinup hold release activity. 1340230557Sjimharris if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL) 1341230557Sjimharris { 1342230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer = 1343230557Sjimharris scif_cb_timer_create( 1344230557Sjimharris (SCI_CONTROLLER_HANDLE_T *)fw_device->domain->controller, 1345230557Sjimharris (SCI_TIMER_CALLBACK_T)scif_sas_smp_remote_device_sata_spinup_hold_release, 1346230557Sjimharris (void*)fw_device 1347230557Sjimharris ); 1348230557Sjimharris } 1349230557Sjimharris else 1350230557Sjimharris { 1351230557Sjimharris ASSERT (0); 1352230557Sjimharris } 1353230557Sjimharris 1354230557Sjimharris scif_cb_timer_start( 1355230557Sjimharris (SCI_CONTROLLER_HANDLE_T)fw_device->domain->controller, 1356230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer, 1357230557Sjimharris SMP_SPINUP_HOLD_RELEASE_WAIT_DURATION 1358230557Sjimharris ); 1359230557Sjimharris } 1360230557Sjimharris else 1361230557Sjimharris scif_sas_smp_remote_device_finish_discover(fw_device); 1362230557Sjimharris} 1363230557Sjimharris 1364230557Sjimharris 1365230557Sjimharris/** 1366230557Sjimharris * @brief This method finishes the smp DISCOVER process. 1367230557Sjimharris * 1368230557Sjimharris * @param[in] fw_device The framework smp device that finishes all the 1369230557Sjimharris * DISCOVER requests. 1370230557Sjimharris * 1371230557Sjimharris * @return none 1372230557Sjimharris */ 1373230557Sjimharrisvoid scif_sas_smp_remote_device_finish_discover( 1374230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1375230557Sjimharris) 1376230557Sjimharris{ 1377230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain; 1378230557Sjimharris 1379230557Sjimharris SCIF_LOG_TRACE(( 1380230557Sjimharris sci_base_object_get_logger(fw_device), 1381230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1382230557Sjimharris "scif_sas_smp_remote_device_finish_discover(0x%x) enter\n", 1383230557Sjimharris fw_device 1384230557Sjimharris )); 1385230557Sjimharris 1386230557Sjimharris if ( fw_domain->is_config_route_table_needed 1387230557Sjimharris && fw_device->protocol_device.smp_device.smp_phy_list.list_head != NULL) 1388230557Sjimharris scif_sas_smp_remote_device_configure_upstream_expander_route_info(fw_device); 1389230557Sjimharris 1390230557Sjimharris //call the common private routine to reset all fields of this smp device. 1391230557Sjimharris scif_sas_smp_remote_device_clear(fw_device); 1392230557Sjimharris 1393230557Sjimharris#ifdef SCI_SMP_PHY_LIST_DEBUG_PRINT 1394230557Sjimharris scif_sas_smp_remote_device_print_smp_phy_list(fw_device); 1395230557Sjimharris#endif 1396230557Sjimharris 1397230557Sjimharris //notify domain this smp device's discover finishes, it's up to domain 1398230557Sjimharris //to continue the discover process in a bigger scope. 1399230557Sjimharris scif_sas_domain_continue_discover(fw_domain); 1400230557Sjimharris} 1401230557Sjimharris 1402230557Sjimharris 1403230557Sjimharris/** 1404230557Sjimharris * @brief This method continues the smp Target Reset (Phy Control) process. 1405230557Sjimharris * 1406230557Sjimharris * @param[in] fw_device The framework smp device that a smp reset targets to. 1407230557Sjimharris * 1408230557Sjimharris * @return none 1409230557Sjimharris */ 1410230557Sjimharrisvoid scif_sas_smp_remote_device_continue_target_reset( 1411230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 1412230557Sjimharris SCIF_SAS_REQUEST_T * fw_request 1413230557Sjimharris) 1414230557Sjimharris{ 1415230557Sjimharris SCIF_SAS_CONTROLLER_T * fw_controller = fw_device->domain->controller; 1416230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * target_device = 1417230557Sjimharris scif_sas_domain_get_device_by_containing_device( 1418230557Sjimharris fw_device->domain, 1419230557Sjimharris fw_device, 1420230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index 1421230557Sjimharris ); 1422230557Sjimharris 1423230557Sjimharris SCIF_LOG_TRACE(( 1424230557Sjimharris sci_base_object_get_logger(fw_device), 1425230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1426230557Sjimharris "scif_sas_smp_remote_device_continue_target_reset(0x%x, 0x%x) enter\n", 1427230557Sjimharris fw_device, fw_request 1428230557Sjimharris )); 1429230557Sjimharris 1430230557Sjimharris if (fw_device->protocol_device.smp_device.current_smp_request == 1431230557Sjimharris SMP_FUNCTION_PHY_CONTROL) 1432230557Sjimharris { 1433230557Sjimharris //query the core remote device to get suggested reset timeout value 1434230557Sjimharris //then scale down by factor of 8 to get the duration of the pause 1435230557Sjimharris //before sending out Discover command to poll. 1436230557Sjimharris U32 delay = 1437230557Sjimharris (scic_remote_device_get_suggested_reset_timeout(target_device->core_object)/8); 1438230557Sjimharris 1439230557Sjimharris //create the timer to send Discover command polling target device's 1440230557Sjimharris //coming back. 1441230557Sjimharris if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL) 1442230557Sjimharris { 1443230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer = 1444230557Sjimharris scif_cb_timer_create( 1445230557Sjimharris (SCI_CONTROLLER_HANDLE_T *)fw_controller, 1446230557Sjimharris (SCI_TIMER_CALLBACK_T)scif_sas_smp_remote_device_target_reset_poll, 1447230557Sjimharris (void*)fw_request 1448230557Sjimharris ); 1449230557Sjimharris } 1450230557Sjimharris else 1451230557Sjimharris { 1452230557Sjimharris ASSERT(0); 1453230557Sjimharris } 1454230557Sjimharris 1455230557Sjimharris //start the timer 1456230557Sjimharris scif_cb_timer_start( 1457230557Sjimharris (SCI_CONTROLLER_HANDLE_T)fw_controller, 1458230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer, 1459230557Sjimharris delay 1460230557Sjimharris ); 1461230557Sjimharris } 1462230557Sjimharris else if (fw_device->protocol_device.smp_device.current_smp_request == 1463230557Sjimharris SMP_FUNCTION_DISCOVER) 1464230557Sjimharris { 1465230557Sjimharris //tell target reset successful 1466230557Sjimharris scif_sas_remote_device_target_reset_complete( 1467230557Sjimharris target_device, fw_request, SCI_SUCCESS); 1468230557Sjimharris } 1469230557Sjimharris} 1470230557Sjimharris 1471230557Sjimharris/** 1472230557Sjimharris * @brief This routine is invoked by timer or when 2 BCN are received 1473230557Sjimharris * after Phy Control command. This routine will construct a 1474230557Sjimharris * Discover command to the same expander phy to poll the target 1475230557Sjimharris * device's coming back. This new request is then put into 1476230557Sjimharris * high priority queue and will be started by a DPC soon. 1477230557Sjimharris * 1478230557Sjimharris * @param[in] fw_request The scif request for smp activities. 1479230557Sjimharris */ 1480230557Sjimharrisvoid scif_sas_smp_remote_device_target_reset_poll( 1481230557Sjimharris SCIF_SAS_REQUEST_T * fw_request 1482230557Sjimharris) 1483230557Sjimharris{ 1484230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device = fw_request->device; 1485230557Sjimharris SCIF_SAS_CONTROLLER_T * fw_controller = fw_device->domain->controller; 1486230557Sjimharris void * new_command_handle; 1487230557Sjimharris 1488230557Sjimharris SCIF_LOG_TRACE(( 1489230557Sjimharris sci_base_object_get_logger(fw_device), 1490230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1491230557Sjimharris "scif_sas_smp_remote_device_target_reset_poll(0x%x) enter\n", 1492230557Sjimharris fw_request 1493230557Sjimharris )); 1494230557Sjimharris 1495230557Sjimharris // Before we construct new io using the same memory, we need to 1496230557Sjimharris // remove the IO from the list of outstanding requests on the domain 1497230557Sjimharris // so that we don't damage the domain's fast list of request. 1498230557Sjimharris sci_fast_list_remove_element(&fw_request->list_element); 1499230557Sjimharris 1500230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 1501230557Sjimharris SMP_FUNCTION_DISCOVER; 1502230557Sjimharris 1503230557Sjimharris //sent smp discover request to poll on remote device's coming back. 1504230557Sjimharris //construct Discover command using the same memory as fw_request. 1505230557Sjimharris new_command_handle = scif_sas_smp_request_construct_discover( 1506230557Sjimharris fw_device->domain->controller, 1507230557Sjimharris fw_device, 1508230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index, 1509230557Sjimharris (void *)sci_object_get_association(fw_request), 1510230557Sjimharris (void *)fw_request 1511230557Sjimharris ); 1512230557Sjimharris 1513230557Sjimharris //put into the high priority queue. 1514230557Sjimharris sci_pool_put(fw_controller->hprq.pool, (POINTER_UINT) new_command_handle); 1515230557Sjimharris 1516230557Sjimharris //schedule the DPC to start new Discover command. 1517230557Sjimharris scif_cb_start_internal_io_task_schedule( 1518230557Sjimharris fw_controller, scif_sas_controller_start_high_priority_io, fw_controller 1519230557Sjimharris ); 1520230557Sjimharris} 1521230557Sjimharris 1522230557Sjimharris 1523230557Sjimharris/** 1524230557Sjimharris * @brief This method fails discover process. 1525230557Sjimharris * 1526230557Sjimharris * @param[in] fw_device The framework smp device that failed at current 1527230557Sjimharris * activity. 1528230557Sjimharris * 1529230557Sjimharris * @return none 1530230557Sjimharris */ 1531230557Sjimharrisvoid scif_sas_smp_remote_device_fail_discover( 1532230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1533230557Sjimharris) 1534230557Sjimharris{ 1535230557Sjimharris SCIF_LOG_TRACE(( 1536230557Sjimharris sci_base_object_get_logger(fw_device), 1537230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1538230557Sjimharris "scif_sas_smp_remote_device_fail_discover(0x%x) enter\n", 1539230557Sjimharris fw_device 1540230557Sjimharris )); 1541230557Sjimharris 1542230557Sjimharris switch (fw_device->protocol_device.smp_device.current_smp_request) 1543230557Sjimharris { 1544230557Sjimharris case SMP_FUNCTION_REPORT_GENERAL: 1545230557Sjimharris case SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION: 1546230557Sjimharris scif_sas_smp_remote_device_finish_discover(fw_device); 1547230557Sjimharris break; 1548230557Sjimharris 1549230557Sjimharris case SMP_FUNCTION_DISCOVER: 1550230557Sjimharris case SMP_FUNCTION_REPORT_PHY_SATA: 1551230557Sjimharris //Retry limit reached, we will continue to send DISCOVER to next phy. 1552230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 1553230557Sjimharris SMP_FUNCTION_DISCOVER; 1554230557Sjimharris 1555230557Sjimharris scif_sas_smp_remote_device_continue_discover(fw_device); 1556230557Sjimharris break; 1557230557Sjimharris 1558230557Sjimharris default: 1559230557Sjimharris break; 1560230557Sjimharris } 1561230557Sjimharris} 1562230557Sjimharris 1563230557Sjimharris 1564230557Sjimharris/** 1565230557Sjimharris * @brief This method fails Target Reset. 1566230557Sjimharris * 1567230557Sjimharris * @param[in] fw_device The framework smp device that failed at current 1568230557Sjimharris * activity. 1569230557Sjimharris * @param[in] fw_request The smp request created for target reset 1570230557Sjimharris * using external resource. 1571230557Sjimharris * 1572230557Sjimharris * @return none 1573230557Sjimharris */ 1574230557Sjimharrisvoid scif_sas_smp_remote_device_fail_target_reset( 1575230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 1576230557Sjimharris SCIF_SAS_REQUEST_T * fw_request 1577230557Sjimharris) 1578230557Sjimharris{ 1579230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * target_device = 1580230557Sjimharris scif_sas_domain_get_device_by_containing_device( 1581230557Sjimharris fw_device->domain, 1582230557Sjimharris fw_device, 1583230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index 1584230557Sjimharris ); 1585230557Sjimharris 1586230557Sjimharris SCIF_LOG_TRACE(( 1587230557Sjimharris sci_base_object_get_logger(fw_device), 1588230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1589230557Sjimharris "scif_sas_smp_remote_device_fail_target_reset(0x%x, 0x%x, 0x%x) enter\n", 1590230557Sjimharris fw_device, target_device, fw_request 1591230557Sjimharris )); 1592230557Sjimharris 1593230557Sjimharris //tell target reset failed 1594230557Sjimharris scif_sas_remote_device_target_reset_complete( 1595230557Sjimharris target_device, fw_request, SCI_FAILURE); 1596230557Sjimharris} 1597230557Sjimharris 1598230557Sjimharris/** 1599230557Sjimharris * @brief This method init or continue the SATA SPINUP_HOLD RELEASE activity. 1600230557Sjimharris * This function searches domain's device list, find a device in STOPPED STATE 1601230557Sjimharris * and its connection_rate is SPINIP, then send DISCOVER command to its expander 1602230557Sjimharris * phy id to poll. But if searching the domain's device list for SATA devices on 1603230557Sjimharris * SPINUP_HOLD finds no device, the activity SPINUP_HOLD_RELEASE is finished. 1604230557Sjimharris * We then call fw_domain->device_start_complete_handler() for this smp-device. 1605230557Sjimharris * 1606230557Sjimharris * @param[in] fw_device The framework smp device that is on SATA SPINUP_HOLD_RELEASE 1607230557Sjimharris * activity. 1608230557Sjimharris * 1609230557Sjimharris * @return none 1610230557Sjimharris */ 1611230557Sjimharrisvoid scif_sas_smp_remote_device_sata_spinup_hold_release( 1612230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1613230557Sjimharris) 1614230557Sjimharris{ 1615230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain; 1616230557Sjimharris SCIF_SAS_CONTROLLER_T * fw_controller = fw_domain->controller; 1617230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * device_to_poll = NULL; 1618230557Sjimharris 1619230557Sjimharris SCIF_LOG_TRACE(( 1620230557Sjimharris sci_base_object_get_logger(fw_device), 1621230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1622230557Sjimharris "scif_sas_smp_remote_device_sata_spinup_hold_release(0x%x) enter\n", 1623230557Sjimharris fw_device 1624230557Sjimharris )); 1625230557Sjimharris 1626230557Sjimharris //search throught domain's device list to find a sata device on spinup_hold 1627230557Sjimharris //state to poll. 1628230557Sjimharris device_to_poll = scif_sas_domain_find_device_in_spinup_hold(fw_domain); 1629230557Sjimharris 1630230557Sjimharris if (device_to_poll != NULL) 1631230557Sjimharris { 1632230557Sjimharris //send DISCOVER command to this device's expaner phy. 1633230557Sjimharris fw_device->protocol_device.smp_device.current_smp_request = 1634230557Sjimharris SMP_FUNCTION_DISCOVER; 1635230557Sjimharris 1636230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index = 1637230557Sjimharris device_to_poll->expander_phy_identifier; 1638230557Sjimharris 1639230557Sjimharris scif_sas_smp_request_construct_discover( 1640230557Sjimharris fw_domain->controller, 1641230557Sjimharris fw_device, 1642230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index, 1643230557Sjimharris NULL, NULL 1644230557Sjimharris ); 1645230557Sjimharris 1646230557Sjimharris //schedule the DPC to start new Discover command. 1647230557Sjimharris scif_cb_start_internal_io_task_schedule( 1648230557Sjimharris fw_controller, scif_sas_controller_start_high_priority_io, fw_controller 1649230557Sjimharris ); 1650230557Sjimharris } 1651230557Sjimharris else //SATA SPINUP HOLD RELEASE activity is done. 1652230557Sjimharris scif_sas_smp_remote_device_finish_discover (fw_device); 1653230557Sjimharris} 1654230557Sjimharris 1655230557Sjimharris 1656230557Sjimharris/** 1657230557Sjimharris * @brief This method fail an action of SATA SPINUP_HOLD RELEASE on a single EA 1658230557Sjimharris * SATA device. It will remove a remote_device object for a sata device 1659230557Sjimharris * that fails to come out of spinup_hold. 1660230557Sjimharris * 1661230557Sjimharris * @param[in] fw_device The framework smp device that is on SATA SPINUP_HOLD_RELEASE 1662230557Sjimharris * activity. 1663230557Sjimharris * @param[in] target_device The expander attached device failed being brought out 1664230557Sjimharris * of SPINUP_HOLD state. 1665230557Sjimharris * 1666230557Sjimharris * @return none 1667230557Sjimharris */ 1668230557Sjimharrisvoid scif_sas_smp_remote_device_fail_target_spinup_hold_release( 1669230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 1670230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * target_device 1671230557Sjimharris) 1672230557Sjimharris{ 1673230557Sjimharris SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain; 1674230557Sjimharris 1675230557Sjimharris SCIF_LOG_TRACE(( 1676230557Sjimharris sci_base_object_get_logger(fw_device), 1677230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1678230557Sjimharris "scif_sas_smp_remote_device_fail_target_spinup_hold_release(0x%x, 0x%x) enter\n", 1679230557Sjimharris fw_device, target_device 1680230557Sjimharris )); 1681230557Sjimharris 1682230557Sjimharris //need to remove the device, since we have to give up on spinup_hold_release 1683230557Sjimharris //activity on this device. 1684230557Sjimharris scif_cb_domain_device_removed( 1685230557Sjimharris fw_domain->controller, fw_domain, target_device 1686230557Sjimharris ); 1687230557Sjimharris 1688230557Sjimharris //move on to next round of SPINUP_HOLD_REALSE activity. 1689230557Sjimharris scif_sas_smp_remote_device_sata_spinup_hold_release(fw_device); 1690230557Sjimharris} 1691230557Sjimharris 1692230557Sjimharris 1693230557Sjimharris/** 1694230557Sjimharris * @brief This method retry only internal IO for the smp device. 1695230557Sjimharris * 1696230557Sjimharris * @param[in] fw_device The framework smp device that has an smp request to retry. 1697230557Sjimharris * @param[in] io_retry_count current count for times the IO being retried. 1698230557Sjimharris * @param[in] delay The time delay before the io gets retried. 1699230557Sjimharris * 1700230557Sjimharris * @return none 1701230557Sjimharris */ 1702230557Sjimharrisvoid scif_sas_smp_remote_device_retry_internal_io( 1703230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 1704230557Sjimharris U8 io_retry_count, 1705230557Sjimharris U32 delay 1706230557Sjimharris) 1707230557Sjimharris{ 1708230557Sjimharris SCIF_LOG_TRACE(( 1709230557Sjimharris sci_base_object_get_logger(fw_device), 1710230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1711230557Sjimharris "scif_sas_smp_remote_device_retry_internal_io(0x%x, 0x%x, 0x%x) enter\n", 1712230557Sjimharris fw_device, io_retry_count, delay 1713230557Sjimharris )); 1714230557Sjimharris 1715230557Sjimharris fw_device->protocol_device.smp_device.io_retry_count = 1716230557Sjimharris io_retry_count; 1717230557Sjimharris 1718230557Sjimharris //create the timer for poll target device's coming back. 1719230557Sjimharris if (fw_device->protocol_device.smp_device.smp_activity_timer == NULL) 1720230557Sjimharris { 1721230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer = 1722230557Sjimharris scif_cb_timer_create( 1723230557Sjimharris (SCI_CONTROLLER_HANDLE_T *)fw_device->domain->controller, 1724230557Sjimharris (SCI_TIMER_CALLBACK_T)scif_sas_smp_internal_request_retry, 1725230557Sjimharris (void*)fw_device 1726230557Sjimharris ); 1727230557Sjimharris } 1728230557Sjimharris else 1729230557Sjimharris { 1730230557Sjimharris ASSERT(0); 1731230557Sjimharris } 1732230557Sjimharris //start the timer for a purpose of waiting. 1733230557Sjimharris scif_cb_timer_start( 1734230557Sjimharris (SCI_CONTROLLER_HANDLE_T)fw_device->domain->controller, 1735230557Sjimharris fw_device->protocol_device.smp_device.smp_activity_timer, 1736230557Sjimharris delay 1737230557Sjimharris ); 1738230557Sjimharris} 1739230557Sjimharris 1740230557Sjimharris 1741230557Sjimharris/** 1742230557Sjimharris * @brief This method indicates whether an expander device is in Discover 1743230557Sjimharris * process. 1744230557Sjimharris * 1745230557Sjimharris * @param[in] fw_device The framework smp device. 1746230557Sjimharris * 1747230557Sjimharris * @return Whether an expander device is in the middle of discovery process. 1748230557Sjimharris */ 1749230557SjimharrisBOOL scif_sas_smp_remote_device_is_in_activity( 1750230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1751230557Sjimharris) 1752230557Sjimharris{ 1753230557Sjimharris return(fw_device->protocol_device.smp_device.current_activity 1754230557Sjimharris != SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE); 1755230557Sjimharris} 1756230557Sjimharris 1757230557Sjimharris/** 1758230557Sjimharris * @brief This method search through the smp phy list of an expander to 1759230557Sjimharris * find a smp phy by its phy id of the expander. 1760230557Sjimharris * 1761230557Sjimharris * @param[in] phy_identifier The search criteria. 1762230557Sjimharris * @param[in] smp_remote_device The expander that owns the smp phy list. 1763230557Sjimharris * 1764230557Sjimharris * @return The found smp phy or a NULL pointer to indicate no smp phy is found. 1765230557Sjimharris */ 1766230557SjimharrisSCIF_SAS_SMP_PHY_T * scif_sas_smp_remote_device_find_smp_phy_by_id( 1767230557Sjimharris U8 phy_identifier, 1768230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device 1769230557Sjimharris) 1770230557Sjimharris{ 1771230557Sjimharris SCI_FAST_LIST_ELEMENT_T * element = smp_remote_device->smp_phy_list.list_head; 1772230557Sjimharris SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; 1773230557Sjimharris 1774231137Sjimharris ASSERT(phy_identifier < smp_remote_device->smp_phy_list.number_of_phys); 1775231137Sjimharris 1776230557Sjimharris while (element != NULL) 1777230557Sjimharris { 1778230557Sjimharris curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); 1779230557Sjimharris element = sci_fast_list_get_next(element); 1780230557Sjimharris 1781230557Sjimharris if (curr_smp_phy->phy_identifier == phy_identifier) 1782230557Sjimharris return curr_smp_phy; 1783230557Sjimharris } 1784230557Sjimharris 1785230557Sjimharris return NULL; 1786230557Sjimharris} 1787230557Sjimharris 1788230557Sjimharris/** 1789230557Sjimharris * @brief This method takes care of removing smp phy list of a smp devcie, which is 1790230557Sjimharris * about to be removed. 1791230557Sjimharris * 1792230557Sjimharris * @param[in] fw_device The expander device that is about to be removed. 1793230557Sjimharris * 1794230557Sjimharris * @return none. 1795230557Sjimharris */ 1796230557Sjimharrisvoid scif_sas_smp_remote_device_removed( 1797230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * this_device 1798230557Sjimharris) 1799230557Sjimharris{ 1800230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device = 1801230557Sjimharris &this_device->protocol_device.smp_device; 1802230557Sjimharris 1803230557Sjimharris SCI_FAST_LIST_ELEMENT_T * element = smp_remote_device->smp_phy_list.list_head; 1804230557Sjimharris SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; 1805230557Sjimharris 1806230557Sjimharris SCIF_LOG_TRACE(( 1807230557Sjimharris sci_base_object_get_logger(this_device), 1808230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1809230557Sjimharris "scif_sas_smp_remote_device_removed(0x%x) enter\n", 1810230557Sjimharris this_device 1811230557Sjimharris )); 1812230557Sjimharris 1813230557Sjimharris //remove all the smp phys in this device's smp_phy_list, and the conterpart smp phys 1814230557Sjimharris //in phy connections. 1815230557Sjimharris while (element != NULL) 1816230557Sjimharris { 1817230557Sjimharris curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); 1818230557Sjimharris element = sci_fast_list_get_next(element); 1819230557Sjimharris 1820230557Sjimharris scif_sas_smp_phy_destruct(curr_smp_phy); 1821230557Sjimharris } 1822230557Sjimharris 1823230557Sjimharris this_device->protocol_device.smp_device.number_of_phys = 0; 1824230557Sjimharris this_device->protocol_device.smp_device.expander_route_indexes = 0; 1825230557Sjimharris this_device->protocol_device.smp_device.is_table_to_table_supported = FALSE; 1826230557Sjimharris this_device->protocol_device.smp_device.is_externally_configurable = FALSE; 1827230557Sjimharris this_device->protocol_device.smp_device.is_able_to_config_others = FALSE; 1828230557Sjimharris 1829230557Sjimharris scif_sas_smp_remote_device_clear(this_device); 1830230557Sjimharris} 1831230557Sjimharris 1832230557Sjimharris 1833230557Sjimharris/** 1834230557Sjimharris * @brief This method takes care of terminated smp request to a smp device. The 1835230557Sjimharris * terminated smp request is most likely timeout and being aborted. A timeout 1836230557Sjimharris * maybe due to OPEN REJECT (NO DESTINATION). 1837230557Sjimharris * 1838230557Sjimharris * @param[in] fw_device The expander device that a timed out smp request towards to. 1839230557Sjimharris * @param[in] fw_request A failed smp request that is terminated by scic. 1840230557Sjimharris * 1841230557Sjimharris * @return none. 1842230557Sjimharris */ 1843230557Sjimharrisvoid scif_sas_smp_remote_device_terminated_request_handler( 1844230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 1845230557Sjimharris SCIF_SAS_REQUEST_T * fw_request 1846230557Sjimharris) 1847230557Sjimharris{ 1848230557Sjimharris SCIF_LOG_TRACE(( 1849230557Sjimharris sci_base_object_get_logger(fw_device), 1850230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1851230557Sjimharris "scif_sas_smp_remote_device_terminated_request_handler(0x%x, 0x%x) enter\n", 1852230557Sjimharris fw_device, fw_request 1853230557Sjimharris )); 1854230557Sjimharris 1855230557Sjimharris scif_sas_smp_remote_device_decode_smp_response( 1856231296Sjimharris fw_device, fw_request, NULL, SCI_IO_FAILURE_RETRY_REQUIRED 1857230557Sjimharris ); 1858230557Sjimharris} 1859230557Sjimharris 1860230557Sjimharris 1861230557Sjimharris/** 1862230557Sjimharris * @brief This method allocates and populates the smp phy list of a expander device. 1863230557Sjimharris * 1864230557Sjimharris * @param[in] fw_device The expander device, whose smp phy list is to be populated after 1865230557Sjimharris * getting REPORT GENERAL response. 1866230557Sjimharris * 1867230557Sjimharris * @return none. 1868230557Sjimharris */ 1869230557Sjimharrisvoid scif_sas_smp_remote_device_populate_smp_phy_list( 1870230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1871230557Sjimharris) 1872230557Sjimharris{ 1873230557Sjimharris SCIF_SAS_SMP_PHY_T * this_smp_phy = NULL; 1874230557Sjimharris U8 expander_phy_id = 0; 1875230557Sjimharris 1876230557Sjimharris SCIF_LOG_TRACE(( 1877230557Sjimharris sci_base_object_get_logger(fw_device), 1878230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1879230557Sjimharris "scif_sas_smp_remote_device_populate_smp_phy_list(0x%x) enter\n", 1880230557Sjimharris fw_device 1881230557Sjimharris )); 1882230557Sjimharris 1883230557Sjimharris for ( expander_phy_id = 0; 1884230557Sjimharris expander_phy_id < fw_device->protocol_device.smp_device.number_of_phys; 1885230557Sjimharris expander_phy_id++ ) 1886230557Sjimharris { 1887230557Sjimharris this_smp_phy = 1888230557Sjimharris scif_sas_controller_allocate_smp_phy(fw_device->domain->controller); 1889230557Sjimharris 1890230557Sjimharris ASSERT( this_smp_phy != NULL ); 1891230557Sjimharris 1892230557Sjimharris if ( this_smp_phy != NULL ) 1893230557Sjimharris scif_sas_smp_phy_construct(this_smp_phy, fw_device, expander_phy_id); 1894230557Sjimharris } 1895230557Sjimharris} 1896230557Sjimharris 1897230557Sjimharris 1898230557Sjimharris/** 1899230557Sjimharris * @brief This method updates a smp phy of a expander device based on DISCOVER response. 1900230557Sjimharris * 1901230557Sjimharris * @param[in] fw_device The expander device, one of whose smp phys is to be updated. 1902230557Sjimharris * @param[in] discover_response The smp DISCOVER response. 1903230557Sjimharris * 1904230557Sjimharris * @return SCI_STATUS If a smp phy pair between expanders has invalid routing attribute, 1905230557Sjimharris * return SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION, otherwise, 1906230557Sjimharris * return SCI_SUCCESS 1907230557Sjimharris */ 1908230557SjimharrisSCI_STATUS scif_sas_smp_remote_device_save_smp_phy_info( 1909230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device, 1910230557Sjimharris SMP_RESPONSE_DISCOVER_T * discover_response 1911230557Sjimharris) 1912230557Sjimharris{ 1913230557Sjimharris SCI_STATUS status = SCI_SUCCESS; 1914230557Sjimharris SCIF_SAS_SMP_PHY_T * smp_phy = NULL; 1915230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * attached_device = NULL; 1916230557Sjimharris 1917230557Sjimharris SCIF_LOG_TRACE(( 1918230557Sjimharris sci_base_object_get_logger(fw_device), 1919230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 1920230557Sjimharris "scif_sas_smp_remote_device_save_smp_phy_info(0x%x, 0x%x) enter\n", 1921230557Sjimharris fw_device, discover_response 1922230557Sjimharris )); 1923230557Sjimharris 1924230557Sjimharris smp_phy = scif_sas_smp_remote_device_find_smp_phy_by_id( 1925230557Sjimharris discover_response->phy_identifier, 1926230557Sjimharris &fw_device->protocol_device.smp_device 1927230557Sjimharris ); 1928230557Sjimharris 1929230557Sjimharris ASSERT( smp_phy != NULL ); 1930230557Sjimharris 1931230557Sjimharris //Note, attached_device could be NULL, not all the smp phy have to connected to a device. 1932230557Sjimharris attached_device = (SCIF_SAS_REMOTE_DEVICE_T *) 1933230557Sjimharris scif_domain_get_device_by_sas_address( 1934230557Sjimharris fw_device->domain, &discover_response->attached_sas_address); 1935230557Sjimharris 1936231137Sjimharris scif_sas_smp_phy_save_information( 1937231137Sjimharris smp_phy, attached_device, discover_response); 1938230557Sjimharris 1939230557Sjimharris //handle the special case of smp phys between expanders. 1940230557Sjimharris if ( discover_response->protocols.u.bits.attached_smp_target ) 1941230557Sjimharris { 1942230557Sjimharris //this fw_device is a child expander, just found its parent expander. 1943230557Sjimharris //And there is no smp_phy constructed yet, record this phy connection. 1944230557Sjimharris if ( attached_device != NULL 1945230557Sjimharris && attached_device == fw_device->containing_device ) 1946230557Sjimharris { 1947230557Sjimharris //record the smp phy info, for this phy connects to a upstream smp device. 1948230557Sjimharris //the connection of a pair of smp phys are completed. 1949230557Sjimharris status = scif_sas_smp_phy_set_attached_phy( 1950230557Sjimharris smp_phy, 1951230557Sjimharris discover_response->attached_phy_identifier, 1952230557Sjimharris attached_device 1953230557Sjimharris ); 1954230557Sjimharris 1955230557Sjimharris if (status == SCI_SUCCESS) 1956230557Sjimharris { 1957230557Sjimharris //check the routing attribute for this phy and its containing device's 1958230557Sjimharris //expander_phy_routing_attribute. 1959230557Sjimharris if ( scif_sas_smp_phy_verify_routing_attribute( 1960230557Sjimharris smp_phy, smp_phy->u.attached_phy) != SCI_SUCCESS ) 1961230557Sjimharris return SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION; 1962230557Sjimharris } 1963230557Sjimharris } 1964230557Sjimharris } 1965230557Sjimharris 1966230557Sjimharris return status; 1967230557Sjimharris} 1968230557Sjimharris 1969230557Sjimharris#ifdef SCI_SMP_PHY_LIST_DEBUG_PRINT 1970230557Sjimharrisvoid scif_sas_smp_remote_device_print_smp_phy_list( 1971230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 1972230557Sjimharris) 1973230557Sjimharris{ 1974230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device = &fw_device->protocol_device.smp_device; 1975230557Sjimharris SCI_FAST_LIST_ELEMENT_T * element = smp_remote_device->smp_phy_list.list_head; 1976230557Sjimharris SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; 1977230557Sjimharris 1978230557Sjimharris SCIF_LOG_ERROR(( 1979230557Sjimharris sci_base_object_get_logger(fw_device), 1980230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 1981230557Sjimharris "==========EXPANDER DEVICE (0x%x) smp phy list========== \n", 1982230557Sjimharris fw_device 1983230557Sjimharris )); 1984230557Sjimharris 1985230557Sjimharris while (element != NULL) 1986230557Sjimharris { 1987230557Sjimharris curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); 1988230557Sjimharris element = sci_fast_list_get_next(element); 1989230557Sjimharris 1990230557Sjimharris //print every thing about a smp phy 1991230557Sjimharris SCIF_LOG_ERROR(( 1992230557Sjimharris sci_base_object_get_logger(fw_device), 1993230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE, 1994230557Sjimharris "SMP_PHY_%d (0x%x), attached device(0x%x), attached_sas_address(%x%x) attached_device_type(%d), routing_attribute(%d)\n", 1995230557Sjimharris curr_smp_phy->phy_identifier, curr_smp_phy, 1996230557Sjimharris curr_smp_phy->u.end_device, 1997230557Sjimharris curr_smp_phy->attached_sas_address.high, curr_smp_phy->attached_sas_address.low, 1998230557Sjimharris curr_smp_phy->attached_device_type, 1999230557Sjimharris curr_smp_phy->routing_attribute 2000230557Sjimharris )); 2001230557Sjimharris } 2002230557Sjimharris} 2003230557Sjimharris#endif 2004230557Sjimharris 2005230557Sjimharris 2006230557Sjimharris/** 2007230557Sjimharris * @brief This method configure upstream expander(s)' (if there is any) route info. 2008230557Sjimharris * 2009230557Sjimharris * @param[in] this_device The expander device that is currently in discover process. 2010230557Sjimharris * 2011230557Sjimharris * @return none. 2012230557Sjimharris */ 2013230557Sjimharrisvoid scif_sas_smp_remote_device_configure_upstream_expander_route_info( 2014230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * this_device 2015230557Sjimharris) 2016230557Sjimharris{ 2017230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * curr_child_expander = this_device; 2018230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * curr_parent_expander = 2019230557Sjimharris scif_sas_remote_device_find_upstream_expander(this_device); 2020230557Sjimharris 2021230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * curr_config_route_info_expander = NULL; 2022230557Sjimharris 2023230557Sjimharris SCIF_LOG_TRACE(( 2024230557Sjimharris sci_base_object_get_logger(this_device), 2025230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2026230557Sjimharris "scif_sas_smp_remote_device_configure_upstream_expander_route_info(0x%x) enter\n", 2027230557Sjimharris this_device 2028230557Sjimharris )); 2029230557Sjimharris 2030230557Sjimharris //traverse back to find root device. 2031230557Sjimharris while(curr_parent_expander != NULL ) 2032230557Sjimharris { 2033230557Sjimharris //must set destination_smp_phy outside of find_upstream_expander() using the device 2034230557Sjimharris //that is just about to finish the discovery. 2035230557Sjimharris curr_parent_expander->protocol_device.smp_device.curr_config_route_destination_smp_phy = 2036230557Sjimharris (SCIF_SAS_SMP_PHY_T*)sci_fast_list_get_object( 2037230557Sjimharris this_device->protocol_device.smp_device.smp_phy_list.list_head); 2038230557Sjimharris 2039230557Sjimharris curr_child_expander = curr_parent_expander; 2040230557Sjimharris curr_parent_expander = scif_sas_remote_device_find_upstream_expander(curr_child_expander); 2041230557Sjimharris } 2042230557Sjimharris 2043230557Sjimharris //found the root device: curr_child_expander. configure it and its downstream expander(s) till 2044230557Sjimharris //this_device or a self-configuring expander that configures others; 2045230557Sjimharris curr_config_route_info_expander = curr_child_expander; 2046230557Sjimharris 2047230557Sjimharris while ( curr_config_route_info_expander != NULL 2048230557Sjimharris && curr_config_route_info_expander != this_device 2049230557Sjimharris && curr_config_route_info_expander->protocol_device.smp_device.scheduled_activity 2050230557Sjimharris == SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE 2051230557Sjimharris ) 2052230557Sjimharris { 2053230557Sjimharris if (curr_config_route_info_expander->protocol_device.smp_device.is_externally_configurable) 2054230557Sjimharris { 2055230557Sjimharris SCIF_SAS_SMP_PHY_T * phy_being_config = 2056230557Sjimharris curr_config_route_info_expander->protocol_device.smp_device.config_route_smp_phy_anchor; 2057230557Sjimharris 2058230557Sjimharris curr_config_route_info_expander->protocol_device.smp_device.curr_config_route_index = 2059230557Sjimharris phy_being_config->config_route_table_index_anchor; 2060230557Sjimharris 2061230557Sjimharris if (curr_config_route_info_expander->protocol_device.smp_device.curr_config_route_index != 0) 2062230557Sjimharris curr_config_route_info_expander->protocol_device.smp_device.curr_config_route_index++; 2063230557Sjimharris 2064230557Sjimharris curr_config_route_info_expander->protocol_device.smp_device.scheduled_activity = 2065230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE; 2066230557Sjimharris 2067230557Sjimharris //Find a downstream expander that has curr_config_route_destination_smp_phy.owning device 2068230557Sjimharris //same as curr_config_route_info_expander. 2069230557Sjimharris curr_config_route_info_expander = scif_sas_remote_device_find_downstream_expander( 2070230557Sjimharris curr_config_route_info_expander); 2071230557Sjimharris } 2072230557Sjimharris else if (curr_config_route_info_expander->protocol_device.smp_device.is_able_to_config_others) 2073230557Sjimharris { 2074230557Sjimharris //no need to config route table to this expander and its children. 2075230557Sjimharris //find its downstream expander and clear the planned config route table activity. 2076230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * curr_downstream_expander = 2077230557Sjimharris scif_sas_remote_device_find_downstream_expander( 2078230557Sjimharris curr_config_route_info_expander); 2079230557Sjimharris 2080230557Sjimharris scif_sas_smp_remote_device_clear(curr_config_route_info_expander); 2081230557Sjimharris 2082230557Sjimharris while ( curr_downstream_expander != NULL 2083230557Sjimharris && curr_downstream_expander != this_device ) 2084230557Sjimharris { 2085230557Sjimharris scif_sas_smp_remote_device_clear(curr_downstream_expander); 2086230557Sjimharris curr_downstream_expander = 2087230557Sjimharris scif_sas_remote_device_find_downstream_expander( 2088230557Sjimharris curr_config_route_info_expander); 2089230557Sjimharris } 2090230557Sjimharris 2091230557Sjimharris break; 2092230557Sjimharris } 2093230557Sjimharris else 2094230557Sjimharris { 2095230557Sjimharris // current expander is a self-configuring expander, which is not externally 2096230557Sjimharris // configurable, and doesn't config others. we need to simply skip this expander. 2097230557Sjimharris curr_config_route_info_expander = scif_sas_remote_device_find_downstream_expander( 2098230557Sjimharris curr_config_route_info_expander); 2099230557Sjimharris } 2100230557Sjimharris } 2101230557Sjimharris} 2102230557Sjimharris 2103230557Sjimharris/** 2104230557Sjimharris * @brief This method finds the immediate upstream expander of a given expander device. 2105230557Sjimharris * 2106230557Sjimharris * @param[in] this_device The given expander device, whose upstream expander is to be found. 2107230557Sjimharris * 2108230557Sjimharris * @return The immediate upstream expander. Or a NULL pointer if this_device is root already. 2109230557Sjimharris */ 2110230557SjimharrisSCIF_SAS_REMOTE_DEVICE_T * scif_sas_remote_device_find_upstream_expander( 2111230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * this_device 2112230557Sjimharris) 2113230557Sjimharris{ 2114230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device = 2115230557Sjimharris &this_device->protocol_device.smp_device; 2116230557Sjimharris 2117230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * upstream_expander = NULL; 2118230557Sjimharris 2119230557Sjimharris SCI_FAST_LIST_ELEMENT_T * element = smp_remote_device->smp_phy_list.list_head; 2120230557Sjimharris SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; 2121230557Sjimharris 2122230557Sjimharris SCIF_LOG_TRACE(( 2123230557Sjimharris sci_base_object_get_logger(this_device), 2124230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2125230557Sjimharris "scif_sas_smp_remote_device_configure_upstream_expander_route_info(0x%x) enter\n", 2126230557Sjimharris this_device 2127230557Sjimharris )); 2128230557Sjimharris 2129230557Sjimharris while (element != NULL) 2130230557Sjimharris { 2131230557Sjimharris curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); 2132230557Sjimharris element = sci_fast_list_get_next(element); 2133230557Sjimharris 2134230557Sjimharris if ( curr_smp_phy->routing_attribute == SUBTRACTIVE_ROUTING_ATTRIBUTE 2135230557Sjimharris && ( curr_smp_phy->attached_device_type == SMP_EDGE_EXPANDER_DEVICE 2136230557Sjimharris || curr_smp_phy->attached_device_type == SMP_FANOUT_EXPANDER_DEVICE) 2137230557Sjimharris && curr_smp_phy->u.attached_phy != NULL 2138230557Sjimharris && curr_smp_phy->u.attached_phy->routing_attribute == TABLE_ROUTING_ATTRIBUTE ) 2139230557Sjimharris { 2140230557Sjimharris //set the current_activity and current_config_route_index for that 2141230557Sjimharris //upstream expander. 2142230557Sjimharris upstream_expander = curr_smp_phy->u.attached_phy->owning_device; 2143230557Sjimharris 2144230557Sjimharris upstream_expander->protocol_device.smp_device.current_smp_request = 2145230557Sjimharris SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION; 2146230557Sjimharris 2147230557Sjimharris //if the upstream_expander's config route table method is config phy0 only or 2148230557Sjimharris //config all phys, the current activity phy is found. 2149230557Sjimharris upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor = 2150230557Sjimharris scif_sas_smp_remote_device_find_smp_phy_by_id( 2151230557Sjimharris curr_smp_phy->u.attached_phy->phy_identifier, 2152230557Sjimharris &(curr_smp_phy->u.attached_phy->owning_device->protocol_device.smp_device) 2153230557Sjimharris ); 2154230557Sjimharris 2155230557Sjimharris //if the upstream_expander's config route table method is config middle phy only 2156230557Sjimharris //config highest phy only, the current activity phy needs a update. 2157230557Sjimharris if ( scif_sas_smp_remote_device_get_config_route_table_method(upstream_expander) 2158230557Sjimharris == SCIF_SAS_CONFIG_ROUTE_TABLE_MIDDLE_PHY_ONLY ) 2159230557Sjimharris { 2160230557Sjimharris upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor = 2161230557Sjimharris scif_sas_smp_phy_find_middle_phy_in_wide_port ( 2162230557Sjimharris upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor 2163230557Sjimharris ); 2164230557Sjimharris } 2165230557Sjimharris else if ( scif_sas_smp_remote_device_get_config_route_table_method(upstream_expander) 2166230557Sjimharris == SCIF_SAS_CONFIG_ROUTE_TABLE_HIGHEST_PHY_ONLY ) 2167230557Sjimharris { 2168230557Sjimharris upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor = 2169230557Sjimharris scif_sas_smp_phy_find_highest_phy_in_wide_port ( 2170230557Sjimharris upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor 2171230557Sjimharris ); 2172230557Sjimharris } 2173230557Sjimharris 2174230557Sjimharris upstream_expander->protocol_device.smp_device.current_activity_phy_index = 2175230557Sjimharris upstream_expander->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier; 2176230557Sjimharris 2177230557Sjimharris return upstream_expander; 2178230557Sjimharris } 2179230557Sjimharris } 2180230557Sjimharris 2181230557Sjimharris return NULL; 2182230557Sjimharris} 2183230557Sjimharris 2184230557Sjimharris 2185230557Sjimharris/** 2186230557Sjimharris * @brief This method finds the immediate downstream expander of a given expander device. 2187230557Sjimharris * 2188230557Sjimharris * @param[in] this_device The given expander device, whose downstream expander is to be found. 2189230557Sjimharris * 2190230557Sjimharris * @return The immediate downstream expander. Or a NULL pointer if there is none. 2191230557Sjimharris */ 2192230557SjimharrisSCIF_SAS_REMOTE_DEVICE_T * scif_sas_remote_device_find_downstream_expander( 2193230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * this_device 2194230557Sjimharris) 2195230557Sjimharris{ 2196230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_T * this_smp_remote_device = 2197230557Sjimharris &this_device->protocol_device.smp_device; 2198230557Sjimharris 2199230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * downstream_expander = NULL; 2200230557Sjimharris 2201230557Sjimharris SCI_FAST_LIST_ELEMENT_T * element = this_smp_remote_device->smp_phy_list.list_head; 2202230557Sjimharris SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; 2203230557Sjimharris 2204230557Sjimharris SCIF_LOG_TRACE(( 2205230557Sjimharris sci_base_object_get_logger(this_device), 2206230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2207230557Sjimharris "scif_sas_remote_device_find_downstream_expander(0x%x) enter\n", 2208230557Sjimharris this_device 2209230557Sjimharris )); 2210230557Sjimharris 2211230557Sjimharris while (element != NULL) 2212230557Sjimharris { 2213230557Sjimharris curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); 2214230557Sjimharris element = sci_fast_list_get_next(element); 2215230557Sjimharris 2216230557Sjimharris if ( curr_smp_phy->routing_attribute == TABLE_ROUTING_ATTRIBUTE 2217230557Sjimharris && curr_smp_phy->attached_device_type == SMP_EDGE_EXPANDER_DEVICE 2218230557Sjimharris && curr_smp_phy->u.attached_phy != NULL) 2219230557Sjimharris { 2220230557Sjimharris //set the current_activity and current_config_route_index for that 2221230557Sjimharris //upstream expander. 2222230557Sjimharris downstream_expander = curr_smp_phy->u.attached_phy->owning_device; 2223230557Sjimharris 2224230557Sjimharris if ( downstream_expander->protocol_device.smp_device.curr_config_route_destination_smp_phy != NULL 2225230557Sjimharris && downstream_expander->protocol_device.smp_device.curr_config_route_destination_smp_phy->owning_device == 2226230557Sjimharris this_smp_remote_device->curr_config_route_destination_smp_phy->owning_device ) 2227230557Sjimharris return downstream_expander; 2228230557Sjimharris } 2229230557Sjimharris } 2230230557Sjimharris 2231230557Sjimharris return NULL; 2232230557Sjimharris} 2233230557Sjimharris 2234230557Sjimharris 2235230557Sjimharris/** 2236230557Sjimharris * @brief This method follows route table optimization rule to check if a destination_device 2237230557Sjimharris * should be recorded in the device_being_config's route table 2238230557Sjimharris * 2239230557Sjimharris * @param[in] device_being_config The upstream expander device, whose route table is being configured. 2240230557Sjimharris * @param[in] destination_smp_phy A smp phy whose attached device is potentially to be 2241230557Sjimharris * recorded in route table. 2242230557Sjimharris * 2243230557Sjimharris * @return BOOL This method returns TRUE if a destination_device should be recorded in route table. 2244230557Sjimharris * This method returns FALSE if a destination_device need not to be recorded 2245230557Sjimharris * in route table. 2246230557Sjimharris */ 2247230557SjimharrisBOOL scif_sas_smp_remote_device_do_config_route_info( 2248230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * device_being_config, 2249230557Sjimharris SCIF_SAS_SMP_PHY_T * destination_smp_phy 2250230557Sjimharris) 2251230557Sjimharris{ 2252230557Sjimharris SCI_SAS_ADDRESS_T device_being_config_sas_address; 2253230557Sjimharris 2254230557Sjimharris SCIF_LOG_TRACE(( 2255230557Sjimharris sci_base_object_get_logger(device_being_config), 2256230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2257230557Sjimharris "scif_sas_smp_remote_device_do_config_route_info(0x%x, 0x%x) enter\n", 2258230557Sjimharris device_being_config, destination_smp_phy 2259230557Sjimharris )); 2260230557Sjimharris 2261230557Sjimharris scic_remote_device_get_sas_address( 2262230557Sjimharris device_being_config->core_object, &device_being_config_sas_address 2263230557Sjimharris ); 2264230557Sjimharris 2265230557Sjimharris //refer to SAS-2 spec 4.8.3, rule (b) 2266230557Sjimharris if ((destination_smp_phy->attached_sas_address.low == 0 2267230557Sjimharris && destination_smp_phy->attached_sas_address.high == 0) 2268230557Sjimharris && (destination_smp_phy->attached_device_type == SMP_NO_DEVICE_ATTACHED)) 2269230557Sjimharris { 2270230557Sjimharris return FALSE; 2271230557Sjimharris } 2272230557Sjimharris 2273230557Sjimharris //refer to SAS-2 spec 4.8.3, rule (c), self-referencing. 2274230557Sjimharris if (destination_smp_phy->attached_sas_address.high == 2275230557Sjimharris device_being_config_sas_address.high 2276230557Sjimharris && destination_smp_phy->attached_sas_address.low == 2277230557Sjimharris device_being_config_sas_address.low) 2278230557Sjimharris { 2279230557Sjimharris return FALSE; 2280230557Sjimharris } 2281230557Sjimharris 2282230557Sjimharris //There will be no cases that falling into rule (a), (d), (e) to be excluded, 2283230557Sjimharris //based on our current mechanism of cofig route table. 2284230557Sjimharris 2285230557Sjimharris return TRUE; 2286230557Sjimharris} 2287230557Sjimharris 2288230557Sjimharris 2289230557Sjimharris/** 2290230557Sjimharris * @brief This method configures device_being_config's route table for all the enclosed devices in 2291230557Sjimharris * a downstream smp device, destination_device. 2292230557Sjimharris * 2293230557Sjimharris * @param[in] device_being_config The upstream expander device, whose route table is being configured. 2294230557Sjimharris * 2295230557Sjimharris * @return None 2296230557Sjimharris */ 2297230557Sjimharrisvoid scif_sas_smp_remote_device_configure_route_table( 2298230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * device_being_config 2299230557Sjimharris) 2300230557Sjimharris{ 2301230557Sjimharris //go through the smp phy list of this_device. 2302230557Sjimharris SCI_FAST_LIST_ELEMENT_T * element = 2303230557Sjimharris &(device_being_config->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element); 2304230557Sjimharris SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; 2305230557Sjimharris 2306230557Sjimharris SCIF_LOG_TRACE(( 2307230557Sjimharris sci_base_object_get_logger(device_being_config), 2308230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2309230557Sjimharris "scif_sas_smp_remote_device_configure_route_table(0x%x) enter\n", 2310230557Sjimharris device_being_config 2311230557Sjimharris )); 2312230557Sjimharris 2313230557Sjimharris device_being_config->protocol_device.smp_device.current_activity = 2314230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE; 2315230557Sjimharris 2316230557Sjimharris while (element != NULL) 2317230557Sjimharris { 2318230557Sjimharris curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); 2319230557Sjimharris element = sci_fast_list_get_next(element); 2320230557Sjimharris 2321230557Sjimharris //check if this phy needs to be added to the expander's route table. 2322230557Sjimharris if (scif_sas_smp_remote_device_do_config_route_info( 2323230557Sjimharris device_being_config, curr_smp_phy) == TRUE ) 2324230557Sjimharris { 2325230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device = 2326230557Sjimharris &device_being_config->protocol_device.smp_device; 2327230557Sjimharris 2328230557Sjimharris smp_remote_device->curr_config_route_destination_smp_phy = 2329230557Sjimharris curr_smp_phy; 2330230557Sjimharris 2331230557Sjimharris //Then config this_device's route table entry at the phy and next route_index. 2332230557Sjimharris //send config_route_info using curr_smp_phy.phy_identifier and sas_address. 2333230557Sjimharris scif_sas_smp_request_construct_config_route_info( 2334230557Sjimharris device_being_config->domain->controller, 2335230557Sjimharris device_being_config, 2336230557Sjimharris smp_remote_device->current_activity_phy_index, 2337230557Sjimharris smp_remote_device->curr_config_route_index, 2338230557Sjimharris curr_smp_phy->attached_sas_address, 2339230557Sjimharris FALSE 2340230557Sjimharris ); 2341230557Sjimharris 2342230557Sjimharris //schedule the DPC. 2343230557Sjimharris scif_cb_start_internal_io_task_schedule( 2344230557Sjimharris device_being_config->domain->controller, 2345230557Sjimharris scif_sas_controller_start_high_priority_io, 2346230557Sjimharris device_being_config->domain->controller 2347230557Sjimharris ); 2348230557Sjimharris 2349230557Sjimharris //stop here, we need to wait for config route info's response then send 2350230557Sjimharris //the next one. 2351230557Sjimharris break; 2352230557Sjimharris } 2353230557Sjimharris } 2354230557Sjimharris} 2355230557Sjimharris 2356230557Sjimharris 2357230557Sjimharris/** 2358230557Sjimharris * @brief This method walks through an expander's route table to clean table 2359230557Sjimharris * attribute phys' route entries. This routine finds one table entry 2360230557Sjimharris * to clean and will be called repeatly till it finishes cleanning the 2361230557Sjimharris * whole table. 2362230557Sjimharris * 2363230557Sjimharris * @param[in] fw_device The expander device, whose route table entry is to be cleaned. 2364230557Sjimharris * 2365230557Sjimharris * @return None. 2366230557Sjimharris */ 2367230557Sjimharrisvoid scif_sas_smp_remote_device_clean_route_table( 2368230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 2369230557Sjimharris) 2370230557Sjimharris{ 2371231137Sjimharris SCIF_SAS_SMP_PHY_T * smp_phy_being_config; 2372230557Sjimharris 2373230557Sjimharris SCIF_LOG_TRACE(( 2374230557Sjimharris sci_base_object_get_logger(fw_device), 2375230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2376230557Sjimharris "scif_sas_smp_remote_device_clean_route_table(0x%x) enter\n", 2377230557Sjimharris fw_device 2378230557Sjimharris )); 2379230557Sjimharris 2380230557Sjimharris //from anchors, start to clean all the other route table entries. 2381230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index++; 2382230557Sjimharris 2383230557Sjimharris if ( fw_device->protocol_device.smp_device.curr_config_route_index >= 2384230557Sjimharris fw_device->protocol_device.smp_device.expander_route_indexes ) 2385230557Sjimharris { 2386230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index = 0; 2387230557Sjimharris 2388230557Sjimharris do //find next table attribute PHY. 2389230557Sjimharris { 2390230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index++; 2391230557Sjimharris if (fw_device->protocol_device.smp_device.current_activity_phy_index == 2392230557Sjimharris fw_device->protocol_device.smp_device.number_of_phys) 2393230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index=0; 2394230557Sjimharris 2395230557Sjimharris //phy_index changed, so update the smp_phy_being_config. 2396230557Sjimharris smp_phy_being_config = 2397230557Sjimharris scif_sas_smp_remote_device_find_smp_phy_by_id( 2398230557Sjimharris fw_device->protocol_device.smp_device.current_activity_phy_index, 2399230557Sjimharris &(fw_device->protocol_device.smp_device) 2400230557Sjimharris ); 2401230557Sjimharris } while( smp_phy_being_config->routing_attribute != TABLE_ROUTING_ATTRIBUTE ); 2402230557Sjimharris 2403230557Sjimharris if ( smp_phy_being_config->phy_identifier != 2404230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier) 2405230557Sjimharris { 2406230557Sjimharris if (smp_phy_being_config->config_route_table_index_anchor != 0) 2407230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index = 2408230557Sjimharris smp_phy_being_config->config_route_table_index_anchor + 1; 2409230557Sjimharris else 2410230557Sjimharris fw_device->protocol_device.smp_device.curr_config_route_index = 0; 2411230557Sjimharris } 2412230557Sjimharris } 2413230557Sjimharris 2414230557Sjimharris if ( !(fw_device->protocol_device.smp_device.current_activity_phy_index == 2415230557Sjimharris fw_device->protocol_device.smp_device.config_route_smp_phy_anchor->phy_identifier 2416230557Sjimharris && fw_device->protocol_device.smp_device.curr_config_route_index == 0) 2417230557Sjimharris ) 2418230557Sjimharris { 2419230557Sjimharris //clean this route entry. 2420230557Sjimharris scif_sas_smp_remote_device_clean_route_table_entry(fw_device); 2421230557Sjimharris } 2422230557Sjimharris else 2423230557Sjimharris { 2424230557Sjimharris fw_device->protocol_device.smp_device.is_route_table_cleaned = TRUE; 2425230557Sjimharris 2426230557Sjimharris //set this device's activity to NON. 2427230557Sjimharris fw_device->protocol_device.smp_device.current_activity = 2428230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_NONE; 2429230557Sjimharris 2430230557Sjimharris //we need to notify domain that this device finished config route table, domain 2431230557Sjimharris //may pick up other activities (i.e. Discover) for other expanders. 2432230557Sjimharris scif_sas_domain_continue_discover(fw_device->domain); 2433230557Sjimharris } 2434230557Sjimharris} 2435230557Sjimharris 2436230557Sjimharris/** 2437230557Sjimharris * @brief This method cleans a device's route table antry. 2438230557Sjimharris * 2439230557Sjimharris * @param[in] fw_device The expander device, whose route table entry is to be cleaned. 2440230557Sjimharris * 2441230557Sjimharris * @return None. 2442230557Sjimharris */ 2443230557Sjimharrisvoid scif_sas_smp_remote_device_clean_route_table_entry( 2444230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 2445230557Sjimharris) 2446230557Sjimharris{ 2447230557Sjimharris SCI_SAS_ADDRESS_T empty_sas_address; 2448230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_T * smp_remote_device = 2449230557Sjimharris &(fw_device->protocol_device.smp_device); 2450230557Sjimharris 2451230557Sjimharris SCIF_LOG_TRACE(( 2452230557Sjimharris sci_base_object_get_logger(fw_device), 2453230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2454230557Sjimharris "scif_sas_smp_remote_device_clean_route_table(0x%x) enter\n", 2455230557Sjimharris fw_device 2456230557Sjimharris )); 2457230557Sjimharris 2458230557Sjimharris empty_sas_address.high = 0; 2459230557Sjimharris empty_sas_address.low = 0; 2460230557Sjimharris 2461230557Sjimharris scif_sas_smp_request_construct_config_route_info( 2462230557Sjimharris fw_device->domain->controller, 2463230557Sjimharris fw_device, 2464230557Sjimharris smp_remote_device->current_activity_phy_index, 2465230557Sjimharris smp_remote_device->curr_config_route_index, 2466230557Sjimharris empty_sas_address, 2467230557Sjimharris TRUE 2468230557Sjimharris ); 2469230557Sjimharris 2470230557Sjimharris //schedule the DPC. 2471230557Sjimharris scif_cb_start_internal_io_task_schedule( 2472230557Sjimharris fw_device->domain->controller, 2473230557Sjimharris scif_sas_controller_start_high_priority_io, 2474230557Sjimharris fw_device->domain->controller 2475230557Sjimharris ); 2476230557Sjimharris} 2477230557Sjimharris 2478230557Sjimharris 2479230557Sjimharris/** 2480230557Sjimharris * @brief This method handles the case of exceeding route index when config route table 2481230557Sjimharris * for a device, by removing the attached device of current config route 2482230557Sjimharris * destination smp phy and the rest of smp phys in the same smp phy list. 2483230557Sjimharris * 2484230557Sjimharris * @param[in] fw_device The expander device, whose route table to be edited but failed 2485230557Sjimharris * with a SMP function result of INDEX DOES NOT EXIST. 2486230557Sjimharris * 2487230557Sjimharris * @return None. 2488230557Sjimharris */ 2489230557Sjimharrisvoid scif_sas_smp_remote_device_cancel_config_route_table_activity( 2490230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 2491230557Sjimharris) 2492230557Sjimharris{ 2493230557Sjimharris //go through the rest of the smp phy list of destination device. 2494230557Sjimharris SCI_FAST_LIST_ELEMENT_T * element = 2495230557Sjimharris &(fw_device->protocol_device.smp_device.curr_config_route_destination_smp_phy->list_element); 2496230557Sjimharris SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; 2497230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * curr_attached_device = NULL; 2498230557Sjimharris 2499230557Sjimharris SCIF_LOG_TRACE(( 2500230557Sjimharris sci_base_object_get_logger(fw_device), 2501230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2502230557Sjimharris "scif_sas_smp_remote_device_cancel_config_route_table_activity(0x%x) enter\n", 2503230557Sjimharris fw_device 2504230557Sjimharris )); 2505230557Sjimharris 2506230557Sjimharris while (element != NULL) 2507230557Sjimharris { 2508230557Sjimharris curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); 2509230557Sjimharris element = sci_fast_list_get_next(element); 2510230557Sjimharris 2511230557Sjimharris //check if this phy needs to be added to the expander's route table but can't due to 2512230557Sjimharris //exceeding max route index. 2513230557Sjimharris if (scif_sas_smp_remote_device_do_config_route_info( 2514230557Sjimharris fw_device, curr_smp_phy) == TRUE ) 2515230557Sjimharris { 2516230557Sjimharris //set the is_currently_discovered to FALSE for attached device. Then when 2517230557Sjimharris //domain finish discover, domain will remove this device. 2518230557Sjimharris curr_attached_device = (SCIF_SAS_REMOTE_DEVICE_T *) 2519230557Sjimharris scif_domain_get_device_by_sas_address( 2520230557Sjimharris fw_device->domain, &(curr_smp_phy->attached_sas_address)); 2521230557Sjimharris 2522230557Sjimharris if (curr_attached_device != NULL) 2523230557Sjimharris curr_attached_device->is_currently_discovered = FALSE; 2524230557Sjimharris } 2525230557Sjimharris } 2526230557Sjimharris} 2527230557Sjimharris 2528230557Sjimharris 2529230557Sjimharris/** 2530230557Sjimharris * @brief This method cancel current activity and terminate the outstanding internal IO 2531230557Sjimharris * if there is one. 2532230557Sjimharris * 2533230557Sjimharris * @param[in] fw_device The expander device, whose smp activity is to be canceled. 2534230557Sjimharris * 2535230557Sjimharris * @return None. 2536230557Sjimharris */ 2537230557Sjimharrisvoid scif_sas_smp_remote_device_cancel_smp_activity( 2538230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 2539230557Sjimharris) 2540230557Sjimharris{ 2541230557Sjimharris SCIF_LOG_TRACE(( 2542230557Sjimharris sci_base_object_get_logger(fw_device), 2543230557Sjimharris SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 2544230557Sjimharris "scif_sas_smp_remote_device_cancel_smp_activity(0x%x) enter\n", 2545230557Sjimharris fw_device 2546230557Sjimharris )); 2547230557Sjimharris 2548230557Sjimharris //Terminate all of the requests in the silicon for this device. 2549230557Sjimharris scif_sas_domain_terminate_requests( 2550230557Sjimharris fw_device->domain, fw_device, NULL, NULL 2551230557Sjimharris ); 2552230557Sjimharris 2553230557Sjimharris if (fw_device->protocol_device.smp_device.current_activity == 2554230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_CONFIG_ROUTE_TABLE) 2555230557Sjimharris scif_sas_smp_remote_device_cancel_config_route_table_activity(fw_device); 2556230557Sjimharris 2557230557Sjimharris //Clear the device to stop the smp sctivity. 2558230557Sjimharris scif_sas_smp_remote_device_clear(fw_device); 2559230557Sjimharris} 2560230557Sjimharris 2561230557Sjimharris 2562230557Sjimharris/** 2563230557Sjimharris * @brief This method tells the way to configure route table for a expander. The 2564230557Sjimharris * possible ways are: configure phy 0's route table, configure middle 2565230557Sjimharris * phy's route table, configure highest order phy's route table, 2566230557Sjimharris * configure all phys. 2567230557Sjimharris * 2568230557Sjimharris * @param[in] fw_device The expander device, whose config route table method is 2569230557Sjimharris * to be chosen. 2570230557Sjimharris * 2571230557Sjimharris * @return one in 4 possible options. 2572230557Sjimharris */ 2573230557SjimharrisU8 scif_sas_smp_remote_device_get_config_route_table_method( 2574230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * fw_device 2575230557Sjimharris) 2576230557Sjimharris{ 2577230557Sjimharris U8 config_route_table_method; 2578230557Sjimharris 2579230557Sjimharris //config_route_table_method = SCIF_SAS_CONFIG_ROUTE_TABLE_MIDDLE_PHY_ONLY; 2580230557Sjimharris config_route_table_method = SCIF_SAS_CONFIG_ROUTE_TABLE_ALL_PHYS; 2581230557Sjimharris 2582230557Sjimharris return config_route_table_method; 2583230557Sjimharris} 2584230557Sjimharris 2585230557Sjimharris 2586230557Sjimharris/** 2587230557Sjimharris * @brief This method starts the EA target reset process by constructing 2588230557Sjimharris * and starting a PHY CONTROL (hard reset) smp request. 2589230557Sjimharris * 2590230557Sjimharris * @param[in] expander_device The expander device, to which a PHY Control smp command is 2591230557Sjimharris * sent. 2592230557Sjimharris * @param[in] target_device The expander attahced target device, to which the target reset 2593230557Sjimharris * request is sent. 2594230557Sjimharris * @param[in] fw_request The target reset task request. 2595230557Sjimharris * 2596230557Sjimharris * @return none 2597230557Sjimharris */ 2598230557Sjimharrisvoid scif_sas_smp_remote_device_start_target_reset( 2599230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * expander_device, 2600230557Sjimharris SCIF_SAS_REMOTE_DEVICE_T * target_device, 2601230557Sjimharris SCIF_SAS_REQUEST_T * fw_request 2602230557Sjimharris) 2603230557Sjimharris{ 2604230557Sjimharris SCIF_SAS_CONTROLLER_T * fw_controller = expander_device->domain->controller; 2605230557Sjimharris 2606230557Sjimharris //set current_activity and current_smp_request to expander device. 2607230557Sjimharris expander_device->protocol_device.smp_device.current_activity = 2608230557Sjimharris SCIF_SAS_SMP_REMOTE_DEVICE_ACTIVITY_TARGET_RESET; 2609230557Sjimharris expander_device->protocol_device.smp_device.current_smp_request = 2610230557Sjimharris SMP_FUNCTION_PHY_CONTROL; 2611230557Sjimharris expander_device->protocol_device.smp_device.current_activity_phy_index = 2612230557Sjimharris target_device->expander_phy_identifier; 2613230557Sjimharris 2614230557Sjimharris //A Phy Control smp request has been constructed towards parent device. 2615230557Sjimharris //Walk the high priority io path. 2616230557Sjimharris fw_controller->state_handlers->start_high_priority_io_handler( 2617230557Sjimharris (SCI_BASE_CONTROLLER_T*) fw_controller, 2618230557Sjimharris (SCI_BASE_REMOTE_DEVICE_T*) expander_device, 2619230557Sjimharris (SCI_BASE_REQUEST_T*) fw_request, 2620230557Sjimharris SCI_CONTROLLER_INVALID_IO_TAG 2621230557Sjimharris ); 2622230557Sjimharris} 2623230557Sjimharris 2624230557Sjimharris 2625