^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is provided under a dual BSD/GPLv2 license. When using or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * redistributing this file, you may do so under either license.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * GPL LICENSE SUMMARY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * it under the terms of version 2 of the GNU General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This program is distributed in the hope that it will be useful, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * along with this program; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * The full GNU General Public License is included in this distribution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * in the file called LICENSE.GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * BSD LICENSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * * Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * * Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * notice, this list of conditions and the following disclaimer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * the documentation and/or other materials provided with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * * Neither the name of Intel Corporation nor the names of its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * contributors may be used to endorse or promote products derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include "isci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include "port.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include "request.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define SCU_DUMMY_INDEX (0xFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #undef C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define C(a) (#a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) const char *port_state_name(enum sci_port_states state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const char * const strings[] = PORT_STATES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return strings[state];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #undef C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static struct device *sciport_to_dev(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int i = iport->physical_port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct isci_port *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct isci_host *ihost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (i == SCIC_SDS_DUMMY_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) i = SCI_MAX_PORTS+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) table = iport - i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ihost = container_of(table, typeof(*ihost), ports[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return &ihost->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void sci_port_get_protocols(struct isci_port *iport, struct sci_phy_proto *proto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) proto->all = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) for (index = 0; index < SCI_MAX_PHYS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct isci_phy *iphy = iport->phy_table[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) sci_phy_get_protocols(iphy, proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static u32 sci_port_get_phys(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for (index = 0; index < SCI_MAX_PHYS; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (iport->phy_table[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) mask |= (1 << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * sci_port_get_properties() - This method simply returns the properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * regarding the port, such as: physical index, protocols, sas address, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @port: this parameter specifies the port for which to retrieve the physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @properties: This parameter specifies the properties structure into which to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * copy the requested information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Indicate if the user specified a valid port. SCI_SUCCESS This value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * value is returned if the specified port is not valid. When this value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * returned, no data is copied to the properties output parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) enum sci_status sci_port_get_properties(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct sci_port_properties *prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return SCI_FAILURE_INVALID_PORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) prop->index = iport->logical_port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) prop->phy_mask = sci_port_get_phys(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) sci_port_get_sas_address(iport, &prop->local.sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) sci_port_get_protocols(iport, &prop->local.protocols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) sci_port_get_attached_sas_address(iport, &prop->remote.sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void sci_port_bcn_enable(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct isci_phy *iphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for (i = 0; i < ARRAY_SIZE(iport->phy_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) iphy = iport->phy_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) val = readl(&iphy->link_layer_registers->link_layer_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* clear the bit by writing 1. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) writel(val, &iphy->link_layer_registers->link_layer_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static void isci_port_bc_change_received(struct isci_host *ihost,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) dev_dbg(&ihost->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) "%s: isci_phy = %p, sas_phy = %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) __func__, iphy, &iphy->sas_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) sas_notify_port_event_gfp(&iphy->sas_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) PORTE_BROADCAST_RCVD, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) sci_port_bcn_enable(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void isci_port_link_up(struct isci_host *isci_host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct sci_port_properties properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) unsigned long success = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dev_dbg(&isci_host->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) "%s: isci_port = %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) __func__, iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) sci_port_get_properties(iport, &properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (iphy->protocol == SAS_PROTOCOL_SATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u64 attached_sas_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) iphy->sas_phy.oob_mode = SATA_OOB_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) iphy->sas_phy.frame_rcvd_size = sizeof(struct dev_to_host_fis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * For direct-attached SATA devices, the SCI core will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * automagically assign a SAS address to the end device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * for the purpose of creating a port. This SAS address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * will not be the same as assigned to the PHY and needs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * to be obtained from struct sci_port_properties properties.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) attached_sas_address = properties.remote.sas_address.high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) attached_sas_address <<= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) attached_sas_address |= properties.remote.sas_address.low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) swab64s(&attached_sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) memcpy(&iphy->sas_phy.attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) &attached_sas_address, sizeof(attached_sas_address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } else if (iphy->protocol == SAS_PROTOCOL_SSP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) iphy->sas_phy.oob_mode = SAS_OOB_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) iphy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Copy the attached SAS address from the IAF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) memcpy(iphy->sas_phy.attached_sas_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) iphy->frame_rcvd.iaf.sas_addr, SAS_ADDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) dev_err(&isci_host->pdev->dev, "%s: unknown target\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) success = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) iphy->sas_phy.phy->negotiated_linkrate = sci_phy_linkrate(iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Notify libsas that we have an address frame, if indeed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * we've found an SSP, SMP, or STP target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) sas_notify_port_event_gfp(&iphy->sas_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) PORTE_BYTES_DMAED, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * isci_port_link_down() - This function is called by the sci core when a link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * becomes inactive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * @isci_host: This parameter specifies the isci host object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * @phy: This parameter specifies the isci phy with the active link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * @port: This parameter specifies the isci port with the active link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void isci_port_link_down(struct isci_host *isci_host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct isci_phy *isci_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct isci_port *isci_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct isci_remote_device *isci_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) dev_dbg(&isci_host->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) "%s: isci_port = %p\n", __func__, isci_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (isci_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* check to see if this is the last phy on this port. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (isci_phy->sas_phy.port &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) isci_phy->sas_phy.port->num_phys == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* change the state for all devices on this port. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * next task sent to this device will be returned as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * SAS_TASK_UNDELIVERED, and the scsi mid layer will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * remove the target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) list_for_each_entry(isci_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) &isci_port->remote_dev_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) dev_dbg(&isci_host->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) "%s: isci_device = %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) __func__, isci_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) set_bit(IDEV_GONE, &isci_device->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* Notify libsas of the borken link, this will trigger calls to our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * isci_port_deformed and isci_dev_gone functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) sas_phy_disconnected(&isci_phy->sas_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) sas_notify_phy_event_gfp(&isci_phy->sas_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) dev_dbg(&isci_host->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) "%s: isci_port = %p - Done\n", __func__, isci_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static bool is_port_ready_state(enum sci_port_states state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case SCI_PORT_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) case SCI_PORT_SUB_WAITING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) case SCI_PORT_SUB_CONFIGURING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* flag dummy rnc hanling when exiting a ready state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static void port_state_machine_change(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) enum sci_port_states state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct sci_base_state_machine *sm = &iport->sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) enum sci_port_states old_state = sm->current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (is_port_ready_state(old_state) && !is_port_ready_state(state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) iport->ready_exit = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) sci_change_state(sm, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) iport->ready_exit = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * isci_port_hard_reset_complete() - This function is called by the sci core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * when the hard reset complete notification has been received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * @port: This parameter specifies the sci port with the active link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * @completion_status: This parameter specifies the core status for the reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static void isci_port_hard_reset_complete(struct isci_port *isci_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) enum sci_status completion_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct isci_host *ihost = isci_port->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dev_dbg(&ihost->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) "%s: isci_port = %p, completion_status=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) __func__, isci_port, completion_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* Save the status of the hard reset from the port. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) isci_port->hard_reset_status = completion_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (completion_status != SCI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* The reset failed. The port state is now SCI_PORT_FAILED. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (isci_port->active_phy_mask == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int phy_idx = isci_port->last_active_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct isci_phy *iphy = &ihost->phys[phy_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* Generate the link down now to the host, since it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * was intercepted by the hard reset state machine when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * it really happened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) isci_port_link_down(ihost, iphy, isci_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* Advance the port state so that link state changes will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * noticed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) clear_bit(IPORT_RESET_PENDING, &isci_port->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) wake_up(&ihost->eventq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* This method will return a true value if the specified phy can be assigned to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * this port The following is a list of phys for each port that are allowed: -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * Port 0 - 3 2 1 0 - Port 1 - 1 - Port 2 - 3 2 - Port 3 - 3 This method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * doesn't preclude all configurations. It merely ensures that a phy is part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * of the allowable set of phy identifiers for that port. For example, one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * could assign phy 3 to port 0 and no other phys. Please refer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * sci_port_is_phy_mask_valid() for information regarding whether the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * phy_mask for a port can be supported. bool true if this is a valid phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * assignment for the port false if this is not a valid phy assignment for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) bool sci_port_is_valid_phy_assignment(struct isci_port *iport, u32 phy_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct sci_user_parameters *user = &ihost->user_parameters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* Initialize to invalid value. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) u32 existing_phy_index = SCI_MAX_PHYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if ((iport->physical_port_index == 1) && (phy_index != 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (iport->physical_port_index == 3 && phy_index != 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (iport->physical_port_index == 2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) (phy_index == 0 || phy_index == 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) for (index = 0; index < SCI_MAX_PHYS; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (iport->phy_table[index] && index != phy_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) existing_phy_index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* Ensure that all of the phys in the port are capable of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * operating at the same maximum link rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (existing_phy_index < SCI_MAX_PHYS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) user->phys[phy_index].max_speed_generation !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) user->phys[existing_phy_index].max_speed_generation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * @sci_port: This is the port object for which to determine if the phy mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * can be supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * This method will return a true value if the port's phy mask can be supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * by the SCU. The following is a list of valid PHY mask configurations for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * each port: - Port 0 - [[3 2] 1] 0 - Port 1 - [1] - Port 2 - [[3] 2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * - Port 3 - [3] This method returns a boolean indication specifying if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * phy mask can be supported. true if this is a valid phy assignment for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * port false if this is not a valid phy assignment for the port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static bool sci_port_is_phy_mask_valid(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) u32 phy_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (iport->physical_port_index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (((phy_mask & 0x0F) == 0x0F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) || ((phy_mask & 0x03) == 0x03)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) || ((phy_mask & 0x01) == 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) || (phy_mask == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) } else if (iport->physical_port_index == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (((phy_mask & 0x02) == 0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) || (phy_mask == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) } else if (iport->physical_port_index == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (((phy_mask & 0x0C) == 0x0C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) || ((phy_mask & 0x04) == 0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) || (phy_mask == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) } else if (iport->physical_port_index == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (((phy_mask & 0x08) == 0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) || (phy_mask == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * This method retrieves a currently active (i.e. connected) phy contained in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * the port. Currently, the lowest order phy that is connected is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * returned if there are no currently active (i.e. connected to a remote end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * point) phys contained in the port. All other values specify a struct sci_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * object that is active in the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static struct isci_phy *sci_port_get_a_connected_phy(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct isci_phy *iphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) for (index = 0; index < SCI_MAX_PHYS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* Ensure that the phy is both part of the port and currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * connected to the remote end-point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) iphy = iport->phy_table[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (iphy && sci_port_active_phy(iport, iphy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return iphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static enum sci_status sci_port_set_phy(struct isci_port *iport, struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /* Check to see if we can add this phy to a port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * that means that the phy is not part of a port and that the port does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * not already have a phy assinged to the phy index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (!iport->phy_table[iphy->phy_index] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) !phy_get_non_dummy_port(iphy) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) sci_port_is_valid_phy_assignment(iport, iphy->phy_index)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Phy is being added in the stopped state so we are in MPC mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * make logical port index = physical port index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) iport->logical_port_index = iport->physical_port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) iport->phy_table[iphy->phy_index] = iphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) sci_phy_set_port(iphy, iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return SCI_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static enum sci_status sci_port_clear_phy(struct isci_port *iport, struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* Make sure that this phy is part of this port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (iport->phy_table[iphy->phy_index] == iphy &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) phy_get_non_dummy_port(iphy) == iport) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* Yep it is assigned to this port so remove it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) sci_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) iport->phy_table[iphy->phy_index] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return SCI_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) void sci_port_get_sas_address(struct isci_port *iport, struct sci_sas_address *sas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) sas->high = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) sas->low = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) for (index = 0; index < SCI_MAX_PHYS; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (iport->phy_table[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) sci_phy_get_sas_address(iport->phy_table[index], sas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) void sci_port_get_attached_sas_address(struct isci_port *iport, struct sci_sas_address *sas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct isci_phy *iphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * Ensure that the phy is both part of the port and currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * connected to the remote end-point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) iphy = sci_port_get_a_connected_phy(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (iphy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (iphy->protocol != SAS_PROTOCOL_SATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) sci_phy_get_attached_sas_address(iphy, sas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) sci_phy_get_sas_address(iphy, sas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) sas->low += iphy->phy_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) sas->high = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) sas->low = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * sci_port_construct_dummy_rnc() - create dummy rnc for si workaround
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * @sci_port: logical port on which we need to create the remote node context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * @rni: remote node index for this remote node context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * This routine will construct a dummy remote node context data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * This structure will be posted to the hardware to work around a scheduler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * error in the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static void sci_port_construct_dummy_rnc(struct isci_port *iport, u16 rni)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) union scu_remote_node_context *rnc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) rnc = &iport->owning_controller->remote_node_context_table[rni];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) memset(rnc, 0, sizeof(union scu_remote_node_context));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) rnc->ssp.remote_sas_address_hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) rnc->ssp.remote_sas_address_lo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) rnc->ssp.remote_node_index = rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) rnc->ssp.remote_node_port_width = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) rnc->ssp.logical_port_index = iport->physical_port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) rnc->ssp.nexus_loss_timer_enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) rnc->ssp.check_bit = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) rnc->ssp.is_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) rnc->ssp.is_remote_node_context = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) rnc->ssp.function_number = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) rnc->ssp.arbitration_wait_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * construct a dummy task context data structure. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * structure will be posted to the hardwre to work around a scheduler error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * in the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static void sci_port_construct_dummy_task(struct isci_port *iport, u16 tag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct scu_task_context *task_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) task_context = &ihost->task_context_table[ISCI_TAG_TCI(tag)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) memset(task_context, 0, sizeof(struct scu_task_context));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) task_context->initiator_request = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) task_context->connection_rate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) task_context->logical_port_index = iport->physical_port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) task_context->task_index = ISCI_TAG_TCI(tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) task_context->valid = SCU_TASK_CONTEXT_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) task_context->context_type = SCU_TASK_CONTEXT_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) task_context->remote_node_index = iport->reserved_rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) task_context->do_not_dma_ssp_good_response = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) task_context->task_phase = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static void sci_port_destroy_dummy_resources(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (iport->reserved_tag != SCI_CONTROLLER_INVALID_IO_TAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) isci_free_tag(ihost, iport->reserved_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (iport->reserved_rni != SCU_DUMMY_INDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) sci_remote_node_table_release_remote_node_index(&ihost->available_remote_nodes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 1, iport->reserved_rni);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) iport->reserved_rni = SCU_DUMMY_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) void sci_port_setup_transports(struct isci_port *iport, u32 device_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) for (index = 0; index < SCI_MAX_PHYS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (iport->active_phy_mask & (1 << index))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) sci_phy_setup_transport(iport->phy_table[index], device_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static void sci_port_resume_phy(struct isci_port *iport, struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) sci_phy_resume(iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) iport->enabled_phy_mask |= 1 << iphy->phy_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static void sci_port_activate_phy(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct isci_phy *iphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) u8 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (iphy->protocol != SAS_PROTOCOL_SATA && (flags & PF_RESUME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) sci_phy_resume(iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) iport->active_phy_mask |= 1 << iphy->phy_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) sci_controller_clear_invalid_phy(ihost, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (flags & PF_NOTIFY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) isci_port_link_up(ihost, iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) bool do_notify_user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) iport->active_phy_mask &= ~(1 << iphy->phy_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) iport->enabled_phy_mask &= ~(1 << iphy->phy_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (!iport->active_phy_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) iport->last_active_phy = iphy->phy_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* Re-assign the phy back to the LP as if it were a narrow port for APC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * mode. For MPC mode, the phy will remain in the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (iport->owning_controller->oem_parameters.controller.mode_type ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) writel(iphy->phy_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) &iport->port_pe_configuration_register[iphy->phy_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (do_notify_user == true)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) isci_port_link_down(ihost, iphy, iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * Check to see if we have alreay reported this link as bad and if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * not go ahead and tell the SCI_USER that we have discovered an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * invalid link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if ((ihost->invalid_phy_mask & (1 << iphy->phy_index)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ihost->invalid_phy_mask |= 1 << iphy->phy_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) dev_warn(&ihost->pdev->dev, "Invalid link up!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * sci_port_general_link_up_handler - phy can be assigned to port?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * @sci_port: sci_port object for which has a phy that has gone link up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * @sci_phy: This is the struct isci_phy object that has gone link up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * @flags: PF_RESUME, PF_NOTIFY to sci_port_activate_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * Determine if this phy can be assigned to this port . If the phy is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * not a valid PHY for this port then the function will notify the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * A PHY can only be part of a port if it's attached SAS ADDRESS is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * same as all other PHYs in the same port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static void sci_port_general_link_up_handler(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct isci_phy *iphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) u8 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct sci_sas_address port_sas_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct sci_sas_address phy_sas_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) sci_port_get_attached_sas_address(iport, &port_sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) sci_phy_get_attached_sas_address(iphy, &phy_sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* If the SAS address of the new phy matches the SAS address of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * other phys in the port OR this is the first phy in the port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * then activate the phy and allow it to be used for operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * in this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if ((phy_sas_address.high == port_sas_address.high &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) phy_sas_address.low == port_sas_address.low) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) iport->active_phy_mask == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct sci_base_state_machine *sm = &iport->sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) sci_port_activate_phy(iport, iphy, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (sm->current_state_id == SCI_PORT_RESETTING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) port_state_machine_change(iport, SCI_PORT_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) sci_port_invalid_link_up(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * This method returns false if the port only has a single phy object assigned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * If there are no phys or more than one phy then the method will return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * @sci_port: The port for which the wide port condition is to be checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * bool true Is returned if this is a wide ported port. false Is returned if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * this is a narrow port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static bool sci_port_is_wide(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) u32 phy_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) for (index = 0; index < SCI_MAX_PHYS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (iport->phy_table[index] != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) phy_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return phy_count != 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * This method is called by the PHY object when the link is detected. if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * port wants the PHY to continue on to the link up state then the port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * layer must return true. If the port object returns false the phy object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * must halt its attempt to go link up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * @sci_port: The port associated with the phy object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * @sci_phy: The phy object that is trying to go link up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * true if the phy object can continue to the link up condition. true Is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * returned if this phy can continue to the ready state. false Is returned if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * can not continue on to the ready state. This notification is in place for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * wide ports and direct attached phys. Since there are no wide ported SATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * devices this could become an invalid port configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) bool sci_port_link_detected(struct isci_port *iport, struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) (iphy->protocol == SAS_PROTOCOL_SATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (sci_port_is_wide(iport)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) sci_port_invalid_link_up(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct isci_port *dst_port = &(ihost->ports[iphy->phy_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) writel(iphy->phy_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) &dst_port->port_pe_configuration_register[iphy->phy_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static void port_timeout(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct sci_timer *tmr = from_timer(tmr, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct isci_port *iport = container_of(tmr, typeof(*iport), timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) u32 current_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) spin_lock_irqsave(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (tmr->cancel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) current_state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (current_state == SCI_PORT_RESETTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /* if the port is still in the resetting state then the timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * fired before the reset completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) port_state_machine_change(iport, SCI_PORT_FAILED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) } else if (current_state == SCI_PORT_STOPPED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* if the port is stopped then the start request failed In this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * case stay in the stopped state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) dev_err(sciport_to_dev(iport),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) "%s: SCIC Port 0x%p failed to stop before timeout.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) } else if (current_state == SCI_PORT_STOPPING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) dev_dbg(sciport_to_dev(iport),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) "%s: port%d: stop complete timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) __func__, iport->physical_port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* The port is in the ready state and we have a timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * reporting a timeout this should not happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) dev_err(sciport_to_dev(iport),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) "%s: SCIC Port 0x%p is processing a timeout operation "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) "in state %d.\n", __func__, iport, current_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) spin_unlock_irqrestore(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* --------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * This function updates the hardwares VIIT entry for this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static void sci_port_update_viit_entry(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct sci_sas_address sas_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) sci_port_get_sas_address(iport, &sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) writel(sas_address.high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) &iport->viit_registers->initiator_sas_address_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) writel(sas_address.low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) &iport->viit_registers->initiator_sas_address_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) /* This value get cleared just in case its not already cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) writel(0, &iport->viit_registers->reserved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* We are required to update the status register last */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) writel(SCU_VIIT_ENTRY_ID_VIIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) SCU_VIIT_IPPT_INITIATOR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ((1 << iport->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) SCU_VIIT_STATUS_ALL_VALID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) &iport->viit_registers->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) enum sas_linkrate sci_port_get_max_allowed_speed(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) u16 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct isci_phy *iphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * Loop through all of the phys in this port and find the phy with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * lowest maximum link rate. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) for (index = 0; index < SCI_MAX_PHYS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) iphy = iport->phy_table[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (iphy && sci_port_active_phy(iport, iphy) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) iphy->max_negotiated_speed < max_allowed_speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) max_allowed_speed = iphy->max_negotiated_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return max_allowed_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static void sci_port_suspend_port_task_scheduler(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) u32 pts_control_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) pts_control_value = readl(&iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) writel(pts_control_value, &iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * sci_port_post_dummy_request() - post dummy/workaround request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * @sci_port: port to post task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * Prevent the hardware scheduler from posting new requests to the front
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * of the scheduler queue causing a starvation problem for currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * ongoing requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) static void sci_port_post_dummy_request(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) u16 tag = iport->reserved_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct scu_task_context *tc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) u32 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) tc = &ihost->task_context_table[ISCI_TAG_TCI(tag)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) tc->abort = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ISCI_TAG_TCI(tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) sci_controller_post_request(ihost, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * This routine will abort the dummy request. This will alow the hardware to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * power down parts of the silicon to save power.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * @sci_port: The port on which the task must be aborted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static void sci_port_abort_dummy_request(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) u16 tag = iport->reserved_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) struct scu_task_context *tc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) u32 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) tc = &ihost->task_context_table[ISCI_TAG_TCI(tag)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) tc->abort = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) ISCI_TAG_TCI(tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) sci_controller_post_request(ihost, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * @sci_port: This is the struct isci_port object to resume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * This method will resume the port task scheduler for this port object. none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) sci_port_resume_port_task_scheduler(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u32 pts_control_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) pts_control_value = readl(&iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) writel(pts_control_value, &iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) sci_port_suspend_port_task_scheduler(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) iport->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (iport->active_phy_mask != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /* At least one of the phys on the port is ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) SCI_PORT_SUB_OPERATIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static void scic_sds_port_ready_substate_waiting_exit(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) sci_port_resume_port_task_scheduler(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) dev_dbg(&ihost->pdev->dev, "%s: port%d ready\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) __func__, iport->physical_port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) for (index = 0; index < SCI_MAX_PHYS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (iport->phy_table[index]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) writel(iport->physical_port_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) &iport->port_pe_configuration_register[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) iport->phy_table[index]->phy_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (((iport->active_phy_mask^iport->enabled_phy_mask) & (1 << index)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) sci_port_resume_phy(iport, iport->phy_table[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) sci_port_update_viit_entry(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * Post the dummy task for the port so the hardware can schedule
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) * io correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) sci_port_post_dummy_request(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static void sci_port_invalidate_dummy_remote_node(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) u8 phys_index = iport->physical_port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) union scu_remote_node_context *rnc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) u16 rni = iport->reserved_rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) u32 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) rnc = &ihost->remote_node_context_table[rni];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) rnc->ssp.is_valid = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /* ensure the preceding tc abort request has reached the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * controller and give it ample time to act before posting the rnc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * invalidate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) readl(&ihost->smu_registers->interrupt_status); /* flush */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) sci_controller_post_request(ihost, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * @object: This is the object which is cast to a struct isci_port object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) * This method will perform the actions required by the struct isci_port on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * exiting the SCI_PORT_SUB_OPERATIONAL. This function reports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * the port not ready and suspends the port task scheduler. none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) static void sci_port_ready_substate_operational_exit(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * Kill the dummy task for this port if it has not yet posted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * the hardware will treat this as a NOP and just return abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) sci_port_abort_dummy_request(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) dev_dbg(&ihost->pdev->dev, "%s: port%d !ready\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) __func__, iport->physical_port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (iport->ready_exit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) sci_port_invalidate_dummy_remote_node(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static void sci_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (iport->active_phy_mask == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) dev_dbg(&ihost->pdev->dev, "%s: port%d !ready\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) __func__, iport->physical_port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) port_state_machine_change(iport, SCI_PORT_SUB_WAITING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) enum sci_status sci_port_start(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) enum sci_status status = SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) u32 phy_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (state != SCI_PORT_STOPPED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (iport->assigned_device_count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) /* TODO This is a start failure operation because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * there are still devices assigned to this port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * There must be no devices assigned to a port on a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * start operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (iport->reserved_rni == SCU_DUMMY_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) u16 rni = sci_remote_node_table_allocate_remote_node(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) &ihost->available_remote_nodes, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (rni != SCU_DUMMY_INDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) sci_port_construct_dummy_rnc(iport, rni);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) iport->reserved_rni = rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (iport->reserved_tag == SCI_CONTROLLER_INVALID_IO_TAG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) u16 tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) tag = isci_alloc_tag(ihost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (tag == SCI_CONTROLLER_INVALID_IO_TAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) sci_port_construct_dummy_task(iport, tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) iport->reserved_tag = tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (status == SCI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) phy_mask = sci_port_get_phys(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * There are one or more phys assigned to this port. Make sure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * the port's phy mask is in fact legal and supported by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * silicon.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (sci_port_is_phy_mask_valid(iport, phy_mask) == true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) SCI_PORT_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) status = SCI_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (status != SCI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) sci_port_destroy_dummy_resources(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) enum sci_status sci_port_stop(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) case SCI_PORT_STOPPED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) case SCI_PORT_SUB_WAITING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) case SCI_PORT_SUB_CONFIGURING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) case SCI_PORT_RESETTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) SCI_PORT_STOPPING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) static enum sci_status sci_port_hard_reset(struct isci_port *iport, u32 timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) enum sci_status status = SCI_FAILURE_INVALID_PHY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) struct isci_phy *iphy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) u32 phy_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (state != SCI_PORT_SUB_OPERATIONAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) /* Select a phy on which we can send the hard reset request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) for (phy_index = 0; phy_index < SCI_MAX_PHYS && !iphy; phy_index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) iphy = iport->phy_table[phy_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (iphy && !sci_port_active_phy(iport, iphy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * We found a phy but it is not ready select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * different phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) iphy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) /* If we have a phy then go ahead and start the reset procedure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (!iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) status = sci_phy_reset(iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (status != SCI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) sci_mod_timer(&iport->timer, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) iport->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) port_state_machine_change(iport, SCI_PORT_RESETTING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) * sci_port_add_phy() -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) * @sci_port: This parameter specifies the port in which the phy will be added.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * @sci_phy: This parameter is the phy which is to be added to the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) * This method will add a PHY to the selected port. This method returns an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) * status is a failure to add the phy to the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) enum sci_status sci_port_add_phy(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) enum sci_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) sci_port_bcn_enable(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) case SCI_PORT_STOPPED: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) struct sci_sas_address port_sas_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) /* Read the port assigned SAS Address if there is one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) sci_port_get_sas_address(iport, &port_sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (port_sas_address.high != 0 && port_sas_address.low != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) struct sci_sas_address phy_sas_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* Make sure that the PHY SAS Address matches the SAS Address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * for this port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) sci_phy_get_sas_address(iphy, &phy_sas_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (port_sas_address.high != phy_sas_address.high ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) port_sas_address.low != phy_sas_address.low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return sci_port_set_phy(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) case SCI_PORT_SUB_WAITING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) status = sci_port_set_phy(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (status != SCI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) case SCI_PORT_SUB_CONFIGURING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) status = sci_port_set_phy(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (status != SCI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /* Re-enter the configuring state since this may be the last phy in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) SCI_PORT_SUB_CONFIGURING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * sci_port_remove_phy() -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * @sci_port: This parameter specifies the port in which the phy will be added.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) * @sci_phy: This parameter is the phy which is to be added to the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * This method will remove the PHY from the selected PORT. This method returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * other status is a failure to add the phy to the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) enum sci_status sci_port_remove_phy(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) enum sci_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) case SCI_PORT_STOPPED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return sci_port_clear_phy(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) status = sci_port_clear_phy(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (status != SCI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) sci_port_deactivate_phy(iport, iphy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) SCI_PORT_SUB_CONFIGURING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) case SCI_PORT_SUB_CONFIGURING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) status = sci_port_clear_phy(iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (status != SCI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) sci_port_deactivate_phy(iport, iphy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /* Re-enter the configuring state since this may be the last phy in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * the port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) SCI_PORT_SUB_CONFIGURING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) enum sci_status sci_port_link_up(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) case SCI_PORT_SUB_WAITING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) /* Since this is the first phy going link up for the port we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * can just enable it and continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) sci_port_activate_phy(iport, iphy, PF_NOTIFY|PF_RESUME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) SCI_PORT_SUB_OPERATIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) case SCI_PORT_RESETTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /* TODO We should make sure that the phy that has gone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * link up is the same one on which we sent the reset. It is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * possible that the phy on which we sent the reset is not the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * one that has gone link up and we want to make sure that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * phy being reset comes back. Consider the case where a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * reset is sent but before the hardware processes the reset it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * get a link up on the port because of a hot plug event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * because of the reset request this phy will go link down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * almost immediately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) /* In the resetting state we don't notify the user regarding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * link up and link down notifications.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) sci_port_general_link_up_handler(iport, iphy, PF_RESUME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) enum sci_status sci_port_link_down(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) sci_port_deactivate_phy(iport, iphy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) /* If there are no active phys left in the port, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) * transition the port to the WAITING state until such time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) * as a phy goes link up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if (iport->active_phy_mask == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) SCI_PORT_SUB_WAITING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) case SCI_PORT_RESETTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) /* In the resetting state we don't notify the user regarding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * link up and link down notifications. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) sci_port_deactivate_phy(iport, iphy, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) enum sci_status sci_port_start_io(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) struct isci_remote_device *idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) struct isci_request *ireq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) case SCI_PORT_SUB_WAITING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) iport->started_request_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) enum sci_status sci_port_complete_io(struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) struct isci_remote_device *idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) struct isci_request *ireq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) enum sci_port_states state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) state = iport->sm.current_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) case SCI_PORT_STOPPED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) dev_warn(sciport_to_dev(iport), "%s: in wrong state: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) __func__, port_state_name(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return SCI_FAILURE_INVALID_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) case SCI_PORT_STOPPING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) sci_port_decrement_request_count(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (iport->started_request_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) SCI_PORT_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) case SCI_PORT_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) case SCI_PORT_RESETTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) case SCI_PORT_FAILED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) case SCI_PORT_SUB_WAITING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) case SCI_PORT_SUB_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) sci_port_decrement_request_count(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) case SCI_PORT_SUB_CONFIGURING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) sci_port_decrement_request_count(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (iport->started_request_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) SCI_PORT_SUB_OPERATIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) return SCI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) static void sci_port_enable_port_task_scheduler(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) u32 pts_control_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) /* enable the port task scheduler in a suspended state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) pts_control_value = readl(&iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) writel(pts_control_value, &iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) static void sci_port_disable_port_task_scheduler(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) u32 pts_control_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) pts_control_value = readl(&iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) pts_control_value &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) ~(SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) writel(pts_control_value, &iport->port_task_scheduler_registers->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) static void sci_port_post_dummy_remote_node(struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) u8 phys_index = iport->physical_port_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) union scu_remote_node_context *rnc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) u16 rni = iport->reserved_rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) u32 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) rnc = &ihost->remote_node_context_table[rni];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) rnc->ssp.is_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) command = SCU_CONTEXT_COMMAND_POST_RNC_32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) sci_controller_post_request(ihost, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) /* ensure hardware has seen the post rnc command and give it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) * ample time to act before sending the suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) readl(&ihost->smu_registers->interrupt_status); /* flush */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) sci_controller_post_request(ihost, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) static void sci_port_stopped_state_enter(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (iport->sm.previous_state_id == SCI_PORT_STOPPING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) * If we enter this state becasuse of a request to stop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) * the port then we want to disable the hardwares port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) * task scheduler. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) sci_port_disable_port_task_scheduler(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) static void sci_port_stopped_state_exit(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) /* Enable and suspend the port task scheduler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) sci_port_enable_port_task_scheduler(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) static void sci_port_ready_state_enter(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) u32 prev_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) prev_state = iport->sm.previous_state_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (prev_state == SCI_PORT_RESETTING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) isci_port_hard_reset_complete(iport, SCI_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) dev_dbg(&ihost->pdev->dev, "%s: port%d !ready\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) __func__, iport->physical_port_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) /* Post and suspend the dummy remote node context for this port. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) sci_port_post_dummy_remote_node(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) /* Start the ready substate machine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) port_state_machine_change(iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) SCI_PORT_SUB_WAITING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) static void sci_port_resetting_state_exit(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) sci_del_timer(&iport->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) static void sci_port_stopping_state_exit(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) sci_del_timer(&iport->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) sci_port_destroy_dummy_resources(iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) static void sci_port_failed_state_enter(struct sci_base_state_machine *sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) struct isci_port *iport = container_of(sm, typeof(*iport), sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) void sci_port_set_hang_detection_timeout(struct isci_port *iport, u32 timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) int phy_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) u32 phy_mask = iport->active_phy_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) ++iport->hang_detect_users;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) else if (iport->hang_detect_users > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) --iport->hang_detect_users;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) iport->hang_detect_users = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (timeout || (iport->hang_detect_users == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if ((phy_mask >> phy_index) & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) writel(timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) &iport->phy_table[phy_index]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) ->link_layer_registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) ->link_layer_hang_detection_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) /* --------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static const struct sci_base_state sci_port_state_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) [SCI_PORT_STOPPED] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) .enter_state = sci_port_stopped_state_enter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) .exit_state = sci_port_stopped_state_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) [SCI_PORT_STOPPING] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) .exit_state = sci_port_stopping_state_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) [SCI_PORT_READY] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) .enter_state = sci_port_ready_state_enter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) [SCI_PORT_SUB_WAITING] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) .enter_state = sci_port_ready_substate_waiting_enter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) .exit_state = scic_sds_port_ready_substate_waiting_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) [SCI_PORT_SUB_OPERATIONAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) .enter_state = sci_port_ready_substate_operational_enter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) .exit_state = sci_port_ready_substate_operational_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) [SCI_PORT_SUB_CONFIGURING] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) .enter_state = sci_port_ready_substate_configuring_enter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) [SCI_PORT_RESETTING] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) .exit_state = sci_port_resetting_state_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) [SCI_PORT_FAILED] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) .enter_state = sci_port_failed_state_enter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) void sci_port_construct(struct isci_port *iport, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) struct isci_host *ihost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) sci_init_sm(&iport->sm, sci_port_state_table, SCI_PORT_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) iport->logical_port_index = SCIC_SDS_DUMMY_PORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) iport->physical_port_index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) iport->active_phy_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) iport->enabled_phy_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) iport->last_active_phy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) iport->ready_exit = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) iport->owning_controller = ihost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) iport->started_request_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) iport->assigned_device_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) iport->hang_detect_users = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) iport->reserved_rni = SCU_DUMMY_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) sci_init_timer(&iport->timer, port_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) iport->port_task_scheduler_registers = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) for (index = 0; index < SCI_MAX_PHYS; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) iport->phy_table[index] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) void sci_port_broadcast_change_received(struct isci_port *iport, struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) struct isci_host *ihost = iport->owning_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) /* notify the user. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) isci_port_bc_change_received(ihost, iport, iphy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) static void wait_port_reset(struct isci_host *ihost, struct isci_port *iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) wait_event(ihost->eventq, !test_bit(IPORT_RESET_PENDING, &iport->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) struct isci_phy *iphy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) enum sci_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) int ret = TMF_RESP_FUNC_COMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) __func__, iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) spin_lock_irqsave(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) set_bit(IPORT_RESET_PENDING, &iport->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) status = sci_port_hard_reset(iport, ISCI_PORT_RESET_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) spin_unlock_irqrestore(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (status == SCI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) wait_port_reset(ihost, iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) dev_dbg(&ihost->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) "%s: iport = %p; hard reset completion\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) __func__, iport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (iport->hard_reset_status != SCI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) ret = TMF_RESP_FUNC_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) dev_err(&ihost->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) "%s: iport = %p; hard reset failed (0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) __func__, iport, iport->hard_reset_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) clear_bit(IPORT_RESET_PENDING, &iport->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) wake_up(&ihost->eventq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) ret = TMF_RESP_FUNC_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) dev_err(&ihost->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) "%s: iport = %p; sci_port_hard_reset call"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) " failed 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) __func__, iport, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) int isci_ata_check_ready(struct domain_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) struct isci_port *iport = dev->port->lldd_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) struct isci_host *ihost = dev_to_ihost(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) struct isci_remote_device *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) spin_lock_irqsave(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) idev = isci_lookup_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) spin_unlock_irqrestore(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) if (test_bit(IPORT_RESET_PENDING, &iport->state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) rc = !!iport->active_phy_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) isci_put_device(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) void isci_port_deformed(struct asd_sas_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct isci_host *ihost = phy->ha->lldd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) struct isci_port *iport = phy->port->lldd_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) /* we got a port notification on a port that was subsequently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) * torn down and libsas is just now catching up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (!iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) spin_lock_irqsave(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) for (i = 0; i < SCI_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (iport->active_phy_mask & 1 << i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) spin_unlock_irqrestore(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (i >= SCI_MAX_PHYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) dev_dbg(&ihost->pdev->dev, "%s: port: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) __func__, (long) (iport - &ihost->ports[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) void isci_port_formed(struct asd_sas_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) struct isci_host *ihost = phy->ha->lldd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) struct isci_phy *iphy = to_iphy(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) struct asd_sas_port *port = phy->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) struct isci_port *iport = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) /* initial ports are formed as the driver is still initializing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) * wait for that process to complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) wait_for_start(ihost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) spin_lock_irqsave(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) for (i = 0; i < SCI_MAX_PORTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) iport = &ihost->ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) if (iport->active_phy_mask & 1 << iphy->phy_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) spin_unlock_irqrestore(&ihost->scic_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (i >= SCI_MAX_PORTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) iport = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) port->lldd_port = iport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }