From c79dd80d73017a88a2c2ae46e7d5303cba6a32e0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 1 Feb 2012 00:44:14 -0800 Subject: isci: kill sci_phy_protocol and sci_request_protocol Holdovers from the initial driver cleanup, replace with enum sas_protocol. Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/isci/port.c') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 5fada73b71ff..923579fa0292 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -184,7 +184,7 @@ static void isci_port_link_up(struct isci_host *isci_host, sci_port_get_properties(iport, &properties); - if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { + if (iphy->protocol == SAS_PROTOCOL_SATA) { u64 attached_sas_address; iphy->sas_phy.oob_mode = SATA_OOB_MODE; @@ -204,7 +204,7 @@ static void isci_port_link_up(struct isci_host *isci_host, memcpy(&iphy->sas_phy.attached_sas_addr, &attached_sas_address, sizeof(attached_sas_address)); - } else if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + } else if (iphy->protocol == SAS_PROTOCOL_SSP) { iphy->sas_phy.oob_mode = SAS_OOB_MODE; iphy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame); @@ -517,7 +517,7 @@ void sci_port_get_attached_sas_address(struct isci_port *iport, struct sci_sas_a */ iphy = sci_port_get_a_connected_phy(iport); if (iphy) { - if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) { + if (iphy->protocol != SAS_PROTOCOL_SATA) { sci_phy_get_attached_sas_address(iphy, sas); } else { sci_phy_get_sas_address(iphy, sas); @@ -624,7 +624,7 @@ static void sci_port_activate_phy(struct isci_port *iport, { struct isci_host *ihost = iport->owning_controller; - if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA && (flags & PF_RESUME)) + if (iphy->protocol != SAS_PROTOCOL_SATA && (flags & PF_RESUME)) sci_phy_resume(iphy); iport->active_phy_mask |= 1 << iphy->phy_index; @@ -751,12 +751,10 @@ static bool sci_port_is_wide(struct isci_port *iport) * wide ports and direct attached phys. Since there are no wide ported SATA * devices this could become an invalid port configuration. */ -bool sci_port_link_detected( - struct isci_port *iport, - struct isci_phy *iphy) +bool sci_port_link_detected(struct isci_port *iport, struct isci_phy *iphy) { if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) && - (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) { + (iphy->protocol == SAS_PROTOCOL_SATA)) { if (sci_port_is_wide(iport)) { sci_port_invalid_link_up(iport, iphy); return false; -- cgit v1.2.1 From ae904d15cf344bcb426f63982016f6bacc45825b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 17 Feb 2012 16:30:47 -0800 Subject: isci: kill isci_port.domain_dev_list Another unused field, and isci_port_init is overkill. Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/scsi/isci/port.c') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 923579fa0292..6ef4bd910f33 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1606,13 +1606,6 @@ void sci_port_construct(struct isci_port *iport, u8 index, iport->phy_table[index] = NULL; } -void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index) -{ - INIT_LIST_HEAD(&iport->remote_dev_list); - INIT_LIST_HEAD(&iport->domain_dev_list); - iport->isci_host = ihost; -} - void sci_port_broadcast_change_received(struct isci_port *iport, struct isci_phy *iphy) { struct isci_host *ihost = iport->owning_controller; -- cgit v1.2.1 From 08e73be56b6b2e5459638481a54b755ed562ada8 Mon Sep 17 00:00:00 2001 From: Maciej Trela Date: Mon, 12 Mar 2012 23:29:30 +0000 Subject: isci: enable BCN in sci_port_add_phy() Ensure we enable receiving BCN's from the hardware when adding phy to isci_port. Otherwise if we get BCN before the port is created we won't see any BCN Signed-off-by: Maciej Trela Reported-by: Richard Boyd Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi/isci/port.c') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 6ef4bd910f33..0a3aec118097 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1199,6 +1199,8 @@ enum sci_status sci_port_add_phy(struct isci_port *iport, enum sci_status status; enum sci_port_states state; + sci_port_bcn_enable(iport); + state = iport->sm.current_state_id; switch (state) { case SCI_PORT_STOPPED: { -- cgit v1.2.1 From 6f48844e3f16b7d8a1f9a1a11bd9a11089a5292f Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 8 Mar 2012 22:41:48 -0800 Subject: isci: Manage the link layer hang detect timer for RNC suspensions. For STP devices under certain protocol conditions, an RNC will not suspend until the current transfer state is broken with a SYNC/ESC sequence from the SCU. The SYNC/ESC driven by expiration of the SCU link layer hang detect timer, which has too small a dynamic range to support slow SATA devices, so normally it is disabled. This change enables the timer with the minimum period at the point when the suspension is requested. Note that there is potential collateral damage to other open connections to slow SATA devices on the same port, since there is no alternative but to enable the LLHANG timer on every phy in the port for the current suspension request - there is no way to tell on which phy the RNC in question is currently active. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/isci/port.c') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 0a3aec118097..ed206c5a00a6 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1548,6 +1548,29 @@ static void sci_port_failed_state_enter(struct sci_base_state_machine *sm) isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); } +void sci_port_set_hang_detection_timeout(struct isci_port *iport, u32 timeout) +{ + int phy_index; + u32 phy_mask = iport->active_phy_mask; + + if (timeout) + ++iport->hang_detect_users; + else if (iport->hang_detect_users > 1) + --iport->hang_detect_users; + else + iport->hang_detect_users = 0; + + if (timeout || (iport->hang_detect_users == 0)) { + for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { + if ((phy_mask >> phy_index) & 1) { + writel(timeout, + &iport->phy_table[phy_index] + ->link_layer_registers + ->link_layer_hang_detection_timeout); + } + } + } +} /* --------------------------------------------------------------------------- */ static const struct sci_base_state sci_port_state_table[] = { @@ -1596,6 +1619,7 @@ void sci_port_construct(struct isci_port *iport, u8 index, iport->started_request_count = 0; iport->assigned_device_count = 0; + iport->hang_detect_users = 0; iport->reserved_rni = SCU_DUMMY_INDEX; iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; @@ -1733,7 +1757,7 @@ void isci_port_formed(struct asd_sas_phy *phy) struct isci_host *ihost = phy->ha->lldd_ha; struct isci_phy *iphy = to_iphy(phy); struct asd_sas_port *port = phy->port; - struct isci_port *iport; + struct isci_port *iport = NULL; unsigned long flags; int i; -- cgit v1.2.1 From 59e35396436c564b5019e1a70073900bc3e19f4f Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 8 Mar 2012 22:41:54 -0800 Subject: isci: Add suspension cases for RNC INVALIDATING, POSTING states. The RNC can be any of the states in the loop from suspended to ready when the API "suspend" or "resume" are called. This change adds destination states parameters that control the suspension / resumption action of the RNC statemachine for those transition states. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/scsi/isci/port.c') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index ed206c5a00a6..f1866b0dc195 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -1688,17 +1688,6 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor __func__, iport, status); } - - /* If the hard reset for the port has failed, consider this - * the same as link failures on all phys in the port. - */ - if (ret != TMF_RESP_FUNC_COMPLETE) { - - dev_err(&ihost->pdev->dev, - "%s: iport = %p; hard reset failed " - "(0x%x) - driving explicit link fail for all phys\n", - __func__, iport, iport->hard_reset_status); - } return ret; } -- cgit v1.2.1 From 033751f6643adf616b85ac5eea7ce784bdde1b50 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Thu, 8 Mar 2012 22:41:56 -0800 Subject: isci: Only set IDEV_GONE in the device stop path. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers/scsi/isci/port.c') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index f1866b0dc195..da0c4e1b9b30 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -240,32 +240,9 @@ static void isci_port_link_down(struct isci_host *isci_host, struct isci_phy *isci_phy, struct isci_port *isci_port) { - struct isci_remote_device *isci_device; - dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, isci_port); - if (isci_port) { - - /* check to see if this is the last phy on this port. */ - if (isci_phy->sas_phy.port && - isci_phy->sas_phy.port->num_phys == 1) { - /* change the state for all devices on this port. The - * next task sent to this device will be returned as - * SAS_TASK_UNDELIVERED, and the scsi mid layer will - * remove the target - */ - list_for_each_entry(isci_device, - &isci_port->remote_dev_list, - node) { - dev_dbg(&isci_host->pdev->dev, - "%s: isci_device = %p\n", - __func__, isci_device); - set_bit(IDEV_GONE, &isci_device->flags); - } - } - } - /* Notify libsas of the borken link, this will trigger calls to our * isci_port_deformed and isci_dev_gone functions. */ -- cgit v1.2.1 From 397497dd61948b0d59d1d21812b93c97b0eeb2dd Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Sat, 10 Mar 2012 05:46:46 +0000 Subject: isci: Check IDEV_GONE before performing abort path operations. In the link fail path, set IDEV_GONE for every device on the domain when the last link in the port fails. In the abort path functions like isci_reset_device, make sure that there has not already been a detected domain failure with the device by checking IDEV_GONE, before performing any kind of hard reset, SMP phy control, or TMF operation. The check for IDEV_GONE makes sure that the device in the abort path really has control of the port with which it is associated. This prevents starting hard resets at incorrect times and scheduling unnecessary LUN resets for SATA devices. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams --- drivers/scsi/isci/port.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/scsi/isci/port.c') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index da0c4e1b9b30..2fb85bf75449 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -240,9 +240,32 @@ static void isci_port_link_down(struct isci_host *isci_host, struct isci_phy *isci_phy, struct isci_port *isci_port) { + struct isci_remote_device *isci_device; + dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p\n", __func__, isci_port); + if (isci_port) { + + /* check to see if this is the last phy on this port. */ + if (isci_phy->sas_phy.port && + isci_phy->sas_phy.port->num_phys == 1) { + /* change the state for all devices on this port. The + * next task sent to this device will be returned as + * SAS_TASK_UNDELIVERED, and the scsi mid layer will + * remove the target + */ + list_for_each_entry(isci_device, + &isci_port->remote_dev_list, + node) { + dev_dbg(&isci_host->pdev->dev, + "%s: isci_device = %p\n", + __func__, isci_device); + set_bit(IDEV_GONE, &isci_device->flags); + } + } + } + /* Notify libsas of the borken link, this will trigger calls to our * isci_port_deformed and isci_dev_gone functions. */ -- cgit v1.2.1