···229229 struct scic_sds_oem_params sds1;230230};231231232232-/**233233- * scic_user_parameters_set() - This method allows the user to attempt to234234- * change the user parameters utilized by the controller.235235- * @controller: This parameter specifies the controller on which to set the236236- * user parameters.237237- * @user_parameters: This parameter specifies the USER_PARAMETERS object238238- * containing the potential new values.239239- *240240- * Indicate if the update of the user parameters was successful. SCI_SUCCESS241241- * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE242242- * This value is returned if the attempt to change the user parameter failed,243243- * because changing one of the parameters is not currently allowed.244244- * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user245245- * supplied an invalid interrupt coalescence time, spin up delay interval, etc.246246- */247247-enum sci_status scic_user_parameters_set(248248- struct scic_sds_controller *controller,249249- union scic_user_parameters *user_parameters);250250-251251-/**252252- * scic_oem_parameters_set() - This method allows the user to attempt to change253253- * the OEM parameters utilized by the controller.254254- * @controller: This parameter specifies the controller on which to set the255255- * user parameters.256256- * @oem_parameters: This parameter specifies the OEM parameters object257257- * containing the potential new values.258258- *259259- * Indicate if the update of the user parameters was successful. SCI_SUCCESS260260- * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE261261- * This value is returned if the attempt to change the user parameter failed,262262- * because changing one of the parameters is not currently allowed.263263- * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user264264- * supplied an unsupported value for one of the OEM parameters.265265- */266266-enum sci_status scic_oem_parameters_set(267267- struct scic_sds_controller *controller,268268- union scic_oem_parameters *oem_parameters);269269-270232int scic_oem_parameters_validate(struct scic_sds_oem_params *oem);271233272234/**
-130
drivers/scsi/isci/core/scic_controller.h
···11-/*22- * This file is provided under a dual BSD/GPLv2 license. When using or33- * redistributing this file, you may do so under either license.44- *55- * GPL LICENSE SUMMARY66- *77- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.88- *99- * This program is free software; you can redistribute it and/or modify1010- * it under the terms of version 2 of the GNU General Public License as1111- * published by the Free Software Foundation.1212- *1313- * This program is distributed in the hope that it will be useful, but1414- * WITHOUT ANY WARRANTY; without even the implied warranty of1515- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1616- * General Public License for more details.1717- *1818- * You should have received a copy of the GNU General Public License1919- * along with this program; if not, write to the Free Software2020- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.2121- * The full GNU General Public License is included in this distribution2222- * in the file called LICENSE.GPL.2323- *2424- * BSD LICENSE2525- *2626- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.2727- * All rights reserved.2828- *2929- * Redistribution and use in source and binary forms, with or without3030- * modification, are permitted provided that the following conditions3131- * are met:3232- *3333- * * Redistributions of source code must retain the above copyright3434- * notice, this list of conditions and the following disclaimer.3535- * * Redistributions in binary form must reproduce the above copyright3636- * notice, this list of conditions and the following disclaimer in3737- * the documentation and/or other materials provided with the3838- * distribution.3939- * * Neither the name of Intel Corporation nor the names of its4040- * contributors may be used to endorse or promote products derived4141- * from this software without specific prior written permission.4242- *4343- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS4444- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT4545- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR4646- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT4747- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,4848- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT4949- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,5050- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY5151- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT5252- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE5353- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454- */5555-5656-#ifndef _SCIC_CONTROLLER_H_5757-#define _SCIC_CONTROLLER_H_5858-5959-#include "scic_config_parameters.h"6060-6161-struct scic_sds_request;6262-struct scic_sds_phy;6363-struct scic_sds_port;6464-struct scic_sds_remote_device;6565-6666-enum sci_status scic_controller_construct(struct scic_sds_controller *c,6767- void __iomem *scu_base,6868- void __iomem *smu_base);6969-7070-void scic_controller_enable_interrupts(7171- struct scic_sds_controller *controller);7272-7373-void scic_controller_disable_interrupts(7474- struct scic_sds_controller *controller);7575-7676-enum sci_status scic_controller_initialize(7777- struct scic_sds_controller *controller);7878-7979-u32 scic_controller_get_suggested_start_timeout(8080- struct scic_sds_controller *controller);8181-8282-enum sci_status scic_controller_start(8383- struct scic_sds_controller *controller,8484- u32 timeout);8585-8686-enum sci_status scic_controller_stop(8787- struct scic_sds_controller *controller,8888- u32 timeout);8989-9090-enum sci_status scic_controller_reset(9191- struct scic_sds_controller *controller);9292-9393-enum sci_status scic_controller_start_io(9494- struct scic_sds_controller *controller,9595- struct scic_sds_remote_device *remote_device,9696- struct scic_sds_request *io_request,9797- u16 io_tag);9898-9999-enum sci_task_status scic_controller_start_task(100100- struct scic_sds_controller *controller,101101- struct scic_sds_remote_device *remote_device,102102- struct scic_sds_request *task_request,103103- u16 io_tag);104104-105105-enum sci_status scic_controller_terminate_request(106106- struct scic_sds_controller *controller,107107- struct scic_sds_remote_device *remote_device,108108- struct scic_sds_request *request);109109-110110-enum sci_status scic_controller_complete_io(111111- struct scic_sds_controller *controller,112112- struct scic_sds_remote_device *remote_device,113113- struct scic_sds_request *io_request);114114-115115-enum sci_status scic_controller_get_phy_handle(116116- struct scic_sds_controller *controller,117117- u8 phy_index,118118- struct scic_sds_phy **phy_handle);119119-120120-u16 scic_controller_allocate_io_tag(121121- struct scic_sds_controller *controller);122122-123123-enum sci_status scic_controller_free_io_tag(124124- struct scic_sds_controller *controller,125125- u16 io_tag);126126-127127-struct device;128128-struct scic_sds_controller *scic_controller_alloc(struct device *dev);129129-int scic_controller_mem_init(struct scic_sds_controller *scic);130130-#endif /* _SCIC_CONTROLLER_H_ */
-2973
drivers/scsi/isci/core/scic_sds_controller.c
···11-/*22- * This file is provided under a dual BSD/GPLv2 license. When using or33- * redistributing this file, you may do so under either license.44- *55- * GPL LICENSE SUMMARY66- *77- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.88- *99- * This program is free software; you can redistribute it and/or modify1010- * it under the terms of version 2 of the GNU General Public License as1111- * published by the Free Software Foundation.1212- *1313- * This program is distributed in the hope that it will be useful, but1414- * WITHOUT ANY WARRANTY; without even the implied warranty of1515- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1616- * General Public License for more details.1717- *1818- * You should have received a copy of the GNU General Public License1919- * along with this program; if not, write to the Free Software2020- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.2121- * The full GNU General Public License is included in this distribution2222- * in the file called LICENSE.GPL.2323- *2424- * BSD LICENSE2525- *2626- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.2727- * All rights reserved.2828- *2929- * Redistribution and use in source and binary forms, with or without3030- * modification, are permitted provided that the following conditions3131- * are met:3232- *3333- * * Redistributions of source code must retain the above copyright3434- * notice, this list of conditions and the following disclaimer.3535- * * Redistributions in binary form must reproduce the above copyright3636- * notice, this list of conditions and the following disclaimer in3737- * the documentation and/or other materials provided with the3838- * distribution.3939- * * Neither the name of Intel Corporation nor the names of its4040- * contributors may be used to endorse or promote products derived4141- * from this software without specific prior written permission.4242- *4343- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS4444- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT4545- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR4646- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT4747- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,4848- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT4949- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,5050- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY5151- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT5252- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE5353- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454- */5555-5656-#include <linux/device.h>5757-#include <scsi/sas.h>5858-#include "scic_controller.h"5959-#include "scic_phy.h"6060-#include "scic_port.h"6161-#include "scic_sds_controller.h"6262-#include "scu_registers.h"6363-#include "scic_sds_phy.h"6464-#include "scic_sds_port_configuration_agent.h"6565-#include "scic_sds_port.h"6666-#include "remote_device.h"6767-#include "scic_sds_request.h"6868-#include "sci_environment.h"6969-#include "sci_util.h"7070-#include "scu_completion_codes.h"7171-#include "scu_event_codes.h"7272-#include "scu_remote_node_context.h"7373-#include "scu_task_context.h"7474-#include "scu_unsolicited_frame.h"7575-#include "timers.h"7676-7777-#define SCU_CONTEXT_RAM_INIT_STALL_TIME 2007878-7979-/**8080- * smu_dcc_get_max_ports() -8181- *8282- * This macro returns the maximum number of logical ports supported by the8383- * hardware. The caller passes in the value read from the device context8484- * capacity register and this macro will mash and shift the value appropriately.8585- */8686-#define smu_dcc_get_max_ports(dcc_value) \8787- (\8888- (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \8989- >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \9090- )9191-9292-/**9393- * smu_dcc_get_max_task_context() -9494- *9595- * This macro returns the maximum number of task contexts supported by the9696- * hardware. The caller passes in the value read from the device context9797- * capacity register and this macro will mash and shift the value appropriately.9898- */9999-#define smu_dcc_get_max_task_context(dcc_value) \100100- (\101101- (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \102102- >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \103103- )104104-105105-/**106106- * smu_dcc_get_max_remote_node_context() -107107- *108108- * This macro returns the maximum number of remote node contexts supported by109109- * the hardware. The caller passes in the value read from the device context110110- * capacity register and this macro will mash and shift the value appropriately.111111- */112112-#define smu_dcc_get_max_remote_node_context(dcc_value) \113113- (\114114- (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \115115- >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \116116- )117117-118118-119119-static void scic_sds_controller_power_control_timer_handler(120120- void *controller);121121-#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3122122-#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3123123-124124-/**125125- *126126- *127127- * The number of milliseconds to wait for a phy to start.128128- */129129-#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100130130-131131-/**132132- *133133- *134134- * The number of milliseconds to wait while a given phy is consuming power135135- * before allowing another set of phys to consume power. Ultimately, this will136136- * be specified by OEM parameter.137137- */138138-#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500139139-140140-/**141141- * COMPLETION_QUEUE_CYCLE_BIT() -142142- *143143- * This macro will return the cycle bit of the completion queue entry144144- */145145-#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)146146-147147-/**148148- * NORMALIZE_GET_POINTER() -149149- *150150- * This macro will normalize the completion queue get pointer so its value can151151- * be used as an index into an array152152- */153153-#define NORMALIZE_GET_POINTER(x) \154154- ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)155155-156156-/**157157- * NORMALIZE_PUT_POINTER() -158158- *159159- * This macro will normalize the completion queue put pointer so its value can160160- * be used as an array inde161161- */162162-#define NORMALIZE_PUT_POINTER(x) \163163- ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)164164-165165-166166-/**167167- * NORMALIZE_GET_POINTER_CYCLE_BIT() -168168- *169169- * This macro will normalize the completion queue cycle pointer so it matches170170- * the completion queue cycle bit171171- */172172-#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \173173- ((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))174174-175175-/**176176- * NORMALIZE_EVENT_POINTER() -177177- *178178- * This macro will normalize the completion queue event entry so its value can179179- * be used as an index.180180- */181181-#define NORMALIZE_EVENT_POINTER(x) \182182- (\183183- ((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \184184- >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \185185- )186186-187187-/**188188- * INCREMENT_COMPLETION_QUEUE_GET() -189189- *190190- * This macro will increment the controllers completion queue index value and191191- * possibly toggle the cycle bit if the completion queue index wraps back to 0.192192- */193193-#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \194194- INCREMENT_QUEUE_GET(\195195- (index), \196196- (cycle), \197197- (controller)->completion_queue_entries, \198198- SMU_CQGR_CYCLE_BIT \199199- )200200-201201-/**202202- * INCREMENT_EVENT_QUEUE_GET() -203203- *204204- * This macro will increment the controllers event queue index value and205205- * possibly toggle the event cycle bit if the event queue index wraps back to 0.206206- */207207-#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \208208- INCREMENT_QUEUE_GET(\209209- (index), \210210- (cycle), \211211- (controller)->completion_event_entries, \212212- SMU_CQGR_EVENT_CYCLE_BIT \213213- )214214-215215-static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic)216216-{217217- struct isci_host *ihost = scic_to_ihost(scic);218218- scic->power_control.timer = isci_timer_create(ihost,219219- scic,220220- scic_sds_controller_power_control_timer_handler);221221-222222- memset(scic->power_control.requesters, 0,223223- sizeof(scic->power_control.requesters));224224-225225- scic->power_control.phys_waiting = 0;226226- scic->power_control.phys_granted_power = 0;227227-}228228-229229-int scic_controller_mem_init(struct scic_sds_controller *scic)230230-{231231- struct device *dev = scic_to_dev(scic);232232- dma_addr_t dma_handle;233233- enum sci_status result;234234-235235- scic->completion_queue = dmam_alloc_coherent(dev,236236- scic->completion_queue_entries * sizeof(u32),237237- &dma_handle, GFP_KERNEL);238238- if (!scic->completion_queue)239239- return -ENOMEM;240240-241241- writel(lower_32_bits(dma_handle),242242- &scic->smu_registers->completion_queue_lower);243243- writel(upper_32_bits(dma_handle),244244- &scic->smu_registers->completion_queue_upper);245245-246246- scic->remote_node_context_table = dmam_alloc_coherent(dev,247247- scic->remote_node_entries *248248- sizeof(union scu_remote_node_context),249249- &dma_handle, GFP_KERNEL);250250- if (!scic->remote_node_context_table)251251- return -ENOMEM;252252-253253- writel(lower_32_bits(dma_handle),254254- &scic->smu_registers->remote_node_context_lower);255255- writel(upper_32_bits(dma_handle),256256- &scic->smu_registers->remote_node_context_upper);257257-258258- scic->task_context_table = dmam_alloc_coherent(dev,259259- scic->task_context_entries *260260- sizeof(struct scu_task_context),261261- &dma_handle, GFP_KERNEL);262262- if (!scic->task_context_table)263263- return -ENOMEM;264264-265265- writel(lower_32_bits(dma_handle),266266- &scic->smu_registers->host_task_table_lower);267267- writel(upper_32_bits(dma_handle),268268- &scic->smu_registers->host_task_table_upper);269269-270270- result = scic_sds_unsolicited_frame_control_construct(scic);271271- if (result)272272- return result;273273-274274- /*275275- * Inform the silicon as to the location of the UF headers and276276- * address table.277277- */278278- writel(lower_32_bits(scic->uf_control.headers.physical_address),279279- &scic->scu_registers->sdma.uf_header_base_address_lower);280280- writel(upper_32_bits(scic->uf_control.headers.physical_address),281281- &scic->scu_registers->sdma.uf_header_base_address_upper);282282-283283- writel(lower_32_bits(scic->uf_control.address_table.physical_address),284284- &scic->scu_registers->sdma.uf_address_table_lower);285285- writel(upper_32_bits(scic->uf_control.address_table.physical_address),286286- &scic->scu_registers->sdma.uf_address_table_upper);287287-288288- return 0;289289-}290290-291291-/**292292- * This method initializes the task context data for the controller.293293- * @scic:294294- *295295- */296296-static void297297-scic_sds_controller_assign_task_entries(struct scic_sds_controller *controller)298298-{299299- u32 task_assignment;300300-301301- /*302302- * Assign all the TCs to function 0303303- * TODO: Do we actually need to read this register to write it back?304304- */305305-306306- task_assignment =307307- readl(&controller->smu_registers->task_context_assignment[0]);308308-309309- task_assignment |= (SMU_TCA_GEN_VAL(STARTING, 0)) |310310- (SMU_TCA_GEN_VAL(ENDING, controller->task_context_entries - 1)) |311311- (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE));312312-313313- writel(task_assignment,314314- &controller->smu_registers->task_context_assignment[0]);315315-316316-}317317-318318-/**319319- * This method initializes the hardware completion queue.320320- *321321- *322322- */323323-static void scic_sds_controller_initialize_completion_queue(324324- struct scic_sds_controller *scic)325325-{326326- u32 index;327327- u32 completion_queue_control_value;328328- u32 completion_queue_get_value;329329- u32 completion_queue_put_value;330330-331331- scic->completion_queue_get = 0;332332-333333- completion_queue_control_value = (334334- SMU_CQC_QUEUE_LIMIT_SET(scic->completion_queue_entries - 1)335335- | SMU_CQC_EVENT_LIMIT_SET(scic->completion_event_entries - 1)336336- );337337-338338- writel(completion_queue_control_value,339339- &scic->smu_registers->completion_queue_control);340340-341341-342342- /* Set the completion queue get pointer and enable the queue */343343- completion_queue_get_value = (344344- (SMU_CQGR_GEN_VAL(POINTER, 0))345345- | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))346346- | (SMU_CQGR_GEN_BIT(ENABLE))347347- | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))348348- );349349-350350- writel(completion_queue_get_value,351351- &scic->smu_registers->completion_queue_get);352352-353353- /* Set the completion queue put pointer */354354- completion_queue_put_value = (355355- (SMU_CQPR_GEN_VAL(POINTER, 0))356356- | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))357357- );358358-359359- writel(completion_queue_put_value,360360- &scic->smu_registers->completion_queue_put);361361-362362- /* Initialize the cycle bit of the completion queue entries */363363- for (index = 0; index < scic->completion_queue_entries; index++) {364364- /*365365- * If get.cycle_bit != completion_queue.cycle_bit366366- * its not a valid completion queue entry367367- * so at system start all entries are invalid */368368- scic->completion_queue[index] = 0x80000000;369369- }370370-}371371-372372-/**373373- * This method initializes the hardware unsolicited frame queue.374374- *375375- *376376- */377377-static void scic_sds_controller_initialize_unsolicited_frame_queue(378378- struct scic_sds_controller *scic)379379-{380380- u32 frame_queue_control_value;381381- u32 frame_queue_get_value;382382- u32 frame_queue_put_value;383383-384384- /* Write the queue size */385385- frame_queue_control_value =386386- SCU_UFQC_GEN_VAL(QUEUE_SIZE,387387- scic->uf_control.address_table.count);388388-389389- writel(frame_queue_control_value,390390- &scic->scu_registers->sdma.unsolicited_frame_queue_control);391391-392392- /* Setup the get pointer for the unsolicited frame queue */393393- frame_queue_get_value = (394394- SCU_UFQGP_GEN_VAL(POINTER, 0)395395- | SCU_UFQGP_GEN_BIT(ENABLE_BIT)396396- );397397-398398- writel(frame_queue_get_value,399399- &scic->scu_registers->sdma.unsolicited_frame_get_pointer);400400- /* Setup the put pointer for the unsolicited frame queue */401401- frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);402402- writel(frame_queue_put_value,403403- &scic->scu_registers->sdma.unsolicited_frame_put_pointer);404404-}405405-406406-/**407407- * This method enables the hardware port task scheduler.408408- *409409- *410410- */411411-static void scic_sds_controller_enable_port_task_scheduler(412412- struct scic_sds_controller *scic)413413-{414414- u32 port_task_scheduler_value;415415-416416- port_task_scheduler_value =417417- readl(&scic->scu_registers->peg0.ptsg.control);418418- port_task_scheduler_value |=419419- (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) |420420- SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));421421- writel(port_task_scheduler_value,422422- &scic->scu_registers->peg0.ptsg.control);423423-}424424-425425-/**426426- *427427- *428428- * This macro is used to delay between writes to the AFE registers during AFE429429- * initialization.430430- */431431-#define AFE_REGISTER_WRITE_DELAY 10432432-433433-/* Initialize the AFE for this phy index. We need to read the AFE setup from434434- * the OEM parameters none435435- */436436-static void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)437437-{438438- const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;439439- u32 afe_status;440440- u32 phy_id;441441-442442- /* Clear DFX Status registers */443443- writel(0x0081000f, &scic->scu_registers->afe.afe_dfx_master_control0);444444- udelay(AFE_REGISTER_WRITE_DELAY);445445-446446- if (is_b0()) {447447- /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement448448- * Timer, PM Stagger Timer */449449- writel(0x0007BFFF, &scic->scu_registers->afe.afe_pmsn_master_control2);450450- udelay(AFE_REGISTER_WRITE_DELAY);451451- }452452-453453- /* Configure bias currents to normal */454454- if (is_a0())455455- writel(0x00005500, &scic->scu_registers->afe.afe_bias_control);456456- else if (is_a2())457457- writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control);458458- else if (is_b0())459459- writel(0x00005F00, &scic->scu_registers->afe.afe_bias_control);460460-461461- udelay(AFE_REGISTER_WRITE_DELAY);462462-463463- /* Enable PLL */464464- if (is_b0())465465- writel(0x80040A08, &scic->scu_registers->afe.afe_pll_control0);466466- else467467- writel(0x80040908, &scic->scu_registers->afe.afe_pll_control0);468468-469469- udelay(AFE_REGISTER_WRITE_DELAY);470470-471471- /* Wait for the PLL to lock */472472- do {473473- afe_status = readl(&scic->scu_registers->afe.afe_common_block_status);474474- udelay(AFE_REGISTER_WRITE_DELAY);475475- } while ((afe_status & 0x00001000) == 0);476476-477477- if (is_a0() || is_a2()) {478478- /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */479479- writel(0x7bcc96ad, &scic->scu_registers->afe.afe_pmsn_master_control0);480480- udelay(AFE_REGISTER_WRITE_DELAY);481481- }482482-483483- for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {484484- const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];485485-486486- if (is_b0()) {487487- /* Configure transmitter SSC parameters */488488- writel(0x00030000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);489489- udelay(AFE_REGISTER_WRITE_DELAY);490490- } else {491491- /*492492- * All defaults, except the Receive Word Alignament/Comma Detect493493- * Enable....(0xe800) */494494- writel(0x00004512, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);495495- udelay(AFE_REGISTER_WRITE_DELAY);496496-497497- writel(0x0050100F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1);498498- udelay(AFE_REGISTER_WRITE_DELAY);499499- }500500-501501- /*502502- * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)503503- * & increase TX int & ext bias 20%....(0xe85c) */504504- if (is_a0())505505- writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);506506- else if (is_a2())507507- writel(0x000003F0, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);508508- else {509509- /* Power down TX and RX (PWRDNTX and PWRDNRX) */510510- writel(0x000003d7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);511511- udelay(AFE_REGISTER_WRITE_DELAY);512512-513513- /*514514- * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)515515- * & increase TX int & ext bias 20%....(0xe85c) */516516- writel(0x000003d4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);517517- }518518- udelay(AFE_REGISTER_WRITE_DELAY);519519-520520- if (is_a0() || is_a2()) {521521- /* Enable TX equalization (0xe824) */522522- writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);523523- udelay(AFE_REGISTER_WRITE_DELAY);524524- }525525-526526- /*527527- * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),528528- * RDD=0x0(RX Detect Enabled) ....(0xe800) */529529- writel(0x00004100, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);530530- udelay(AFE_REGISTER_WRITE_DELAY);531531-532532- /* Leave DFE/FFE on */533533- if (is_a0())534534- writel(0x3F09983F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);535535- else if (is_a2())536536- writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);537537- else {538538- writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);539539- udelay(AFE_REGISTER_WRITE_DELAY);540540- /* Enable TX equalization (0xe824) */541541- writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);542542- }543543- udelay(AFE_REGISTER_WRITE_DELAY);544544-545545- writel(oem_phy->afe_tx_amp_control0,546546- &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0);547547- udelay(AFE_REGISTER_WRITE_DELAY);548548-549549- writel(oem_phy->afe_tx_amp_control1,550550- &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1);551551- udelay(AFE_REGISTER_WRITE_DELAY);552552-553553- writel(oem_phy->afe_tx_amp_control2,554554- &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2);555555- udelay(AFE_REGISTER_WRITE_DELAY);556556-557557- writel(oem_phy->afe_tx_amp_control3,558558- &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3);559559- udelay(AFE_REGISTER_WRITE_DELAY);560560- }561561-562562- /* Transfer control to the PEs */563563- writel(0x00010f00, &scic->scu_registers->afe.afe_dfx_master_control0);564564- udelay(AFE_REGISTER_WRITE_DELAY);565565-}566566-567567-/*568568- * ****************************************************************************-569569- * * SCIC SDS Controller Internal Start/Stop Routines570570- * ****************************************************************************- */571571-572572-573573-/**574574- * This method will attempt to transition into the ready state for the575575- * controller and indicate that the controller start operation has completed576576- * if all criteria are met.577577- * @scic: This parameter indicates the controller object for which578578- * to transition to ready.579579- * @status: This parameter indicates the status value to be pass into the call580580- * to scic_cb_controller_start_complete().581581- *582582- * none.583583- */584584-static void scic_sds_controller_transition_to_ready(585585- struct scic_sds_controller *scic,586586- enum sci_status status)587587-{588588- struct isci_host *ihost = scic_to_ihost(scic);589589-590590- if (scic->state_machine.current_state_id ==591591- SCI_BASE_CONTROLLER_STATE_STARTING) {592592- /*593593- * We move into the ready state, because some of the phys/ports594594- * may be up and operational.595595- */596596- sci_base_state_machine_change_state(&scic->state_machine,597597- SCI_BASE_CONTROLLER_STATE_READY);598598-599599- isci_host_start_complete(ihost, status);600600- }601601-}602602-603603-static void scic_sds_controller_timeout_handler(void *_scic)604604-{605605- struct scic_sds_controller *scic = _scic;606606- struct isci_host *ihost = scic_to_ihost(scic);607607- struct sci_base_state_machine *sm = &scic->state_machine;608608-609609- if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING)610610- scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT);611611- else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) {612612- sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED);613613- isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT);614614- } else /* / @todo Now what do we want to do in this case? */615615- dev_err(scic_to_dev(scic),616616- "%s: Controller timer fired when controller was not "617617- "in a state being timed.\n",618618- __func__);619619-}620620-621621-static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)622622-{623623- u32 index;624624- enum sci_status port_status;625625- enum sci_status status = SCI_SUCCESS;626626- struct isci_host *ihost = scic_to_ihost(scic);627627-628628- for (index = 0; index < scic->logical_port_entries; index++) {629629- struct scic_sds_port *sci_port = &ihost->ports[index].sci;630630- scic_sds_port_handler_t stop;631631-632632- stop = sci_port->state_handlers->stop_handler;633633- port_status = stop(sci_port);634634-635635- if ((port_status != SCI_SUCCESS) &&636636- (port_status != SCI_FAILURE_INVALID_STATE)) {637637- status = SCI_FAILURE;638638-639639- dev_warn(scic_to_dev(scic),640640- "%s: Controller stop operation failed to "641641- "stop port %d because of status %d.\n",642642- __func__,643643- sci_port->logical_port_index,644644- port_status);645645- }646646- }647647-648648- return status;649649-}650650-651651-static inline void scic_sds_controller_phy_timer_start(652652- struct scic_sds_controller *scic)653653-{654654- isci_timer_start(scic->phy_startup_timer,655655- SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT);656656-657657- scic->phy_startup_timer_pending = true;658658-}659659-660660-static void scic_sds_controller_phy_timer_stop(struct scic_sds_controller *scic)661661-{662662- isci_timer_stop(scic->phy_startup_timer);663663-664664- scic->phy_startup_timer_pending = false;665665-}666666-667667-/**668668- * scic_sds_controller_start_next_phy - start phy669669- * @scic: controller670670- *671671- * If all the phys have been started, then attempt to transition the672672- * controller to the READY state and inform the user673673- * (scic_cb_controller_start_complete()).674674- */675675-static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic)676676-{677677- struct isci_host *ihost = scic_to_ihost(scic);678678- struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;679679- struct scic_sds_phy *sci_phy;680680- enum sci_status status;681681-682682- status = SCI_SUCCESS;683683-684684- if (scic->phy_startup_timer_pending)685685- return status;686686-687687- if (scic->next_phy_to_start >= SCI_MAX_PHYS) {688688- bool is_controller_start_complete = true;689689- u32 state;690690- u8 index;691691-692692- for (index = 0; index < SCI_MAX_PHYS; index++) {693693- sci_phy = &ihost->phys[index].sci;694694- state = sci_phy->state_machine.current_state_id;695695-696696- if (!scic_sds_phy_get_port(sci_phy))697697- continue;698698-699699- /* The controller start operation is complete iff:700700- * - all links have been given an opportunity to start701701- * - have no indication of a connected device702702- * - have an indication of a connected device and it has703703- * finished the link training process.704704- */705705- if ((sci_phy->is_in_link_training == false &&706706- state == SCI_BASE_PHY_STATE_INITIAL) ||707707- (sci_phy->is_in_link_training == false &&708708- state == SCI_BASE_PHY_STATE_STOPPED) ||709709- (sci_phy->is_in_link_training == true &&710710- state == SCI_BASE_PHY_STATE_STARTING)) {711711- is_controller_start_complete = false;712712- break;713713- }714714- }715715-716716- /*717717- * The controller has successfully finished the start process.718718- * Inform the SCI Core user and transition to the READY state. */719719- if (is_controller_start_complete == true) {720720- scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS);721721- scic_sds_controller_phy_timer_stop(scic);722722- }723723- } else {724724- sci_phy = &ihost->phys[scic->next_phy_to_start].sci;725725-726726- if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {727727- if (scic_sds_phy_get_port(sci_phy) == NULL) {728728- scic->next_phy_to_start++;729729-730730- /* Caution recursion ahead be forwarned731731- *732732- * The PHY was never added to a PORT in MPC mode733733- * so start the next phy in sequence This phy734734- * will never go link up and will not draw power735735- * the OEM parameters either configured the phy736736- * incorrectly for the PORT or it was never737737- * assigned to a PORT738738- */739739- return scic_sds_controller_start_next_phy(scic);740740- }741741- }742742-743743- status = scic_sds_phy_start(sci_phy);744744-745745- if (status == SCI_SUCCESS) {746746- scic_sds_controller_phy_timer_start(scic);747747- } else {748748- dev_warn(scic_to_dev(scic),749749- "%s: Controller stop operation failed "750750- "to stop phy %d because of status "751751- "%d.\n",752752- __func__,753753- ihost->phys[scic->next_phy_to_start].sci.phy_index,754754- status);755755- }756756-757757- scic->next_phy_to_start++;758758- }759759-760760- return status;761761-}762762-763763-static void scic_sds_controller_phy_startup_timeout_handler(void *_scic)764764-{765765- struct scic_sds_controller *scic = _scic;766766- enum sci_status status;767767-768768- scic->phy_startup_timer_pending = false;769769- status = SCI_FAILURE;770770- while (status != SCI_SUCCESS)771771- status = scic_sds_controller_start_next_phy(scic);772772-}773773-774774-static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic)775775-{776776- struct isci_host *ihost = scic_to_ihost(scic);777777-778778- scic->phy_startup_timer = isci_timer_create(ihost,779779- scic,780780- scic_sds_controller_phy_startup_timeout_handler);781781-782782- if (scic->phy_startup_timer == NULL)783783- return SCI_FAILURE_INSUFFICIENT_RESOURCES;784784- else {785785- scic->next_phy_to_start = 0;786786- scic->phy_startup_timer_pending = false;787787- }788788-789789- return SCI_SUCCESS;790790-}791791-792792-static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller *scic)793793-{794794- u32 index;795795- enum sci_status status;796796- enum sci_status phy_status;797797- struct isci_host *ihost = scic_to_ihost(scic);798798-799799- status = SCI_SUCCESS;800800-801801- for (index = 0; index < SCI_MAX_PHYS; index++) {802802- phy_status = scic_sds_phy_stop(&ihost->phys[index].sci);803803-804804- if (phy_status != SCI_SUCCESS &&805805- phy_status != SCI_FAILURE_INVALID_STATE) {806806- status = SCI_FAILURE;807807-808808- dev_warn(scic_to_dev(scic),809809- "%s: Controller stop operation failed to stop "810810- "phy %d because of status %d.\n",811811- __func__,812812- ihost->phys[index].sci.phy_index, phy_status);813813- }814814- }815815-816816- return status;817817-}818818-819819-static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controller *scic)820820-{821821- u32 index;822822- enum sci_status status;823823- enum sci_status device_status;824824-825825- status = SCI_SUCCESS;826826-827827- for (index = 0; index < scic->remote_node_entries; index++) {828828- if (scic->device_table[index] != NULL) {829829- /* / @todo What timeout value do we want to provide to this request? */830830- device_status = scic_remote_device_stop(scic->device_table[index], 0);831831-832832- if ((device_status != SCI_SUCCESS) &&833833- (device_status != SCI_FAILURE_INVALID_STATE)) {834834- dev_warn(scic_to_dev(scic),835835- "%s: Controller stop operation failed "836836- "to stop device 0x%p because of "837837- "status %d.\n",838838- __func__,839839- scic->device_table[index], device_status);840840- }841841- }842842- }843843-844844- return status;845845-}846846-847847-static void scic_sds_controller_power_control_timer_start(struct scic_sds_controller *scic)848848-{849849- isci_timer_start(scic->power_control.timer,850850- SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);851851-852852- scic->power_control.timer_started = true;853853-}854854-855855-static void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic)856856-{857857- if (scic->power_control.timer_started) {858858- isci_timer_stop(scic->power_control.timer);859859- scic->power_control.timer_started = false;860860- }861861-}862862-863863-static void scic_sds_controller_power_control_timer_restart(struct scic_sds_controller *scic)864864-{865865- scic_sds_controller_power_control_timer_stop(scic);866866- scic_sds_controller_power_control_timer_start(scic);867867-}868868-869869-static void scic_sds_controller_power_control_timer_handler(870870- void *controller)871871-{872872- struct scic_sds_controller *scic;873873-874874- scic = (struct scic_sds_controller *)controller;875875-876876- scic->power_control.phys_granted_power = 0;877877-878878- if (scic->power_control.phys_waiting == 0) {879879- scic->power_control.timer_started = false;880880- } else {881881- struct scic_sds_phy *sci_phy = NULL;882882- u8 i;883883-884884- for (i = 0;885885- (i < SCI_MAX_PHYS)886886- && (scic->power_control.phys_waiting != 0);887887- i++) {888888- if (scic->power_control.requesters[i] != NULL) {889889- if (scic->power_control.phys_granted_power <890890- scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {891891- sci_phy = scic->power_control.requesters[i];892892- scic->power_control.requesters[i] = NULL;893893- scic->power_control.phys_waiting--;894894- scic->power_control.phys_granted_power++;895895- scic_sds_phy_consume_power_handler(sci_phy);896896- } else {897897- break;898898- }899899- }900900- }901901-902902- /*903903- * It doesn't matter if the power list is empty, we need to start the904904- * timer in case another phy becomes ready.905905- */906906- scic_sds_controller_power_control_timer_start(scic);907907- }908908-}909909-910910-/**911911- * This method inserts the phy in the stagger spinup control queue.912912- * @scic:913913- *914914- *915915- */916916-void scic_sds_controller_power_control_queue_insert(917917- struct scic_sds_controller *scic,918918- struct scic_sds_phy *sci_phy)919919-{920920- BUG_ON(sci_phy == NULL);921921-922922- if (scic->power_control.phys_granted_power <923923- scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {924924- scic->power_control.phys_granted_power++;925925- scic_sds_phy_consume_power_handler(sci_phy);926926-927927- /*928928- * stop and start the power_control timer. When the timer fires, the929929- * no_of_phys_granted_power will be set to 0930930- */931931- scic_sds_controller_power_control_timer_restart(scic);932932- } else {933933- /* Add the phy in the waiting list */934934- scic->power_control.requesters[sci_phy->phy_index] = sci_phy;935935- scic->power_control.phys_waiting++;936936- }937937-}938938-939939-/**940940- * This method removes the phy from the stagger spinup control queue.941941- * @scic:942942- *943943- *944944- */945945-void scic_sds_controller_power_control_queue_remove(946946- struct scic_sds_controller *scic,947947- struct scic_sds_phy *sci_phy)948948-{949949- BUG_ON(sci_phy == NULL);950950-951951- if (scic->power_control.requesters[sci_phy->phy_index] != NULL) {952952- scic->power_control.phys_waiting--;953953- }954954-955955- scic->power_control.requesters[sci_phy->phy_index] = NULL;956956-}957957-958958-/*959959- * ****************************************************************************-960960- * * SCIC SDS Controller Completion Routines961961- * ****************************************************************************- */962962-963963-/**964964- * This method returns a true value if the completion queue has entries that965965- * can be processed966966- * @scic:967967- *968968- * bool true if the completion queue has entries to process false if the969969- * completion queue has no entries to process970970- */971971-static bool scic_sds_controller_completion_queue_has_entries(972972- struct scic_sds_controller *scic)973973-{974974- u32 get_value = scic->completion_queue_get;975975- u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;976976-977977- if (NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) ==978978- COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index]))979979- return true;980980-981981- return false;982982-}983983-984984-/**985985- * This method processes a task completion notification. This is called from986986- * within the controller completion handler.987987- * @scic:988988- * @completion_entry:989989- *990990- */991991-static void scic_sds_controller_task_completion(992992- struct scic_sds_controller *scic,993993- u32 completion_entry)994994-{995995- u32 index;996996- struct scic_sds_request *io_request;997997-998998- index = SCU_GET_COMPLETION_INDEX(completion_entry);999999- io_request = scic->io_request_table[index];10001000-10011001- /* Make sure that we really want to process this IO request */10021002- if (10031003- (io_request != NULL)10041004- && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)10051005- && (10061006- scic_sds_io_tag_get_sequence(io_request->io_tag)10071007- == scic->io_request_sequence[index]10081008- )10091009- ) {10101010- /* Yep this is a valid io request pass it along to the io request handler */10111011- scic_sds_io_request_tc_completion(io_request, completion_entry);10121012- }10131013-}10141014-10151015-/**10161016- * This method processes an SDMA completion event. This is called from within10171017- * the controller completion handler.10181018- * @scic:10191019- * @completion_entry:10201020- *10211021- */10221022-static void scic_sds_controller_sdma_completion(10231023- struct scic_sds_controller *scic,10241024- u32 completion_entry)10251025-{10261026- u32 index;10271027- struct scic_sds_request *io_request;10281028- struct scic_sds_remote_device *device;10291029-10301030- index = SCU_GET_COMPLETION_INDEX(completion_entry);10311031-10321032- switch (scu_get_command_request_type(completion_entry)) {10331033- case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:10341034- case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:10351035- io_request = scic->io_request_table[index];10361036- dev_warn(scic_to_dev(scic),10371037- "%s: SCIC SDS Completion type SDMA %x for io request "10381038- "%p\n",10391039- __func__,10401040- completion_entry,10411041- io_request);10421042- /* @todo For a post TC operation we need to fail the IO10431043- * request10441044- */10451045- break;10461046-10471047- case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:10481048- case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:10491049- case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:10501050- device = scic->device_table[index];10511051- dev_warn(scic_to_dev(scic),10521052- "%s: SCIC SDS Completion type SDMA %x for remote "10531053- "device %p\n",10541054- __func__,10551055- completion_entry,10561056- device);10571057- /* @todo For a port RNC operation we need to fail the10581058- * device10591059- */10601060- break;10611061-10621062- default:10631063- dev_warn(scic_to_dev(scic),10641064- "%s: SCIC SDS Completion unknown SDMA completion "10651065- "type %x\n",10661066- __func__,10671067- completion_entry);10681068- break;10691069-10701070- }10711071-}10721072-10731073-static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *scic,10741074- u32 completion_entry)10751075-{10761076- u32 index;10771077- u32 frame_index;10781078-10791079- struct isci_host *ihost = scic_to_ihost(scic);10801080- struct scu_unsolicited_frame_header *frame_header;10811081- struct scic_sds_phy *phy;10821082- struct scic_sds_remote_device *device;10831083-10841084- enum sci_status result = SCI_FAILURE;10851085-10861086- frame_index = SCU_GET_FRAME_INDEX(completion_entry);10871087-10881088- frame_header = scic->uf_control.buffers.array[frame_index].header;10891089- scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE;10901090-10911091- if (SCU_GET_FRAME_ERROR(completion_entry)) {10921092- /*10931093- * / @todo If the IAF frame or SIGNATURE FIS frame has an error will10941094- * / this cause a problem? We expect the phy initialization will10951095- * / fail if there is an error in the frame. */10961096- scic_sds_controller_release_frame(scic, frame_index);10971097- return;10981098- }10991099-11001100- if (frame_header->is_address_frame) {11011101- index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);11021102- phy = &ihost->phys[index].sci;11031103- result = scic_sds_phy_frame_handler(phy, frame_index);11041104- } else {11051105-11061106- index = SCU_GET_COMPLETION_INDEX(completion_entry);11071107-11081108- if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {11091109- /*11101110- * This is a signature fis or a frame from a direct attached SATA11111111- * device that has not yet been created. In either case forwared11121112- * the frame to the PE and let it take care of the frame data. */11131113- index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);11141114- phy = &ihost->phys[index].sci;11151115- result = scic_sds_phy_frame_handler(phy, frame_index);11161116- } else {11171117- if (index < scic->remote_node_entries)11181118- device = scic->device_table[index];11191119- else11201120- device = NULL;11211121-11221122- if (device != NULL)11231123- result = scic_sds_remote_device_frame_handler(device, frame_index);11241124- else11251125- scic_sds_controller_release_frame(scic, frame_index);11261126- }11271127- }11281128-11291129- if (result != SCI_SUCCESS) {11301130- /*11311131- * / @todo Is there any reason to report some additional error message11321132- * / when we get this failure notifiction? */11331133- }11341134-}11351135-11361136-static void scic_sds_controller_event_completion(struct scic_sds_controller *scic,11371137- u32 completion_entry)11381138-{11391139- struct isci_host *ihost = scic_to_ihost(scic);11401140- struct scic_sds_request *io_request;11411141- struct scic_sds_remote_device *device;11421142- struct scic_sds_phy *phy;11431143- u32 index;11441144-11451145- index = SCU_GET_COMPLETION_INDEX(completion_entry);11461146-11471147- switch (scu_get_event_type(completion_entry)) {11481148- case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:11491149- /* / @todo The driver did something wrong and we need to fix the condtion. */11501150- dev_err(scic_to_dev(scic),11511151- "%s: SCIC Controller 0x%p received SMU command error "11521152- "0x%x\n",11531153- __func__,11541154- scic,11551155- completion_entry);11561156- break;11571157-11581158- case SCU_EVENT_TYPE_SMU_PCQ_ERROR:11591159- case SCU_EVENT_TYPE_SMU_ERROR:11601160- case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:11611161- /*11621162- * / @todo This is a hardware failure and its likely that we want to11631163- * / reset the controller. */11641164- dev_err(scic_to_dev(scic),11651165- "%s: SCIC Controller 0x%p received fatal controller "11661166- "event 0x%x\n",11671167- __func__,11681168- scic,11691169- completion_entry);11701170- break;11711171-11721172- case SCU_EVENT_TYPE_TRANSPORT_ERROR:11731173- io_request = scic->io_request_table[index];11741174- scic_sds_io_request_event_handler(io_request, completion_entry);11751175- break;11761176-11771177- case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:11781178- switch (scu_get_event_specifier(completion_entry)) {11791179- case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:11801180- case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:11811181- io_request = scic->io_request_table[index];11821182- if (io_request != NULL)11831183- scic_sds_io_request_event_handler(io_request, completion_entry);11841184- else11851185- dev_warn(scic_to_dev(scic),11861186- "%s: SCIC Controller 0x%p received "11871187- "event 0x%x for io request object "11881188- "that doesnt exist.\n",11891189- __func__,11901190- scic,11911191- completion_entry);11921192-11931193- break;11941194-11951195- case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:11961196- device = scic->device_table[index];11971197- if (device != NULL)11981198- scic_sds_remote_device_event_handler(device, completion_entry);11991199- else12001200- dev_warn(scic_to_dev(scic),12011201- "%s: SCIC Controller 0x%p received "12021202- "event 0x%x for remote device object "12031203- "that doesnt exist.\n",12041204- __func__,12051205- scic,12061206- completion_entry);12071207-12081208- break;12091209- }12101210- break;12111211-12121212- case SCU_EVENT_TYPE_BROADCAST_CHANGE:12131213- /*12141214- * direct the broadcast change event to the phy first and then let12151215- * the phy redirect the broadcast change to the port object */12161216- case SCU_EVENT_TYPE_ERR_CNT_EVENT:12171217- /*12181218- * direct error counter event to the phy object since that is where12191219- * we get the event notification. This is a type 4 event. */12201220- case SCU_EVENT_TYPE_OSSP_EVENT:12211221- index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);12221222- phy = &ihost->phys[index].sci;12231223- scic_sds_phy_event_handler(phy, completion_entry);12241224- break;12251225-12261226- case SCU_EVENT_TYPE_RNC_SUSPEND_TX:12271227- case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:12281228- case SCU_EVENT_TYPE_RNC_OPS_MISC:12291229- if (index < scic->remote_node_entries) {12301230- device = scic->device_table[index];12311231-12321232- if (device != NULL)12331233- scic_sds_remote_device_event_handler(device, completion_entry);12341234- } else12351235- dev_err(scic_to_dev(scic),12361236- "%s: SCIC Controller 0x%p received event 0x%x "12371237- "for remote device object 0x%0x that doesnt "12381238- "exist.\n",12391239- __func__,12401240- scic,12411241- completion_entry,12421242- index);12431243-12441244- break;12451245-12461246- default:12471247- dev_warn(scic_to_dev(scic),12481248- "%s: SCIC Controller received unknown event code %x\n",12491249- __func__,12501250- completion_entry);12511251- break;12521252- }12531253-}12541254-12551255-/**12561256- * This method is a private routine for processing the completion queue entries.12571257- * @scic:12581258- *12591259- */12601260-static void scic_sds_controller_process_completions(12611261- struct scic_sds_controller *scic)12621262-{12631263- u32 completion_count = 0;12641264- u32 completion_entry;12651265- u32 get_index;12661266- u32 get_cycle;12671267- u32 event_index;12681268- u32 event_cycle;12691269-12701270- dev_dbg(scic_to_dev(scic),12711271- "%s: completion queue begining get:0x%08x\n",12721272- __func__,12731273- scic->completion_queue_get);12741274-12751275- /* Get the component parts of the completion queue */12761276- get_index = NORMALIZE_GET_POINTER(scic->completion_queue_get);12771277- get_cycle = SMU_CQGR_CYCLE_BIT & scic->completion_queue_get;12781278-12791279- event_index = NORMALIZE_EVENT_POINTER(scic->completion_queue_get);12801280- event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & scic->completion_queue_get;12811281-12821282- while (12831283- NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)12841284- == COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index])12851285- ) {12861286- completion_count++;12871287-12881288- completion_entry = scic->completion_queue[get_index];12891289- INCREMENT_COMPLETION_QUEUE_GET(scic, get_index, get_cycle);12901290-12911291- dev_dbg(scic_to_dev(scic),12921292- "%s: completion queue entry:0x%08x\n",12931293- __func__,12941294- completion_entry);12951295-12961296- switch (SCU_GET_COMPLETION_TYPE(completion_entry)) {12971297- case SCU_COMPLETION_TYPE_TASK:12981298- scic_sds_controller_task_completion(scic, completion_entry);12991299- break;13001300-13011301- case SCU_COMPLETION_TYPE_SDMA:13021302- scic_sds_controller_sdma_completion(scic, completion_entry);13031303- break;13041304-13051305- case SCU_COMPLETION_TYPE_UFI:13061306- scic_sds_controller_unsolicited_frame(scic, completion_entry);13071307- break;13081308-13091309- case SCU_COMPLETION_TYPE_EVENT:13101310- INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle);13111311- scic_sds_controller_event_completion(scic, completion_entry);13121312- break;13131313-13141314- case SCU_COMPLETION_TYPE_NOTIFY:13151315- /*13161316- * Presently we do the same thing with a notify event that we do with the13171317- * other event codes. */13181318- INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle);13191319- scic_sds_controller_event_completion(scic, completion_entry);13201320- break;13211321-13221322- default:13231323- dev_warn(scic_to_dev(scic),13241324- "%s: SCIC Controller received unknown "13251325- "completion type %x\n",13261326- __func__,13271327- completion_entry);13281328- break;13291329- }13301330- }13311331-13321332- /* Update the get register if we completed one or more entries */13331333- if (completion_count > 0) {13341334- scic->completion_queue_get =13351335- SMU_CQGR_GEN_BIT(ENABLE) |13361336- SMU_CQGR_GEN_BIT(EVENT_ENABLE) |13371337- event_cycle |13381338- SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) |13391339- get_cycle |13401340- SMU_CQGR_GEN_VAL(POINTER, get_index);13411341-13421342- writel(scic->completion_queue_get,13431343- &scic->smu_registers->completion_queue_get);13441344-13451345- }13461346-13471347- dev_dbg(scic_to_dev(scic),13481348- "%s: completion queue ending get:0x%08x\n",13491349- __func__,13501350- scic->completion_queue_get);13511351-13521352-}13531353-13541354-bool scic_sds_controller_isr(struct scic_sds_controller *scic)13551355-{13561356- if (scic_sds_controller_completion_queue_has_entries(scic)) {13571357- return true;13581358- } else {13591359- /*13601360- * we have a spurious interrupt it could be that we have already13611361- * emptied the completion queue from a previous interrupt */13621362- writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status);13631363-13641364- /*13651365- * There is a race in the hardware that could cause us not to be notified13661366- * of an interrupt completion if we do not take this step. We will mask13671367- * then unmask the interrupts so if there is another interrupt pending13681368- * the clearing of the interrupt source we get the next interrupt message. */13691369- writel(0xFF000000, &scic->smu_registers->interrupt_mask);13701370- writel(0, &scic->smu_registers->interrupt_mask);13711371- }13721372-13731373- return false;13741374-}13751375-13761376-void scic_sds_controller_completion_handler(struct scic_sds_controller *scic)13771377-{13781378- /* Empty out the completion queue */13791379- if (scic_sds_controller_completion_queue_has_entries(scic))13801380- scic_sds_controller_process_completions(scic);13811381-13821382- /* Clear the interrupt and enable all interrupts again */13831383- writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status);13841384- /* Could we write the value of SMU_ISR_COMPLETION? */13851385- writel(0xFF000000, &scic->smu_registers->interrupt_mask);13861386- writel(0, &scic->smu_registers->interrupt_mask);13871387-}13881388-13891389-bool scic_sds_controller_error_isr(struct scic_sds_controller *scic)13901390-{13911391- u32 interrupt_status;13921392-13931393- interrupt_status =13941394- readl(&scic->smu_registers->interrupt_status);13951395- interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);13961396-13971397- if (interrupt_status != 0) {13981398- /*13991399- * There is an error interrupt pending so let it through and handle14001400- * in the callback */14011401- return true;14021402- }14031403-14041404- /*14051405- * There is a race in the hardware that could cause us not to be notified14061406- * of an interrupt completion if we do not take this step. We will mask14071407- * then unmask the error interrupts so if there was another interrupt14081408- * pending we will be notified.14091409- * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */14101410- writel(0xff, &scic->smu_registers->interrupt_mask);14111411- writel(0, &scic->smu_registers->interrupt_mask);14121412-14131413- return false;14141414-}14151415-14161416-void scic_sds_controller_error_handler(struct scic_sds_controller *scic)14171417-{14181418- u32 interrupt_status;14191419-14201420- interrupt_status =14211421- readl(&scic->smu_registers->interrupt_status);14221422-14231423- if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&14241424- scic_sds_controller_completion_queue_has_entries(scic)) {14251425-14261426- scic_sds_controller_process_completions(scic);14271427- writel(SMU_ISR_QUEUE_SUSPEND, &scic->smu_registers->interrupt_status);14281428- } else {14291429- dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__,14301430- interrupt_status);14311431-14321432- sci_base_state_machine_change_state(&scic->state_machine,14331433- SCI_BASE_CONTROLLER_STATE_FAILED);14341434-14351435- return;14361436- }14371437-14381438- /* If we dont process any completions I am not sure that we want to do this.14391439- * We are in the middle of a hardware fault and should probably be reset.14401440- */14411441- writel(0, &scic->smu_registers->interrupt_mask);14421442-}14431443-14441444-14451445-14461446-14471447-void scic_sds_controller_link_up(struct scic_sds_controller *scic,14481448- struct scic_sds_port *port, struct scic_sds_phy *phy)14491449-{14501450- switch (scic->state_machine.current_state_id) {14511451- case SCI_BASE_CONTROLLER_STATE_STARTING:14521452- scic_sds_controller_phy_timer_stop(scic);14531453- scic->port_agent.link_up_handler(scic, &scic->port_agent,14541454- port, phy);14551455- scic_sds_controller_start_next_phy(scic);14561456- break;14571457- case SCI_BASE_CONTROLLER_STATE_READY:14581458- scic->port_agent.link_up_handler(scic, &scic->port_agent,14591459- port, phy);14601460- break;14611461- default:14621462- dev_dbg(scic_to_dev(scic),14631463- "%s: SCIC Controller linkup event from phy %d in "14641464- "unexpected state %d\n", __func__, phy->phy_index,14651465- scic->state_machine.current_state_id);14661466- }14671467-}14681468-14691469-void scic_sds_controller_link_down(struct scic_sds_controller *scic,14701470- struct scic_sds_port *port, struct scic_sds_phy *phy)14711471-{14721472- switch (scic->state_machine.current_state_id) {14731473- case SCI_BASE_CONTROLLER_STATE_STARTING:14741474- case SCI_BASE_CONTROLLER_STATE_READY:14751475- scic->port_agent.link_down_handler(scic, &scic->port_agent,14761476- port, phy);14771477- break;14781478- default:14791479- dev_dbg(scic_to_dev(scic),14801480- "%s: SCIC Controller linkdown event from phy %d in "14811481- "unexpected state %d\n",14821482- __func__,14831483- phy->phy_index,14841484- scic->state_machine.current_state_id);14851485- }14861486-}14871487-14881488-/**14891489- * This is a helper method to determine if any remote devices on this14901490- * controller are still in the stopping state.14911491- *14921492- */14931493-static bool scic_sds_controller_has_remote_devices_stopping(14941494- struct scic_sds_controller *controller)14951495-{14961496- u32 index;14971497-14981498- for (index = 0; index < controller->remote_node_entries; index++) {14991499- if ((controller->device_table[index] != NULL) &&15001500- (controller->device_table[index]->state_machine.current_state_id15011501- == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING))15021502- return true;15031503- }15041504-15051505- return false;15061506-}15071507-15081508-/**15091509- * This method is called by the remote device to inform the controller15101510- * object that the remote device has stopped.15111511- */15121512-void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic,15131513- struct scic_sds_remote_device *sci_dev)15141514-{15151515- if (scic->state_machine.current_state_id !=15161516- SCI_BASE_CONTROLLER_STATE_STOPPING) {15171517- dev_dbg(scic_to_dev(scic),15181518- "SCIC Controller 0x%p remote device stopped event "15191519- "from device 0x%p in unexpected state %d\n",15201520- scic, sci_dev,15211521- scic->state_machine.current_state_id);15221522- return;15231523- }15241524-15251525- if (!scic_sds_controller_has_remote_devices_stopping(scic)) {15261526- sci_base_state_machine_change_state(&scic->state_machine,15271527- SCI_BASE_CONTROLLER_STATE_STOPPED);15281528- }15291529-}15301530-15311531-/**15321532- * This method will write to the SCU PCP register the request value. The method15331533- * is used to suspend/resume ports, devices, and phys.15341534- * @scic:15351535- *15361536- *15371537- */15381538-void scic_sds_controller_post_request(15391539- struct scic_sds_controller *scic,15401540- u32 request)15411541-{15421542- dev_dbg(scic_to_dev(scic),15431543- "%s: SCIC Controller 0x%p post request 0x%08x\n",15441544- __func__,15451545- scic,15461546- request);15471547-15481548- writel(request, &scic->smu_registers->post_context_port);15491549-}15501550-15511551-/**15521552- * This method will copy the soft copy of the task context into the physical15531553- * memory accessible by the controller.15541554- * @scic: This parameter specifies the controller for which to copy15551555- * the task context.15561556- * @sci_req: This parameter specifies the request for which the task15571557- * context is being copied.15581558- *15591559- * After this call is made the SCIC_SDS_IO_REQUEST object will always point to15601560- * the physical memory version of the task context. Thus, all subsequent15611561- * updates to the task context are performed in the TC table (i.e. DMAable15621562- * memory). none15631563- */15641564-void scic_sds_controller_copy_task_context(15651565- struct scic_sds_controller *scic,15661566- struct scic_sds_request *sci_req)15671567-{15681568- struct scu_task_context *task_context_buffer;15691569-15701570- task_context_buffer = scic_sds_controller_get_task_context_buffer(15711571- scic, sci_req->io_tag);15721572-15731573- memcpy(task_context_buffer,15741574- sci_req->task_context_buffer,15751575- offsetof(struct scu_task_context, sgl_snapshot_ac));15761576-15771577- /*15781578- * Now that the soft copy of the TC has been copied into the TC15791579- * table accessible by the silicon. Thus, any further changes to15801580- * the TC (e.g. TC termination) occur in the appropriate location. */15811581- sci_req->task_context_buffer = task_context_buffer;15821582-}15831583-15841584-/**15851585- * This method returns the task context buffer for the given io tag.15861586- * @scic:15871587- * @io_tag:15881588- *15891589- * struct scu_task_context*15901590- */15911591-struct scu_task_context *scic_sds_controller_get_task_context_buffer(15921592- struct scic_sds_controller *scic,15931593- u16 io_tag15941594- ) {15951595- u16 task_index = scic_sds_io_tag_get_index(io_tag);15961596-15971597- if (task_index < scic->task_context_entries) {15981598- return &scic->task_context_table[task_index];15991599- }16001600-16011601- return NULL;16021602-}16031603-16041604-struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic,16051605- u16 io_tag)16061606-{16071607- u16 task_index;16081608- u16 task_sequence;16091609-16101610- task_index = scic_sds_io_tag_get_index(io_tag);16111611-16121612- if (task_index < scic->task_context_entries) {16131613- if (scic->io_request_table[task_index] != NULL) {16141614- task_sequence = scic_sds_io_tag_get_sequence(io_tag);16151615-16161616- if (task_sequence == scic->io_request_sequence[task_index]) {16171617- return scic->io_request_table[task_index];16181618- }16191619- }16201620- }16211621-16221622- return NULL;16231623-}16241624-16251625-/**16261626- * This method allocates remote node index and the reserves the remote node16271627- * context space for use. This method can fail if there are no more remote16281628- * node index available.16291629- * @scic: This is the controller object which contains the set of16301630- * free remote node ids16311631- * @sci_dev: This is the device object which is requesting the a remote node16321632- * id16331633- * @node_id: This is the remote node id that is assinged to the device if one16341634- * is available16351635- *16361636- * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote16371637- * node index available.16381638- */16391639-enum sci_status scic_sds_controller_allocate_remote_node_context(16401640- struct scic_sds_controller *scic,16411641- struct scic_sds_remote_device *sci_dev,16421642- u16 *node_id)16431643-{16441644- u16 node_index;16451645- u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev);16461646-16471647- node_index = scic_sds_remote_node_table_allocate_remote_node(16481648- &scic->available_remote_nodes, remote_node_count16491649- );16501650-16511651- if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {16521652- scic->device_table[node_index] = sci_dev;16531653-16541654- *node_id = node_index;16551655-16561656- return SCI_SUCCESS;16571657- }16581658-16591659- return SCI_FAILURE_INSUFFICIENT_RESOURCES;16601660-}16611661-16621662-/**16631663- * This method frees the remote node index back to the available pool. Once16641664- * this is done the remote node context buffer is no longer valid and can16651665- * not be used.16661666- * @scic:16671667- * @sci_dev:16681668- * @node_id:16691669- *16701670- */16711671-void scic_sds_controller_free_remote_node_context(16721672- struct scic_sds_controller *scic,16731673- struct scic_sds_remote_device *sci_dev,16741674- u16 node_id)16751675-{16761676- u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev);16771677-16781678- if (scic->device_table[node_id] == sci_dev) {16791679- scic->device_table[node_id] = NULL;16801680-16811681- scic_sds_remote_node_table_release_remote_node_index(16821682- &scic->available_remote_nodes, remote_node_count, node_id16831683- );16841684- }16851685-}16861686-16871687-/**16881688- * This method returns the union scu_remote_node_context for the specified remote16891689- * node id.16901690- * @scic:16911691- * @node_id:16921692- *16931693- * union scu_remote_node_context*16941694- */16951695-union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(16961696- struct scic_sds_controller *scic,16971697- u16 node_id16981698- ) {16991699- if (17001700- (node_id < scic->remote_node_entries)17011701- && (scic->device_table[node_id] != NULL)17021702- ) {17031703- return &scic->remote_node_context_table[node_id];17041704- }17051705-17061706- return NULL;17071707-}17081708-17091709-/**17101710- *17111711- * @resposne_buffer: This is the buffer into which the D2H register FIS will be17121712- * constructed.17131713- * @frame_header: This is the frame header returned by the hardware.17141714- * @frame_buffer: This is the frame buffer returned by the hardware.17151715- *17161716- * This method will combind the frame header and frame buffer to create a SATA17171717- * D2H register FIS none17181718- */17191719-void scic_sds_controller_copy_sata_response(17201720- void *response_buffer,17211721- void *frame_header,17221722- void *frame_buffer)17231723-{17241724- memcpy(response_buffer, frame_header, sizeof(u32));17251725-17261726- memcpy(response_buffer + sizeof(u32),17271727- frame_buffer,17281728- sizeof(struct dev_to_host_fis) - sizeof(u32));17291729-}17301730-17311731-/**17321732- * This method releases the frame once this is done the frame is available for17331733- * re-use by the hardware. The data contained in the frame header and frame17341734- * buffer is no longer valid. The UF queue get pointer is only updated if UF17351735- * control indicates this is appropriate.17361736- * @scic:17371737- * @frame_index:17381738- *17391739- */17401740-void scic_sds_controller_release_frame(17411741- struct scic_sds_controller *scic,17421742- u32 frame_index)17431743-{17441744- if (scic_sds_unsolicited_frame_control_release_frame(17451745- &scic->uf_control, frame_index) == true)17461746- writel(scic->uf_control.get,17471747- &scic->scu_registers->sdma.unsolicited_frame_get_pointer);17481748-}17491749-17501750-/**17511751- * This method sets user parameters and OEM parameters to default values.17521752- * Users can override these values utilizing the scic_user_parameters_set()17531753- * and scic_oem_parameters_set() methods.17541754- * @scic: This parameter specifies the controller for which to set the17551755- * configuration parameters to their default values.17561756- *17571757- */17581758-static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic)17591759-{17601760- struct isci_host *ihost = scic_to_ihost(scic);17611761- u16 index;17621762-17631763- /* Default to APC mode. */17641764- scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;17651765-17661766- /* Default to APC mode. */17671767- scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1;17681768-17691769- /* Default to no SSC operation. */17701770- scic->oem_parameters.sds1.controller.do_enable_ssc = false;17711771-17721772- /* Initialize all of the port parameter information to narrow ports. */17731773- for (index = 0; index < SCI_MAX_PORTS; index++) {17741774- scic->oem_parameters.sds1.ports[index].phy_mask = 0;17751775- }17761776-17771777- /* Initialize all of the phy parameter information. */17781778- for (index = 0; index < SCI_MAX_PHYS; index++) {17791779- /* Default to 6G (i.e. Gen 3) for now. */17801780- scic->user_parameters.sds1.phys[index].max_speed_generation = 3;17811781-17821782- /* the frequencies cannot be 0 */17831783- scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;17841784- scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;17851785- scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;17861786-17871787- /*17881788- * Previous Vitesse based expanders had a arbitration issue that17891789- * is worked around by having the upper 32-bits of SAS address17901790- * with a value greater then the Vitesse company identifier.17911791- * Hence, usage of 0x5FCFFFFF. */17921792- scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id;17931793- scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF;17941794- }17951795-17961796- scic->user_parameters.sds1.stp_inactivity_timeout = 5;17971797- scic->user_parameters.sds1.ssp_inactivity_timeout = 5;17981798- scic->user_parameters.sds1.stp_max_occupancy_timeout = 5;17991799- scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20;18001800- scic->user_parameters.sds1.no_outbound_task_timeout = 20;18011801-}18021802-18031803-/**18041804- * scic_controller_get_suggested_start_timeout() - This method returns the18051805- * suggested scic_controller_start() timeout amount. The user is free to18061806- * use any timeout value, but this method provides the suggested minimum18071807- * start timeout value. The returned value is based upon empirical18081808- * information determined as a result of interoperability testing.18091809- * @controller: the handle to the controller object for which to return the18101810- * suggested start timeout.18111811- *18121812- * This method returns the number of milliseconds for the suggested start18131813- * operation timeout.18141814- */18151815-u32 scic_controller_get_suggested_start_timeout(18161816- struct scic_sds_controller *sc)18171817-{18181818- /* Validate the user supplied parameters. */18191819- if (sc == NULL)18201820- return 0;18211821-18221822- /*18231823- * The suggested minimum timeout value for a controller start operation:18241824- *18251825- * Signature FIS Timeout18261826- * + Phy Start Timeout18271827- * + Number of Phy Spin Up Intervals18281828- * ---------------------------------18291829- * Number of milliseconds for the controller start operation.18301830- *18311831- * NOTE: The number of phy spin up intervals will be equivalent18321832- * to the number of phys divided by the number phys allowed18331833- * per interval - 1 (once OEM parameters are supported).18341834- * Currently we assume only 1 phy per interval. */18351835-18361836- return SCIC_SDS_SIGNATURE_FIS_TIMEOUT18371837- + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT18381838- + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);18391839-}18401840-18411841-/**18421842- * scic_controller_stop() - This method will stop an individual controller18431843- * object.This method will invoke the associated user callback upon18441844- * completion. The completion callback is called when the following18451845- * conditions are met: -# the method return status is SCI_SUCCESS. -# the18461846- * controller has been quiesced. This method will ensure that all IO18471847- * requests are quiesced, phys are stopped, and all additional operation by18481848- * the hardware is halted.18491849- * @controller: the handle to the controller object to stop.18501850- * @timeout: This parameter specifies the number of milliseconds in which the18511851- * stop operation should complete.18521852- *18531853- * The controller must be in the STARTED or STOPPED state. Indicate if the18541854- * controller stop method succeeded or failed in some way. SCI_SUCCESS if the18551855- * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the18561856- * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the18571857- * controller is not either in the STARTED or STOPPED states.18581858- */18591859-enum sci_status scic_controller_stop(18601860- struct scic_sds_controller *scic,18611861- u32 timeout)18621862-{18631863- if (scic->state_machine.current_state_id !=18641864- SCI_BASE_CONTROLLER_STATE_READY) {18651865- dev_warn(scic_to_dev(scic),18661866- "SCIC Controller stop operation requested in "18671867- "invalid state\n");18681868- return SCI_FAILURE_INVALID_STATE;18691869- }18701870-18711871- isci_timer_start(scic->timeout_timer, timeout);18721872- sci_base_state_machine_change_state(&scic->state_machine,18731873- SCI_BASE_CONTROLLER_STATE_STOPPING);18741874- return SCI_SUCCESS;18751875-}18761876-18771877-/**18781878- * scic_controller_reset() - This method will reset the supplied core18791879- * controller regardless of the state of said controller. This operation is18801880- * considered destructive. In other words, all current operations are wiped18811881- * out. No IO completions for outstanding devices occur. Outstanding IO18821882- * requests are not aborted or completed at the actual remote device.18831883- * @controller: the handle to the controller object to reset.18841884- *18851885- * Indicate if the controller reset method succeeded or failed in some way.18861886- * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if18871887- * the controller reset operation is unable to complete.18881888- */18891889-enum sci_status scic_controller_reset(18901890- struct scic_sds_controller *scic)18911891-{18921892- switch (scic->state_machine.current_state_id) {18931893- case SCI_BASE_CONTROLLER_STATE_RESET:18941894- case SCI_BASE_CONTROLLER_STATE_READY:18951895- case SCI_BASE_CONTROLLER_STATE_STOPPED:18961896- case SCI_BASE_CONTROLLER_STATE_FAILED:18971897- /*18981898- * The reset operation is not a graceful cleanup, just18991899- * perform the state transition.19001900- */19011901- sci_base_state_machine_change_state(&scic->state_machine,19021902- SCI_BASE_CONTROLLER_STATE_RESETTING);19031903- return SCI_SUCCESS;19041904- default:19051905- dev_warn(scic_to_dev(scic),19061906- "SCIC Controller reset operation requested in "19071907- "invalid state\n");19081908- return SCI_FAILURE_INVALID_STATE;19091909- }19101910-}19111911-19121912-/**19131913- * scic_controller_start_io() - This method is called by the SCI user to19141914- * send/start an IO request. If the method invocation is successful, then19151915- * the IO request has been queued to the hardware for processing.19161916- * @controller: the handle to the controller object for which to start an IO19171917- * request.19181918- * @remote_device: the handle to the remote device object for which to start an19191919- * IO request.19201920- * @io_request: the handle to the io request object to start.19211921- * @io_tag: This parameter specifies a previously allocated IO tag that the19221922- * user desires to be utilized for this request. This parameter is optional.19231923- * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value19241924- * for this parameter.19251925- *19261926- * - IO tags are a protected resource. It is incumbent upon the SCI Core user19271927- * to ensure that each of the methods that may allocate or free available IO19281928- * tags are handled in a mutually exclusive manner. This method is one of said19291929- * methods requiring proper critical code section protection (e.g. semaphore,19301930- * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a19311931- * result, it is expected the user will have set the NCQ tag field in the host19321932- * to device register FIS prior to calling this method. There is also a19331933- * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking19341934- * the scic_controller_start_io() method. scic_controller_allocate_tag() for19351935- * more information on allocating a tag. Indicate if the controller19361936- * successfully started the IO request. SCI_SUCCESS if the IO request was19371937- * successfully started. Determine the failure situations and return values.19381938- */19391939-enum sci_status scic_controller_start_io(19401940- struct scic_sds_controller *scic,19411941- struct scic_sds_remote_device *rdev,19421942- struct scic_sds_request *req,19431943- u16 io_tag)19441944-{19451945- enum sci_status status;19461946-19471947- if (scic->state_machine.current_state_id !=19481948- SCI_BASE_CONTROLLER_STATE_READY) {19491949- dev_warn(scic_to_dev(scic), "invalid state to start I/O");19501950- return SCI_FAILURE_INVALID_STATE;19511951- }19521952-19531953- status = scic_sds_remote_device_start_io(scic, rdev, req);19541954- if (status != SCI_SUCCESS)19551955- return status;19561956-19571957- scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req;19581958- scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req));19591959- return SCI_SUCCESS;19601960-}19611961-19621962-/**19631963- * scic_controller_terminate_request() - This method is called by the SCI Core19641964- * user to terminate an ongoing (i.e. started) core IO request. This does19651965- * not abort the IO request at the target, but rather removes the IO request19661966- * from the host controller.19671967- * @controller: the handle to the controller object for which to terminate a19681968- * request.19691969- * @remote_device: the handle to the remote device object for which to19701970- * terminate a request.19711971- * @request: the handle to the io or task management request object to19721972- * terminate.19731973- *19741974- * Indicate if the controller successfully began the terminate process for the19751975- * IO request. SCI_SUCCESS if the terminate process was successfully started19761976- * for the request. Determine the failure situations and return values.19771977- */19781978-enum sci_status scic_controller_terminate_request(19791979- struct scic_sds_controller *scic,19801980- struct scic_sds_remote_device *rdev,19811981- struct scic_sds_request *req)19821982-{19831983- enum sci_status status;19841984-19851985- if (scic->state_machine.current_state_id !=19861986- SCI_BASE_CONTROLLER_STATE_READY) {19871987- dev_warn(scic_to_dev(scic),19881988- "invalid state to terminate request\n");19891989- return SCI_FAILURE_INVALID_STATE;19901990- }19911991-19921992- status = scic_sds_io_request_terminate(req);19931993- if (status != SCI_SUCCESS)19941994- return status;19951995-19961996- /*19971997- * Utilize the original post context command and or in the POST_TC_ABORT19981998- * request sub-type.19991999- */20002000- scic_sds_controller_post_request(scic,20012001- scic_sds_request_get_post_context(req) |20022002- SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT);20032003- return SCI_SUCCESS;20042004-}20052005-20062006-/**20072007- * scic_controller_complete_io() - This method will perform core specific20082008- * completion operations for an IO request. After this method is invoked,20092009- * the user should consider the IO request as invalid until it is properly20102010- * reused (i.e. re-constructed).20112011- * @controller: The handle to the controller object for which to complete the20122012- * IO request.20132013- * @remote_device: The handle to the remote device object for which to complete20142014- * the IO request.20152015- * @io_request: the handle to the io request object to complete.20162016- *20172017- * - IO tags are a protected resource. It is incumbent upon the SCI Core user20182018- * to ensure that each of the methods that may allocate or free available IO20192019- * tags are handled in a mutually exclusive manner. This method is one of said20202020- * methods requiring proper critical code section protection (e.g. semaphore,20212021- * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI20222022- * Core user, using the scic_controller_allocate_io_tag() method, then it is20232023- * the responsibility of the caller to invoke the scic_controller_free_io_tag()20242024- * method to free the tag (i.e. this method will not free the IO tag). Indicate20252025- * if the controller successfully completed the IO request. SCI_SUCCESS if the20262026- * completion process was successful.20272027- */20282028-enum sci_status scic_controller_complete_io(20292029- struct scic_sds_controller *scic,20302030- struct scic_sds_remote_device *rdev,20312031- struct scic_sds_request *request)20322032-{20332033- enum sci_status status;20342034- u16 index;20352035-20362036- switch (scic->state_machine.current_state_id) {20372037- case SCI_BASE_CONTROLLER_STATE_STOPPING:20382038- /* XXX: Implement this function */20392039- return SCI_FAILURE;20402040- case SCI_BASE_CONTROLLER_STATE_READY:20412041- status = scic_sds_remote_device_complete_io(scic, rdev, request);20422042- if (status != SCI_SUCCESS)20432043- return status;20442044-20452045- index = scic_sds_io_tag_get_index(request->io_tag);20462046- scic->io_request_table[index] = NULL;20472047- return SCI_SUCCESS;20482048- default:20492049- dev_warn(scic_to_dev(scic), "invalid state to complete I/O");20502050- return SCI_FAILURE_INVALID_STATE;20512051- }20522052-20532053-}20542054-20552055-enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req)20562056-{20572057- struct scic_sds_controller *scic = sci_req->owning_controller;20582058-20592059- if (scic->state_machine.current_state_id !=20602060- SCI_BASE_CONTROLLER_STATE_READY) {20612061- dev_warn(scic_to_dev(scic), "invalid state to continue I/O");20622062- return SCI_FAILURE_INVALID_STATE;20632063- }20642064-20652065- scic->io_request_table[scic_sds_io_tag_get_index(sci_req->io_tag)] = sci_req;20662066- scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req));20672067- return SCI_SUCCESS;20682068-}20692069-20702070-/**20712071- * scic_controller_start_task() - This method is called by the SCIC user to20722072- * send/start a framework task management request.20732073- * @controller: the handle to the controller object for which to start the task20742074- * management request.20752075- * @remote_device: the handle to the remote device object for which to start20762076- * the task management request.20772077- * @task_request: the handle to the task request object to start.20782078- * @io_tag: This parameter specifies a previously allocated IO tag that the20792079- * user desires to be utilized for this request. Note this not the io_tag20802080- * of the request being managed. It is to be utilized for the task request20812081- * itself. This parameter is optional. The user is allowed to supply20822082- * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.20832083- *20842084- * - IO tags are a protected resource. It is incumbent upon the SCI Core user20852085- * to ensure that each of the methods that may allocate or free available IO20862086- * tags are handled in a mutually exclusive manner. This method is one of said20872087- * methods requiring proper critical code section protection (e.g. semaphore,20882088- * spin-lock, etc.). - The user must synchronize this task with completion20892089- * queue processing. If they are not synchronized then it is possible for the20902090- * io requests that are being managed by the task request can complete before20912091- * starting the task request. scic_controller_allocate_tag() for more20922092- * information on allocating a tag. Indicate if the controller successfully20932093- * started the IO request. SCI_TASK_SUCCESS if the task request was20942094- * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is20952095- * returned if there is/are task(s) outstanding that require termination or20962096- * completion before this request can succeed.20972097- */20982098-enum sci_task_status scic_controller_start_task(20992099- struct scic_sds_controller *scic,21002100- struct scic_sds_remote_device *rdev,21012101- struct scic_sds_request *req,21022102- u16 task_tag)21032103-{21042104- enum sci_status status;21052105-21062106- if (scic->state_machine.current_state_id !=21072107- SCI_BASE_CONTROLLER_STATE_READY) {21082108- dev_warn(scic_to_dev(scic),21092109- "%s: SCIC Controller starting task from invalid "21102110- "state\n",21112111- __func__);21122112- return SCI_TASK_FAILURE_INVALID_STATE;21132113- }21142114-21152115- status = scic_sds_remote_device_start_task(scic, rdev, req);21162116- switch (status) {21172117- case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS:21182118- scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req;21192119-21202120- /*21212121- * We will let framework know this task request started successfully,21222122- * although core is still woring on starting the request (to post tc when21232123- * RNC is resumed.)21242124- */21252125- return SCI_SUCCESS;21262126- case SCI_SUCCESS:21272127- scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req;21282128-21292129- scic_sds_controller_post_request(scic,21302130- scic_sds_request_get_post_context(req));21312131- break;21322132- default:21332133- break;21342134- }21352135-21362136- return status;21372137-}21382138-21392139-/**21402140- * scic_controller_allocate_io_tag() - This method will allocate a tag from the21412141- * pool of free IO tags. Direct allocation of IO tags by the SCI Core user21422142- * is optional. The scic_controller_start_io() method will allocate an IO21432143- * tag if this method is not utilized and the tag is not supplied to the IO21442144- * construct routine. Direct allocation of IO tags may provide additional21452145- * performance improvements in environments capable of supporting this usage21462146- * model. Additionally, direct allocation of IO tags also provides21472147- * additional flexibility to the SCI Core user. Specifically, the user may21482148- * retain IO tags across the lives of multiple IO requests.21492149- * @controller: the handle to the controller object for which to allocate the21502150- * tag.21512151- *21522152- * IO tags are a protected resource. It is incumbent upon the SCI Core user to21532153- * ensure that each of the methods that may allocate or free available IO tags21542154- * are handled in a mutually exclusive manner. This method is one of said21552155- * methods requiring proper critical code section protection (e.g. semaphore,21562156- * spin-lock, etc.). An unsigned integer representing an available IO tag.21572157- * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no21582158- * currently available tags to be allocated. All return other values indicate a21592159- * legitimate tag.21602160- */21612161-u16 scic_controller_allocate_io_tag(21622162- struct scic_sds_controller *scic)21632163-{21642164- u16 task_context;21652165- u16 sequence_count;21662166-21672167- if (!sci_pool_empty(scic->tci_pool)) {21682168- sci_pool_get(scic->tci_pool, task_context);21692169-21702170- sequence_count = scic->io_request_sequence[task_context];21712171-21722172- return scic_sds_io_tag_construct(sequence_count, task_context);21732173- }21742174-21752175- return SCI_CONTROLLER_INVALID_IO_TAG;21762176-}21772177-21782178-/**21792179- * scic_controller_free_io_tag() - This method will free an IO tag to the pool21802180- * of free IO tags. This method provides the SCI Core user more flexibility21812181- * with regards to IO tags. The user may desire to keep an IO tag after an21822182- * IO request has completed, because they plan on re-using the tag for a21832183- * subsequent IO request. This method is only legal if the tag was21842184- * allocated via scic_controller_allocate_io_tag().21852185- * @controller: This parameter specifies the handle to the controller object21862186- * for which to free/return the tag.21872187- * @io_tag: This parameter represents the tag to be freed to the pool of21882188- * available tags.21892189- *21902190- * - IO tags are a protected resource. It is incumbent upon the SCI Core user21912191- * to ensure that each of the methods that may allocate or free available IO21922192- * tags are handled in a mutually exclusive manner. This method is one of said21932193- * methods requiring proper critical code section protection (e.g. semaphore,21942194- * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI21952195- * Core user, using the scic_controller_allocate_io_tag() method, then it is21962196- * the responsibility of the caller to invoke this method to free the tag. This21972197- * method returns an indication of whether the tag was successfully put back21982198- * (freed) to the pool of available tags. SCI_SUCCESS This return value21992199- * indicates the tag was successfully placed into the pool of available IO22002200- * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag22012201- * is not a valid IO tag value.22022202- */22032203-enum sci_status scic_controller_free_io_tag(22042204- struct scic_sds_controller *scic,22052205- u16 io_tag)22062206-{22072207- u16 sequence;22082208- u16 index;22092209-22102210- BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG);22112211-22122212- sequence = scic_sds_io_tag_get_sequence(io_tag);22132213- index = scic_sds_io_tag_get_index(io_tag);22142214-22152215- if (!sci_pool_full(scic->tci_pool)) {22162216- if (sequence == scic->io_request_sequence[index]) {22172217- scic_sds_io_sequence_increment(22182218- scic->io_request_sequence[index]);22192219-22202220- sci_pool_put(scic->tci_pool, index);22212221-22222222- return SCI_SUCCESS;22232223- }22242224- }22252225-22262226- return SCI_FAILURE_INVALID_IO_TAG;22272227-}22282228-22292229-void scic_controller_enable_interrupts(22302230- struct scic_sds_controller *scic)22312231-{22322232- BUG_ON(scic->smu_registers == NULL);22332233- writel(0, &scic->smu_registers->interrupt_mask);22342234-}22352235-22362236-void scic_controller_disable_interrupts(22372237- struct scic_sds_controller *scic)22382238-{22392239- BUG_ON(scic->smu_registers == NULL);22402240- writel(0xffffffff, &scic->smu_registers->interrupt_mask);22412241-}22422242-22432243-static enum sci_status scic_controller_set_mode(22442244- struct scic_sds_controller *scic,22452245- enum sci_controller_mode operating_mode)22462246-{22472247- enum sci_status status = SCI_SUCCESS;22482248-22492249- if ((scic->state_machine.current_state_id ==22502250- SCI_BASE_CONTROLLER_STATE_INITIALIZING) ||22512251- (scic->state_machine.current_state_id ==22522252- SCI_BASE_CONTROLLER_STATE_INITIALIZED)) {22532253- switch (operating_mode) {22542254- case SCI_MODE_SPEED:22552255- scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES;22562256- scic->task_context_entries = SCU_IO_REQUEST_COUNT;22572257- scic->uf_control.buffers.count =22582258- SCU_UNSOLICITED_FRAME_COUNT;22592259- scic->completion_event_entries = SCU_EVENT_COUNT;22602260- scic->completion_queue_entries =22612261- SCU_COMPLETION_QUEUE_COUNT;22622262- break;22632263-22642264- case SCI_MODE_SIZE:22652265- scic->remote_node_entries = SCI_MIN_REMOTE_DEVICES;22662266- scic->task_context_entries = SCI_MIN_IO_REQUESTS;22672267- scic->uf_control.buffers.count =22682268- SCU_MIN_UNSOLICITED_FRAMES;22692269- scic->completion_event_entries = SCU_MIN_EVENTS;22702270- scic->completion_queue_entries =22712271- SCU_MIN_COMPLETION_QUEUE_ENTRIES;22722272- break;22732273-22742274- default:22752275- status = SCI_FAILURE_INVALID_PARAMETER_VALUE;22762276- break;22772277- }22782278- } else22792279- status = SCI_FAILURE_INVALID_STATE;22802280-22812281- return status;22822282-}22832283-22842284-/**22852285- * scic_sds_controller_reset_hardware() -22862286- *22872287- * This method will reset the controller hardware.22882288- */22892289-static void scic_sds_controller_reset_hardware(22902290- struct scic_sds_controller *scic)22912291-{22922292- /* Disable interrupts so we dont take any spurious interrupts */22932293- scic_controller_disable_interrupts(scic);22942294-22952295- /* Reset the SCU */22962296- writel(0xFFFFFFFF, &scic->smu_registers->soft_reset_control);22972297-22982298- /* Delay for 1ms to before clearing the CQP and UFQPR. */22992299- udelay(1000);23002300-23012301- /* The write to the CQGR clears the CQP */23022302- writel(0x00000000, &scic->smu_registers->completion_queue_get);23032303-23042304- /* The write to the UFQGP clears the UFQPR */23052305- writel(0, &scic->scu_registers->sdma.unsolicited_frame_get_pointer);23062306-}23072307-23082308-enum sci_status scic_user_parameters_set(23092309- struct scic_sds_controller *scic,23102310- union scic_user_parameters *scic_parms)23112311-{23122312- u32 state = scic->state_machine.current_state_id;23132313-23142314- if (state == SCI_BASE_CONTROLLER_STATE_RESET ||23152315- state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||23162316- state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {23172317- u16 index;23182318-23192319- /*23202320- * Validate the user parameters. If they are not legal, then23212321- * return a failure.23222322- */23232323- for (index = 0; index < SCI_MAX_PHYS; index++) {23242324- struct sci_phy_user_params *user_phy;23252325-23262326- user_phy = &scic_parms->sds1.phys[index];23272327-23282328- if (!((user_phy->max_speed_generation <=23292329- SCIC_SDS_PARM_MAX_SPEED) &&23302330- (user_phy->max_speed_generation >23312331- SCIC_SDS_PARM_NO_SPEED)))23322332- return SCI_FAILURE_INVALID_PARAMETER_VALUE;23332333-23342334- if (user_phy->in_connection_align_insertion_frequency <23352335- 3)23362336- return SCI_FAILURE_INVALID_PARAMETER_VALUE;23372337-23382338- if ((user_phy->in_connection_align_insertion_frequency <23392339- 3) ||23402340- (user_phy->align_insertion_frequency == 0) ||23412341- (user_phy->23422342- notify_enable_spin_up_insertion_frequency ==23432343- 0))23442344- return SCI_FAILURE_INVALID_PARAMETER_VALUE;23452345- }23462346-23472347- if ((scic_parms->sds1.stp_inactivity_timeout == 0) ||23482348- (scic_parms->sds1.ssp_inactivity_timeout == 0) ||23492349- (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||23502350- (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||23512351- (scic_parms->sds1.no_outbound_task_timeout == 0))23522352- return SCI_FAILURE_INVALID_PARAMETER_VALUE;23532353-23542354- memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms));23552355-23562356- return SCI_SUCCESS;23572357- }23582358-23592359- return SCI_FAILURE_INVALID_STATE;23602360-}23612361-23622362-int scic_oem_parameters_validate(struct scic_sds_oem_params *oem)23632363-{23642364- int i;23652365-23662366- for (i = 0; i < SCI_MAX_PORTS; i++)23672367- if (oem->ports[i].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)23682368- return -EINVAL;23692369-23702370- for (i = 0; i < SCI_MAX_PHYS; i++)23712371- if (oem->phys[i].sas_address.high == 0 &&23722372- oem->phys[i].sas_address.low == 0)23732373- return -EINVAL;23742374-23752375- if (oem->controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) {23762376- for (i = 0; i < SCI_MAX_PHYS; i++)23772377- if (oem->ports[i].phy_mask != 0)23782378- return -EINVAL;23792379- } else if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {23802380- u8 phy_mask = 0;23812381-23822382- for (i = 0; i < SCI_MAX_PHYS; i++)23832383- phy_mask |= oem->ports[i].phy_mask;23842384-23852385- if (phy_mask == 0)23862386- return -EINVAL;23872387- } else23882388- return -EINVAL;23892389-23902390- if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)23912391- return -EINVAL;23922392-23932393- return 0;23942394-}23952395-23962396-enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic,23972397- union scic_oem_parameters *scic_parms)23982398-{23992399- u32 state = scic->state_machine.current_state_id;24002400-24012401- if (state == SCI_BASE_CONTROLLER_STATE_RESET ||24022402- state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||24032403- state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {24042404-24052405- if (scic_oem_parameters_validate(&scic_parms->sds1))24062406- return SCI_FAILURE_INVALID_PARAMETER_VALUE;24072407- scic->oem_parameters.sds1 = scic_parms->sds1;24082408-24092409- return SCI_SUCCESS;24102410- }24112411-24122412- return SCI_FAILURE_INVALID_STATE;24132413-}24142414-24152415-void scic_oem_parameters_get(24162416- struct scic_sds_controller *scic,24172417- union scic_oem_parameters *scic_parms)24182418-{24192419- memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms));24202420-}24212421-24222422-#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 85324232423-#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 128024242424-#define INTERRUPT_COALESCE_TIMEOUT_MAX_US 270000024252425-#define INTERRUPT_COALESCE_NUMBER_MAX 25624262426-#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 724272427-#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 2824282428-24292429-/**24302430- * scic_controller_set_interrupt_coalescence() - This method allows the user to24312431- * configure the interrupt coalescence.24322432- * @controller: This parameter represents the handle to the controller object24332433- * for which its interrupt coalesce register is overridden.24342434- * @coalesce_number: Used to control the number of entries in the Completion24352435- * Queue before an interrupt is generated. If the number of entries exceed24362436- * this number, an interrupt will be generated. The valid range of the input24372437- * is [0, 256]. A setting of 0 results in coalescing being disabled.24382438- * @coalesce_timeout: Timeout value in microseconds. The valid range of the24392439- * input is [0, 2700000] . A setting of 0 is allowed and results in no24402440- * interrupt coalescing timeout.24412441- *24422442- * Indicate if the user successfully set the interrupt coalesce parameters.24432443- * SCI_SUCCESS The user successfully updated the interrutp coalescence.24442444- * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range.24452445- */24462446-static enum sci_status scic_controller_set_interrupt_coalescence(24472447- struct scic_sds_controller *scic_controller,24482448- u32 coalesce_number,24492449- u32 coalesce_timeout)24502450-{24512451- u8 timeout_encode = 0;24522452- u32 min = 0;24532453- u32 max = 0;24542454-24552455- /* Check if the input parameters fall in the range. */24562456- if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)24572457- return SCI_FAILURE_INVALID_PARAMETER_VALUE;24582458-24592459- /*24602460- * Defined encoding for interrupt coalescing timeout:24612461- * Value Min Max Units24622462- * ----- --- --- -----24632463- * 0 - - Disabled24642464- * 1 13.3 20.0 ns24652465- * 2 26.7 40.024662466- * 3 53.3 80.024672467- * 4 106.7 160.024682468- * 5 213.3 320.024692469- * 6 426.7 640.024702470- * 7 853.3 1280.024712471- * 8 1.7 2.6 us24722472- * 9 3.4 5.124732473- * 10 6.8 10.224742474- * 11 13.7 20.524752475- * 12 27.3 41.024762476- * 13 54.6 81.924772477- * 14 109.2 163.824782478- * 15 218.5 327.724792479- * 16 436.9 655.424802480- * 17 873.8 1310.724812481- * 18 1.7 2.6 ms24822482- * 19 3.5 5.224832483- * 20 7.0 10.524842484- * 21 14.0 21.024852485- * 22 28.0 41.924862486- * 23 55.9 83.924872487- * 24 111.8 167.824882488- * 25 223.7 335.524892489- * 26 447.4 671.124902490- * 27 894.8 1342.224912491- * 28 1.8 2.7 s24922492- * Others Undefined */24932493-24942494- /*24952495- * Use the table above to decide the encode of interrupt coalescing timeout24962496- * value for register writing. */24972497- if (coalesce_timeout == 0)24982498- timeout_encode = 0;24992499- else{25002500- /* make the timeout value in unit of (10 ns). */25012501- coalesce_timeout = coalesce_timeout * 100;25022502- min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;25032503- max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;25042504-25052505- /* get the encode of timeout for register writing. */25062506- for (timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;25072507- timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;25082508- timeout_encode++) {25092509- if (min <= coalesce_timeout && max > coalesce_timeout)25102510- break;25112511- else if (coalesce_timeout >= max && coalesce_timeout < min * 225122512- && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US * 100) {25132513- if ((coalesce_timeout - max) < (2 * min - coalesce_timeout))25142514- break;25152515- else{25162516- timeout_encode++;25172517- break;25182518- }25192519- } else {25202520- max = max * 2;25212521- min = min * 2;25222522- }25232523- }25242524-25252525- if (timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX + 1)25262526- /* the value is out of range. */25272527- return SCI_FAILURE_INVALID_PARAMETER_VALUE;25282528- }25292529-25302530- writel(SMU_ICC_GEN_VAL(NUMBER, coalesce_number) |25312531- SMU_ICC_GEN_VAL(TIMER, timeout_encode),25322532- &scic_controller->smu_registers->interrupt_coalesce_control);25332533-25342534-25352535- scic_controller->interrupt_coalesce_number = (u16)coalesce_number;25362536- scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100;25372537-25382538- return SCI_SUCCESS;25392539-}25402540-25412541-25422542-25432543-enum sci_status scic_controller_initialize(struct scic_sds_controller *scic)25442544-{25452545- struct sci_base_state_machine *sm = &scic->state_machine;25462546- enum sci_status result = SCI_SUCCESS;25472547- struct isci_host *ihost = scic_to_ihost(scic);25482548- u32 index, state;25492549-25502550- if (scic->state_machine.current_state_id !=25512551- SCI_BASE_CONTROLLER_STATE_RESET) {25522552- dev_warn(scic_to_dev(scic),25532553- "SCIC Controller initialize operation requested "25542554- "in invalid state\n");25552555- return SCI_FAILURE_INVALID_STATE;25562556- }25572557-25582558- sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING);25592559-25602560- scic->timeout_timer = isci_timer_create(ihost,25612561- scic,25622562- scic_sds_controller_timeout_handler);25632563-25642564- scic_sds_controller_initialize_phy_startup(scic);25652565-25662566- scic_sds_controller_initialize_power_control(scic);25672567-25682568- /*25692569- * There is nothing to do here for B0 since we do not have to25702570- * program the AFE registers.25712571- * / @todo The AFE settings are supposed to be correct for the B0 but25722572- * / presently they seem to be wrong. */25732573- scic_sds_controller_afe_initialization(scic);25742574-25752575- if (result == SCI_SUCCESS) {25762576- u32 status;25772577- u32 terminate_loop;25782578-25792579- /* Take the hardware out of reset */25802580- writel(0, &scic->smu_registers->soft_reset_control);25812581-25822582- /*25832583- * / @todo Provide meaningfull error code for hardware failure25842584- * result = SCI_FAILURE_CONTROLLER_HARDWARE; */25852585- result = SCI_FAILURE;25862586- terminate_loop = 100;25872587-25882588- while (terminate_loop-- && (result != SCI_SUCCESS)) {25892589- /* Loop until the hardware reports success */25902590- udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME);25912591- status = readl(&scic->smu_registers->control_status);25922592-25932593- if ((status & SCU_RAM_INIT_COMPLETED) ==25942594- SCU_RAM_INIT_COMPLETED)25952595- result = SCI_SUCCESS;25962596- }25972597- }25982598-25992599- if (result == SCI_SUCCESS) {26002600- u32 max_supported_ports;26012601- u32 max_supported_devices;26022602- u32 max_supported_io_requests;26032603- u32 device_context_capacity;26042604-26052605- /*26062606- * Determine what are the actaul device capacities that the26072607- * hardware will support */26082608- device_context_capacity =26092609- readl(&scic->smu_registers->device_context_capacity);26102610-26112611-26122612- max_supported_ports = smu_dcc_get_max_ports(device_context_capacity);26132613- max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity);26142614- max_supported_io_requests = smu_dcc_get_max_task_context(device_context_capacity);26152615-26162616- /*26172617- * Make all PEs that are unassigned match up with the26182618- * logical ports26192619- */26202620- for (index = 0; index < max_supported_ports; index++) {26212621- struct scu_port_task_scheduler_group_registers __iomem26222622- *ptsg = &scic->scu_registers->peg0.ptsg;26232623-26242624- writel(index, &ptsg->protocol_engine[index]);26252625- }26262626-26272627- /* Record the smaller of the two capacity values */26282628- scic->logical_port_entries =26292629- min(max_supported_ports, scic->logical_port_entries);26302630-26312631- scic->task_context_entries =26322632- min(max_supported_io_requests,26332633- scic->task_context_entries);26342634-26352635- scic->remote_node_entries =26362636- min(max_supported_devices, scic->remote_node_entries);26372637-26382638- /*26392639- * Now that we have the correct hardware reported minimum values26402640- * build the MDL for the controller. Default to a performance26412641- * configuration.26422642- */26432643- scic_controller_set_mode(scic, SCI_MODE_SPEED);26442644- }26452645-26462646- /* Initialize hardware PCI Relaxed ordering in DMA engines */26472647- if (result == SCI_SUCCESS) {26482648- u32 dma_configuration;26492649-26502650- /* Configure the payload DMA */26512651- dma_configuration =26522652- readl(&scic->scu_registers->sdma.pdma_configuration);26532653- dma_configuration |=26542654- SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);26552655- writel(dma_configuration,26562656- &scic->scu_registers->sdma.pdma_configuration);26572657-26582658- /* Configure the control DMA */26592659- dma_configuration =26602660- readl(&scic->scu_registers->sdma.cdma_configuration);26612661- dma_configuration |=26622662- SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);26632663- writel(dma_configuration,26642664- &scic->scu_registers->sdma.cdma_configuration);26652665- }26662666-26672667- /*26682668- * Initialize the PHYs before the PORTs because the PHY registers26692669- * are accessed during the port initialization.26702670- */26712671- if (result == SCI_SUCCESS) {26722672- /* Initialize the phys */26732673- for (index = 0;26742674- (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);26752675- index++) {26762676- result = scic_sds_phy_initialize(26772677- &ihost->phys[index].sci,26782678- &scic->scu_registers->peg0.pe[index].tl,26792679- &scic->scu_registers->peg0.pe[index].ll);26802680- }26812681- }26822682-26832683- if (result == SCI_SUCCESS) {26842684- /* Initialize the logical ports */26852685- for (index = 0;26862686- (index < scic->logical_port_entries) &&26872687- (result == SCI_SUCCESS);26882688- index++) {26892689- result = scic_sds_port_initialize(26902690- &ihost->ports[index].sci,26912691- &scic->scu_registers->peg0.ptsg.port[index],26922692- &scic->scu_registers->peg0.ptsg.protocol_engine,26932693- &scic->scu_registers->peg0.viit[index]);26942694- }26952695- }26962696-26972697- if (result == SCI_SUCCESS)26982698- result = scic_sds_port_configuration_agent_initialize(26992699- scic,27002700- &scic->port_agent);27012701-27022702- /* Advance the controller state machine */27032703- if (result == SCI_SUCCESS)27042704- state = SCI_BASE_CONTROLLER_STATE_INITIALIZED;27052705- else27062706- state = SCI_BASE_CONTROLLER_STATE_FAILED;27072707- sci_base_state_machine_change_state(sm, state);27082708-27092709- return result;27102710-}27112711-27122712-enum sci_status scic_controller_start(struct scic_sds_controller *scic,27132713- u32 timeout)27142714-{27152715- struct isci_host *ihost = scic_to_ihost(scic);27162716- enum sci_status result;27172717- u16 index;27182718-27192719- if (scic->state_machine.current_state_id !=27202720- SCI_BASE_CONTROLLER_STATE_INITIALIZED) {27212721- dev_warn(scic_to_dev(scic),27222722- "SCIC Controller start operation requested in "27232723- "invalid state\n");27242724- return SCI_FAILURE_INVALID_STATE;27252725- }27262726-27272727- /* Build the TCi free pool */27282728- sci_pool_initialize(scic->tci_pool);27292729- for (index = 0; index < scic->task_context_entries; index++)27302730- sci_pool_put(scic->tci_pool, index);27312731-27322732- /* Build the RNi free pool */27332733- scic_sds_remote_node_table_initialize(27342734- &scic->available_remote_nodes,27352735- scic->remote_node_entries);27362736-27372737- /*27382738- * Before anything else lets make sure we will not be27392739- * interrupted by the hardware.27402740- */27412741- scic_controller_disable_interrupts(scic);27422742-27432743- /* Enable the port task scheduler */27442744- scic_sds_controller_enable_port_task_scheduler(scic);27452745-27462746- /* Assign all the task entries to scic physical function */27472747- scic_sds_controller_assign_task_entries(scic);27482748-27492749- /* Now initialize the completion queue */27502750- scic_sds_controller_initialize_completion_queue(scic);27512751-27522752- /* Initialize the unsolicited frame queue for use */27532753- scic_sds_controller_initialize_unsolicited_frame_queue(scic);27542754-27552755- /* Start all of the ports on this controller */27562756- for (index = 0; index < scic->logical_port_entries; index++) {27572757- struct scic_sds_port *sci_port = &ihost->ports[index].sci;27582758-27592759- result = sci_port->state_handlers->start_handler(sci_port);27602760- if (result)27612761- return result;27622762- }27632763-27642764- scic_sds_controller_start_next_phy(scic);27652765-27662766- isci_timer_start(scic->timeout_timer, timeout);27672767-27682768- sci_base_state_machine_change_state(&scic->state_machine,27692769- SCI_BASE_CONTROLLER_STATE_STARTING);27702770-27712771- return SCI_SUCCESS;27722772-}27732773-27742774-/**27752775- *27762776- * @object: This is the object which is cast to a struct scic_sds_controller27772777- * object.27782778- *27792779- * This method implements the actions taken by the struct scic_sds_controller on entry27802780- * to the SCI_BASE_CONTROLLER_STATE_INITIAL. - Set the state handlers to the27812781- * controllers initial state. none This function should initialize the27822782- * controller object.27832783- */27842784-static void scic_sds_controller_initial_state_enter(void *object)27852785-{27862786- struct scic_sds_controller *scic = object;27872787-27882788- sci_base_state_machine_change_state(&scic->state_machine,27892789- SCI_BASE_CONTROLLER_STATE_RESET);27902790-}27912791-27922792-/**27932793- *27942794- * @object: This is the object which is cast to a struct scic_sds_controller27952795- * object.27962796- *27972797- * This method implements the actions taken by the struct scic_sds_controller on exit27982798- * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the27992799- * controller starting timeout timer. none28002800- */28012801-static inline void scic_sds_controller_starting_state_exit(void *object)28022802-{28032803- struct scic_sds_controller *scic = object;28042804-28052805- isci_timer_stop(scic->timeout_timer);28062806-}28072807-28082808-/**28092809- *28102810- * @object: This is the object which is cast to a struct scic_sds_controller28112811- * object.28122812- *28132813- * This method implements the actions taken by the struct scic_sds_controller on entry28142814- * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the28152815- * controllers ready state. none28162816- */28172817-static void scic_sds_controller_ready_state_enter(void *object)28182818-{28192819- struct scic_sds_controller *scic = object;28202820-28212821- /* set the default interrupt coalescence number and timeout value. */28222822- scic_controller_set_interrupt_coalescence(28232823- scic, 0x10, 250);28242824-}28252825-28262826-/**28272827- *28282828- * @object: This is the object which is cast to a struct scic_sds_controller28292829- * object.28302830- *28312831- * This method implements the actions taken by the struct scic_sds_controller on exit28322832- * from the SCI_BASE_CONTROLLER_STATE_READY. - This function does nothing. none28332833- */28342834-static void scic_sds_controller_ready_state_exit(void *object)28352835-{28362836- struct scic_sds_controller *scic = object;28372837-28382838- /* disable interrupt coalescence. */28392839- scic_controller_set_interrupt_coalescence(scic, 0, 0);28402840-}28412841-28422842-/**28432843- *28442844- * @object: This is the object which is cast to a struct scic_sds_controller28452845- * object.28462846- *28472847- * This method implements the actions taken by the struct scic_sds_controller on entry28482848- * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the28492849- * controllers ready state. - Stop the phys on this controller - Stop the ports28502850- * on this controller - Stop all of the remote devices on this controller none28512851- */28522852-static void scic_sds_controller_stopping_state_enter(void *object)28532853-{28542854- struct scic_sds_controller *scic = object;28552855-28562856- /* Stop all of the components for this controller */28572857- scic_sds_controller_stop_phys(scic);28582858- scic_sds_controller_stop_ports(scic);28592859- scic_sds_controller_stop_devices(scic);28602860-}28612861-28622862-/**28632863- *28642864- * @object: This is the object which is cast to a struct28652865- * scic_sds_controller object.28662866- *28672867- * This function implements the actions taken by the struct scic_sds_controller28682868- * on exit from the SCI_BASE_CONTROLLER_STATE_STOPPING. -28692869- * This function stops the controller stopping timeout timer.28702870- */28712871-static inline void scic_sds_controller_stopping_state_exit(void *object)28722872-{28732873- struct scic_sds_controller *scic = object;28742874-28752875- isci_timer_stop(scic->timeout_timer);28762876-}28772877-28782878-static void scic_sds_controller_resetting_state_enter(void *object)28792879-{28802880- struct scic_sds_controller *scic = object;28812881-28822882- scic_sds_controller_reset_hardware(scic);28832883- sci_base_state_machine_change_state(&scic->state_machine,28842884- SCI_BASE_CONTROLLER_STATE_RESET);28852885-}28862886-28872887-static const struct sci_base_state scic_sds_controller_state_table[] = {28882888- [SCI_BASE_CONTROLLER_STATE_INITIAL] = {28892889- .enter_state = scic_sds_controller_initial_state_enter,28902890- },28912891- [SCI_BASE_CONTROLLER_STATE_RESET] = {},28922892- [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {},28932893- [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {},28942894- [SCI_BASE_CONTROLLER_STATE_STARTING] = {28952895- .exit_state = scic_sds_controller_starting_state_exit,28962896- },28972897- [SCI_BASE_CONTROLLER_STATE_READY] = {28982898- .enter_state = scic_sds_controller_ready_state_enter,28992899- .exit_state = scic_sds_controller_ready_state_exit,29002900- },29012901- [SCI_BASE_CONTROLLER_STATE_RESETTING] = {29022902- .enter_state = scic_sds_controller_resetting_state_enter,29032903- },29042904- [SCI_BASE_CONTROLLER_STATE_STOPPING] = {29052905- .enter_state = scic_sds_controller_stopping_state_enter,29062906- .exit_state = scic_sds_controller_stopping_state_exit,29072907- },29082908- [SCI_BASE_CONTROLLER_STATE_STOPPED] = {},29092909- [SCI_BASE_CONTROLLER_STATE_FAILED] = {}29102910-};29112911-29122912-/**29132913- * scic_controller_construct() - This method will attempt to construct a29142914- * controller object utilizing the supplied parameter information.29152915- * @c: This parameter specifies the controller to be constructed.29162916- * @scu_base: mapped base address of the scu registers29172917- * @smu_base: mapped base address of the smu registers29182918- *29192919- * Indicate if the controller was successfully constructed or if it failed in29202920- * some way. SCI_SUCCESS This value is returned if the controller was29212921- * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned29222922- * if the interrupt coalescence timer may cause SAS compliance issues for SMP29232923- * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE29242924- * This value is returned if the controller does not support the supplied type.29252925- * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the29262926- * controller does not support the supplied initialization data version.29272927- */29282928-enum sci_status scic_controller_construct(struct scic_sds_controller *scic,29292929- void __iomem *scu_base,29302930- void __iomem *smu_base)29312931-{29322932- struct isci_host *ihost = scic_to_ihost(scic);29332933- u8 i;29342934-29352935- sci_base_state_machine_construct(&scic->state_machine,29362936- scic, scic_sds_controller_state_table,29372937- SCI_BASE_CONTROLLER_STATE_INITIAL);29382938-29392939- sci_base_state_machine_start(&scic->state_machine);29402940-29412941- scic->scu_registers = scu_base;29422942- scic->smu_registers = smu_base;29432943-29442944- scic_sds_port_configuration_agent_construct(&scic->port_agent);29452945-29462946- /* Construct the ports for this controller */29472947- for (i = 0; i < SCI_MAX_PORTS; i++)29482948- scic_sds_port_construct(&ihost->ports[i].sci, i, scic);29492949- scic_sds_port_construct(&ihost->ports[i].sci, SCIC_SDS_DUMMY_PORT, scic);29502950-29512951- /* Construct the phys for this controller */29522952- for (i = 0; i < SCI_MAX_PHYS; i++) {29532953- /* Add all the PHYs to the dummy port */29542954- scic_sds_phy_construct(&ihost->phys[i].sci,29552955- &ihost->ports[SCI_MAX_PORTS].sci, i);29562956- }29572957-29582958- scic->invalid_phy_mask = 0;29592959-29602960- /* Set the default maximum values */29612961- scic->completion_event_entries = SCU_EVENT_COUNT;29622962- scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT;29632963- scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES;29642964- scic->logical_port_entries = SCI_MAX_PORTS;29652965- scic->task_context_entries = SCU_IO_REQUEST_COUNT;29662966- scic->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT;29672967- scic->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT;29682968-29692969- /* Initialize the User and OEM parameters to default values. */29702970- scic_sds_controller_set_default_config_parameters(scic);29712971-29722972- return scic_controller_reset(scic);29732973-}
-576
drivers/scsi/isci/core/scic_sds_controller.h
···11-/*22- * This file is provided under a dual BSD/GPLv2 license. When using or33- * redistributing this file, you may do so under either license.44- *55- * GPL LICENSE SUMMARY66- *77- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.88- *99- * This program is free software; you can redistribute it and/or modify1010- * it under the terms of version 2 of the GNU General Public License as1111- * published by the Free Software Foundation.1212- *1313- * This program is distributed in the hope that it will be useful, but1414- * WITHOUT ANY WARRANTY; without even the implied warranty of1515- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1616- * General Public License for more details.1717- *1818- * You should have received a copy of the GNU General Public License1919- * along with this program; if not, write to the Free Software2020- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.2121- * The full GNU General Public License is included in this distribution2222- * in the file called LICENSE.GPL.2323- *2424- * BSD LICENSE2525- *2626- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.2727- * All rights reserved.2828- *2929- * Redistribution and use in source and binary forms, with or without3030- * modification, are permitted provided that the following conditions3131- * are met:3232- *3333- * * Redistributions of source code must retain the above copyright3434- * notice, this list of conditions and the following disclaimer.3535- * * Redistributions in binary form must reproduce the above copyright3636- * notice, this list of conditions and the following disclaimer in3737- * the documentation and/or other materials provided with the3838- * distribution.3939- * * Neither the name of Intel Corporation nor the names of its4040- * contributors may be used to endorse or promote products derived4141- * from this software without specific prior written permission.4242- *4343- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS4444- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT4545- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR4646- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT4747- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,4848- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT4949- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,5050- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY5151- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT5252- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE5353- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454- */5555-5656-#ifndef _SCIC_SDS_CONTROLLER_H_5757-#define _SCIC_SDS_CONTROLLER_H_5858-5959-#include <linux/string.h>6060-#include <linux/io.h>6161-6262-/**6363- * This file contains the structures, constants and prototypes used for the6464- * core controller object.6565- *6666- *6767- */6868-6969-#include "sci_pool.h"7070-#include "sci_base_state.h"7171-#include "sci_base_state_machine.h"7272-#include "scic_config_parameters.h"7373-#include "scic_sds_port.h"7474-#include "scic_sds_phy.h"7575-#include "remote_node_table.h"7676-#include "remote_device.h"7777-#include "scu_registers.h"7878-#include "scu_task_context.h"7979-#include "scu_unsolicited_frame.h"8080-#include "scic_sds_unsolicited_frame_control.h"8181-#include "scic_sds_port_configuration_agent.h"8282-8383-struct sci_base_remote_device;8484-struct scic_sds_remote_device;8585-struct scic_sds_request;8686-struct scic_sds_controller;8787-8888-/**8989- * struct scic_power_control -9090- *9191- * This structure defines the fields for managing power control for direct9292- * attached disk devices.9393- */9494-struct scic_power_control {9595- /**9696- * This field is set when the power control timer is running and cleared when9797- * it is not.9898- */9999- bool timer_started;100100-101101- /**102102- * This field is the handle to the driver timer object. This timer is used to103103- * control when the directed attached disks can consume power.104104- */105105- void *timer;106106-107107- /**108108- * This field is used to keep track of how many phys are put into the109109- * requesters field.110110- */111111- u8 phys_waiting;112112-113113- /**114114- * This field is used to keep track of how many phys have been granted to consume power115115- */116116- u8 phys_granted_power;117117-118118- /**119119- * This field is an array of phys that we are waiting on. The phys are direct120120- * mapped into requesters via struct scic_sds_phy.phy_index121121- */122122- struct scic_sds_phy *requesters[SCI_MAX_PHYS];123123-124124-};125125-126126-/**127127- * struct scic_sds_controller -128128- *129129- * This structure represents the SCU controller object.130130- */131131-struct scic_sds_controller {132132- /**133133- * This field contains the information for the base controller state134134- * machine.135135- */136136- struct sci_base_state_machine state_machine;137137-138138- /**139139- * This field is the driver timer object handler used to time the controller140140- * object start and stop requests.141141- */142142- void *timeout_timer;143143-144144- /**145145- * This field contains the user parameters to be utilized for this146146- * core controller object.147147- */148148- union scic_user_parameters user_parameters;149149-150150- /**151151- * This field contains the OEM parameters to be utilized for this152152- * core controller object.153153- */154154- union scic_oem_parameters oem_parameters;155155-156156- /**157157- * This field contains the port configuration agent for this controller.158158- */159159- struct scic_sds_port_configuration_agent port_agent;160160-161161- /**162162- * This field is the array of device objects that are currently constructed163163- * for this controller object. This table is used as a fast lookup of device164164- * objects that need to handle device completion notifications from the165165- * hardware. The table is RNi based.166166- */167167- struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES];168168-169169- /**170170- * This field is the array of IO request objects that are currently active for171171- * this controller object. This table is used as a fast lookup of the io172172- * request object that need to handle completion queue notifications. The173173- * table is TCi based.174174- */175175- struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS];176176-177177- /**178178- * This field is the free RNi data structure179179- */180180- struct scic_remote_node_table available_remote_nodes;181181-182182- /**183183- * This field is the TCi pool used to manage the task context index.184184- */185185- SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS);186186-187187- /**188188- * This filed is the struct scic_power_control data used to controll when direct189189- * attached devices can consume power.190190- */191191- struct scic_power_control power_control;192192-193193- /**194194- * This field is the array of sequence values for the IO Tag fields. Even195195- * though only 4 bits of the field is used for the sequence the sequence is 16196196- * bits in size so the sequence can be bitwise or'd with the TCi to build the197197- * IO Tag value.198198- */199199- u16 io_request_sequence[SCI_MAX_IO_REQUESTS];200200-201201- /**202202- * This field in the array of sequence values for the RNi. These are used203203- * to control io request build to io request start operations. The sequence204204- * value is recorded into an io request when it is built and is checked on205205- * the io request start operation to make sure that there was not a device206206- * hot plug between the build and start operation.207207- */208208- u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES];209209-210210- /**211211- * This field is a pointer to the memory allocated by the driver for the task212212- * context table. This data is shared between the hardware and software.213213- */214214- struct scu_task_context *task_context_table;215215-216216- /**217217- * This field is a pointer to the memory allocated by the driver for the218218- * remote node context table. This table is shared between the hardware and219219- * software.220220- */221221- union scu_remote_node_context *remote_node_context_table;222222-223223- /**224224- * This field is a pointer to the completion queue. This memory is225225- * written to by the hardware and read by the software.226226- */227227- u32 *completion_queue;228228-229229- /**230230- * This field is the software copy of the completion queue get pointer. The231231- * controller object writes this value to the hardware after processing the232232- * completion entries.233233- */234234- u32 completion_queue_get;235235-236236- /**237237- * This field is the minimum of the number of hardware supported port entries238238- * and the software requested port entries.239239- */240240- u32 logical_port_entries;241241-242242- /**243243- * This field is the minimum number of hardware supported completion queue244244- * entries and the software requested completion queue entries.245245- */246246- u32 completion_queue_entries;247247-248248- /**249249- * This field is the minimum number of hardware supported event entries and250250- * the software requested event entries.251251- */252252- u32 completion_event_entries;253253-254254- /**255255- * This field is the minimum number of devices supported by the hardware and256256- * the number of devices requested by the software.257257- */258258- u32 remote_node_entries;259259-260260- /**261261- * This field is the minimum number of IO requests supported by the hardware262262- * and the number of IO requests requested by the software.263263- */264264- u32 task_context_entries;265265-266266- /**267267- * This object contains all of the unsolicited frame specific268268- * data utilized by the core controller.269269- */270270- struct scic_sds_unsolicited_frame_control uf_control;271271-272272- /* Phy Startup Data */273273- /**274274- * This field is the driver timer handle for controller phy request startup.275275- * On controller start the controller will start each PHY individually in276276- * order of phy index.277277- */278278- void *phy_startup_timer;279279-280280- /**281281- * This field is set when the phy_startup_timer is running and is cleared when282282- * the phy_startup_timer is stopped.283283- */284284- bool phy_startup_timer_pending;285285-286286- /**287287- * This field is the index of the next phy start. It is initialized to 0 and288288- * increments for each phy index that is started.289289- */290290- u32 next_phy_to_start;291291-292292- /**293293- * This field controlls the invalid link up notifications to the SCI_USER. If294294- * an invalid_link_up notification is reported a bit for the PHY index is set295295- * so further notifications are not made. Once the PHY object reports link up296296- * and is made part of a port then this bit for the PHY index is cleared.297297- */298298- u8 invalid_phy_mask;299299-300300- /*301301- * This field saves the current interrupt coalescing number of the controller.302302- */303303- u16 interrupt_coalesce_number;304304-305305- /*306306- * This field saves the current interrupt coalescing timeout value in microseconds.307307- */308308- u32 interrupt_coalesce_timeout;309309-310310- /**311311- * This field is a pointer to the memory mapped register space for the312312- * struct smu_registers.313313- */314314- struct smu_registers __iomem *smu_registers;315315-316316- /**317317- * This field is a pointer to the memory mapped register space for the318318- * struct scu_registers.319319- */320320- struct scu_registers __iomem *scu_registers;321321-322322-};323323-324324-/**325325- * enum scic_sds_controller_states - This enumeration depicts all the states326326- * for the common controller state machine.327327- */328328-enum scic_sds_controller_states {329329- /**330330- * Simply the initial state for the base controller state machine.331331- */332332- SCI_BASE_CONTROLLER_STATE_INITIAL = 0,333333-334334- /**335335- * This state indicates that the controller is reset. The memory for336336- * the controller is in it's initial state, but the controller requires337337- * initialization.338338- * This state is entered from the INITIAL state.339339- * This state is entered from the RESETTING state.340340- */341341- SCI_BASE_CONTROLLER_STATE_RESET,342342-343343- /**344344- * This state is typically an action state that indicates the controller345345- * is in the process of initialization. In this state no new IO operations346346- * are permitted.347347- * This state is entered from the RESET state.348348- */349349- SCI_BASE_CONTROLLER_STATE_INITIALIZING,350350-351351- /**352352- * This state indicates that the controller has been successfully353353- * initialized. In this state no new IO operations are permitted.354354- * This state is entered from the INITIALIZING state.355355- */356356- SCI_BASE_CONTROLLER_STATE_INITIALIZED,357357-358358- /**359359- * This state indicates the the controller is in the process of becoming360360- * ready (i.e. starting). In this state no new IO operations are permitted.361361- * This state is entered from the INITIALIZED state.362362- */363363- SCI_BASE_CONTROLLER_STATE_STARTING,364364-365365- /**366366- * This state indicates the controller is now ready. Thus, the user367367- * is able to perform IO operations on the controller.368368- * This state is entered from the STARTING state.369369- */370370- SCI_BASE_CONTROLLER_STATE_READY,371371-372372- /**373373- * This state is typically an action state that indicates the controller374374- * is in the process of resetting. Thus, the user is unable to perform375375- * IO operations on the controller. A reset is considered destructive in376376- * most cases.377377- * This state is entered from the READY state.378378- * This state is entered from the FAILED state.379379- * This state is entered from the STOPPED state.380380- */381381- SCI_BASE_CONTROLLER_STATE_RESETTING,382382-383383- /**384384- * This state indicates that the controller is in the process of stopping.385385- * In this state no new IO operations are permitted, but existing IO386386- * operations are allowed to complete.387387- * This state is entered from the READY state.388388- */389389- SCI_BASE_CONTROLLER_STATE_STOPPING,390390-391391- /**392392- * This state indicates that the controller has successfully been stopped.393393- * In this state no new IO operations are permitted.394394- * This state is entered from the STOPPING state.395395- */396396- SCI_BASE_CONTROLLER_STATE_STOPPED,397397-398398- /**399399- * This state indicates that the controller could not successfully be400400- * initialized. In this state no new IO operations are permitted.401401- * This state is entered from the INITIALIZING state.402402- * This state is entered from the STARTING state.403403- * This state is entered from the STOPPING state.404404- * This state is entered from the RESETTING state.405405- */406406- SCI_BASE_CONTROLLER_STATE_FAILED,407407-408408- SCI_BASE_CONTROLLER_MAX_STATES409409-410410-};411411-412412-/**413413- * INCREMENT_QUEUE_GET() -414414- *415415- * This macro will increment the specified index to and if the index wraps to 0416416- * it will toggel the cycle bit.417417- */418418-#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \419419- { \420420- if ((index) + 1 == entry_count) { \421421- (index) = 0; \422422- (cycle) = (cycle) ^ (bit_toggle); \423423- } else { \424424- index = index + 1; \425425- } \426426- }427427-428428-/**429429- * scic_sds_controller_get_port_configuration_agent() -430430- *431431- * This is a helper macro to get the port configuration agent from the432432- * controller object.433433- */434434-#define scic_sds_controller_get_port_configuration_agent(controller) \435435- (&(controller)->port_agent)436436-437437-/**438438- * scic_sds_controller_get_protocol_engine_group() -439439- *440440- * This macro returns the protocol engine group for this controller object.441441- * Presently we only support protocol engine group 0 so just return that442442- */443443-#define scic_sds_controller_get_protocol_engine_group(controller) 0444444-445445-/**446446- * scic_sds_io_tag_construct() -447447- *448448- * This macro constructs an IO tag from the sequence and index values.449449- */450450-#define scic_sds_io_tag_construct(sequence, task_index) \451451- ((sequence) << 12 | (task_index))452452-453453-/**454454- * scic_sds_io_tag_get_sequence() -455455- *456456- * This macro returns the IO sequence from the IO tag value.457457- */458458-#define scic_sds_io_tag_get_sequence(io_tag) \459459- (((io_tag) & 0xF000) >> 12)460460-461461-/**462462- * scic_sds_io_tag_get_index() -463463- *464464- * This macro returns the TCi from the io tag value465465- */466466-#define scic_sds_io_tag_get_index(io_tag) \467467- ((io_tag) & 0x0FFF)468468-469469-/**470470- * scic_sds_io_sequence_increment() -471471- *472472- * This is a helper macro to increment the io sequence count. We may find in473473- * the future that it will be faster to store the sequence count in such a way474474- * as we dont perform the shift operation to build io tag values so therefore475475- * need a way to incrment them correctly476476- */477477-#define scic_sds_io_sequence_increment(value) \478478- ((value) = (((value) + 1) & 0x000F))479479-480480-/* expander attached sata devices require 3 rnc slots */481481-static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev)482482-{483483- struct domain_device *dev = sci_dev_to_domain(sci_dev);484484-485485- if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&486486- !sci_dev->is_direct_attached)487487- return SCU_STP_REMOTE_NODE_COUNT;488488- return SCU_SSP_REMOTE_NODE_COUNT;489489-}490490-491491-/**492492- * scic_sds_controller_set_invalid_phy() -493493- *494494- * This macro will set the bit in the invalid phy mask for this controller495495- * object. This is used to control messages reported for invalid link up496496- * notifications.497497- */498498-#define scic_sds_controller_set_invalid_phy(controller, phy) \499499- ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index))500500-501501-/**502502- * scic_sds_controller_clear_invalid_phy() -503503- *504504- * This macro will clear the bit in the invalid phy mask for this controller505505- * object. This is used to control messages reported for invalid link up506506- * notifications.507507- */508508-#define scic_sds_controller_clear_invalid_phy(controller, phy) \509509- ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))510510-511511-void scic_sds_controller_post_request(512512- struct scic_sds_controller *this_controller,513513- u32 request);514514-515515-void scic_sds_controller_release_frame(516516- struct scic_sds_controller *this_controller,517517- u32 frame_index);518518-519519-void scic_sds_controller_copy_sata_response(520520- void *response_buffer,521521- void *frame_header,522522- void *frame_buffer);523523-524524-enum sci_status scic_sds_controller_allocate_remote_node_context(525525- struct scic_sds_controller *this_controller,526526- struct scic_sds_remote_device *sci_dev,527527- u16 *node_id);528528-529529-void scic_sds_controller_free_remote_node_context(530530- struct scic_sds_controller *this_controller,531531- struct scic_sds_remote_device *sci_dev,532532- u16 node_id);533533-534534-union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(535535- struct scic_sds_controller *this_controller,536536- u16 node_id);537537-538538-struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic,539539- u16 io_tag);540540-541541-struct scu_task_context *scic_sds_controller_get_task_context_buffer(542542- struct scic_sds_controller *this_controller,543543- u16 io_tag);544544-545545-void scic_sds_controller_power_control_queue_insert(546546- struct scic_sds_controller *this_controller,547547- struct scic_sds_phy *sci_phy);548548-549549-void scic_sds_controller_power_control_queue_remove(550550- struct scic_sds_controller *this_controller,551551- struct scic_sds_phy *sci_phy);552552-553553-void scic_sds_controller_link_up(554554- struct scic_sds_controller *this_controller,555555- struct scic_sds_port *sci_port,556556- struct scic_sds_phy *sci_phy);557557-558558-void scic_sds_controller_link_down(559559- struct scic_sds_controller *this_controller,560560- struct scic_sds_port *sci_port,561561- struct scic_sds_phy *sci_phy);562562-563563-void scic_sds_controller_remote_device_stopped(564564- struct scic_sds_controller *this_controller,565565- struct scic_sds_remote_device *sci_dev);566566-567567-void scic_sds_controller_copy_task_context(568568- struct scic_sds_controller *this_controller,569569- struct scic_sds_request *this_request);570570-571571-void scic_sds_controller_register_setup(572572- struct scic_sds_controller *this_controller);573573-574574-enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req);575575-576576-#endif /* _SCIC_SDS_CONTROLLER_H_ */
···5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */55555656-#include "scic_controller.h"5656+#include "host.h"5757#include "scic_phy.h"5858#include "scic_port.h"5959-#include "scic_sds_controller.h"6059#include "scic_sds_phy.h"6160#include "scic_sds_port.h"6261#include "remote_device.h"6362#include "remote_node_context.h"6463#include "scic_sds_request.h"6565-#include "sci_environment.h"6664#include "scu_registers.h"6765#include "timers.h"6866
···5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */55555656-#include "sci_environment.h"5757-#include "scic_controller.h"5858-#include "scic_sds_controller.h"5656+#include "host.h"5957#include "scic_sds_port_configuration_agent.h"6058#include "timers.h"6159
···5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */55555656+#include "host.h"5657#include "sci_base_state_machine.h"5757-#include "scic_controller.h"5858-#include "scic_sds_controller.h"5958#include "scic_sds_request.h"6060-#include "sci_environment.h"6159#include "scu_completion_codes.h"6260#include "scu_task_context.h"6361
···5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */55555656-/**5757- * This file contains the implementation of the5858- * struct scic_sds_unsolicited_frame_control object and it's public, protected, and5959- * private methods.6060- *6161- *6262- */6363-5656+#include "host.h"6457#include "scic_sds_unsolicited_frame_control.h"6558#include "scu_registers.h"6666-#include "scic_sds_controller.h"6759#include "sci_util.h"6868-#include "sci_environment.h"69607061/**7162 * This method will program the unsolicited frames (UFs) into the UF address
+2777-8
drivers/scsi/isci/host.c
···5252 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */5555-5555+#include <linux/device.h>5656+#include <scsi/sas.h>5757+#include "host.h"5658#include "isci.h"5757-#include "scic_io_request.h"5858-#include "scic_port.h"5959#include "port.h"6060-#include "request.h"6160#include "host.h"6261#include "probe_roms.h"6363-#include "scic_controller.h"6464-#include "scic_sds_controller.h"6262+#include "remote_device.h"6363+#include "request.h"6464+#include "scic_io_request.h"6565+#include "scic_sds_port_configuration_agent.h"6666+#include "sci_util.h"6767+#include "scu_completion_codes.h"6868+#include "scu_event_codes.h"6969+#include "scu_registers.h"7070+#include "scu_remote_node_context.h"7171+#include "scu_task_context.h"7272+#include "scu_unsolicited_frame.h"6573#include "timers.h"7474+7575+#define SCU_CONTEXT_RAM_INIT_STALL_TIME 2007676+7777+/**7878+ * smu_dcc_get_max_ports() -7979+ *8080+ * This macro returns the maximum number of logical ports supported by the8181+ * hardware. The caller passes in the value read from the device context8282+ * capacity register and this macro will mash and shift the value appropriately.8383+ */8484+#define smu_dcc_get_max_ports(dcc_value) \8585+ (\8686+ (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \8787+ >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \8888+ )8989+9090+/**9191+ * smu_dcc_get_max_task_context() -9292+ *9393+ * This macro returns the maximum number of task contexts supported by the9494+ * hardware. The caller passes in the value read from the device context9595+ * capacity register and this macro will mash and shift the value appropriately.9696+ */9797+#define smu_dcc_get_max_task_context(dcc_value) \9898+ (\9999+ (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \100100+ >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \101101+ )102102+103103+/**104104+ * smu_dcc_get_max_remote_node_context() -105105+ *106106+ * This macro returns the maximum number of remote node contexts supported by107107+ * the hardware. The caller passes in the value read from the device context108108+ * capacity register and this macro will mash and shift the value appropriately.109109+ */110110+#define smu_dcc_get_max_remote_node_context(dcc_value) \111111+ (\112112+ (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \113113+ >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \114114+ )115115+116116+117117+#define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3118118+#define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3119119+120120+/**121121+ *122122+ *123123+ * The number of milliseconds to wait for a phy to start.124124+ */125125+#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100126126+127127+/**128128+ *129129+ *130130+ * The number of milliseconds to wait while a given phy is consuming power131131+ * before allowing another set of phys to consume power. Ultimately, this will132132+ * be specified by OEM parameter.133133+ */134134+#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500135135+136136+/**137137+ * NORMALIZE_PUT_POINTER() -138138+ *139139+ * This macro will normalize the completion queue put pointer so its value can140140+ * be used as an array inde141141+ */142142+#define NORMALIZE_PUT_POINTER(x) \143143+ ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)144144+145145+146146+/**147147+ * NORMALIZE_EVENT_POINTER() -148148+ *149149+ * This macro will normalize the completion queue event entry so its value can150150+ * be used as an index.151151+ */152152+#define NORMALIZE_EVENT_POINTER(x) \153153+ (\154154+ ((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \155155+ >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \156156+ )157157+158158+/**159159+ * INCREMENT_COMPLETION_QUEUE_GET() -160160+ *161161+ * This macro will increment the controllers completion queue index value and162162+ * possibly toggle the cycle bit if the completion queue index wraps back to 0.163163+ */164164+#define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \165165+ INCREMENT_QUEUE_GET(\166166+ (index), \167167+ (cycle), \168168+ (controller)->completion_queue_entries, \169169+ SMU_CQGR_CYCLE_BIT \170170+ )171171+172172+/**173173+ * INCREMENT_EVENT_QUEUE_GET() -174174+ *175175+ * This macro will increment the controllers event queue index value and176176+ * possibly toggle the event cycle bit if the event queue index wraps back to 0.177177+ */178178+#define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \179179+ INCREMENT_QUEUE_GET(\180180+ (index), \181181+ (cycle), \182182+ (controller)->completion_event_entries, \183183+ SMU_CQGR_EVENT_CYCLE_BIT \184184+ )185185+186186+187187+/**188188+ * NORMALIZE_GET_POINTER() -189189+ *190190+ * This macro will normalize the completion queue get pointer so its value can191191+ * be used as an index into an array192192+ */193193+#define NORMALIZE_GET_POINTER(x) \194194+ ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)195195+196196+/**197197+ * NORMALIZE_GET_POINTER_CYCLE_BIT() -198198+ *199199+ * This macro will normalize the completion queue cycle pointer so it matches200200+ * the completion queue cycle bit201201+ */202202+#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \203203+ ((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))204204+205205+/**206206+ * COMPLETION_QUEUE_CYCLE_BIT() -207207+ *208208+ * This macro will return the cycle bit of the completion queue entry209209+ */210210+#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)211211+212212+static bool scic_sds_controller_completion_queue_has_entries(213213+ struct scic_sds_controller *scic)214214+{215215+ u32 get_value = scic->completion_queue_get;216216+ u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;217217+218218+ if (NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) ==219219+ COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index]))220220+ return true;221221+222222+ return false;223223+}224224+225225+static bool scic_sds_controller_isr(struct scic_sds_controller *scic)226226+{227227+ if (scic_sds_controller_completion_queue_has_entries(scic)) {228228+ return true;229229+ } else {230230+ /*231231+ * we have a spurious interrupt it could be that we have already232232+ * emptied the completion queue from a previous interrupt */233233+ writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status);234234+235235+ /*236236+ * There is a race in the hardware that could cause us not to be notified237237+ * of an interrupt completion if we do not take this step. We will mask238238+ * then unmask the interrupts so if there is another interrupt pending239239+ * the clearing of the interrupt source we get the next interrupt message. */240240+ writel(0xFF000000, &scic->smu_registers->interrupt_mask);241241+ writel(0, &scic->smu_registers->interrupt_mask);242242+ }243243+244244+ return false;245245+}6624667247irqreturn_t isci_msix_isr(int vec, void *data)68248{···25272 tasklet_schedule(&ihost->completion_tasklet);2537325474 return IRQ_HANDLED;7575+}7676+7777+static bool scic_sds_controller_error_isr(struct scic_sds_controller *scic)7878+{7979+ u32 interrupt_status;8080+8181+ interrupt_status =8282+ readl(&scic->smu_registers->interrupt_status);8383+ interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);8484+8585+ if (interrupt_status != 0) {8686+ /*8787+ * There is an error interrupt pending so let it through and handle8888+ * in the callback */8989+ return true;9090+ }9191+9292+ /*9393+ * There is a race in the hardware that could cause us not to be notified9494+ * of an interrupt completion if we do not take this step. We will mask9595+ * then unmask the error interrupts so if there was another interrupt9696+ * pending we will be notified.9797+ * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */9898+ writel(0xff, &scic->smu_registers->interrupt_mask);9999+ writel(0, &scic->smu_registers->interrupt_mask);100100+101101+ return false;102102+}103103+104104+static void scic_sds_controller_task_completion(struct scic_sds_controller *scic,105105+ u32 completion_entry)106106+{107107+ u32 index;108108+ struct scic_sds_request *io_request;109109+110110+ index = SCU_GET_COMPLETION_INDEX(completion_entry);111111+ io_request = scic->io_request_table[index];112112+113113+ /* Make sure that we really want to process this IO request */114114+ if (115115+ (io_request != NULL)116116+ && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG)117117+ && (118118+ scic_sds_io_tag_get_sequence(io_request->io_tag)119119+ == scic->io_request_sequence[index]120120+ )121121+ ) {122122+ /* Yep this is a valid io request pass it along to the io request handler */123123+ scic_sds_io_request_tc_completion(io_request, completion_entry);124124+ }125125+}126126+127127+static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic,128128+ u32 completion_entry)129129+{130130+ u32 index;131131+ struct scic_sds_request *io_request;132132+ struct scic_sds_remote_device *device;133133+134134+ index = SCU_GET_COMPLETION_INDEX(completion_entry);135135+136136+ switch (scu_get_command_request_type(completion_entry)) {137137+ case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:138138+ case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:139139+ io_request = scic->io_request_table[index];140140+ dev_warn(scic_to_dev(scic),141141+ "%s: SCIC SDS Completion type SDMA %x for io request "142142+ "%p\n",143143+ __func__,144144+ completion_entry,145145+ io_request);146146+ /* @todo For a post TC operation we need to fail the IO147147+ * request148148+ */149149+ break;150150+151151+ case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:152152+ case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:153153+ case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:154154+ device = scic->device_table[index];155155+ dev_warn(scic_to_dev(scic),156156+ "%s: SCIC SDS Completion type SDMA %x for remote "157157+ "device %p\n",158158+ __func__,159159+ completion_entry,160160+ device);161161+ /* @todo For a port RNC operation we need to fail the162162+ * device163163+ */164164+ break;165165+166166+ default:167167+ dev_warn(scic_to_dev(scic),168168+ "%s: SCIC SDS Completion unknown SDMA completion "169169+ "type %x\n",170170+ __func__,171171+ completion_entry);172172+ break;173173+174174+ }175175+}176176+177177+static void scic_sds_controller_unsolicited_frame(struct scic_sds_controller *scic,178178+ u32 completion_entry)179179+{180180+ u32 index;181181+ u32 frame_index;182182+183183+ struct isci_host *ihost = scic_to_ihost(scic);184184+ struct scu_unsolicited_frame_header *frame_header;185185+ struct scic_sds_phy *phy;186186+ struct scic_sds_remote_device *device;187187+188188+ enum sci_status result = SCI_FAILURE;189189+190190+ frame_index = SCU_GET_FRAME_INDEX(completion_entry);191191+192192+ frame_header = scic->uf_control.buffers.array[frame_index].header;193193+ scic->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE;194194+195195+ if (SCU_GET_FRAME_ERROR(completion_entry)) {196196+ /*197197+ * / @todo If the IAF frame or SIGNATURE FIS frame has an error will198198+ * / this cause a problem? We expect the phy initialization will199199+ * / fail if there is an error in the frame. */200200+ scic_sds_controller_release_frame(scic, frame_index);201201+ return;202202+ }203203+204204+ if (frame_header->is_address_frame) {205205+ index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);206206+ phy = &ihost->phys[index].sci;207207+ result = scic_sds_phy_frame_handler(phy, frame_index);208208+ } else {209209+210210+ index = SCU_GET_COMPLETION_INDEX(completion_entry);211211+212212+ if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {213213+ /*214214+ * This is a signature fis or a frame from a direct attached SATA215215+ * device that has not yet been created. In either case forwared216216+ * the frame to the PE and let it take care of the frame data. */217217+ index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);218218+ phy = &ihost->phys[index].sci;219219+ result = scic_sds_phy_frame_handler(phy, frame_index);220220+ } else {221221+ if (index < scic->remote_node_entries)222222+ device = scic->device_table[index];223223+ else224224+ device = NULL;225225+226226+ if (device != NULL)227227+ result = scic_sds_remote_device_frame_handler(device, frame_index);228228+ else229229+ scic_sds_controller_release_frame(scic, frame_index);230230+ }231231+ }232232+233233+ if (result != SCI_SUCCESS) {234234+ /*235235+ * / @todo Is there any reason to report some additional error message236236+ * / when we get this failure notifiction? */237237+ }238238+}239239+240240+static void scic_sds_controller_event_completion(struct scic_sds_controller *scic,241241+ u32 completion_entry)242242+{243243+ struct isci_host *ihost = scic_to_ihost(scic);244244+ struct scic_sds_request *io_request;245245+ struct scic_sds_remote_device *device;246246+ struct scic_sds_phy *phy;247247+ u32 index;248248+249249+ index = SCU_GET_COMPLETION_INDEX(completion_entry);250250+251251+ switch (scu_get_event_type(completion_entry)) {252252+ case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:253253+ /* / @todo The driver did something wrong and we need to fix the condtion. */254254+ dev_err(scic_to_dev(scic),255255+ "%s: SCIC Controller 0x%p received SMU command error "256256+ "0x%x\n",257257+ __func__,258258+ scic,259259+ completion_entry);260260+ break;261261+262262+ case SCU_EVENT_TYPE_SMU_PCQ_ERROR:263263+ case SCU_EVENT_TYPE_SMU_ERROR:264264+ case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:265265+ /*266266+ * / @todo This is a hardware failure and its likely that we want to267267+ * / reset the controller. */268268+ dev_err(scic_to_dev(scic),269269+ "%s: SCIC Controller 0x%p received fatal controller "270270+ "event 0x%x\n",271271+ __func__,272272+ scic,273273+ completion_entry);274274+ break;275275+276276+ case SCU_EVENT_TYPE_TRANSPORT_ERROR:277277+ io_request = scic->io_request_table[index];278278+ scic_sds_io_request_event_handler(io_request, completion_entry);279279+ break;280280+281281+ case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:282282+ switch (scu_get_event_specifier(completion_entry)) {283283+ case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:284284+ case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:285285+ io_request = scic->io_request_table[index];286286+ if (io_request != NULL)287287+ scic_sds_io_request_event_handler(io_request, completion_entry);288288+ else289289+ dev_warn(scic_to_dev(scic),290290+ "%s: SCIC Controller 0x%p received "291291+ "event 0x%x for io request object "292292+ "that doesnt exist.\n",293293+ __func__,294294+ scic,295295+ completion_entry);296296+297297+ break;298298+299299+ case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:300300+ device = scic->device_table[index];301301+ if (device != NULL)302302+ scic_sds_remote_device_event_handler(device, completion_entry);303303+ else304304+ dev_warn(scic_to_dev(scic),305305+ "%s: SCIC Controller 0x%p received "306306+ "event 0x%x for remote device object "307307+ "that doesnt exist.\n",308308+ __func__,309309+ scic,310310+ completion_entry);311311+312312+ break;313313+ }314314+ break;315315+316316+ case SCU_EVENT_TYPE_BROADCAST_CHANGE:317317+ /*318318+ * direct the broadcast change event to the phy first and then let319319+ * the phy redirect the broadcast change to the port object */320320+ case SCU_EVENT_TYPE_ERR_CNT_EVENT:321321+ /*322322+ * direct error counter event to the phy object since that is where323323+ * we get the event notification. This is a type 4 event. */324324+ case SCU_EVENT_TYPE_OSSP_EVENT:325325+ index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry);326326+ phy = &ihost->phys[index].sci;327327+ scic_sds_phy_event_handler(phy, completion_entry);328328+ break;329329+330330+ case SCU_EVENT_TYPE_RNC_SUSPEND_TX:331331+ case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:332332+ case SCU_EVENT_TYPE_RNC_OPS_MISC:333333+ if (index < scic->remote_node_entries) {334334+ device = scic->device_table[index];335335+336336+ if (device != NULL)337337+ scic_sds_remote_device_event_handler(device, completion_entry);338338+ } else339339+ dev_err(scic_to_dev(scic),340340+ "%s: SCIC Controller 0x%p received event 0x%x "341341+ "for remote device object 0x%0x that doesnt "342342+ "exist.\n",343343+ __func__,344344+ scic,345345+ completion_entry,346346+ index);347347+348348+ break;349349+350350+ default:351351+ dev_warn(scic_to_dev(scic),352352+ "%s: SCIC Controller received unknown event code %x\n",353353+ __func__,354354+ completion_entry);355355+ break;356356+ }357357+}358358+359359+360360+361361+static void scic_sds_controller_process_completions(struct scic_sds_controller *scic)362362+{363363+ u32 completion_count = 0;364364+ u32 completion_entry;365365+ u32 get_index;366366+ u32 get_cycle;367367+ u32 event_index;368368+ u32 event_cycle;369369+370370+ dev_dbg(scic_to_dev(scic),371371+ "%s: completion queue begining get:0x%08x\n",372372+ __func__,373373+ scic->completion_queue_get);374374+375375+ /* Get the component parts of the completion queue */376376+ get_index = NORMALIZE_GET_POINTER(scic->completion_queue_get);377377+ get_cycle = SMU_CQGR_CYCLE_BIT & scic->completion_queue_get;378378+379379+ event_index = NORMALIZE_EVENT_POINTER(scic->completion_queue_get);380380+ event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & scic->completion_queue_get;381381+382382+ while (383383+ NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)384384+ == COMPLETION_QUEUE_CYCLE_BIT(scic->completion_queue[get_index])385385+ ) {386386+ completion_count++;387387+388388+ completion_entry = scic->completion_queue[get_index];389389+ INCREMENT_COMPLETION_QUEUE_GET(scic, get_index, get_cycle);390390+391391+ dev_dbg(scic_to_dev(scic),392392+ "%s: completion queue entry:0x%08x\n",393393+ __func__,394394+ completion_entry);395395+396396+ switch (SCU_GET_COMPLETION_TYPE(completion_entry)) {397397+ case SCU_COMPLETION_TYPE_TASK:398398+ scic_sds_controller_task_completion(scic, completion_entry);399399+ break;400400+401401+ case SCU_COMPLETION_TYPE_SDMA:402402+ scic_sds_controller_sdma_completion(scic, completion_entry);403403+ break;404404+405405+ case SCU_COMPLETION_TYPE_UFI:406406+ scic_sds_controller_unsolicited_frame(scic, completion_entry);407407+ break;408408+409409+ case SCU_COMPLETION_TYPE_EVENT:410410+ INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle);411411+ scic_sds_controller_event_completion(scic, completion_entry);412412+ break;413413+414414+ case SCU_COMPLETION_TYPE_NOTIFY:415415+ /*416416+ * Presently we do the same thing with a notify event that we do with the417417+ * other event codes. */418418+ INCREMENT_EVENT_QUEUE_GET(scic, event_index, event_cycle);419419+ scic_sds_controller_event_completion(scic, completion_entry);420420+ break;421421+422422+ default:423423+ dev_warn(scic_to_dev(scic),424424+ "%s: SCIC Controller received unknown "425425+ "completion type %x\n",426426+ __func__,427427+ completion_entry);428428+ break;429429+ }430430+ }431431+432432+ /* Update the get register if we completed one or more entries */433433+ if (completion_count > 0) {434434+ scic->completion_queue_get =435435+ SMU_CQGR_GEN_BIT(ENABLE) |436436+ SMU_CQGR_GEN_BIT(EVENT_ENABLE) |437437+ event_cycle |438438+ SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) |439439+ get_cycle |440440+ SMU_CQGR_GEN_VAL(POINTER, get_index);441441+442442+ writel(scic->completion_queue_get,443443+ &scic->smu_registers->completion_queue_get);444444+445445+ }446446+447447+ dev_dbg(scic_to_dev(scic),448448+ "%s: completion queue ending get:0x%08x\n",449449+ __func__,450450+ scic->completion_queue_get);451451+452452+}453453+454454+static void scic_sds_controller_error_handler(struct scic_sds_controller *scic)455455+{456456+ u32 interrupt_status;457457+458458+ interrupt_status =459459+ readl(&scic->smu_registers->interrupt_status);460460+461461+ if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&462462+ scic_sds_controller_completion_queue_has_entries(scic)) {463463+464464+ scic_sds_controller_process_completions(scic);465465+ writel(SMU_ISR_QUEUE_SUSPEND, &scic->smu_registers->interrupt_status);466466+ } else {467467+ dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__,468468+ interrupt_status);469469+470470+ sci_base_state_machine_change_state(&scic->state_machine,471471+ SCI_BASE_CONTROLLER_STATE_FAILED);472472+473473+ return;474474+ }475475+476476+ /* If we dont process any completions I am not sure that we want to do this.477477+ * We are in the middle of a hardware fault and should probably be reset.478478+ */479479+ writel(0, &scic->smu_registers->interrupt_mask);255480}256481257482irqreturn_t isci_intx_isr(int vec, void *data)···697112 * core library.698113 *699114 */700700-void isci_host_start_complete(struct isci_host *ihost, enum sci_status completion_status)115115+static void isci_host_start_complete(struct isci_host *ihost, enum sci_status completion_status)701116{702117 if (completion_status != SCI_SUCCESS)703118 dev_info(&ihost->pdev->dev,···727142728143}729144145145+/**146146+ * scic_controller_get_suggested_start_timeout() - This method returns the147147+ * suggested scic_controller_start() timeout amount. The user is free to148148+ * use any timeout value, but this method provides the suggested minimum149149+ * start timeout value. The returned value is based upon empirical150150+ * information determined as a result of interoperability testing.151151+ * @controller: the handle to the controller object for which to return the152152+ * suggested start timeout.153153+ *154154+ * This method returns the number of milliseconds for the suggested start155155+ * operation timeout.156156+ */157157+static u32 scic_controller_get_suggested_start_timeout(158158+ struct scic_sds_controller *sc)159159+{160160+ /* Validate the user supplied parameters. */161161+ if (sc == NULL)162162+ return 0;163163+164164+ /*165165+ * The suggested minimum timeout value for a controller start operation:166166+ *167167+ * Signature FIS Timeout168168+ * + Phy Start Timeout169169+ * + Number of Phy Spin Up Intervals170170+ * ---------------------------------171171+ * Number of milliseconds for the controller start operation.172172+ *173173+ * NOTE: The number of phy spin up intervals will be equivalent174174+ * to the number of phys divided by the number phys allowed175175+ * per interval - 1 (once OEM parameters are supported).176176+ * Currently we assume only 1 phy per interval. */177177+178178+ return SCIC_SDS_SIGNATURE_FIS_TIMEOUT179179+ + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT180180+ + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);181181+}182182+183183+static void scic_controller_enable_interrupts(184184+ struct scic_sds_controller *scic)185185+{186186+ BUG_ON(scic->smu_registers == NULL);187187+ writel(0, &scic->smu_registers->interrupt_mask);188188+}189189+190190+void scic_controller_disable_interrupts(191191+ struct scic_sds_controller *scic)192192+{193193+ BUG_ON(scic->smu_registers == NULL);194194+ writel(0xffffffff, &scic->smu_registers->interrupt_mask);195195+}196196+197197+static void scic_sds_controller_enable_port_task_scheduler(198198+ struct scic_sds_controller *scic)199199+{200200+ u32 port_task_scheduler_value;201201+202202+ port_task_scheduler_value =203203+ readl(&scic->scu_registers->peg0.ptsg.control);204204+ port_task_scheduler_value |=205205+ (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) |206206+ SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));207207+ writel(port_task_scheduler_value,208208+ &scic->scu_registers->peg0.ptsg.control);209209+}210210+211211+static void scic_sds_controller_assign_task_entries(struct scic_sds_controller *scic)212212+{213213+ u32 task_assignment;214214+215215+ /*216216+ * Assign all the TCs to function 0217217+ * TODO: Do we actually need to read this register to write it back?218218+ */219219+220220+ task_assignment =221221+ readl(&scic->smu_registers->task_context_assignment[0]);222222+223223+ task_assignment |= (SMU_TCA_GEN_VAL(STARTING, 0)) |224224+ (SMU_TCA_GEN_VAL(ENDING, scic->task_context_entries - 1)) |225225+ (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE));226226+227227+ writel(task_assignment,228228+ &scic->smu_registers->task_context_assignment[0]);229229+230230+}231231+232232+static void scic_sds_controller_initialize_completion_queue(struct scic_sds_controller *scic)233233+{234234+ u32 index;235235+ u32 completion_queue_control_value;236236+ u32 completion_queue_get_value;237237+ u32 completion_queue_put_value;238238+239239+ scic->completion_queue_get = 0;240240+241241+ completion_queue_control_value = (242242+ SMU_CQC_QUEUE_LIMIT_SET(scic->completion_queue_entries - 1)243243+ | SMU_CQC_EVENT_LIMIT_SET(scic->completion_event_entries - 1)244244+ );245245+246246+ writel(completion_queue_control_value,247247+ &scic->smu_registers->completion_queue_control);248248+249249+250250+ /* Set the completion queue get pointer and enable the queue */251251+ completion_queue_get_value = (252252+ (SMU_CQGR_GEN_VAL(POINTER, 0))253253+ | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))254254+ | (SMU_CQGR_GEN_BIT(ENABLE))255255+ | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))256256+ );257257+258258+ writel(completion_queue_get_value,259259+ &scic->smu_registers->completion_queue_get);260260+261261+ /* Set the completion queue put pointer */262262+ completion_queue_put_value = (263263+ (SMU_CQPR_GEN_VAL(POINTER, 0))264264+ | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))265265+ );266266+267267+ writel(completion_queue_put_value,268268+ &scic->smu_registers->completion_queue_put);269269+270270+ /* Initialize the cycle bit of the completion queue entries */271271+ for (index = 0; index < scic->completion_queue_entries; index++) {272272+ /*273273+ * If get.cycle_bit != completion_queue.cycle_bit274274+ * its not a valid completion queue entry275275+ * so at system start all entries are invalid */276276+ scic->completion_queue[index] = 0x80000000;277277+ }278278+}279279+280280+static void scic_sds_controller_initialize_unsolicited_frame_queue(struct scic_sds_controller *scic)281281+{282282+ u32 frame_queue_control_value;283283+ u32 frame_queue_get_value;284284+ u32 frame_queue_put_value;285285+286286+ /* Write the queue size */287287+ frame_queue_control_value =288288+ SCU_UFQC_GEN_VAL(QUEUE_SIZE,289289+ scic->uf_control.address_table.count);290290+291291+ writel(frame_queue_control_value,292292+ &scic->scu_registers->sdma.unsolicited_frame_queue_control);293293+294294+ /* Setup the get pointer for the unsolicited frame queue */295295+ frame_queue_get_value = (296296+ SCU_UFQGP_GEN_VAL(POINTER, 0)297297+ | SCU_UFQGP_GEN_BIT(ENABLE_BIT)298298+ );299299+300300+ writel(frame_queue_get_value,301301+ &scic->scu_registers->sdma.unsolicited_frame_get_pointer);302302+ /* Setup the put pointer for the unsolicited frame queue */303303+ frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);304304+ writel(frame_queue_put_value,305305+ &scic->scu_registers->sdma.unsolicited_frame_put_pointer);306306+}307307+308308+/**309309+ * This method will attempt to transition into the ready state for the310310+ * controller and indicate that the controller start operation has completed311311+ * if all criteria are met.312312+ * @scic: This parameter indicates the controller object for which313313+ * to transition to ready.314314+ * @status: This parameter indicates the status value to be pass into the call315315+ * to scic_cb_controller_start_complete().316316+ *317317+ * none.318318+ */319319+static void scic_sds_controller_transition_to_ready(320320+ struct scic_sds_controller *scic,321321+ enum sci_status status)322322+{323323+ struct isci_host *ihost = scic_to_ihost(scic);324324+325325+ if (scic->state_machine.current_state_id ==326326+ SCI_BASE_CONTROLLER_STATE_STARTING) {327327+ /*328328+ * We move into the ready state, because some of the phys/ports329329+ * may be up and operational.330330+ */331331+ sci_base_state_machine_change_state(&scic->state_machine,332332+ SCI_BASE_CONTROLLER_STATE_READY);333333+334334+ isci_host_start_complete(ihost, status);335335+ }336336+}337337+338338+static void scic_sds_controller_phy_timer_stop(struct scic_sds_controller *scic)339339+{340340+ isci_timer_stop(scic->phy_startup_timer);341341+342342+ scic->phy_startup_timer_pending = false;343343+}344344+345345+static void scic_sds_controller_phy_timer_start(struct scic_sds_controller *scic)346346+{347347+ isci_timer_start(scic->phy_startup_timer,348348+ SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT);349349+350350+ scic->phy_startup_timer_pending = true;351351+}352352+353353+/**354354+ * scic_sds_controller_start_next_phy - start phy355355+ * @scic: controller356356+ *357357+ * If all the phys have been started, then attempt to transition the358358+ * controller to the READY state and inform the user359359+ * (scic_cb_controller_start_complete()).360360+ */361361+static enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic)362362+{363363+ struct isci_host *ihost = scic_to_ihost(scic);364364+ struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;365365+ struct scic_sds_phy *sci_phy;366366+ enum sci_status status;367367+368368+ status = SCI_SUCCESS;369369+370370+ if (scic->phy_startup_timer_pending)371371+ return status;372372+373373+ if (scic->next_phy_to_start >= SCI_MAX_PHYS) {374374+ bool is_controller_start_complete = true;375375+ u32 state;376376+ u8 index;377377+378378+ for (index = 0; index < SCI_MAX_PHYS; index++) {379379+ sci_phy = &ihost->phys[index].sci;380380+ state = sci_phy->state_machine.current_state_id;381381+382382+ if (!scic_sds_phy_get_port(sci_phy))383383+ continue;384384+385385+ /* The controller start operation is complete iff:386386+ * - all links have been given an opportunity to start387387+ * - have no indication of a connected device388388+ * - have an indication of a connected device and it has389389+ * finished the link training process.390390+ */391391+ if ((sci_phy->is_in_link_training == false &&392392+ state == SCI_BASE_PHY_STATE_INITIAL) ||393393+ (sci_phy->is_in_link_training == false &&394394+ state == SCI_BASE_PHY_STATE_STOPPED) ||395395+ (sci_phy->is_in_link_training == true &&396396+ state == SCI_BASE_PHY_STATE_STARTING)) {397397+ is_controller_start_complete = false;398398+ break;399399+ }400400+ }401401+402402+ /*403403+ * The controller has successfully finished the start process.404404+ * Inform the SCI Core user and transition to the READY state. */405405+ if (is_controller_start_complete == true) {406406+ scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS);407407+ scic_sds_controller_phy_timer_stop(scic);408408+ }409409+ } else {410410+ sci_phy = &ihost->phys[scic->next_phy_to_start].sci;411411+412412+ if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {413413+ if (scic_sds_phy_get_port(sci_phy) == NULL) {414414+ scic->next_phy_to_start++;415415+416416+ /* Caution recursion ahead be forwarned417417+ *418418+ * The PHY was never added to a PORT in MPC mode419419+ * so start the next phy in sequence This phy420420+ * will never go link up and will not draw power421421+ * the OEM parameters either configured the phy422422+ * incorrectly for the PORT or it was never423423+ * assigned to a PORT424424+ */425425+ return scic_sds_controller_start_next_phy(scic);426426+ }427427+ }428428+429429+ status = scic_sds_phy_start(sci_phy);430430+431431+ if (status == SCI_SUCCESS) {432432+ scic_sds_controller_phy_timer_start(scic);433433+ } else {434434+ dev_warn(scic_to_dev(scic),435435+ "%s: Controller stop operation failed "436436+ "to stop phy %d because of status "437437+ "%d.\n",438438+ __func__,439439+ ihost->phys[scic->next_phy_to_start].sci.phy_index,440440+ status);441441+ }442442+443443+ scic->next_phy_to_start++;444444+ }445445+446446+ return status;447447+}448448+449449+static void scic_sds_controller_phy_startup_timeout_handler(void *_scic)450450+{451451+ struct scic_sds_controller *scic = _scic;452452+ enum sci_status status;453453+454454+ scic->phy_startup_timer_pending = false;455455+ status = SCI_FAILURE;456456+ while (status != SCI_SUCCESS)457457+ status = scic_sds_controller_start_next_phy(scic);458458+}459459+460460+static enum sci_status scic_controller_start(struct scic_sds_controller *scic,461461+ u32 timeout)462462+{463463+ struct isci_host *ihost = scic_to_ihost(scic);464464+ enum sci_status result;465465+ u16 index;466466+467467+ if (scic->state_machine.current_state_id !=468468+ SCI_BASE_CONTROLLER_STATE_INITIALIZED) {469469+ dev_warn(scic_to_dev(scic),470470+ "SCIC Controller start operation requested in "471471+ "invalid state\n");472472+ return SCI_FAILURE_INVALID_STATE;473473+ }474474+475475+ /* Build the TCi free pool */476476+ sci_pool_initialize(scic->tci_pool);477477+ for (index = 0; index < scic->task_context_entries; index++)478478+ sci_pool_put(scic->tci_pool, index);479479+480480+ /* Build the RNi free pool */481481+ scic_sds_remote_node_table_initialize(482482+ &scic->available_remote_nodes,483483+ scic->remote_node_entries);484484+485485+ /*486486+ * Before anything else lets make sure we will not be487487+ * interrupted by the hardware.488488+ */489489+ scic_controller_disable_interrupts(scic);490490+491491+ /* Enable the port task scheduler */492492+ scic_sds_controller_enable_port_task_scheduler(scic);493493+494494+ /* Assign all the task entries to scic physical function */495495+ scic_sds_controller_assign_task_entries(scic);496496+497497+ /* Now initialize the completion queue */498498+ scic_sds_controller_initialize_completion_queue(scic);499499+500500+ /* Initialize the unsolicited frame queue for use */501501+ scic_sds_controller_initialize_unsolicited_frame_queue(scic);502502+503503+ /* Start all of the ports on this controller */504504+ for (index = 0; index < scic->logical_port_entries; index++) {505505+ struct scic_sds_port *sci_port = &ihost->ports[index].sci;506506+507507+ result = sci_port->state_handlers->start_handler(sci_port);508508+ if (result)509509+ return result;510510+ }511511+512512+ scic_sds_controller_start_next_phy(scic);513513+514514+ isci_timer_start(scic->timeout_timer, timeout);515515+516516+ sci_base_state_machine_change_state(&scic->state_machine,517517+ SCI_BASE_CONTROLLER_STATE_STARTING);518518+519519+ return SCI_SUCCESS;520520+}521521+730522void isci_host_scan_start(struct Scsi_Host *shost)731523{732524 struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha;···1117155 spin_unlock_irq(&ihost->scic_lock);1118156}111915711201120-void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status)158158+static void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status)1121159{1122160 isci_host_change_state(ihost, isci_stopped);1123161 scic_controller_disable_interrupts(&ihost->sci);1124162 clear_bit(IHOST_STOP_PENDING, &ihost->flags);1125163 wake_up(&ihost->eventq);164164+}165165+166166+static void scic_sds_controller_completion_handler(struct scic_sds_controller *scic)167167+{168168+ /* Empty out the completion queue */169169+ if (scic_sds_controller_completion_queue_has_entries(scic))170170+ scic_sds_controller_process_completions(scic);171171+172172+ /* Clear the interrupt and enable all interrupts again */173173+ writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status);174174+ /* Could we write the value of SMU_ISR_COMPLETION? */175175+ writel(0xFF000000, &scic->smu_registers->interrupt_mask);176176+ writel(0, &scic->smu_registers->interrupt_mask);1126177}11271781128179/**···12482731249274}1250275276276+/**277277+ * scic_controller_stop() - This method will stop an individual controller278278+ * object.This method will invoke the associated user callback upon279279+ * completion. The completion callback is called when the following280280+ * conditions are met: -# the method return status is SCI_SUCCESS. -# the281281+ * controller has been quiesced. This method will ensure that all IO282282+ * requests are quiesced, phys are stopped, and all additional operation by283283+ * the hardware is halted.284284+ * @controller: the handle to the controller object to stop.285285+ * @timeout: This parameter specifies the number of milliseconds in which the286286+ * stop operation should complete.287287+ *288288+ * The controller must be in the STARTED or STOPPED state. Indicate if the289289+ * controller stop method succeeded or failed in some way. SCI_SUCCESS if the290290+ * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the291291+ * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the292292+ * controller is not either in the STARTED or STOPPED states.293293+ */294294+static enum sci_status scic_controller_stop(struct scic_sds_controller *scic,295295+ u32 timeout)296296+{297297+ if (scic->state_machine.current_state_id !=298298+ SCI_BASE_CONTROLLER_STATE_READY) {299299+ dev_warn(scic_to_dev(scic),300300+ "SCIC Controller stop operation requested in "301301+ "invalid state\n");302302+ return SCI_FAILURE_INVALID_STATE;303303+ }304304+305305+ isci_timer_start(scic->timeout_timer, timeout);306306+ sci_base_state_machine_change_state(&scic->state_machine,307307+ SCI_BASE_CONTROLLER_STATE_STOPPING);308308+ return SCI_SUCCESS;309309+}310310+311311+/**312312+ * scic_controller_reset() - This method will reset the supplied core313313+ * controller regardless of the state of said controller. This operation is314314+ * considered destructive. In other words, all current operations are wiped315315+ * out. No IO completions for outstanding devices occur. Outstanding IO316316+ * requests are not aborted or completed at the actual remote device.317317+ * @controller: the handle to the controller object to reset.318318+ *319319+ * Indicate if the controller reset method succeeded or failed in some way.320320+ * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if321321+ * the controller reset operation is unable to complete.322322+ */323323+static enum sci_status scic_controller_reset(struct scic_sds_controller *scic)324324+{325325+ switch (scic->state_machine.current_state_id) {326326+ case SCI_BASE_CONTROLLER_STATE_RESET:327327+ case SCI_BASE_CONTROLLER_STATE_READY:328328+ case SCI_BASE_CONTROLLER_STATE_STOPPED:329329+ case SCI_BASE_CONTROLLER_STATE_FAILED:330330+ /*331331+ * The reset operation is not a graceful cleanup, just332332+ * perform the state transition.333333+ */334334+ sci_base_state_machine_change_state(&scic->state_machine,335335+ SCI_BASE_CONTROLLER_STATE_RESETTING);336336+ return SCI_SUCCESS;337337+ default:338338+ dev_warn(scic_to_dev(scic),339339+ "SCIC Controller reset operation requested in "340340+ "invalid state\n");341341+ return SCI_FAILURE_INVALID_STATE;342342+ }343343+}344344+1251345void isci_host_deinit(struct isci_host *ihost)1252346{1253347 int i;···1383339 u->ssp_max_occupancy_timeout = ssp_max_occ_to;1384340 u->no_outbound_task_timeout = no_outbound_task_to;1385341 u->max_number_concurrent_device_spin_up = max_concurr_spinup;342342+}343343+344344+static void scic_sds_controller_initial_state_enter(void *object)345345+{346346+ struct scic_sds_controller *scic = object;347347+348348+ sci_base_state_machine_change_state(&scic->state_machine,349349+ SCI_BASE_CONTROLLER_STATE_RESET);350350+}351351+352352+static inline void scic_sds_controller_starting_state_exit(void *object)353353+{354354+ struct scic_sds_controller *scic = object;355355+356356+ isci_timer_stop(scic->timeout_timer);357357+}358358+359359+#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853360360+#define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280361361+#define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000362362+#define INTERRUPT_COALESCE_NUMBER_MAX 256363363+#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7364364+#define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28365365+366366+/**367367+ * scic_controller_set_interrupt_coalescence() - This method allows the user to368368+ * configure the interrupt coalescence.369369+ * @controller: This parameter represents the handle to the controller object370370+ * for which its interrupt coalesce register is overridden.371371+ * @coalesce_number: Used to control the number of entries in the Completion372372+ * Queue before an interrupt is generated. If the number of entries exceed373373+ * this number, an interrupt will be generated. The valid range of the input374374+ * is [0, 256]. A setting of 0 results in coalescing being disabled.375375+ * @coalesce_timeout: Timeout value in microseconds. The valid range of the376376+ * input is [0, 2700000] . A setting of 0 is allowed and results in no377377+ * interrupt coalescing timeout.378378+ *379379+ * Indicate if the user successfully set the interrupt coalesce parameters.380380+ * SCI_SUCCESS The user successfully updated the interrutp coalescence.381381+ * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range.382382+ */383383+static enum sci_status scic_controller_set_interrupt_coalescence(384384+ struct scic_sds_controller *scic_controller,385385+ u32 coalesce_number,386386+ u32 coalesce_timeout)387387+{388388+ u8 timeout_encode = 0;389389+ u32 min = 0;390390+ u32 max = 0;391391+392392+ /* Check if the input parameters fall in the range. */393393+ if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX)394394+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;395395+396396+ /*397397+ * Defined encoding for interrupt coalescing timeout:398398+ * Value Min Max Units399399+ * ----- --- --- -----400400+ * 0 - - Disabled401401+ * 1 13.3 20.0 ns402402+ * 2 26.7 40.0403403+ * 3 53.3 80.0404404+ * 4 106.7 160.0405405+ * 5 213.3 320.0406406+ * 6 426.7 640.0407407+ * 7 853.3 1280.0408408+ * 8 1.7 2.6 us409409+ * 9 3.4 5.1410410+ * 10 6.8 10.2411411+ * 11 13.7 20.5412412+ * 12 27.3 41.0413413+ * 13 54.6 81.9414414+ * 14 109.2 163.8415415+ * 15 218.5 327.7416416+ * 16 436.9 655.4417417+ * 17 873.8 1310.7418418+ * 18 1.7 2.6 ms419419+ * 19 3.5 5.2420420+ * 20 7.0 10.5421421+ * 21 14.0 21.0422422+ * 22 28.0 41.9423423+ * 23 55.9 83.9424424+ * 24 111.8 167.8425425+ * 25 223.7 335.5426426+ * 26 447.4 671.1427427+ * 27 894.8 1342.2428428+ * 28 1.8 2.7 s429429+ * Others Undefined */430430+431431+ /*432432+ * Use the table above to decide the encode of interrupt coalescing timeout433433+ * value for register writing. */434434+ if (coalesce_timeout == 0)435435+ timeout_encode = 0;436436+ else{437437+ /* make the timeout value in unit of (10 ns). */438438+ coalesce_timeout = coalesce_timeout * 100;439439+ min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10;440440+ max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10;441441+442442+ /* get the encode of timeout for register writing. */443443+ for (timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN;444444+ timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX;445445+ timeout_encode++) {446446+ if (min <= coalesce_timeout && max > coalesce_timeout)447447+ break;448448+ else if (coalesce_timeout >= max && coalesce_timeout < min * 2449449+ && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US * 100) {450450+ if ((coalesce_timeout - max) < (2 * min - coalesce_timeout))451451+ break;452452+ else{453453+ timeout_encode++;454454+ break;455455+ }456456+ } else {457457+ max = max * 2;458458+ min = min * 2;459459+ }460460+ }461461+462462+ if (timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX + 1)463463+ /* the value is out of range. */464464+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;465465+ }466466+467467+ writel(SMU_ICC_GEN_VAL(NUMBER, coalesce_number) |468468+ SMU_ICC_GEN_VAL(TIMER, timeout_encode),469469+ &scic_controller->smu_registers->interrupt_coalesce_control);470470+471471+472472+ scic_controller->interrupt_coalesce_number = (u16)coalesce_number;473473+ scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100;474474+475475+ return SCI_SUCCESS;476476+}477477+478478+479479+static void scic_sds_controller_ready_state_enter(void *object)480480+{481481+ struct scic_sds_controller *scic = object;482482+483483+ /* set the default interrupt coalescence number and timeout value. */484484+ scic_controller_set_interrupt_coalescence(scic, 0x10, 250);485485+}486486+487487+static void scic_sds_controller_ready_state_exit(void *object)488488+{489489+ struct scic_sds_controller *scic = object;490490+491491+ /* disable interrupt coalescence. */492492+ scic_controller_set_interrupt_coalescence(scic, 0, 0);493493+}494494+495495+static enum sci_status scic_sds_controller_stop_phys(struct scic_sds_controller *scic)496496+{497497+ u32 index;498498+ enum sci_status status;499499+ enum sci_status phy_status;500500+ struct isci_host *ihost = scic_to_ihost(scic);501501+502502+ status = SCI_SUCCESS;503503+504504+ for (index = 0; index < SCI_MAX_PHYS; index++) {505505+ phy_status = scic_sds_phy_stop(&ihost->phys[index].sci);506506+507507+ if (phy_status != SCI_SUCCESS &&508508+ phy_status != SCI_FAILURE_INVALID_STATE) {509509+ status = SCI_FAILURE;510510+511511+ dev_warn(scic_to_dev(scic),512512+ "%s: Controller stop operation failed to stop "513513+ "phy %d because of status %d.\n",514514+ __func__,515515+ ihost->phys[index].sci.phy_index, phy_status);516516+ }517517+ }518518+519519+ return status;520520+}521521+522522+static enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)523523+{524524+ u32 index;525525+ enum sci_status port_status;526526+ enum sci_status status = SCI_SUCCESS;527527+ struct isci_host *ihost = scic_to_ihost(scic);528528+529529+ for (index = 0; index < scic->logical_port_entries; index++) {530530+ struct scic_sds_port *sci_port = &ihost->ports[index].sci;531531+ scic_sds_port_handler_t stop;532532+533533+ stop = sci_port->state_handlers->stop_handler;534534+ port_status = stop(sci_port);535535+536536+ if ((port_status != SCI_SUCCESS) &&537537+ (port_status != SCI_FAILURE_INVALID_STATE)) {538538+ status = SCI_FAILURE;539539+540540+ dev_warn(scic_to_dev(scic),541541+ "%s: Controller stop operation failed to "542542+ "stop port %d because of status %d.\n",543543+ __func__,544544+ sci_port->logical_port_index,545545+ port_status);546546+ }547547+ }548548+549549+ return status;550550+}551551+552552+static enum sci_status scic_sds_controller_stop_devices(struct scic_sds_controller *scic)553553+{554554+ u32 index;555555+ enum sci_status status;556556+ enum sci_status device_status;557557+558558+ status = SCI_SUCCESS;559559+560560+ for (index = 0; index < scic->remote_node_entries; index++) {561561+ if (scic->device_table[index] != NULL) {562562+ /* / @todo What timeout value do we want to provide to this request? */563563+ device_status = scic_remote_device_stop(scic->device_table[index], 0);564564+565565+ if ((device_status != SCI_SUCCESS) &&566566+ (device_status != SCI_FAILURE_INVALID_STATE)) {567567+ dev_warn(scic_to_dev(scic),568568+ "%s: Controller stop operation failed "569569+ "to stop device 0x%p because of "570570+ "status %d.\n",571571+ __func__,572572+ scic->device_table[index], device_status);573573+ }574574+ }575575+ }576576+577577+ return status;578578+}579579+580580+static void scic_sds_controller_stopping_state_enter(void *object)581581+{582582+ struct scic_sds_controller *scic = object;583583+584584+ /* Stop all of the components for this controller */585585+ scic_sds_controller_stop_phys(scic);586586+ scic_sds_controller_stop_ports(scic);587587+ scic_sds_controller_stop_devices(scic);588588+}589589+590590+static void scic_sds_controller_stopping_state_exit(void *object)591591+{592592+ struct scic_sds_controller *scic = object;593593+594594+ isci_timer_stop(scic->timeout_timer);595595+}596596+597597+598598+/**599599+ * scic_sds_controller_reset_hardware() -600600+ *601601+ * This method will reset the controller hardware.602602+ */603603+static void scic_sds_controller_reset_hardware(struct scic_sds_controller *scic)604604+{605605+ /* Disable interrupts so we dont take any spurious interrupts */606606+ scic_controller_disable_interrupts(scic);607607+608608+ /* Reset the SCU */609609+ writel(0xFFFFFFFF, &scic->smu_registers->soft_reset_control);610610+611611+ /* Delay for 1ms to before clearing the CQP and UFQPR. */612612+ udelay(1000);613613+614614+ /* The write to the CQGR clears the CQP */615615+ writel(0x00000000, &scic->smu_registers->completion_queue_get);616616+617617+ /* The write to the UFQGP clears the UFQPR */618618+ writel(0, &scic->scu_registers->sdma.unsolicited_frame_get_pointer);619619+}620620+621621+static void scic_sds_controller_resetting_state_enter(void *object)622622+{623623+ struct scic_sds_controller *scic = object;624624+625625+ scic_sds_controller_reset_hardware(scic);626626+ sci_base_state_machine_change_state(&scic->state_machine,627627+ SCI_BASE_CONTROLLER_STATE_RESET);628628+}629629+630630+static const struct sci_base_state scic_sds_controller_state_table[] = {631631+ [SCI_BASE_CONTROLLER_STATE_INITIAL] = {632632+ .enter_state = scic_sds_controller_initial_state_enter,633633+ },634634+ [SCI_BASE_CONTROLLER_STATE_RESET] = {},635635+ [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {},636636+ [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {},637637+ [SCI_BASE_CONTROLLER_STATE_STARTING] = {638638+ .exit_state = scic_sds_controller_starting_state_exit,639639+ },640640+ [SCI_BASE_CONTROLLER_STATE_READY] = {641641+ .enter_state = scic_sds_controller_ready_state_enter,642642+ .exit_state = scic_sds_controller_ready_state_exit,643643+ },644644+ [SCI_BASE_CONTROLLER_STATE_RESETTING] = {645645+ .enter_state = scic_sds_controller_resetting_state_enter,646646+ },647647+ [SCI_BASE_CONTROLLER_STATE_STOPPING] = {648648+ .enter_state = scic_sds_controller_stopping_state_enter,649649+ .exit_state = scic_sds_controller_stopping_state_exit,650650+ },651651+ [SCI_BASE_CONTROLLER_STATE_STOPPED] = {},652652+ [SCI_BASE_CONTROLLER_STATE_FAILED] = {}653653+};654654+655655+static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic)656656+{657657+ /* these defaults are overridden by the platform / firmware */658658+ struct isci_host *ihost = scic_to_ihost(scic);659659+ u16 index;660660+661661+ /* Default to APC mode. */662662+ scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;663663+664664+ /* Default to APC mode. */665665+ scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1;666666+667667+ /* Default to no SSC operation. */668668+ scic->oem_parameters.sds1.controller.do_enable_ssc = false;669669+670670+ /* Initialize all of the port parameter information to narrow ports. */671671+ for (index = 0; index < SCI_MAX_PORTS; index++) {672672+ scic->oem_parameters.sds1.ports[index].phy_mask = 0;673673+ }674674+675675+ /* Initialize all of the phy parameter information. */676676+ for (index = 0; index < SCI_MAX_PHYS; index++) {677677+ /* Default to 6G (i.e. Gen 3) for now. */678678+ scic->user_parameters.sds1.phys[index].max_speed_generation = 3;679679+680680+ /* the frequencies cannot be 0 */681681+ scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f;682682+ scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff;683683+ scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33;684684+685685+ /*686686+ * Previous Vitesse based expanders had a arbitration issue that687687+ * is worked around by having the upper 32-bits of SAS address688688+ * with a value greater then the Vitesse company identifier.689689+ * Hence, usage of 0x5FCFFFFF. */690690+ scic->oem_parameters.sds1.phys[index].sas_address.low = 0x1 + ihost->id;691691+ scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF;692692+ }693693+694694+ scic->user_parameters.sds1.stp_inactivity_timeout = 5;695695+ scic->user_parameters.sds1.ssp_inactivity_timeout = 5;696696+ scic->user_parameters.sds1.stp_max_occupancy_timeout = 5;697697+ scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20;698698+ scic->user_parameters.sds1.no_outbound_task_timeout = 20;699699+}700700+701701+702702+703703+/**704704+ * scic_controller_construct() - This method will attempt to construct a705705+ * controller object utilizing the supplied parameter information.706706+ * @c: This parameter specifies the controller to be constructed.707707+ * @scu_base: mapped base address of the scu registers708708+ * @smu_base: mapped base address of the smu registers709709+ *710710+ * Indicate if the controller was successfully constructed or if it failed in711711+ * some way. SCI_SUCCESS This value is returned if the controller was712712+ * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned713713+ * if the interrupt coalescence timer may cause SAS compliance issues for SMP714714+ * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE715715+ * This value is returned if the controller does not support the supplied type.716716+ * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the717717+ * controller does not support the supplied initialization data version.718718+ */719719+static enum sci_status scic_controller_construct(struct scic_sds_controller *scic,720720+ void __iomem *scu_base,721721+ void __iomem *smu_base)722722+{723723+ struct isci_host *ihost = scic_to_ihost(scic);724724+ u8 i;725725+726726+ sci_base_state_machine_construct(&scic->state_machine,727727+ scic, scic_sds_controller_state_table,728728+ SCI_BASE_CONTROLLER_STATE_INITIAL);729729+730730+ sci_base_state_machine_start(&scic->state_machine);731731+732732+ scic->scu_registers = scu_base;733733+ scic->smu_registers = smu_base;734734+735735+ scic_sds_port_configuration_agent_construct(&scic->port_agent);736736+737737+ /* Construct the ports for this controller */738738+ for (i = 0; i < SCI_MAX_PORTS; i++)739739+ scic_sds_port_construct(&ihost->ports[i].sci, i, scic);740740+ scic_sds_port_construct(&ihost->ports[i].sci, SCIC_SDS_DUMMY_PORT, scic);741741+742742+ /* Construct the phys for this controller */743743+ for (i = 0; i < SCI_MAX_PHYS; i++) {744744+ /* Add all the PHYs to the dummy port */745745+ scic_sds_phy_construct(&ihost->phys[i].sci,746746+ &ihost->ports[SCI_MAX_PORTS].sci, i);747747+ }748748+749749+ scic->invalid_phy_mask = 0;750750+751751+ /* Set the default maximum values */752752+ scic->completion_event_entries = SCU_EVENT_COUNT;753753+ scic->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT;754754+ scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES;755755+ scic->logical_port_entries = SCI_MAX_PORTS;756756+ scic->task_context_entries = SCU_IO_REQUEST_COUNT;757757+ scic->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT;758758+ scic->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT;759759+760760+ /* Initialize the User and OEM parameters to default values. */761761+ scic_sds_controller_set_default_config_parameters(scic);762762+763763+ return scic_controller_reset(scic);764764+}765765+766766+int scic_oem_parameters_validate(struct scic_sds_oem_params *oem)767767+{768768+ int i;769769+770770+ for (i = 0; i < SCI_MAX_PORTS; i++)771771+ if (oem->ports[i].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX)772772+ return -EINVAL;773773+774774+ for (i = 0; i < SCI_MAX_PHYS; i++)775775+ if (oem->phys[i].sas_address.high == 0 &&776776+ oem->phys[i].sas_address.low == 0)777777+ return -EINVAL;778778+779779+ if (oem->controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) {780780+ for (i = 0; i < SCI_MAX_PHYS; i++)781781+ if (oem->ports[i].phy_mask != 0)782782+ return -EINVAL;783783+ } else if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {784784+ u8 phy_mask = 0;785785+786786+ for (i = 0; i < SCI_MAX_PHYS; i++)787787+ phy_mask |= oem->ports[i].phy_mask;788788+789789+ if (phy_mask == 0)790790+ return -EINVAL;791791+ } else792792+ return -EINVAL;793793+794794+ if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)795795+ return -EINVAL;796796+797797+ return 0;798798+}799799+800800+static enum sci_status scic_oem_parameters_set(struct scic_sds_controller *scic,801801+ union scic_oem_parameters *scic_parms)802802+{803803+ u32 state = scic->state_machine.current_state_id;804804+805805+ if (state == SCI_BASE_CONTROLLER_STATE_RESET ||806806+ state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||807807+ state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {808808+809809+ if (scic_oem_parameters_validate(&scic_parms->sds1))810810+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;811811+ scic->oem_parameters.sds1 = scic_parms->sds1;812812+813813+ return SCI_SUCCESS;814814+ }815815+816816+ return SCI_FAILURE_INVALID_STATE;817817+}818818+819819+void scic_oem_parameters_get(820820+ struct scic_sds_controller *scic,821821+ union scic_oem_parameters *scic_parms)822822+{823823+ memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms));824824+}825825+826826+static void scic_sds_controller_timeout_handler(void *_scic)827827+{828828+ struct scic_sds_controller *scic = _scic;829829+ struct isci_host *ihost = scic_to_ihost(scic);830830+ struct sci_base_state_machine *sm = &scic->state_machine;831831+832832+ if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STARTING)833833+ scic_sds_controller_transition_to_ready(scic, SCI_FAILURE_TIMEOUT);834834+ else if (sm->current_state_id == SCI_BASE_CONTROLLER_STATE_STOPPING) {835835+ sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_FAILED);836836+ isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT);837837+ } else /* / @todo Now what do we want to do in this case? */838838+ dev_err(scic_to_dev(scic),839839+ "%s: Controller timer fired when controller was not "840840+ "in a state being timed.\n",841841+ __func__);842842+}843843+844844+static enum sci_status scic_sds_controller_initialize_phy_startup(struct scic_sds_controller *scic)845845+{846846+ struct isci_host *ihost = scic_to_ihost(scic);847847+848848+ scic->phy_startup_timer = isci_timer_create(ihost,849849+ scic,850850+ scic_sds_controller_phy_startup_timeout_handler);851851+852852+ if (scic->phy_startup_timer == NULL)853853+ return SCI_FAILURE_INSUFFICIENT_RESOURCES;854854+ else {855855+ scic->next_phy_to_start = 0;856856+ scic->phy_startup_timer_pending = false;857857+ }858858+859859+ return SCI_SUCCESS;860860+}861861+862862+static void scic_sds_controller_power_control_timer_start(struct scic_sds_controller *scic)863863+{864864+ isci_timer_start(scic->power_control.timer,865865+ SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);866866+867867+ scic->power_control.timer_started = true;868868+}869869+870870+static void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic)871871+{872872+ if (scic->power_control.timer_started) {873873+ isci_timer_stop(scic->power_control.timer);874874+ scic->power_control.timer_started = false;875875+ }876876+}877877+878878+static void scic_sds_controller_power_control_timer_restart(struct scic_sds_controller *scic)879879+{880880+ scic_sds_controller_power_control_timer_stop(scic);881881+ scic_sds_controller_power_control_timer_start(scic);882882+}883883+884884+static void scic_sds_controller_power_control_timer_handler(885885+ void *controller)886886+{887887+ struct scic_sds_controller *scic;888888+889889+ scic = (struct scic_sds_controller *)controller;890890+891891+ scic->power_control.phys_granted_power = 0;892892+893893+ if (scic->power_control.phys_waiting == 0) {894894+ scic->power_control.timer_started = false;895895+ } else {896896+ struct scic_sds_phy *sci_phy = NULL;897897+ u8 i;898898+899899+ for (i = 0;900900+ (i < SCI_MAX_PHYS)901901+ && (scic->power_control.phys_waiting != 0);902902+ i++) {903903+ if (scic->power_control.requesters[i] != NULL) {904904+ if (scic->power_control.phys_granted_power <905905+ scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {906906+ sci_phy = scic->power_control.requesters[i];907907+ scic->power_control.requesters[i] = NULL;908908+ scic->power_control.phys_waiting--;909909+ scic->power_control.phys_granted_power++;910910+ scic_sds_phy_consume_power_handler(sci_phy);911911+ } else {912912+ break;913913+ }914914+ }915915+ }916916+917917+ /*918918+ * It doesn't matter if the power list is empty, we need to start the919919+ * timer in case another phy becomes ready.920920+ */921921+ scic_sds_controller_power_control_timer_start(scic);922922+ }923923+}924924+925925+/**926926+ * This method inserts the phy in the stagger spinup control queue.927927+ * @scic:928928+ *929929+ *930930+ */931931+void scic_sds_controller_power_control_queue_insert(932932+ struct scic_sds_controller *scic,933933+ struct scic_sds_phy *sci_phy)934934+{935935+ BUG_ON(sci_phy == NULL);936936+937937+ if (scic->power_control.phys_granted_power <938938+ scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {939939+ scic->power_control.phys_granted_power++;940940+ scic_sds_phy_consume_power_handler(sci_phy);941941+942942+ /*943943+ * stop and start the power_control timer. When the timer fires, the944944+ * no_of_phys_granted_power will be set to 0945945+ */946946+ scic_sds_controller_power_control_timer_restart(scic);947947+ } else {948948+ /* Add the phy in the waiting list */949949+ scic->power_control.requesters[sci_phy->phy_index] = sci_phy;950950+ scic->power_control.phys_waiting++;951951+ }952952+}953953+954954+/**955955+ * This method removes the phy from the stagger spinup control queue.956956+ * @scic:957957+ *958958+ *959959+ */960960+void scic_sds_controller_power_control_queue_remove(961961+ struct scic_sds_controller *scic,962962+ struct scic_sds_phy *sci_phy)963963+{964964+ BUG_ON(sci_phy == NULL);965965+966966+ if (scic->power_control.requesters[sci_phy->phy_index] != NULL) {967967+ scic->power_control.phys_waiting--;968968+ }969969+970970+ scic->power_control.requesters[sci_phy->phy_index] = NULL;971971+}972972+973973+#define AFE_REGISTER_WRITE_DELAY 10974974+975975+/* Initialize the AFE for this phy index. We need to read the AFE setup from976976+ * the OEM parameters977977+ */978978+static void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic)979979+{980980+ const struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;981981+ u32 afe_status;982982+ u32 phy_id;983983+984984+ /* Clear DFX Status registers */985985+ writel(0x0081000f, &scic->scu_registers->afe.afe_dfx_master_control0);986986+ udelay(AFE_REGISTER_WRITE_DELAY);987987+988988+ if (is_b0()) {989989+ /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement990990+ * Timer, PM Stagger Timer */991991+ writel(0x0007BFFF, &scic->scu_registers->afe.afe_pmsn_master_control2);992992+ udelay(AFE_REGISTER_WRITE_DELAY);993993+ }994994+995995+ /* Configure bias currents to normal */996996+ if (is_a0())997997+ writel(0x00005500, &scic->scu_registers->afe.afe_bias_control);998998+ else if (is_a2())999999+ writel(0x00005A00, &scic->scu_registers->afe.afe_bias_control);10001000+ else if (is_b0())10011001+ writel(0x00005F00, &scic->scu_registers->afe.afe_bias_control);10021002+10031003+ udelay(AFE_REGISTER_WRITE_DELAY);10041004+10051005+ /* Enable PLL */10061006+ if (is_b0())10071007+ writel(0x80040A08, &scic->scu_registers->afe.afe_pll_control0);10081008+ else10091009+ writel(0x80040908, &scic->scu_registers->afe.afe_pll_control0);10101010+10111011+ udelay(AFE_REGISTER_WRITE_DELAY);10121012+10131013+ /* Wait for the PLL to lock */10141014+ do {10151015+ afe_status = readl(&scic->scu_registers->afe.afe_common_block_status);10161016+ udelay(AFE_REGISTER_WRITE_DELAY);10171017+ } while ((afe_status & 0x00001000) == 0);10181018+10191019+ if (is_a0() || is_a2()) {10201020+ /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */10211021+ writel(0x7bcc96ad, &scic->scu_registers->afe.afe_pmsn_master_control0);10221022+ udelay(AFE_REGISTER_WRITE_DELAY);10231023+ }10241024+10251025+ for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {10261026+ const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];10271027+10281028+ if (is_b0()) {10291029+ /* Configure transmitter SSC parameters */10301030+ writel(0x00030000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);10311031+ udelay(AFE_REGISTER_WRITE_DELAY);10321032+ } else {10331033+ /*10341034+ * All defaults, except the Receive Word Alignament/Comma Detect10351035+ * Enable....(0xe800) */10361036+ writel(0x00004512, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);10371037+ udelay(AFE_REGISTER_WRITE_DELAY);10381038+10391039+ writel(0x0050100F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1);10401040+ udelay(AFE_REGISTER_WRITE_DELAY);10411041+ }10421042+10431043+ /*10441044+ * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)10451045+ * & increase TX int & ext bias 20%....(0xe85c) */10461046+ if (is_a0())10471047+ writel(0x000003D4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);10481048+ else if (is_a2())10491049+ writel(0x000003F0, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);10501050+ else {10511051+ /* Power down TX and RX (PWRDNTX and PWRDNRX) */10521052+ writel(0x000003d7, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);10531053+ udelay(AFE_REGISTER_WRITE_DELAY);10541054+10551055+ /*10561056+ * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)10571057+ * & increase TX int & ext bias 20%....(0xe85c) */10581058+ writel(0x000003d4, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);10591059+ }10601060+ udelay(AFE_REGISTER_WRITE_DELAY);10611061+10621062+ if (is_a0() || is_a2()) {10631063+ /* Enable TX equalization (0xe824) */10641064+ writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);10651065+ udelay(AFE_REGISTER_WRITE_DELAY);10661066+ }10671067+10681068+ /*10691069+ * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),10701070+ * RDD=0x0(RX Detect Enabled) ....(0xe800) */10711071+ writel(0x00004100, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);10721072+ udelay(AFE_REGISTER_WRITE_DELAY);10731073+10741074+ /* Leave DFE/FFE on */10751075+ if (is_a0())10761076+ writel(0x3F09983F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);10771077+ else if (is_a2())10781078+ writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);10791079+ else {10801080+ writel(0x3F11103F, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);10811081+ udelay(AFE_REGISTER_WRITE_DELAY);10821082+ /* Enable TX equalization (0xe824) */10831083+ writel(0x00040000, &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);10841084+ }10851085+ udelay(AFE_REGISTER_WRITE_DELAY);10861086+10871087+ writel(oem_phy->afe_tx_amp_control0,10881088+ &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0);10891089+ udelay(AFE_REGISTER_WRITE_DELAY);10901090+10911091+ writel(oem_phy->afe_tx_amp_control1,10921092+ &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1);10931093+ udelay(AFE_REGISTER_WRITE_DELAY);10941094+10951095+ writel(oem_phy->afe_tx_amp_control2,10961096+ &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2);10971097+ udelay(AFE_REGISTER_WRITE_DELAY);10981098+10991099+ writel(oem_phy->afe_tx_amp_control3,11001100+ &scic->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3);11011101+ udelay(AFE_REGISTER_WRITE_DELAY);11021102+ }11031103+11041104+ /* Transfer control to the PEs */11051105+ writel(0x00010f00, &scic->scu_registers->afe.afe_dfx_master_control0);11061106+ udelay(AFE_REGISTER_WRITE_DELAY);11071107+}11081108+11091109+static enum sci_status scic_controller_set_mode(struct scic_sds_controller *scic,11101110+ enum sci_controller_mode operating_mode)11111111+{11121112+ enum sci_status status = SCI_SUCCESS;11131113+11141114+ if ((scic->state_machine.current_state_id ==11151115+ SCI_BASE_CONTROLLER_STATE_INITIALIZING) ||11161116+ (scic->state_machine.current_state_id ==11171117+ SCI_BASE_CONTROLLER_STATE_INITIALIZED)) {11181118+ switch (operating_mode) {11191119+ case SCI_MODE_SPEED:11201120+ scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES;11211121+ scic->task_context_entries = SCU_IO_REQUEST_COUNT;11221122+ scic->uf_control.buffers.count =11231123+ SCU_UNSOLICITED_FRAME_COUNT;11241124+ scic->completion_event_entries = SCU_EVENT_COUNT;11251125+ scic->completion_queue_entries =11261126+ SCU_COMPLETION_QUEUE_COUNT;11271127+ break;11281128+11291129+ case SCI_MODE_SIZE:11301130+ scic->remote_node_entries = SCI_MIN_REMOTE_DEVICES;11311131+ scic->task_context_entries = SCI_MIN_IO_REQUESTS;11321132+ scic->uf_control.buffers.count =11331133+ SCU_MIN_UNSOLICITED_FRAMES;11341134+ scic->completion_event_entries = SCU_MIN_EVENTS;11351135+ scic->completion_queue_entries =11361136+ SCU_MIN_COMPLETION_QUEUE_ENTRIES;11371137+ break;11381138+11391139+ default:11401140+ status = SCI_FAILURE_INVALID_PARAMETER_VALUE;11411141+ break;11421142+ }11431143+ } else11441144+ status = SCI_FAILURE_INVALID_STATE;11451145+11461146+ return status;11471147+}11481148+11491149+static void scic_sds_controller_initialize_power_control(struct scic_sds_controller *scic)11501150+{11511151+ struct isci_host *ihost = scic_to_ihost(scic);11521152+ scic->power_control.timer = isci_timer_create(ihost,11531153+ scic,11541154+ scic_sds_controller_power_control_timer_handler);11551155+11561156+ memset(scic->power_control.requesters, 0,11571157+ sizeof(scic->power_control.requesters));11581158+11591159+ scic->power_control.phys_waiting = 0;11601160+ scic->power_control.phys_granted_power = 0;11611161+}11621162+11631163+static enum sci_status scic_controller_initialize(struct scic_sds_controller *scic)11641164+{11651165+ struct sci_base_state_machine *sm = &scic->state_machine;11661166+ enum sci_status result = SCI_SUCCESS;11671167+ struct isci_host *ihost = scic_to_ihost(scic);11681168+ u32 index, state;11691169+11701170+ if (scic->state_machine.current_state_id !=11711171+ SCI_BASE_CONTROLLER_STATE_RESET) {11721172+ dev_warn(scic_to_dev(scic),11731173+ "SCIC Controller initialize operation requested "11741174+ "in invalid state\n");11751175+ return SCI_FAILURE_INVALID_STATE;11761176+ }11771177+11781178+ sci_base_state_machine_change_state(sm, SCI_BASE_CONTROLLER_STATE_INITIALIZING);11791179+11801180+ scic->timeout_timer = isci_timer_create(ihost, scic,11811181+ scic_sds_controller_timeout_handler);11821182+11831183+ scic_sds_controller_initialize_phy_startup(scic);11841184+11851185+ scic_sds_controller_initialize_power_control(scic);11861186+11871187+ /*11881188+ * There is nothing to do here for B0 since we do not have to11891189+ * program the AFE registers.11901190+ * / @todo The AFE settings are supposed to be correct for the B0 but11911191+ * / presently they seem to be wrong. */11921192+ scic_sds_controller_afe_initialization(scic);11931193+11941194+ if (result == SCI_SUCCESS) {11951195+ u32 status;11961196+ u32 terminate_loop;11971197+11981198+ /* Take the hardware out of reset */11991199+ writel(0, &scic->smu_registers->soft_reset_control);12001200+12011201+ /*12021202+ * / @todo Provide meaningfull error code for hardware failure12031203+ * result = SCI_FAILURE_CONTROLLER_HARDWARE; */12041204+ result = SCI_FAILURE;12051205+ terminate_loop = 100;12061206+12071207+ while (terminate_loop-- && (result != SCI_SUCCESS)) {12081208+ /* Loop until the hardware reports success */12091209+ udelay(SCU_CONTEXT_RAM_INIT_STALL_TIME);12101210+ status = readl(&scic->smu_registers->control_status);12111211+12121212+ if ((status & SCU_RAM_INIT_COMPLETED) ==12131213+ SCU_RAM_INIT_COMPLETED)12141214+ result = SCI_SUCCESS;12151215+ }12161216+ }12171217+12181218+ if (result == SCI_SUCCESS) {12191219+ u32 max_supported_ports;12201220+ u32 max_supported_devices;12211221+ u32 max_supported_io_requests;12221222+ u32 device_context_capacity;12231223+12241224+ /*12251225+ * Determine what are the actaul device capacities that the12261226+ * hardware will support */12271227+ device_context_capacity =12281228+ readl(&scic->smu_registers->device_context_capacity);12291229+12301230+12311231+ max_supported_ports = smu_dcc_get_max_ports(device_context_capacity);12321232+ max_supported_devices = smu_dcc_get_max_remote_node_context(device_context_capacity);12331233+ max_supported_io_requests = smu_dcc_get_max_task_context(device_context_capacity);12341234+12351235+ /*12361236+ * Make all PEs that are unassigned match up with the12371237+ * logical ports12381238+ */12391239+ for (index = 0; index < max_supported_ports; index++) {12401240+ struct scu_port_task_scheduler_group_registers __iomem12411241+ *ptsg = &scic->scu_registers->peg0.ptsg;12421242+12431243+ writel(index, &ptsg->protocol_engine[index]);12441244+ }12451245+12461246+ /* Record the smaller of the two capacity values */12471247+ scic->logical_port_entries =12481248+ min(max_supported_ports, scic->logical_port_entries);12491249+12501250+ scic->task_context_entries =12511251+ min(max_supported_io_requests,12521252+ scic->task_context_entries);12531253+12541254+ scic->remote_node_entries =12551255+ min(max_supported_devices, scic->remote_node_entries);12561256+12571257+ /*12581258+ * Now that we have the correct hardware reported minimum values12591259+ * build the MDL for the controller. Default to a performance12601260+ * configuration.12611261+ */12621262+ scic_controller_set_mode(scic, SCI_MODE_SPEED);12631263+ }12641264+12651265+ /* Initialize hardware PCI Relaxed ordering in DMA engines */12661266+ if (result == SCI_SUCCESS) {12671267+ u32 dma_configuration;12681268+12691269+ /* Configure the payload DMA */12701270+ dma_configuration =12711271+ readl(&scic->scu_registers->sdma.pdma_configuration);12721272+ dma_configuration |=12731273+ SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);12741274+ writel(dma_configuration,12751275+ &scic->scu_registers->sdma.pdma_configuration);12761276+12771277+ /* Configure the control DMA */12781278+ dma_configuration =12791279+ readl(&scic->scu_registers->sdma.cdma_configuration);12801280+ dma_configuration |=12811281+ SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE);12821282+ writel(dma_configuration,12831283+ &scic->scu_registers->sdma.cdma_configuration);12841284+ }12851285+12861286+ /*12871287+ * Initialize the PHYs before the PORTs because the PHY registers12881288+ * are accessed during the port initialization.12891289+ */12901290+ if (result == SCI_SUCCESS) {12911291+ /* Initialize the phys */12921292+ for (index = 0;12931293+ (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS);12941294+ index++) {12951295+ result = scic_sds_phy_initialize(12961296+ &ihost->phys[index].sci,12971297+ &scic->scu_registers->peg0.pe[index].tl,12981298+ &scic->scu_registers->peg0.pe[index].ll);12991299+ }13001300+ }13011301+13021302+ if (result == SCI_SUCCESS) {13031303+ /* Initialize the logical ports */13041304+ for (index = 0;13051305+ (index < scic->logical_port_entries) &&13061306+ (result == SCI_SUCCESS);13071307+ index++) {13081308+ result = scic_sds_port_initialize(13091309+ &ihost->ports[index].sci,13101310+ &scic->scu_registers->peg0.ptsg.port[index],13111311+ &scic->scu_registers->peg0.ptsg.protocol_engine,13121312+ &scic->scu_registers->peg0.viit[index]);13131313+ }13141314+ }13151315+13161316+ if (result == SCI_SUCCESS)13171317+ result = scic_sds_port_configuration_agent_initialize(13181318+ scic,13191319+ &scic->port_agent);13201320+13211321+ /* Advance the controller state machine */13221322+ if (result == SCI_SUCCESS)13231323+ state = SCI_BASE_CONTROLLER_STATE_INITIALIZED;13241324+ else13251325+ state = SCI_BASE_CONTROLLER_STATE_FAILED;13261326+ sci_base_state_machine_change_state(sm, state);13271327+13281328+ return result;13291329+}13301330+13311331+static enum sci_status scic_user_parameters_set(13321332+ struct scic_sds_controller *scic,13331333+ union scic_user_parameters *scic_parms)13341334+{13351335+ u32 state = scic->state_machine.current_state_id;13361336+13371337+ if (state == SCI_BASE_CONTROLLER_STATE_RESET ||13381338+ state == SCI_BASE_CONTROLLER_STATE_INITIALIZING ||13391339+ state == SCI_BASE_CONTROLLER_STATE_INITIALIZED) {13401340+ u16 index;13411341+13421342+ /*13431343+ * Validate the user parameters. If they are not legal, then13441344+ * return a failure.13451345+ */13461346+ for (index = 0; index < SCI_MAX_PHYS; index++) {13471347+ struct sci_phy_user_params *user_phy;13481348+13491349+ user_phy = &scic_parms->sds1.phys[index];13501350+13511351+ if (!((user_phy->max_speed_generation <=13521352+ SCIC_SDS_PARM_MAX_SPEED) &&13531353+ (user_phy->max_speed_generation >13541354+ SCIC_SDS_PARM_NO_SPEED)))13551355+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;13561356+13571357+ if (user_phy->in_connection_align_insertion_frequency <13581358+ 3)13591359+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;13601360+13611361+ if ((user_phy->in_connection_align_insertion_frequency <13621362+ 3) ||13631363+ (user_phy->align_insertion_frequency == 0) ||13641364+ (user_phy->13651365+ notify_enable_spin_up_insertion_frequency ==13661366+ 0))13671367+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;13681368+ }13691369+13701370+ if ((scic_parms->sds1.stp_inactivity_timeout == 0) ||13711371+ (scic_parms->sds1.ssp_inactivity_timeout == 0) ||13721372+ (scic_parms->sds1.stp_max_occupancy_timeout == 0) ||13731373+ (scic_parms->sds1.ssp_max_occupancy_timeout == 0) ||13741374+ (scic_parms->sds1.no_outbound_task_timeout == 0))13751375+ return SCI_FAILURE_INVALID_PARAMETER_VALUE;13761376+13771377+ memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms));13781378+13791379+ return SCI_SUCCESS;13801380+ }13811381+13821382+ return SCI_FAILURE_INVALID_STATE;13831383+}13841384+13851385+static int scic_controller_mem_init(struct scic_sds_controller *scic)13861386+{13871387+ struct device *dev = scic_to_dev(scic);13881388+ dma_addr_t dma_handle;13891389+ enum sci_status result;13901390+13911391+ scic->completion_queue = dmam_alloc_coherent(dev,13921392+ scic->completion_queue_entries * sizeof(u32),13931393+ &dma_handle, GFP_KERNEL);13941394+ if (!scic->completion_queue)13951395+ return -ENOMEM;13961396+13971397+ writel(lower_32_bits(dma_handle),13981398+ &scic->smu_registers->completion_queue_lower);13991399+ writel(upper_32_bits(dma_handle),14001400+ &scic->smu_registers->completion_queue_upper);14011401+14021402+ scic->remote_node_context_table = dmam_alloc_coherent(dev,14031403+ scic->remote_node_entries *14041404+ sizeof(union scu_remote_node_context),14051405+ &dma_handle, GFP_KERNEL);14061406+ if (!scic->remote_node_context_table)14071407+ return -ENOMEM;14081408+14091409+ writel(lower_32_bits(dma_handle),14101410+ &scic->smu_registers->remote_node_context_lower);14111411+ writel(upper_32_bits(dma_handle),14121412+ &scic->smu_registers->remote_node_context_upper);14131413+14141414+ scic->task_context_table = dmam_alloc_coherent(dev,14151415+ scic->task_context_entries *14161416+ sizeof(struct scu_task_context),14171417+ &dma_handle, GFP_KERNEL);14181418+ if (!scic->task_context_table)14191419+ return -ENOMEM;14201420+14211421+ writel(lower_32_bits(dma_handle),14221422+ &scic->smu_registers->host_task_table_lower);14231423+ writel(upper_32_bits(dma_handle),14241424+ &scic->smu_registers->host_task_table_upper);14251425+14261426+ result = scic_sds_unsolicited_frame_control_construct(scic);14271427+ if (result)14281428+ return result;14291429+14301430+ /*14311431+ * Inform the silicon as to the location of the UF headers and14321432+ * address table.14331433+ */14341434+ writel(lower_32_bits(scic->uf_control.headers.physical_address),14351435+ &scic->scu_registers->sdma.uf_header_base_address_lower);14361436+ writel(upper_32_bits(scic->uf_control.headers.physical_address),14371437+ &scic->scu_registers->sdma.uf_header_base_address_upper);14381438+14391439+ writel(lower_32_bits(scic->uf_control.address_table.physical_address),14401440+ &scic->scu_registers->sdma.uf_address_table_lower);14411441+ writel(upper_32_bits(scic->uf_control.address_table.physical_address),14421442+ &scic->scu_registers->sdma.uf_address_table_upper);14431443+14441444+ return 0;13861445}1387144613881447int isci_host_init(struct isci_host *isci_host)···26004532601454 return 0;2602455}456456+457457+void scic_sds_controller_link_up(struct scic_sds_controller *scic,458458+ struct scic_sds_port *port, struct scic_sds_phy *phy)459459+{460460+ switch (scic->state_machine.current_state_id) {461461+ case SCI_BASE_CONTROLLER_STATE_STARTING:462462+ scic_sds_controller_phy_timer_stop(scic);463463+ scic->port_agent.link_up_handler(scic, &scic->port_agent,464464+ port, phy);465465+ scic_sds_controller_start_next_phy(scic);466466+ break;467467+ case SCI_BASE_CONTROLLER_STATE_READY:468468+ scic->port_agent.link_up_handler(scic, &scic->port_agent,469469+ port, phy);470470+ break;471471+ default:472472+ dev_dbg(scic_to_dev(scic),473473+ "%s: SCIC Controller linkup event from phy %d in "474474+ "unexpected state %d\n", __func__, phy->phy_index,475475+ scic->state_machine.current_state_id);476476+ }477477+}478478+479479+void scic_sds_controller_link_down(struct scic_sds_controller *scic,480480+ struct scic_sds_port *port, struct scic_sds_phy *phy)481481+{482482+ switch (scic->state_machine.current_state_id) {483483+ case SCI_BASE_CONTROLLER_STATE_STARTING:484484+ case SCI_BASE_CONTROLLER_STATE_READY:485485+ scic->port_agent.link_down_handler(scic, &scic->port_agent,486486+ port, phy);487487+ break;488488+ default:489489+ dev_dbg(scic_to_dev(scic),490490+ "%s: SCIC Controller linkdown event from phy %d in "491491+ "unexpected state %d\n",492492+ __func__,493493+ phy->phy_index,494494+ scic->state_machine.current_state_id);495495+ }496496+}497497+498498+/**499499+ * This is a helper method to determine if any remote devices on this500500+ * controller are still in the stopping state.501501+ *502502+ */503503+static bool scic_sds_controller_has_remote_devices_stopping(504504+ struct scic_sds_controller *controller)505505+{506506+ u32 index;507507+508508+ for (index = 0; index < controller->remote_node_entries; index++) {509509+ if ((controller->device_table[index] != NULL) &&510510+ (controller->device_table[index]->state_machine.current_state_id511511+ == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING))512512+ return true;513513+ }514514+515515+ return false;516516+}517517+518518+/**519519+ * This method is called by the remote device to inform the controller520520+ * object that the remote device has stopped.521521+ */522522+void scic_sds_controller_remote_device_stopped(struct scic_sds_controller *scic,523523+ struct scic_sds_remote_device *sci_dev)524524+{525525+ if (scic->state_machine.current_state_id !=526526+ SCI_BASE_CONTROLLER_STATE_STOPPING) {527527+ dev_dbg(scic_to_dev(scic),528528+ "SCIC Controller 0x%p remote device stopped event "529529+ "from device 0x%p in unexpected state %d\n",530530+ scic, sci_dev,531531+ scic->state_machine.current_state_id);532532+ return;533533+ }534534+535535+ if (!scic_sds_controller_has_remote_devices_stopping(scic)) {536536+ sci_base_state_machine_change_state(&scic->state_machine,537537+ SCI_BASE_CONTROLLER_STATE_STOPPED);538538+ }539539+}540540+541541+/**542542+ * This method will write to the SCU PCP register the request value. The method543543+ * is used to suspend/resume ports, devices, and phys.544544+ * @scic:545545+ *546546+ *547547+ */548548+void scic_sds_controller_post_request(549549+ struct scic_sds_controller *scic,550550+ u32 request)551551+{552552+ dev_dbg(scic_to_dev(scic),553553+ "%s: SCIC Controller 0x%p post request 0x%08x\n",554554+ __func__,555555+ scic,556556+ request);557557+558558+ writel(request, &scic->smu_registers->post_context_port);559559+}560560+561561+/**562562+ * This method will copy the soft copy of the task context into the physical563563+ * memory accessible by the controller.564564+ * @scic: This parameter specifies the controller for which to copy565565+ * the task context.566566+ * @sci_req: This parameter specifies the request for which the task567567+ * context is being copied.568568+ *569569+ * After this call is made the SCIC_SDS_IO_REQUEST object will always point to570570+ * the physical memory version of the task context. Thus, all subsequent571571+ * updates to the task context are performed in the TC table (i.e. DMAable572572+ * memory). none573573+ */574574+void scic_sds_controller_copy_task_context(575575+ struct scic_sds_controller *scic,576576+ struct scic_sds_request *sci_req)577577+{578578+ struct scu_task_context *task_context_buffer;579579+580580+ task_context_buffer = scic_sds_controller_get_task_context_buffer(581581+ scic, sci_req->io_tag);582582+583583+ memcpy(task_context_buffer,584584+ sci_req->task_context_buffer,585585+ offsetof(struct scu_task_context, sgl_snapshot_ac));586586+587587+ /*588588+ * Now that the soft copy of the TC has been copied into the TC589589+ * table accessible by the silicon. Thus, any further changes to590590+ * the TC (e.g. TC termination) occur in the appropriate location. */591591+ sci_req->task_context_buffer = task_context_buffer;592592+}593593+594594+/**595595+ * This method returns the task context buffer for the given io tag.596596+ * @scic:597597+ * @io_tag:598598+ *599599+ * struct scu_task_context*600600+ */601601+struct scu_task_context *scic_sds_controller_get_task_context_buffer(602602+ struct scic_sds_controller *scic,603603+ u16 io_tag604604+ ) {605605+ u16 task_index = scic_sds_io_tag_get_index(io_tag);606606+607607+ if (task_index < scic->task_context_entries) {608608+ return &scic->task_context_table[task_index];609609+ }610610+611611+ return NULL;612612+}613613+614614+struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic,615615+ u16 io_tag)616616+{617617+ u16 task_index;618618+ u16 task_sequence;619619+620620+ task_index = scic_sds_io_tag_get_index(io_tag);621621+622622+ if (task_index < scic->task_context_entries) {623623+ if (scic->io_request_table[task_index] != NULL) {624624+ task_sequence = scic_sds_io_tag_get_sequence(io_tag);625625+626626+ if (task_sequence == scic->io_request_sequence[task_index]) {627627+ return scic->io_request_table[task_index];628628+ }629629+ }630630+ }631631+632632+ return NULL;633633+}634634+635635+/**636636+ * This method allocates remote node index and the reserves the remote node637637+ * context space for use. This method can fail if there are no more remote638638+ * node index available.639639+ * @scic: This is the controller object which contains the set of640640+ * free remote node ids641641+ * @sci_dev: This is the device object which is requesting the a remote node642642+ * id643643+ * @node_id: This is the remote node id that is assinged to the device if one644644+ * is available645645+ *646646+ * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote647647+ * node index available.648648+ */649649+enum sci_status scic_sds_controller_allocate_remote_node_context(650650+ struct scic_sds_controller *scic,651651+ struct scic_sds_remote_device *sci_dev,652652+ u16 *node_id)653653+{654654+ u16 node_index;655655+ u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev);656656+657657+ node_index = scic_sds_remote_node_table_allocate_remote_node(658658+ &scic->available_remote_nodes, remote_node_count659659+ );660660+661661+ if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {662662+ scic->device_table[node_index] = sci_dev;663663+664664+ *node_id = node_index;665665+666666+ return SCI_SUCCESS;667667+ }668668+669669+ return SCI_FAILURE_INSUFFICIENT_RESOURCES;670670+}671671+672672+/**673673+ * This method frees the remote node index back to the available pool. Once674674+ * this is done the remote node context buffer is no longer valid and can675675+ * not be used.676676+ * @scic:677677+ * @sci_dev:678678+ * @node_id:679679+ *680680+ */681681+void scic_sds_controller_free_remote_node_context(682682+ struct scic_sds_controller *scic,683683+ struct scic_sds_remote_device *sci_dev,684684+ u16 node_id)685685+{686686+ u32 remote_node_count = scic_sds_remote_device_node_count(sci_dev);687687+688688+ if (scic->device_table[node_id] == sci_dev) {689689+ scic->device_table[node_id] = NULL;690690+691691+ scic_sds_remote_node_table_release_remote_node_index(692692+ &scic->available_remote_nodes, remote_node_count, node_id693693+ );694694+ }695695+}696696+697697+/**698698+ * This method returns the union scu_remote_node_context for the specified remote699699+ * node id.700700+ * @scic:701701+ * @node_id:702702+ *703703+ * union scu_remote_node_context*704704+ */705705+union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(706706+ struct scic_sds_controller *scic,707707+ u16 node_id708708+ ) {709709+ if (710710+ (node_id < scic->remote_node_entries)711711+ && (scic->device_table[node_id] != NULL)712712+ ) {713713+ return &scic->remote_node_context_table[node_id];714714+ }715715+716716+ return NULL;717717+}718718+719719+/**720720+ *721721+ * @resposne_buffer: This is the buffer into which the D2H register FIS will be722722+ * constructed.723723+ * @frame_header: This is the frame header returned by the hardware.724724+ * @frame_buffer: This is the frame buffer returned by the hardware.725725+ *726726+ * This method will combind the frame header and frame buffer to create a SATA727727+ * D2H register FIS none728728+ */729729+void scic_sds_controller_copy_sata_response(730730+ void *response_buffer,731731+ void *frame_header,732732+ void *frame_buffer)733733+{734734+ memcpy(response_buffer, frame_header, sizeof(u32));735735+736736+ memcpy(response_buffer + sizeof(u32),737737+ frame_buffer,738738+ sizeof(struct dev_to_host_fis) - sizeof(u32));739739+}740740+741741+/**742742+ * This method releases the frame once this is done the frame is available for743743+ * re-use by the hardware. The data contained in the frame header and frame744744+ * buffer is no longer valid. The UF queue get pointer is only updated if UF745745+ * control indicates this is appropriate.746746+ * @scic:747747+ * @frame_index:748748+ *749749+ */750750+void scic_sds_controller_release_frame(751751+ struct scic_sds_controller *scic,752752+ u32 frame_index)753753+{754754+ if (scic_sds_unsolicited_frame_control_release_frame(755755+ &scic->uf_control, frame_index) == true)756756+ writel(scic->uf_control.get,757757+ &scic->scu_registers->sdma.unsolicited_frame_get_pointer);758758+}759759+760760+/**761761+ * scic_controller_start_io() - This method is called by the SCI user to762762+ * send/start an IO request. If the method invocation is successful, then763763+ * the IO request has been queued to the hardware for processing.764764+ * @controller: the handle to the controller object for which to start an IO765765+ * request.766766+ * @remote_device: the handle to the remote device object for which to start an767767+ * IO request.768768+ * @io_request: the handle to the io request object to start.769769+ * @io_tag: This parameter specifies a previously allocated IO tag that the770770+ * user desires to be utilized for this request. This parameter is optional.771771+ * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value772772+ * for this parameter.773773+ *774774+ * - IO tags are a protected resource. It is incumbent upon the SCI Core user775775+ * to ensure that each of the methods that may allocate or free available IO776776+ * tags are handled in a mutually exclusive manner. This method is one of said777777+ * methods requiring proper critical code section protection (e.g. semaphore,778778+ * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a779779+ * result, it is expected the user will have set the NCQ tag field in the host780780+ * to device register FIS prior to calling this method. There is also a781781+ * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking782782+ * the scic_controller_start_io() method. scic_controller_allocate_tag() for783783+ * more information on allocating a tag. Indicate if the controller784784+ * successfully started the IO request. SCI_SUCCESS if the IO request was785785+ * successfully started. Determine the failure situations and return values.786786+ */787787+enum sci_status scic_controller_start_io(788788+ struct scic_sds_controller *scic,789789+ struct scic_sds_remote_device *rdev,790790+ struct scic_sds_request *req,791791+ u16 io_tag)792792+{793793+ enum sci_status status;794794+795795+ if (scic->state_machine.current_state_id !=796796+ SCI_BASE_CONTROLLER_STATE_READY) {797797+ dev_warn(scic_to_dev(scic), "invalid state to start I/O");798798+ return SCI_FAILURE_INVALID_STATE;799799+ }800800+801801+ status = scic_sds_remote_device_start_io(scic, rdev, req);802802+ if (status != SCI_SUCCESS)803803+ return status;804804+805805+ scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req;806806+ scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req));807807+ return SCI_SUCCESS;808808+}809809+810810+/**811811+ * scic_controller_terminate_request() - This method is called by the SCI Core812812+ * user to terminate an ongoing (i.e. started) core IO request. This does813813+ * not abort the IO request at the target, but rather removes the IO request814814+ * from the host controller.815815+ * @controller: the handle to the controller object for which to terminate a816816+ * request.817817+ * @remote_device: the handle to the remote device object for which to818818+ * terminate a request.819819+ * @request: the handle to the io or task management request object to820820+ * terminate.821821+ *822822+ * Indicate if the controller successfully began the terminate process for the823823+ * IO request. SCI_SUCCESS if the terminate process was successfully started824824+ * for the request. Determine the failure situations and return values.825825+ */826826+enum sci_status scic_controller_terminate_request(827827+ struct scic_sds_controller *scic,828828+ struct scic_sds_remote_device *rdev,829829+ struct scic_sds_request *req)830830+{831831+ enum sci_status status;832832+833833+ if (scic->state_machine.current_state_id !=834834+ SCI_BASE_CONTROLLER_STATE_READY) {835835+ dev_warn(scic_to_dev(scic),836836+ "invalid state to terminate request\n");837837+ return SCI_FAILURE_INVALID_STATE;838838+ }839839+840840+ status = scic_sds_io_request_terminate(req);841841+ if (status != SCI_SUCCESS)842842+ return status;843843+844844+ /*845845+ * Utilize the original post context command and or in the POST_TC_ABORT846846+ * request sub-type.847847+ */848848+ scic_sds_controller_post_request(scic,849849+ scic_sds_request_get_post_context(req) |850850+ SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT);851851+ return SCI_SUCCESS;852852+}853853+854854+/**855855+ * scic_controller_complete_io() - This method will perform core specific856856+ * completion operations for an IO request. After this method is invoked,857857+ * the user should consider the IO request as invalid until it is properly858858+ * reused (i.e. re-constructed).859859+ * @controller: The handle to the controller object for which to complete the860860+ * IO request.861861+ * @remote_device: The handle to the remote device object for which to complete862862+ * the IO request.863863+ * @io_request: the handle to the io request object to complete.864864+ *865865+ * - IO tags are a protected resource. It is incumbent upon the SCI Core user866866+ * to ensure that each of the methods that may allocate or free available IO867867+ * tags are handled in a mutually exclusive manner. This method is one of said868868+ * methods requiring proper critical code section protection (e.g. semaphore,869869+ * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI870870+ * Core user, using the scic_controller_allocate_io_tag() method, then it is871871+ * the responsibility of the caller to invoke the scic_controller_free_io_tag()872872+ * method to free the tag (i.e. this method will not free the IO tag). Indicate873873+ * if the controller successfully completed the IO request. SCI_SUCCESS if the874874+ * completion process was successful.875875+ */876876+enum sci_status scic_controller_complete_io(877877+ struct scic_sds_controller *scic,878878+ struct scic_sds_remote_device *rdev,879879+ struct scic_sds_request *request)880880+{881881+ enum sci_status status;882882+ u16 index;883883+884884+ switch (scic->state_machine.current_state_id) {885885+ case SCI_BASE_CONTROLLER_STATE_STOPPING:886886+ /* XXX: Implement this function */887887+ return SCI_FAILURE;888888+ case SCI_BASE_CONTROLLER_STATE_READY:889889+ status = scic_sds_remote_device_complete_io(scic, rdev, request);890890+ if (status != SCI_SUCCESS)891891+ return status;892892+893893+ index = scic_sds_io_tag_get_index(request->io_tag);894894+ scic->io_request_table[index] = NULL;895895+ return SCI_SUCCESS;896896+ default:897897+ dev_warn(scic_to_dev(scic), "invalid state to complete I/O");898898+ return SCI_FAILURE_INVALID_STATE;899899+ }900900+901901+}902902+903903+enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req)904904+{905905+ struct scic_sds_controller *scic = sci_req->owning_controller;906906+907907+ if (scic->state_machine.current_state_id !=908908+ SCI_BASE_CONTROLLER_STATE_READY) {909909+ dev_warn(scic_to_dev(scic), "invalid state to continue I/O");910910+ return SCI_FAILURE_INVALID_STATE;911911+ }912912+913913+ scic->io_request_table[scic_sds_io_tag_get_index(sci_req->io_tag)] = sci_req;914914+ scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req));915915+ return SCI_SUCCESS;916916+}917917+918918+/**919919+ * scic_controller_start_task() - This method is called by the SCIC user to920920+ * send/start a framework task management request.921921+ * @controller: the handle to the controller object for which to start the task922922+ * management request.923923+ * @remote_device: the handle to the remote device object for which to start924924+ * the task management request.925925+ * @task_request: the handle to the task request object to start.926926+ * @io_tag: This parameter specifies a previously allocated IO tag that the927927+ * user desires to be utilized for this request. Note this not the io_tag928928+ * of the request being managed. It is to be utilized for the task request929929+ * itself. This parameter is optional. The user is allowed to supply930930+ * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.931931+ *932932+ * - IO tags are a protected resource. It is incumbent upon the SCI Core user933933+ * to ensure that each of the methods that may allocate or free available IO934934+ * tags are handled in a mutually exclusive manner. This method is one of said935935+ * methods requiring proper critical code section protection (e.g. semaphore,936936+ * spin-lock, etc.). - The user must synchronize this task with completion937937+ * queue processing. If they are not synchronized then it is possible for the938938+ * io requests that are being managed by the task request can complete before939939+ * starting the task request. scic_controller_allocate_tag() for more940940+ * information on allocating a tag. Indicate if the controller successfully941941+ * started the IO request. SCI_TASK_SUCCESS if the task request was942942+ * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is943943+ * returned if there is/are task(s) outstanding that require termination or944944+ * completion before this request can succeed.945945+ */946946+enum sci_task_status scic_controller_start_task(947947+ struct scic_sds_controller *scic,948948+ struct scic_sds_remote_device *rdev,949949+ struct scic_sds_request *req,950950+ u16 task_tag)951951+{952952+ enum sci_status status;953953+954954+ if (scic->state_machine.current_state_id !=955955+ SCI_BASE_CONTROLLER_STATE_READY) {956956+ dev_warn(scic_to_dev(scic),957957+ "%s: SCIC Controller starting task from invalid "958958+ "state\n",959959+ __func__);960960+ return SCI_TASK_FAILURE_INVALID_STATE;961961+ }962962+963963+ status = scic_sds_remote_device_start_task(scic, rdev, req);964964+ switch (status) {965965+ case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS:966966+ scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req;967967+968968+ /*969969+ * We will let framework know this task request started successfully,970970+ * although core is still woring on starting the request (to post tc when971971+ * RNC is resumed.)972972+ */973973+ return SCI_SUCCESS;974974+ case SCI_SUCCESS:975975+ scic->io_request_table[scic_sds_io_tag_get_index(req->io_tag)] = req;976976+977977+ scic_sds_controller_post_request(scic,978978+ scic_sds_request_get_post_context(req));979979+ break;980980+ default:981981+ break;982982+ }983983+984984+ return status;985985+}986986+987987+/**988988+ * scic_controller_allocate_io_tag() - This method will allocate a tag from the989989+ * pool of free IO tags. Direct allocation of IO tags by the SCI Core user990990+ * is optional. The scic_controller_start_io() method will allocate an IO991991+ * tag if this method is not utilized and the tag is not supplied to the IO992992+ * construct routine. Direct allocation of IO tags may provide additional993993+ * performance improvements in environments capable of supporting this usage994994+ * model. Additionally, direct allocation of IO tags also provides995995+ * additional flexibility to the SCI Core user. Specifically, the user may996996+ * retain IO tags across the lives of multiple IO requests.997997+ * @controller: the handle to the controller object for which to allocate the998998+ * tag.999999+ *10001000+ * IO tags are a protected resource. It is incumbent upon the SCI Core user to10011001+ * ensure that each of the methods that may allocate or free available IO tags10021002+ * are handled in a mutually exclusive manner. This method is one of said10031003+ * methods requiring proper critical code section protection (e.g. semaphore,10041004+ * spin-lock, etc.). An unsigned integer representing an available IO tag.10051005+ * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no10061006+ * currently available tags to be allocated. All return other values indicate a10071007+ * legitimate tag.10081008+ */10091009+u16 scic_controller_allocate_io_tag(10101010+ struct scic_sds_controller *scic)10111011+{10121012+ u16 task_context;10131013+ u16 sequence_count;10141014+10151015+ if (!sci_pool_empty(scic->tci_pool)) {10161016+ sci_pool_get(scic->tci_pool, task_context);10171017+10181018+ sequence_count = scic->io_request_sequence[task_context];10191019+10201020+ return scic_sds_io_tag_construct(sequence_count, task_context);10211021+ }10221022+10231023+ return SCI_CONTROLLER_INVALID_IO_TAG;10241024+}10251025+10261026+/**10271027+ * scic_controller_free_io_tag() - This method will free an IO tag to the pool10281028+ * of free IO tags. This method provides the SCI Core user more flexibility10291029+ * with regards to IO tags. The user may desire to keep an IO tag after an10301030+ * IO request has completed, because they plan on re-using the tag for a10311031+ * subsequent IO request. This method is only legal if the tag was10321032+ * allocated via scic_controller_allocate_io_tag().10331033+ * @controller: This parameter specifies the handle to the controller object10341034+ * for which to free/return the tag.10351035+ * @io_tag: This parameter represents the tag to be freed to the pool of10361036+ * available tags.10371037+ *10381038+ * - IO tags are a protected resource. It is incumbent upon the SCI Core user10391039+ * to ensure that each of the methods that may allocate or free available IO10401040+ * tags are handled in a mutually exclusive manner. This method is one of said10411041+ * methods requiring proper critical code section protection (e.g. semaphore,10421042+ * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI10431043+ * Core user, using the scic_controller_allocate_io_tag() method, then it is10441044+ * the responsibility of the caller to invoke this method to free the tag. This10451045+ * method returns an indication of whether the tag was successfully put back10461046+ * (freed) to the pool of available tags. SCI_SUCCESS This return value10471047+ * indicates the tag was successfully placed into the pool of available IO10481048+ * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag10491049+ * is not a valid IO tag value.10501050+ */10511051+enum sci_status scic_controller_free_io_tag(10521052+ struct scic_sds_controller *scic,10531053+ u16 io_tag)10541054+{10551055+ u16 sequence;10561056+ u16 index;10571057+10581058+ BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG);10591059+10601060+ sequence = scic_sds_io_tag_get_sequence(io_tag);10611061+ index = scic_sds_io_tag_get_index(io_tag);10621062+10631063+ if (!sci_pool_full(scic->tci_pool)) {10641064+ if (sequence == scic->io_request_sequence[index]) {10651065+ scic_sds_io_sequence_increment(10661066+ scic->io_request_sequence[index]);10671067+10681068+ sci_pool_put(scic->tci_pool, index);10691069+10701070+ return SCI_SUCCESS;10711071+ }10721072+ }10731073+10741074+ return SCI_FAILURE_INVALID_IO_TAG;10751075+}10761076+10771077+
+576-38
drivers/scsi/isci/host.h
···5252 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */5555-5655#ifndef _SCI_HOST_H_5756#define _SCI_HOST_H_58575959-#include "scic_sds_controller.h"5858+#include "scic_config_parameters.h"6059#include "remote_device.h"6160#include "phy.h"6161+#include "pool.h"6262+#include "sci_base_state_machine.h"6363+#include "remote_node_table.h"6464+#include "scu_registers.h"6565+#include "scu_unsolicited_frame.h"6666+#include "scic_sds_unsolicited_frame_control.h"6767+#include "scic_sds_port_configuration_agent.h"6868+6969+struct scic_sds_request;7070+struct scu_task_context;7171+7272+/**7373+ * struct scic_power_control -7474+ *7575+ * This structure defines the fields for managing power control for direct7676+ * attached disk devices.7777+ */7878+struct scic_power_control {7979+ /**8080+ * This field is set when the power control timer is running and cleared when8181+ * it is not.8282+ */8383+ bool timer_started;8484+8585+ /**8686+ * This field is the handle to the driver timer object. This timer is used to8787+ * control when the directed attached disks can consume power.8888+ */8989+ void *timer;9090+9191+ /**9292+ * This field is used to keep track of how many phys are put into the9393+ * requesters field.9494+ */9595+ u8 phys_waiting;9696+9797+ /**9898+ * This field is used to keep track of how many phys have been granted to consume power9999+ */100100+ u8 phys_granted_power;101101+102102+ /**103103+ * This field is an array of phys that we are waiting on. The phys are direct104104+ * mapped into requesters via struct scic_sds_phy.phy_index105105+ */106106+ struct scic_sds_phy *requesters[SCI_MAX_PHYS];107107+108108+};109109+110110+/**111111+ * struct scic_sds_controller -112112+ *113113+ * This structure represents the SCU controller object.114114+ */115115+struct scic_sds_controller {116116+ /**117117+ * This field contains the information for the base controller state118118+ * machine.119119+ */120120+ struct sci_base_state_machine state_machine;121121+122122+ /**123123+ * This field is the driver timer object handler used to time the controller124124+ * object start and stop requests.125125+ */126126+ void *timeout_timer;127127+128128+ /**129129+ * This field contains the user parameters to be utilized for this130130+ * core controller object.131131+ */132132+ union scic_user_parameters user_parameters;133133+134134+ /**135135+ * This field contains the OEM parameters to be utilized for this136136+ * core controller object.137137+ */138138+ union scic_oem_parameters oem_parameters;139139+140140+ /**141141+ * This field contains the port configuration agent for this controller.142142+ */143143+ struct scic_sds_port_configuration_agent port_agent;144144+145145+ /**146146+ * This field is the array of device objects that are currently constructed147147+ * for this controller object. This table is used as a fast lookup of device148148+ * objects that need to handle device completion notifications from the149149+ * hardware. The table is RNi based.150150+ */151151+ struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES];152152+153153+ /**154154+ * This field is the array of IO request objects that are currently active for155155+ * this controller object. This table is used as a fast lookup of the io156156+ * request object that need to handle completion queue notifications. The157157+ * table is TCi based.158158+ */159159+ struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS];160160+161161+ /**162162+ * This field is the free RNi data structure163163+ */164164+ struct scic_remote_node_table available_remote_nodes;165165+166166+ /**167167+ * This field is the TCi pool used to manage the task context index.168168+ */169169+ SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS);170170+171171+ /**172172+ * This filed is the struct scic_power_control data used to controll when direct173173+ * attached devices can consume power.174174+ */175175+ struct scic_power_control power_control;176176+177177+ /**178178+ * This field is the array of sequence values for the IO Tag fields. Even179179+ * though only 4 bits of the field is used for the sequence the sequence is 16180180+ * bits in size so the sequence can be bitwise or'd with the TCi to build the181181+ * IO Tag value.182182+ */183183+ u16 io_request_sequence[SCI_MAX_IO_REQUESTS];184184+185185+ /**186186+ * This field in the array of sequence values for the RNi. These are used187187+ * to control io request build to io request start operations. The sequence188188+ * value is recorded into an io request when it is built and is checked on189189+ * the io request start operation to make sure that there was not a device190190+ * hot plug between the build and start operation.191191+ */192192+ u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES];193193+194194+ /**195195+ * This field is a pointer to the memory allocated by the driver for the task196196+ * context table. This data is shared between the hardware and software.197197+ */198198+ struct scu_task_context *task_context_table;199199+200200+ /**201201+ * This field is a pointer to the memory allocated by the driver for the202202+ * remote node context table. This table is shared between the hardware and203203+ * software.204204+ */205205+ union scu_remote_node_context *remote_node_context_table;206206+207207+ /**208208+ * This field is a pointer to the completion queue. This memory is209209+ * written to by the hardware and read by the software.210210+ */211211+ u32 *completion_queue;212212+213213+ /**214214+ * This field is the software copy of the completion queue get pointer. The215215+ * controller object writes this value to the hardware after processing the216216+ * completion entries.217217+ */218218+ u32 completion_queue_get;219219+220220+ /**221221+ * This field is the minimum of the number of hardware supported port entries222222+ * and the software requested port entries.223223+ */224224+ u32 logical_port_entries;225225+226226+ /**227227+ * This field is the minimum number of hardware supported completion queue228228+ * entries and the software requested completion queue entries.229229+ */230230+ u32 completion_queue_entries;231231+232232+ /**233233+ * This field is the minimum number of hardware supported event entries and234234+ * the software requested event entries.235235+ */236236+ u32 completion_event_entries;237237+238238+ /**239239+ * This field is the minimum number of devices supported by the hardware and240240+ * the number of devices requested by the software.241241+ */242242+ u32 remote_node_entries;243243+244244+ /**245245+ * This field is the minimum number of IO requests supported by the hardware246246+ * and the number of IO requests requested by the software.247247+ */248248+ u32 task_context_entries;249249+250250+ /**251251+ * This object contains all of the unsolicited frame specific252252+ * data utilized by the core controller.253253+ */254254+ struct scic_sds_unsolicited_frame_control uf_control;255255+256256+ /* Phy Startup Data */257257+ /**258258+ * This field is the driver timer handle for controller phy request startup.259259+ * On controller start the controller will start each PHY individually in260260+ * order of phy index.261261+ */262262+ void *phy_startup_timer;263263+264264+ /**265265+ * This field is set when the phy_startup_timer is running and is cleared when266266+ * the phy_startup_timer is stopped.267267+ */268268+ bool phy_startup_timer_pending;269269+270270+ /**271271+ * This field is the index of the next phy start. It is initialized to 0 and272272+ * increments for each phy index that is started.273273+ */274274+ u32 next_phy_to_start;275275+276276+ /**277277+ * This field controlls the invalid link up notifications to the SCI_USER. If278278+ * an invalid_link_up notification is reported a bit for the PHY index is set279279+ * so further notifications are not made. Once the PHY object reports link up280280+ * and is made part of a port then this bit for the PHY index is cleared.281281+ */282282+ u8 invalid_phy_mask;283283+284284+ /*285285+ * This field saves the current interrupt coalescing number of the controller.286286+ */287287+ u16 interrupt_coalesce_number;288288+289289+ /*290290+ * This field saves the current interrupt coalescing timeout value in microseconds.291291+ */292292+ u32 interrupt_coalesce_timeout;293293+294294+ /**295295+ * This field is a pointer to the memory mapped register space for the296296+ * struct smu_registers.297297+ */298298+ struct smu_registers __iomem *smu_registers;299299+300300+ /**301301+ * This field is a pointer to the memory mapped register space for the302302+ * struct scu_registers.303303+ */304304+ struct scu_registers __iomem *scu_registers;305305+306306+};6230763308struct isci_host {64309 struct scic_sds_controller sci;···33893};3399434095/**9696+ * enum scic_sds_controller_states - This enumeration depicts all the states9797+ * for the common controller state machine.9898+ */9999+enum scic_sds_controller_states {100100+ /**101101+ * Simply the initial state for the base controller state machine.102102+ */103103+ SCI_BASE_CONTROLLER_STATE_INITIAL = 0,104104+105105+ /**106106+ * This state indicates that the controller is reset. The memory for107107+ * the controller is in it's initial state, but the controller requires108108+ * initialization.109109+ * This state is entered from the INITIAL state.110110+ * This state is entered from the RESETTING state.111111+ */112112+ SCI_BASE_CONTROLLER_STATE_RESET,113113+114114+ /**115115+ * This state is typically an action state that indicates the controller116116+ * is in the process of initialization. In this state no new IO operations117117+ * are permitted.118118+ * This state is entered from the RESET state.119119+ */120120+ SCI_BASE_CONTROLLER_STATE_INITIALIZING,121121+122122+ /**123123+ * This state indicates that the controller has been successfully124124+ * initialized. In this state no new IO operations are permitted.125125+ * This state is entered from the INITIALIZING state.126126+ */127127+ SCI_BASE_CONTROLLER_STATE_INITIALIZED,128128+129129+ /**130130+ * This state indicates the the controller is in the process of becoming131131+ * ready (i.e. starting). In this state no new IO operations are permitted.132132+ * This state is entered from the INITIALIZED state.133133+ */134134+ SCI_BASE_CONTROLLER_STATE_STARTING,135135+136136+ /**137137+ * This state indicates the controller is now ready. Thus, the user138138+ * is able to perform IO operations on the controller.139139+ * This state is entered from the STARTING state.140140+ */141141+ SCI_BASE_CONTROLLER_STATE_READY,142142+143143+ /**144144+ * This state is typically an action state that indicates the controller145145+ * is in the process of resetting. Thus, the user is unable to perform146146+ * IO operations on the controller. A reset is considered destructive in147147+ * most cases.148148+ * This state is entered from the READY state.149149+ * This state is entered from the FAILED state.150150+ * This state is entered from the STOPPED state.151151+ */152152+ SCI_BASE_CONTROLLER_STATE_RESETTING,153153+154154+ /**155155+ * This state indicates that the controller is in the process of stopping.156156+ * In this state no new IO operations are permitted, but existing IO157157+ * operations are allowed to complete.158158+ * This state is entered from the READY state.159159+ */160160+ SCI_BASE_CONTROLLER_STATE_STOPPING,161161+162162+ /**163163+ * This state indicates that the controller has successfully been stopped.164164+ * In this state no new IO operations are permitted.165165+ * This state is entered from the STOPPING state.166166+ */167167+ SCI_BASE_CONTROLLER_STATE_STOPPED,168168+169169+ /**170170+ * This state indicates that the controller could not successfully be171171+ * initialized. In this state no new IO operations are permitted.172172+ * This state is entered from the INITIALIZING state.173173+ * This state is entered from the STARTING state.174174+ * This state is entered from the STOPPING state.175175+ * This state is entered from the RESETTING state.176176+ */177177+ SCI_BASE_CONTROLLER_STATE_FAILED,178178+179179+ SCI_BASE_CONTROLLER_MAX_STATES180180+181181+};182182+183183+184184+185185+/**341186 * struct isci_pci_info - This class represents the pci function containing the342187 * controllers. Depending on PCI SKU, there could be up to 2 controllers in343188 * the PCI function.···450115 id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \451116 ihost = to_pci_info(pdev)->hosts[++id])452117453453-static inline454454-enum isci_status isci_host_get_state(455455- struct isci_host *isci_host)118118+static inline enum isci_status isci_host_get_state(struct isci_host *isci_host)456119{457120 return isci_host->status;458121}459122460460-461461-static inline void isci_host_change_state(462462- struct isci_host *isci_host,463463- enum isci_status status)123123+static inline void isci_host_change_state(struct isci_host *isci_host,124124+ enum isci_status status)464125{465126 unsigned long flags;466127···471140472141}473142474474-static inline int isci_host_can_queue(475475- struct isci_host *isci_host,476476- int num)143143+static inline int isci_host_can_queue(struct isci_host *isci_host, int num)477144{478145 int ret = 0;479146 unsigned long flags;···492163 return ret;493164}494165495495-static inline void isci_host_can_dequeue(496496- struct isci_host *isci_host,497497- int num)166166+static inline void isci_host_can_dequeue(struct isci_host *isci_host, int num)498167{499168 unsigned long flags;500169···535208}536209537210/**538538- * isci_host_scan_finished() -211211+ * INCREMENT_QUEUE_GET() -539212 *540540- * This function is one of the SCSI Host Template functions. The SCSI midlayer541541- * calls this function during a target scan, approx. once every 10 millisecs.213213+ * This macro will increment the specified index to and if the index wraps to 0214214+ * it will toggel the cycle bit.542215 */543543-int isci_host_scan_finished(544544- struct Scsi_Host *,545545- unsigned long);546546-216216+#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \217217+ { \218218+ if ((index) + 1 == entry_count) { \219219+ (index) = 0; \220220+ (cycle) = (cycle) ^ (bit_toggle); \221221+ } else { \222222+ index = index + 1; \223223+ } \224224+ }547225548226/**549549- * isci_host_scan_start() -227227+ * scic_sds_controller_get_port_configuration_agent() -550228 *551551- * This function is one of the SCSI Host Template function, called by the SCSI552552- * mid layer berfore a target scan begins. The core library controller start553553- * routine is called from here.229229+ * This is a helper macro to get the port configuration agent from the230230+ * controller object.554231 */555555-void isci_host_scan_start(556556- struct Scsi_Host *);232232+#define scic_sds_controller_get_port_configuration_agent(controller) \233233+ (&(controller)->port_agent)557234558235/**559559- * isci_host_start_complete() -236236+ * scic_sds_controller_get_protocol_engine_group() -560237 *561561- * This function is called by the core library, through the ISCI Module, to562562- * indicate controller start status.238238+ * This macro returns the protocol engine group for this controller object.239239+ * Presently we only support protocol engine group 0 so just return that563240 */564564-void isci_host_start_complete(565565- struct isci_host *,566566- enum sci_status);241241+#define scic_sds_controller_get_protocol_engine_group(controller) 0567242568568-void isci_host_stop_complete(569569- struct isci_host *isci_host,570570- enum sci_status completion_status);243243+/**244244+ * scic_sds_io_tag_construct() -245245+ *246246+ * This macro constructs an IO tag from the sequence and index values.247247+ */248248+#define scic_sds_io_tag_construct(sequence, task_index) \249249+ ((sequence) << 12 | (task_index))250250+251251+/**252252+ * scic_sds_io_tag_get_sequence() -253253+ *254254+ * This macro returns the IO sequence from the IO tag value.255255+ */256256+#define scic_sds_io_tag_get_sequence(io_tag) \257257+ (((io_tag) & 0xF000) >> 12)258258+259259+/**260260+ * scic_sds_io_tag_get_index() -261261+ *262262+ * This macro returns the TCi from the io tag value263263+ */264264+#define scic_sds_io_tag_get_index(io_tag) \265265+ ((io_tag) & 0x0FFF)266266+267267+/**268268+ * scic_sds_io_sequence_increment() -269269+ *270270+ * This is a helper macro to increment the io sequence count. We may find in271271+ * the future that it will be faster to store the sequence count in such a way272272+ * as we dont perform the shift operation to build io tag values so therefore273273+ * need a way to incrment them correctly274274+ */275275+#define scic_sds_io_sequence_increment(value) \276276+ ((value) = (((value) + 1) & 0x000F))277277+278278+/* expander attached sata devices require 3 rnc slots */279279+static inline int scic_sds_remote_device_node_count(struct scic_sds_remote_device *sci_dev)280280+{281281+ struct domain_device *dev = sci_dev_to_domain(sci_dev);282282+283283+ if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&284284+ !sci_dev->is_direct_attached)285285+ return SCU_STP_REMOTE_NODE_COUNT;286286+ return SCU_SSP_REMOTE_NODE_COUNT;287287+}288288+289289+/**290290+ * scic_sds_controller_set_invalid_phy() -291291+ *292292+ * This macro will set the bit in the invalid phy mask for this controller293293+ * object. This is used to control messages reported for invalid link up294294+ * notifications.295295+ */296296+#define scic_sds_controller_set_invalid_phy(controller, phy) \297297+ ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index))298298+299299+/**300300+ * scic_sds_controller_clear_invalid_phy() -301301+ *302302+ * This macro will clear the bit in the invalid phy mask for this controller303303+ * object. This is used to control messages reported for invalid link up304304+ * notifications.305305+ */306306+#define scic_sds_controller_clear_invalid_phy(controller, phy) \307307+ ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))308308+309309+static inline struct device *scic_to_dev(struct scic_sds_controller *scic)310310+{311311+ return &scic_to_ihost(scic)->pdev->dev;312312+}313313+314314+static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy)315315+{316316+ struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);317317+318318+ if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)319319+ return NULL;320320+321321+ return &iphy->isci_port->isci_host->pdev->dev;322322+}323323+324324+static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port)325325+{326326+ struct isci_port *iport = sci_port_to_iport(sci_port);327327+328328+ if (!iport || !iport->isci_host)329329+ return NULL;330330+331331+ return &iport->isci_host->pdev->dev;332332+}333333+334334+static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev)335335+{336336+ struct isci_remote_device *idev =337337+ container_of(sci_dev, typeof(*idev), sci);338338+339339+ if (!idev || !idev->isci_port || !idev->isci_port->isci_host)340340+ return NULL;341341+342342+ return &idev->isci_port->isci_host->pdev->dev;343343+}344344+345345+enum {346346+ ISCI_SI_REVA0,347347+ ISCI_SI_REVA2,348348+ ISCI_SI_REVB0,349349+};350350+351351+extern int isci_si_rev;352352+353353+static inline bool is_a0(void)354354+{355355+ return isci_si_rev == ISCI_SI_REVA0;356356+}357357+358358+static inline bool is_a2(void)359359+{360360+ return isci_si_rev == ISCI_SI_REVA2;361361+}362362+363363+static inline bool is_b0(void)364364+{365365+ return isci_si_rev > ISCI_SI_REVA2;366366+}367367+368368+void scic_sds_controller_post_request(struct scic_sds_controller *scic,369369+ u32 request);370370+void scic_sds_controller_release_frame(struct scic_sds_controller *scic,371371+ u32 frame_index);372372+void scic_sds_controller_copy_sata_response(void *response_buffer,373373+ void *frame_header,374374+ void *frame_buffer);375375+enum sci_status scic_sds_controller_allocate_remote_node_context(struct scic_sds_controller *scic,376376+ struct scic_sds_remote_device *sci_dev,377377+ u16 *node_id);378378+void scic_sds_controller_free_remote_node_context(379379+ struct scic_sds_controller *scic,380380+ struct scic_sds_remote_device *sci_dev,381381+ u16 node_id);382382+union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(383383+ struct scic_sds_controller *scic,384384+ u16 node_id);385385+386386+struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic,387387+ u16 io_tag);388388+389389+struct scu_task_context *scic_sds_controller_get_task_context_buffer(390390+ struct scic_sds_controller *scic,391391+ u16 io_tag);392392+393393+void scic_sds_controller_power_control_queue_insert(394394+ struct scic_sds_controller *scic,395395+ struct scic_sds_phy *sci_phy);396396+397397+void scic_sds_controller_power_control_queue_remove(398398+ struct scic_sds_controller *scic,399399+ struct scic_sds_phy *sci_phy);400400+401401+void scic_sds_controller_link_up(402402+ struct scic_sds_controller *scic,403403+ struct scic_sds_port *sci_port,404404+ struct scic_sds_phy *sci_phy);405405+406406+void scic_sds_controller_link_down(407407+ struct scic_sds_controller *scic,408408+ struct scic_sds_port *sci_port,409409+ struct scic_sds_phy *sci_phy);410410+411411+void scic_sds_controller_remote_device_stopped(412412+ struct scic_sds_controller *scic,413413+ struct scic_sds_remote_device *sci_dev);414414+415415+void scic_sds_controller_copy_task_context(416416+ struct scic_sds_controller *scic,417417+ struct scic_sds_request *this_request);418418+419419+void scic_sds_controller_register_setup(struct scic_sds_controller *scic);420420+421421+enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req);422422+int isci_host_scan_finished(struct Scsi_Host *, unsigned long);423423+void isci_host_scan_start(struct Scsi_Host *);571424572425int isci_host_init(struct isci_host *);573426···769262 struct isci_remote_device *,770263 enum sci_status);771264772772-#endif /* !defined(_SCI_HOST_H_) */265265+void scic_controller_disable_interrupts(266266+ struct scic_sds_controller *scic);267267+268268+enum sci_status scic_controller_start_io(269269+ struct scic_sds_controller *scic,270270+ struct scic_sds_remote_device *remote_device,271271+ struct scic_sds_request *io_request,272272+ u16 io_tag);273273+274274+enum sci_task_status scic_controller_start_task(275275+ struct scic_sds_controller *scic,276276+ struct scic_sds_remote_device *remote_device,277277+ struct scic_sds_request *task_request,278278+ u16 io_tag);279279+280280+enum sci_status scic_controller_terminate_request(281281+ struct scic_sds_controller *scic,282282+ struct scic_sds_remote_device *remote_device,283283+ struct scic_sds_request *request);284284+285285+enum sci_status scic_controller_complete_io(286286+ struct scic_sds_controller *scic,287287+ struct scic_sds_remote_device *remote_device,288288+ struct scic_sds_request *io_request);289289+290290+u16 scic_controller_allocate_io_tag(291291+ struct scic_sds_controller *scic);292292+293293+enum sci_status scic_controller_free_io_tag(294294+ struct scic_sds_controller *scic,295295+ u16 io_tag);296296+#endif
···5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */55555656-/**5757- * This file contains the isci port implementation.5858- *5959- *6060- */6161-6262-6356#include <linux/workqueue.h>6457#include "isci.h"6558#include "scic_io_request.h"···6168#include "scic_port.h"6269#include "port.h"6370#include "request.h"6464-#include "core/scic_sds_controller.h"65716672static void isci_port_change_state(struct isci_port *iport, enum isci_status status)6773{
···5353 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454 */55555656+#include "host.h"5657#include "sci_base_state_machine.h"5757-#include "scic_sds_controller.h"5858#include "scic_sds_port.h"5959#include "remote_device.h"6060#include "remote_node_context.h"6161-#include "sci_environment.h"6261#include "sci_util.h"6362#include "scu_event_codes.h"6463#include "scu_task_context.h"
···11-/*22- * This file is provided under a dual BSD/GPLv2 license. When using or33- * redistributing this file, you may do so under either license.44- *55- * GPL LICENSE SUMMARY66- *77- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.88- *99- * This program is free software; you can redistribute it and/or modify1010- * it under the terms of version 2 of the GNU General Public License as1111- * published by the Free Software Foundation.1212- *1313- * This program is distributed in the hope that it will be useful, but1414- * WITHOUT ANY WARRANTY; without even the implied warranty of1515- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1616- * General Public License for more details.1717- *1818- * You should have received a copy of the GNU General Public License1919- * along with this program; if not, write to the Free Software2020- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.2121- * The full GNU General Public License is included in this distribution2222- * in the file called LICENSE.GPL.2323- *2424- * BSD LICENSE2525- *2626- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.2727- * All rights reserved.2828- *2929- * Redistribution and use in source and binary forms, with or without3030- * modification, are permitted provided that the following conditions3131- * are met:3232- *3333- * * Redistributions of source code must retain the above copyright3434- * notice, this list of conditions and the following disclaimer.3535- * * Redistributions in binary form must reproduce the above copyright3636- * notice, this list of conditions and the following disclaimer in3737- * the documentation and/or other materials provided with the3838- * distribution.3939- * * Neither the name of Intel Corporation nor the names of its4040- * contributors may be used to endorse or promote products derived4141- * from this software without specific prior written permission.4242- *4343- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS4444- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT4545- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR4646- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT4747- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,4848- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT4949- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,5050- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY5151- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT5252- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE5353- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.5454- */5555-5656-#ifndef _SCI_ENVIRONMENT_H_5757-#define _SCI_ENVIRONMENT_H_5858-5959-#include "host.h"6060-6161-6262-static inline struct device *scic_to_dev(struct scic_sds_controller *scic)6363-{6464- return &scic_to_ihost(scic)->pdev->dev;6565-}6666-6767-static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy)6868-{6969- struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);7070-7171- if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)7272- return NULL;7373-7474- return &iphy->isci_port->isci_host->pdev->dev;7575-}7676-7777-static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port)7878-{7979- struct isci_port *iport = sci_port_to_iport(sci_port);8080-8181- if (!iport || !iport->isci_host)8282- return NULL;8383-8484- return &iport->isci_host->pdev->dev;8585-}8686-8787-static inline struct device *scirdev_to_dev(8888- struct scic_sds_remote_device *sci_dev)8989-{9090- struct isci_remote_device *idev =9191- container_of(sci_dev, typeof(*idev), sci);9292-9393- if (!idev || !idev->isci_port || !idev->isci_port->isci_host)9494- return NULL;9595-9696- return &idev->isci_port->isci_host->pdev->dev;9797-}9898-9999-enum {100100- ISCI_SI_REVA0,101101- ISCI_SI_REVA2,102102- ISCI_SI_REVB0,103103-};104104-105105-extern int isci_si_rev;106106-107107-static inline bool is_a0(void)108108-{109109- return isci_si_rev == ISCI_SI_REVA0;110110-}111111-112112-static inline bool is_a2(void)113113-{114114- return isci_si_rev == ISCI_SI_REVA2;115115-}116116-117117-static inline bool is_b0(void)118118-{119119- return isci_si_rev > ISCI_SI_REVA2;120120-}121121-122122-#endif