1108684Sphk/*- 2108684Sphk * This file is provided under a dual BSD/GPLv2 license. When using or 3108684Sphk * redistributing this file, you may do so under either license. 4108684Sphk * 5108684Sphk * GPL LICENSE SUMMARY 6108684Sphk * 7108684Sphk * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8108684Sphk * 9108684Sphk * This program is free software; you can redistribute it and/or modify 10108684Sphk * it under the terms of version 2 of the GNU General Public License as 11108684Sphk * published by the Free Software Foundation. 12108684Sphk * 13108684Sphk * This program is distributed in the hope that it will be useful, but 14108684Sphk * WITHOUT ANY WARRANTY; without even the implied warranty of 15108684Sphk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16108684Sphk * General Public License for more details. 17108684Sphk * 18108684Sphk * You should have received a copy of the GNU General Public License 19108684Sphk * along with this program; if not, write to the Free Software 20108684Sphk * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21108684Sphk * The full GNU General Public License is included in this distribution 22108684Sphk * in the file called LICENSE.GPL. 23108684Sphk * 24108684Sphk * BSD LICENSE 25108684Sphk * 26108684Sphk * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27108684Sphk * All rights reserved. 28108684Sphk * 29108684Sphk * Redistribution and use in source and binary forms, with or without 30108684Sphk * modification, are permitted provided that the following conditions 31108684Sphk * are met: 32108684Sphk * 33108684Sphk * * Redistributions of source code must retain the above copyright 34108684Sphk * notice, this list of conditions and the following disclaimer. 35108684Sphk * * Redistributions in binary form must reproduce the above copyright 36108684Sphk * notice, this list of conditions and the following disclaimer in 37108684Sphk * the documentation and/or other materials provided with the 38126775Sdwmalone * distribution. 39108684Sphk * 40175239Sdelphij * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41247036Smelifaro * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42108684Sphk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43108684Sphk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44108684Sphk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45108684Sphk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46108684Sphk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47226396Sed * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48108684Sphk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49108684Sphk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50158161Sbde * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51108684Sphk */ 52108684Sphk 53108684Sphk#include <sys/cdefs.h> 54108684Sphk__FBSDID("$FreeBSD$"); 55126775Sdwmalone 56126775Sdwmalone/** 57126775Sdwmalone * @file 58126775Sdwmalone * 59126775Sdwmalone * @brief This file contains the method implementations for the 60126775Sdwmalone * SCIF_SAS_SMP_IO_REQUEST object. The contents will implement SMP 61108684Sphk * specific functionality. 62158161Sbde */ 63108684Sphk 64108684Sphk#include <dev/isci/scil/scif_sas_smp_io_request.h> 65108684Sphk#include <dev/isci/scil/scif_sas_logger.h> 66108684Sphk#include <dev/isci/scil/scif_sas_controller.h> 67108684Sphk#include <dev/isci/scil/sci_controller.h> 68108684Sphk 69108684Sphk#include <dev/isci/scil/sci_status.h> 70108684Sphk#include <dev/isci/scil/scic_io_request.h> 71279473Srstone#include <dev/isci/scil/scic_user_callback.h> 72279473Srstone 73279473Srstone#include <dev/isci/scil/intel_sas.h> 74279473Srstone 75279473Srstone/** 76279473Srstone * @brief This routine is to fill in the space given by core the SMP command 77279473Srstone * frame. Then it calls core's construction. 78279473Srstone * 79108684Sphk * @param[in] fw_io The smp io request to be constructed. 80108684Sphk * @param[in] smp_command The SMP request filled according to SAS spec. 81108684Sphk * 82247036Smelifaro * @return none 83108684Sphk */ 84108684Sphkvoid scif_sas_smp_request_construct( 85247036Smelifaro SCIF_SAS_REQUEST_T * fw_request, 86247036Smelifaro SMP_REQUEST_T * smp_command 87247036Smelifaro) 88247036Smelifaro{ 89108684Sphk void * command_iu_address = 90247036Smelifaro scic_io_request_get_command_iu_address(fw_request->core_object); 91247036Smelifaro 92164677Syar //copy the smp_command to the address; 93108684Sphk memcpy( (char*) command_iu_address, 94108684Sphk smp_command, 95108684Sphk sizeof(SMP_REQUEST_T) 96108684Sphk ); 97108684Sphk 98231011Sed scic_io_request_construct_smp(fw_request->core_object); 99108684Sphk 100108684Sphk fw_request->protocol_complete_handler 101108684Sphk = NULL; 102108684Sphk} 103158160Sbde 104108684Sphk/** 105108684Sphk * @brief This method will perform all of the construction common to all 106108684Sphk * SMP requests (e.g. filling in the frame type, zero-out memory, 107158160Sbde * etc.). 108158160Sbde * 109158160Sbde * @param[out] smp_request This parameter specifies the SMP request 110247036Smelifaro * structure containing the SMP request to be sent to the 111247036Smelifaro * SMP target. 112247036Smelifaro * @param[in] smp_function This parameter specifies the SMP function to 113247036Smelifaro * sent. 114247036Smelifaro * @param[in] smp_response_length This parameter specifies the length of 115247036Smelifaro * the response (in DWORDs) that will be returned for this 116247036Smelifaro * SMP request. 117247036Smelifaro * @param[in] smp_request_length This parameter specifies the length of 118247036Smelifaro * the request (in DWORDs) that will be sent. 119247036Smelifaro */ 120108684Sphkstatic 121108684Sphkvoid scif_sas_smp_protocol_request_construct( 122108684Sphk SMP_REQUEST_T * smp_request, 123108684Sphk U8 smp_function, 124108684Sphk U8 smp_response_length, 125108684Sphk U8 smp_request_length 126247036Smelifaro) 127247036Smelifaro{ 128247036Smelifaro memset((char*)smp_request, 0, sizeof(SMP_REQUEST_T)); 129247036Smelifaro 130247036Smelifaro smp_request->header.smp_frame_type = SMP_FRAME_TYPE_REQUEST; 131247036Smelifaro smp_request->header.function = smp_function; 132247036Smelifaro smp_request->header.allocated_response_length = smp_response_length; 133247036Smelifaro smp_request->header.request_length = smp_request_length; 134247036Smelifaro} 135247036Smelifaro 136247036Smelifaro 137247036Smelifaro/** 138108684Sphk * @brief This method will allocate the internal IO request object and 139108684Sphk * construct its contents based upon the supplied SMP request. 140108684Sphk * 141226396Sed * @param[in] fw_controller This parameter specifies the controller object 142247036Smelifaro * from which to allocate the internal IO request. 143247036Smelifaro * @param[in] fw_device This parameter specifies the remote device for 144247036Smelifaro * which the internal IO request is destined. 145247036Smelifaro * @param[in] smp_request This parameter specifies the SMP request contents 146247036Smelifaro * to be sent to the SMP target. 147247036Smelifaro * 148247036Smelifaro * @return void * The address of built scif sas smp request. 149247036Smelifaro */ 150247036Smelifarostatic 151247036Smelifarovoid * scif_sas_smp_request_build( 152108684Sphk SCIF_SAS_CONTROLLER_T * fw_controller, 153108684Sphk SCIF_SAS_REMOTE_DEVICE_T * fw_device, 154108684Sphk SMP_REQUEST_T * smp_request, 155108684Sphk void * external_request_object, 156108684Sphk void * external_memory 157108684Sphk) 158108684Sphk{ 159108684Sphk if (external_memory != NULL && external_request_object != NULL) 160108684Sphk { 161108684Sphk scif_sas_io_request_construct_smp( 162108684Sphk fw_controller, 163108684Sphk fw_device, 164108684Sphk external_memory, 165108684Sphk (char *)external_memory + sizeof(SCIF_SAS_IO_REQUEST_T), 166108684Sphk SCI_CONTROLLER_INVALID_IO_TAG, 167108684Sphk smp_request, 168108684Sphk external_request_object 169108684Sphk ); 170108684Sphk 171108684Sphk return external_memory; 172108684Sphk } 173158160Sbde else 174108684Sphk { 175108684Sphk void * internal_io_memory; 176108684Sphk internal_io_memory = scif_sas_controller_allocate_internal_request(fw_controller); 177108684Sphk ASSERT(internal_io_memory != NULL); 178108684Sphk 179108684Sphk if (internal_io_memory != NULL) 180108684Sphk { 181108684Sphk //construct, only when we got valid io memory. 182108684Sphk scif_sas_internal_io_request_construct_smp( 183108684Sphk fw_controller, 184108684Sphk fw_device, 185108684Sphk internal_io_memory, 186108684Sphk SCI_CONTROLLER_INVALID_IO_TAG, 187108684Sphk smp_request 188108684Sphk ); 189108684Sphk } 190108684Sphk else 191108684Sphk { 192108684Sphk SCIF_LOG_ERROR(( 193108684Sphk sci_base_object_get_logger(fw_controller), 194108684Sphk SCIF_LOG_OBJECT_IO_REQUEST, 195108684Sphk "scif_sas_smp_request_build, no memory available!\n" 196108684Sphk )); 197108684Sphk } 198108684Sphk 199108684Sphk return internal_io_memory; 200108684Sphk } 201108684Sphk} 202108684Sphk 203108684Sphk/** 204108684Sphk * @brief construct a smp Report Genernal command to the fw_device. 205108684Sphk * 206108684Sphk * @param[in] fw_controller The framework controller object. 207108684Sphk * @param[in] fw_device the framework device that the REPORT GENERAL command 208108684Sphk * targets to. 209108684Sphk * 210108684Sphk * @return void * address to the built scif sas smp request. 211247036Smelifaro */ 212108684Sphkvoid * scif_sas_smp_request_construct_report_general( 213247036Smelifaro SCIF_SAS_CONTROLLER_T * fw_controller, 214247036Smelifaro SCIF_SAS_REMOTE_DEVICE_T * fw_device 215108684Sphk) 216108684Sphk{ 217108684Sphk SMP_REQUEST_T smp_report_general; 218108684Sphk 219108684Sphk // Build the REPORT GENERAL request. 220108684Sphk scif_sas_smp_protocol_request_construct( 221108684Sphk &smp_report_general, 222108684Sphk SMP_FUNCTION_REPORT_GENERAL, 223108684Sphk sizeof(SMP_RESPONSE_REPORT_GENERAL_T) / sizeof(U32), 224108684Sphk 0 225158161Sbde ); 226108684Sphk 227108684Sphk smp_report_general.request.report_general.crc = 0; 228108684Sphk 229108684Sphk SCIF_LOG_INFO(( 230108684Sphk sci_base_object_get_logger(fw_device), 231108684Sphk SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 232108684Sphk "SMP REPORT GENERAL - Device:0x%x\n", 233247037Smelifaro fw_device 234108684Sphk )); 235108684Sphk 236108684Sphk return scif_sas_smp_request_build( 237108684Sphk fw_controller, fw_device, &smp_report_general, NULL, NULL); 238175239Sdelphij} 239108684Sphk 240108684Sphk/** 241108684Sphk * @brief construct a SMP Report Manufacturer Info request to the fw_device. 242108684Sphk * 243108684Sphk * @param[in] fw_controller The framework controller object. 244108684Sphk * @param[in] fw_device the framework device that the REPORT MANUFACTURER 245247036Smelifaro * INFO targets to. 246108684Sphk * 247158161Sbde * @return void * address to the built scif sas smp request. 248108684Sphk */ 249108684Sphkvoid * scif_sas_smp_request_construct_report_manufacturer_info( 250108684Sphk SCIF_SAS_CONTROLLER_T * fw_controller, 251108684Sphk SCIF_SAS_REMOTE_DEVICE_T * fw_device 252108684Sphk) 253108684Sphk{ 254108684Sphk SMP_REQUEST_T smp_report_manufacturer_info; 255108684Sphk 256108684Sphk scif_sas_smp_protocol_request_construct( 257247037Smelifaro &smp_report_manufacturer_info, 258108684Sphk SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION, 259108684Sphk sizeof(SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T) / sizeof(U32), 260108684Sphk 0 261108684Sphk ); 262108684Sphk 263108684Sphk smp_report_manufacturer_info.request.report_general.crc = 0; 264108684Sphk 265108684Sphk SCIF_LOG_INFO(( 266279473Srstone sci_base_object_get_logger(fw_device), 267279473Srstone SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 268108684Sphk "SMP REPORT MANUFACTURER_INFO - Device:0x%x\n", 269108684Sphk fw_device 270158161Sbde )); 271108684Sphk 272108684Sphk return scif_sas_smp_request_build( 273108684Sphk fw_controller, fw_device, &smp_report_manufacturer_info, NULL, NULL 274158161Sbde ); 275108684Sphk} 276247036Smelifaro 277247036Smelifaro/** 278108684Sphk * @brief construct a smp Discover command to the fw_device. 279108684Sphk * @param[in] fw_controller The framework controller object. 280239991Sed * @param[in] fw_device the framework smp device that DISCOVER command targets 281108684Sphk * to. 282108684Sphk * @param[in] phy_identifier The phy index the DISCOVER command targets to. 283226396Sed * 284226396Sed * @return void * address to the built scif sas smp request. 285247036Smelifaro */ 286247036Smelifarovoid * scif_sas_smp_request_construct_discover( 287108684Sphk SCIF_SAS_CONTROLLER_T * fw_controller, 288108684Sphk SCIF_SAS_REMOTE_DEVICE_T * fw_device, 289108684Sphk U8 phy_identifier, 290108684Sphk void * external_request_object, 291247036Smelifaro void * external_memory 292158161Sbde) 293108684Sphk{ 294108684Sphk SMP_REQUEST_T smp_discover; 295108684Sphk 296108684Sphk scif_sas_smp_protocol_request_construct( 297108684Sphk &smp_discover, 298108684Sphk SMP_FUNCTION_DISCOVER, 299226396Sed sizeof(SMP_RESPONSE_DISCOVER_T) / sizeof(U32), 300226396Sed sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32) 301226396Sed ); 302108684Sphk 303108684Sphk smp_discover.request.discover.phy_identifier = phy_identifier; 304108684Sphk 305108684Sphk SCIF_LOG_INFO(( 306247036Smelifaro sci_base_object_get_logger(fw_device), 307247036Smelifaro SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 308247036Smelifaro "SMP DISCOVER - Device:0x%x PhyId:0x%x\n", 309108684Sphk fw_device, phy_identifier 310108684Sphk )); 311108684Sphk 312108684Sphk return scif_sas_smp_request_build( 313108684Sphk fw_controller, fw_device, &smp_discover, 314226396Sed external_request_object, external_memory 315226396Sed ); 316247036Smelifaro} 317247036Smelifaro 318108684Sphk 319108684Sphk/** 320108684Sphk * @brief construct a smp REPORT PHY SATA command to the fw_device. 321108684Sphk * @param[in] fw_controller The framework controller object. 322108684Sphk * @param[in] fw_device the framework smp device that DISCOVER command targets 323108684Sphk * to. 324108684Sphk * @param[in] phy_identifier The phy index the DISCOVER command targets to. 325247036Smelifaro * 326247036Smelifaro * @return void * address to the built scif sas smp request. 327247036Smelifaro */ 328247036Smelifarovoid * scif_sas_smp_request_construct_report_phy_sata( 329247036Smelifaro SCIF_SAS_CONTROLLER_T * fw_controller, 330247036Smelifaro SCIF_SAS_REMOTE_DEVICE_T * fw_device, 331108684Sphk U8 phy_identifier 332108684Sphk) 333108684Sphk{ 334108684Sphk SMP_REQUEST_T report_phy_sata; 335108684Sphk 336247036Smelifaro scif_sas_smp_protocol_request_construct( 337108684Sphk &report_phy_sata, 338108684Sphk SMP_FUNCTION_REPORT_PHY_SATA, 339108684Sphk sizeof(SMP_RESPONSE_REPORT_PHY_SATA_T) / sizeof(U32), 340108684Sphk sizeof(SMP_REQUEST_PHY_IDENTIFIER_T) / sizeof(U32) 341108684Sphk ); 342158161Sbde 343108684Sphk report_phy_sata.request.report_phy_sata.phy_identifier = phy_identifier; 344108684Sphk 345108684Sphk SCIF_LOG_INFO(( 346108684Sphk sci_base_object_get_logger(fw_device), 347164677Syar SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 348108684Sphk "SMP REPORT PHY SATA - Device:0x%x PhyId:0x%x\n", 349108684Sphk fw_device, phy_identifier 350108684Sphk )); 351108684Sphk 352108684Sphk return scif_sas_smp_request_build( 353108684Sphk fw_controller, fw_device, &report_phy_sata, NULL, NULL); 354108684Sphk} 355108684Sphk 356108684Sphk 357108684Sphk/** 358108684Sphk * @brief construct a smp REPORT PHY SATA command to the fw_device. 359164677Syar * @param[in] fw_controller The framework controller object. 360108684Sphk * @param[in] fw_device the framework smp device that PHY CONTROL command 361108684Sphk * targets to. 362108684Sphk * @param[in] phy_identifier The phy index the DISCOVER command targets to. 363108684Sphk * 364108684Sphk * @return void * address to the built scif sas smp request. 365108684Sphk */ 366108684Sphkvoid * scif_sas_smp_request_construct_phy_control( 367108684Sphk SCIF_SAS_CONTROLLER_T * fw_controller, 368108684Sphk SCIF_SAS_REMOTE_DEVICE_T * fw_device, 369247036Smelifaro U8 phy_operation, 370247036Smelifaro U8 phy_identifier, 371247036Smelifaro void * external_request_object, 372247036Smelifaro void * external_memory 373247036Smelifaro) 374247036Smelifaro{ 375247037Smelifaro SMP_REQUEST_T phy_control; 376247037Smelifaro 377247037Smelifaro scif_sas_smp_protocol_request_construct( 378247036Smelifaro &phy_control, 379247036Smelifaro SMP_FUNCTION_PHY_CONTROL, 380247036Smelifaro 0, 381247036Smelifaro sizeof(SMP_REQUEST_PHY_CONTROL_T) / sizeof(U32) 382247036Smelifaro ); 383247036Smelifaro 384247036Smelifaro phy_control.request.phy_control.phy_operation = phy_operation; 385247036Smelifaro phy_control.request.phy_control.phy_identifier = phy_identifier; 386247036Smelifaro 387247036Smelifaro return scif_sas_smp_request_build( 388247036Smelifaro fw_controller, fw_device, &phy_control, 389247036Smelifaro external_request_object, external_memory 390247037Smelifaro ); 391247036Smelifaro} 392247036Smelifaro 393247036Smelifaro 394247036Smelifaro/** 395247036Smelifaro * @brief construct a smp CONFIG ROUTE INFO command to the fw_device. 396247036Smelifaro * 397247036Smelifaro * @param[in] fw_controller The framework controller object. 398247036Smelifaro * @param[in] fw_device the framework smp device that PHY CONTROL command 399247036Smelifaro * targets to. 400247037Smelifaro * @param[in] phy_id The phy, whose route entry at route_index is to be configured. 401247036Smelifaro * @param[in] route_index The index of a phy's route entry that is to be configured. 402247036Smelifaro * @param[in] destination_sas_address A sas address for an route table entry 403108684Sphk * 404108684Sphk * @return void * address to the built scif sas smp request. 405108684Sphk */ 406108684Sphkvoid * scif_sas_smp_request_construct_config_route_info( 407108684Sphk struct SCIF_SAS_CONTROLLER * fw_controller, 408108684Sphk struct SCIF_SAS_REMOTE_DEVICE * fw_device, 409108684Sphk U8 phy_id, 410108684Sphk U16 route_index, 411108684Sphk SCI_SAS_ADDRESS_T destination_sas_address, 412108684Sphk BOOL disable_expander_route_entry 413108684Sphk) 414108684Sphk{ 415108684Sphk SMP_REQUEST_T config_route_info; 416158161Sbde 417108684Sphk scif_sas_smp_protocol_request_construct( 418108684Sphk &config_route_info, 419108684Sphk SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION, 420247036Smelifaro 0, 421247036Smelifaro sizeof(SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T) / sizeof(U32) 422247036Smelifaro ); 423247036Smelifaro 424247036Smelifaro config_route_info.request.configure_route_information.phy_identifier = phy_id; 425108684Sphk config_route_info.request.configure_route_information.expander_route_index_high = 426108684Sphk ((route_index & 0xff00) >> 8); 427108684Sphk config_route_info.request.configure_route_information.expander_route_index = 428108684Sphk route_index & 0xff; 429247036Smelifaro config_route_info.request.configure_route_information.routed_sas_address[0] = 430247036Smelifaro destination_sas_address.high; 431247036Smelifaro config_route_info.request.configure_route_information.routed_sas_address[1] = 432108684Sphk destination_sas_address.low; 433108684Sphk 434108684Sphk if (disable_expander_route_entry == TRUE) 435108684Sphk config_route_info.request.configure_route_information.disable_route_entry = 1; 436108684Sphk 437108684Sphk return scif_sas_smp_request_build( 438108684Sphk fw_controller, fw_device, &config_route_info, 439108684Sphk NULL, NULL 440108684Sphk ); 441108684Sphk} 442108684Sphk 443108684Sphk/** 444108684Sphk * @brief This method retry the internal smp request. 445108684Sphk * 446108684Sphk * @param[in] fw_device This parameter specifies the remote device for 447126775Sdwmalone * which the internal IO request is destined. 448126775Sdwmalone * @param[in] retry_count This parameter specifies how many times the 449108684Sphk * old smp request has been retried. 450247037Smelifaro * 451108684Sphk * @return none. 452108684Sphk */ 453158161SbdeSCI_STATUS scif_sas_smp_internal_request_retry( 454108684Sphk SCIF_SAS_REMOTE_DEVICE_T * fw_device 455108684Sphk) 456108684Sphk{ 457108684Sphk SCIF_SAS_CONTROLLER_T * fw_controller; 458108684Sphk SCIF_SAS_IO_REQUEST_T * new_io; 459108684Sphk void * new_request_memory = NULL; 460108684Sphk U8 retry_count = fw_device->protocol_device.smp_device.io_retry_count; 461108684Sphk 462108684Sphk SCIF_LOG_TRACE(( 463108684Sphk sci_base_object_get_logger(fw_device), 464108684Sphk SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 465108684Sphk "scif_sas_smp_internal_request_retry(0x%x, 0x%x) time %d!\n", 466175239Sdelphij fw_device, retry_count 467175239Sdelphij )); 468108684Sphk 469108684Sphk fw_controller = fw_device->domain->controller; 470108684Sphk 471108684Sphk switch (fw_device->protocol_device.smp_device.current_smp_request) 472108684Sphk { 473108684Sphk case SMP_FUNCTION_REPORT_GENERAL: 474108684Sphk new_request_memory = scif_sas_smp_request_construct_report_general( 475108684Sphk fw_controller, fw_device 476108684Sphk ); 477108684Sphk break; 478108684Sphk 479108684Sphk case SMP_FUNCTION_DISCOVER: 480108684Sphk //We are retrying an internal io. So we are going to allocate 481247036Smelifaro //a new memory from internal io memory pool. 482247036Smelifaro new_request_memory = scif_sas_smp_request_construct_discover( 483247036Smelifaro fw_controller, fw_device, 484247036Smelifaro fw_device->protocol_device.smp_device.current_activity_phy_index, 485247036Smelifaro NULL, NULL 486108684Sphk ); 487108684Sphk 488247037Smelifaro break; 489108684Sphk 490 case SMP_FUNCTION_REPORT_PHY_SATA: 491 new_request_memory = scif_sas_smp_request_construct_report_phy_sata( 492 fw_controller, fw_device, 493 fw_device->protocol_device.smp_device.current_activity_phy_index 494 ); 495 break; 496 497 default: 498 //unsupported case, TBD 499 break; 500 } //end of switch 501 502 if (new_request_memory != NULL) 503 { 504 //set the retry count to new built smp request. 505 new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory; 506 new_io->retry_count = ++retry_count; 507 508 //need to schedule the DPC here. 509 scif_cb_start_internal_io_task_schedule( 510 fw_controller, 511 scif_sas_controller_start_high_priority_io, 512 fw_controller 513 ); 514 515 return SCI_SUCCESS; 516 } 517 else 518 return SCI_FAILURE_INSUFFICIENT_RESOURCES; 519 520} 521 522/** 523 * @brief This method retry the external smp request. 524 * 525 * @param[in] fw_device This parameter specifies the remote device for 526 * which the internal IO request is destined. 527 * @param[in] old_internal_io This parameter specifies the old smp request to be 528 * retried. 529 * 530 * @return none. 531 */ 532SCI_STATUS scif_sas_smp_external_request_retry( 533 SCIF_SAS_IO_REQUEST_T * old_io 534) 535{ 536 SCIF_SAS_REMOTE_DEVICE_T * fw_device = old_io->parent.device; 537 SCIF_SAS_CONTROLLER_T * fw_controller; 538 SCIF_SAS_IO_REQUEST_T * new_io; 539 void * new_request_memory = NULL; 540 U8 retry_count = old_io->retry_count; 541 542 SCIF_LOG_TRACE(( 543 sci_base_object_get_logger(fw_device), 544 SCIF_LOG_OBJECT_IO_REQUEST | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY, 545 "scif_sas_smp_external_request_retry(0x%x) time %d!\n", 546 old_io 547 )); 548 549 fw_controller = fw_device->domain->controller; 550 551 // Before we construct new io using the same memory, we need to 552 // remove the IO from the list of outstanding requests on the domain 553 // so that we don't damage the domain's fast list of request. 554 sci_fast_list_remove_element(&old_io->parent.list_element); 555 556 switch (fw_device->protocol_device.smp_device.current_smp_request) 557 { 558 case SMP_FUNCTION_DISCOVER: 559 //we are retrying an external io, we are going to reuse the 560 //old io's memory. new_request_memory is same as old_io. 561 new_request_memory = scif_sas_smp_request_construct_discover( 562 fw_controller, fw_device, 563 fw_device->protocol_device.smp_device.current_activity_phy_index, 564 (void *)sci_object_get_association(old_io), 565 (void *)old_io 566 ); 567 568 break; 569 570 case SMP_FUNCTION_PHY_CONTROL: 571 //Phy Control command always uses external io memory. 572 new_request_memory = scif_sas_smp_request_construct_phy_control( 573 fw_controller, fw_device, PHY_OPERATION_HARD_RESET, 574 fw_device->protocol_device.smp_device.current_activity_phy_index, 575 (void *)sci_object_get_association(old_io), 576 (void *)old_io 577 ); 578 579 break; 580 581 default: 582 //unsupported case, TBD 583 return SCI_FAILURE; 584 } //end of switch 585 586 //set the retry count to new built smp request. 587 new_io = (SCIF_SAS_IO_REQUEST_T *) new_request_memory; 588 new_io->retry_count = ++retry_count; 589 590 //put into the high priority queue. 591 sci_pool_put(fw_controller->hprq.pool, (POINTER_UINT) new_request_memory); 592 593 //schedule the DPC to start new io. 594 scif_cb_start_internal_io_task_schedule( 595 fw_controller, scif_sas_controller_start_high_priority_io, fw_controller 596 ); 597 598 return SCI_SUCCESS; 599} 600 601