aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/port.c
diff options
context:
space:
mode:
authorMarcin Tomczak <marcin.tomczak@intel.com>2012-01-04 04:33:41 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-01-16 02:48:02 -0500
commit05b080fc933bb068b32fa119db00e8efcc10e3bd (patch)
tree8442420c0733da0a9c1d7b85828e4e297d0163c0 /drivers/scsi/isci/port.c
parent0953dbea1d9a84c8443b5f5bb45229a6c9d7f9f3 (diff)
[SCSI] isci: fix, prevent port from getting stuck in the 'configuring' state
When expander connected in x2 or x4 mode and with IO runnning, if a cable from wideport is plugged out from the phy, IO's start failing on all the targets. Observed that when cable is pulled with IO running, cominit is happening on all the links and IO's start dropping to 0 and eventually the whole IO fails. Second observation, target is trying to open and SCU is responding with "Open reject no destination". A cause of the problem is when the port went from the "ready configuring substate" back to "ready configuring substate" as a result of phy being pulled off, scic suspended the port task scheduler register. As a result no IO was allowed and in the "substate configuring enter" routine the IO never goes back to 0. As a result the port never comes out of "ready substate configuring". The patch adds a mechanism of activate and deactivate phy when a port link up, which fixes the problem. Signed-off-by: Bartek Nowakowski <bartek.nowakowski@intel.com> Signed-off-by: Maciej Trela <maciej.trela@intel.com> Signed-off-by: Marcin Tomczak <marcin.tomczak@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/isci/port.c')
-rw-r--r--drivers/scsi/isci/port.c92
1 files changed, 50 insertions, 42 deletions
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 49e8a72d1c5b..7c6ac58a5c4c 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -647,19 +647,26 @@ void sci_port_setup_transports(struct isci_port *iport, u32 device_id)
647 } 647 }
648} 648}
649 649
650static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy, 650static void sci_port_resume_phy(struct isci_port *iport, struct isci_phy *iphy)
651 bool do_notify_user) 651{
652 sci_phy_resume(iphy);
653 iport->enabled_phy_mask |= 1 << iphy->phy_index;
654}
655
656static void sci_port_activate_phy(struct isci_port *iport,
657 struct isci_phy *iphy,
658 u8 flags)
652{ 659{
653 struct isci_host *ihost = iport->owning_controller; 660 struct isci_host *ihost = iport->owning_controller;
654 661
655 if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) 662 if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA && (flags & PF_RESUME))
656 sci_phy_resume(iphy); 663 sci_phy_resume(iphy);
657 664
658 iport->active_phy_mask |= 1 << iphy->phy_index; 665 iport->active_phy_mask |= 1 << iphy->phy_index;
659 666
660 sci_controller_clear_invalid_phy(ihost, iphy); 667 sci_controller_clear_invalid_phy(ihost, iphy);
661 668
662 if (do_notify_user == true) 669 if (flags & PF_NOTIFY)
663 isci_port_link_up(ihost, iport, iphy); 670 isci_port_link_up(ihost, iport, iphy);
664} 671}
665 672
@@ -669,6 +676,7 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
669 struct isci_host *ihost = iport->owning_controller; 676 struct isci_host *ihost = iport->owning_controller;
670 677
671 iport->active_phy_mask &= ~(1 << iphy->phy_index); 678 iport->active_phy_mask &= ~(1 << iphy->phy_index);
679 iport->enabled_phy_mask &= ~(1 << iphy->phy_index);
672 if (!iport->active_phy_mask) 680 if (!iport->active_phy_mask)
673 iport->last_active_phy = iphy->phy_index; 681 iport->last_active_phy = iphy->phy_index;
674 682
@@ -705,18 +713,16 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
705 * sci_port_general_link_up_handler - phy can be assigned to port? 713 * sci_port_general_link_up_handler - phy can be assigned to port?
706 * @sci_port: sci_port object for which has a phy that has gone link up. 714 * @sci_port: sci_port object for which has a phy that has gone link up.
707 * @sci_phy: This is the struct isci_phy object that has gone link up. 715 * @sci_phy: This is the struct isci_phy object that has gone link up.
708 * @do_notify_user: This parameter specifies whether to inform the user (via 716 * @flags: PF_RESUME, PF_NOTIFY to sci_port_activate_phy
709 * sci_port_link_up()) as to the fact that a new phy as become ready.
710 * 717 *
711 * Determine if this phy can be assigned to this 718 * Determine if this phy can be assigned to this port . If the phy is
712 * port . If the phy is not a valid PHY for 719 * not a valid PHY for this port then the function will notify the user.
713 * this port then the function will notify the user. A PHY can only be 720 * A PHY can only be part of a port if it's attached SAS ADDRESS is the
714 * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in 721 * same as all other PHYs in the same port.
715 * the same port. none
716 */ 722 */
717static void sci_port_general_link_up_handler(struct isci_port *iport, 723static void sci_port_general_link_up_handler(struct isci_port *iport,
718 struct isci_phy *iphy, 724 struct isci_phy *iphy,
719 bool do_notify_user) 725 u8 flags)
720{ 726{
721 struct sci_sas_address port_sas_address; 727 struct sci_sas_address port_sas_address;
722 struct sci_sas_address phy_sas_address; 728 struct sci_sas_address phy_sas_address;
@@ -734,7 +740,7 @@ static void sci_port_general_link_up_handler(struct isci_port *iport,
734 iport->active_phy_mask == 0) { 740 iport->active_phy_mask == 0) {
735 struct sci_base_state_machine *sm = &iport->sm; 741 struct sci_base_state_machine *sm = &iport->sm;
736 742
737 sci_port_activate_phy(iport, iphy, do_notify_user); 743 sci_port_activate_phy(iport, iphy, flags);
738 if (sm->current_state_id == SCI_PORT_RESETTING) 744 if (sm->current_state_id == SCI_PORT_RESETTING)
739 port_state_machine_change(iport, SCI_PORT_READY); 745 port_state_machine_change(iport, SCI_PORT_READY);
740 } else 746 } else
@@ -785,11 +791,16 @@ bool sci_port_link_detected(
785 struct isci_phy *iphy) 791 struct isci_phy *iphy)
786{ 792{
787 if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) && 793 if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
788 (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && 794 (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) {
789 sci_port_is_wide(iport)) { 795 if (sci_port_is_wide(iport)) {
790 sci_port_invalid_link_up(iport, iphy); 796 sci_port_invalid_link_up(iport, iphy);
791 797 return false;
792 return false; 798 } else {
799 struct isci_host *ihost = iport->owning_controller;
800 struct isci_port *dst_port = &(ihost->ports[iphy->phy_index]);
801 writel(iphy->phy_index,
802 &dst_port->port_pe_configuration_register[iphy->phy_index]);
803 }
793 } 804 }
794 805
795 return true; 806 return true;
@@ -979,6 +990,13 @@ static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine
979 } 990 }
980} 991}
981 992
993static void scic_sds_port_ready_substate_waiting_exit(
994 struct sci_base_state_machine *sm)
995{
996 struct isci_port *iport = container_of(sm, typeof(*iport), sm);
997 sci_port_resume_port_task_scheduler(iport);
998}
999
982static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) 1000static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm)
983{ 1001{
984 u32 index; 1002 u32 index;
@@ -992,13 +1010,13 @@ static void sci_port_ready_substate_operational_enter(struct sci_base_state_mach
992 writel(iport->physical_port_index, 1010 writel(iport->physical_port_index,
993 &iport->port_pe_configuration_register[ 1011 &iport->port_pe_configuration_register[
994 iport->phy_table[index]->phy_index]); 1012 iport->phy_table[index]->phy_index]);
1013 if (((iport->active_phy_mask^iport->enabled_phy_mask) & (1 << index)) != 0)
1014 sci_port_resume_phy(iport, iport->phy_table[index]);
995 } 1015 }
996 } 1016 }
997 1017
998 sci_port_update_viit_entry(iport); 1018 sci_port_update_viit_entry(iport);
999 1019
1000 sci_port_resume_port_task_scheduler(iport);
1001
1002 /* 1020 /*
1003 * Post the dummy task for the port so the hardware can schedule 1021 * Post the dummy task for the port so the hardware can schedule
1004 * io correctly 1022 * io correctly
@@ -1065,20 +1083,9 @@ static void sci_port_ready_substate_configuring_enter(struct sci_base_state_mach
1065 if (iport->active_phy_mask == 0) { 1083 if (iport->active_phy_mask == 0) {
1066 isci_port_not_ready(ihost, iport); 1084 isci_port_not_ready(ihost, iport);
1067 1085
1068 port_state_machine_change(iport, 1086 port_state_machine_change(iport, SCI_PORT_SUB_WAITING);
1069 SCI_PORT_SUB_WAITING); 1087 } else
1070 } else if (iport->started_request_count == 0) 1088 port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL);
1071 port_state_machine_change(iport,
1072 SCI_PORT_SUB_OPERATIONAL);
1073}
1074
1075static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm)
1076{
1077 struct isci_port *iport = container_of(sm, typeof(*iport), sm);
1078
1079 sci_port_suspend_port_task_scheduler(iport);
1080 if (iport->ready_exit)
1081 sci_port_invalidate_dummy_remote_node(iport);
1082} 1089}
1083 1090
1084enum sci_status sci_port_start(struct isci_port *iport) 1091enum sci_status sci_port_start(struct isci_port *iport)
@@ -1256,7 +1263,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
1256 if (status != SCI_SUCCESS) 1263 if (status != SCI_SUCCESS)
1257 return status; 1264 return status;
1258 1265
1259 sci_port_general_link_up_handler(iport, iphy, true); 1266 sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
1260 iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; 1267 iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
1261 port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); 1268 port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING);
1262 1269
@@ -1266,7 +1273,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
1266 1273
1267 if (status != SCI_SUCCESS) 1274 if (status != SCI_SUCCESS)
1268 return status; 1275 return status;
1269 sci_port_general_link_up_handler(iport, iphy, true); 1276 sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY);
1270 1277
1271 /* Re-enter the configuring state since this may be the last phy in 1278 /* Re-enter the configuring state since this may be the last phy in
1272 * the port. 1279 * the port.
@@ -1342,13 +1349,13 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
1342 /* Since this is the first phy going link up for the port we 1349 /* Since this is the first phy going link up for the port we
1343 * can just enable it and continue 1350 * can just enable it and continue
1344 */ 1351 */
1345 sci_port_activate_phy(iport, iphy, true); 1352 sci_port_activate_phy(iport, iphy, PF_NOTIFY|PF_RESUME);
1346 1353
1347 port_state_machine_change(iport, 1354 port_state_machine_change(iport,
1348 SCI_PORT_SUB_OPERATIONAL); 1355 SCI_PORT_SUB_OPERATIONAL);
1349 return SCI_SUCCESS; 1356 return SCI_SUCCESS;
1350 case SCI_PORT_SUB_OPERATIONAL: 1357 case SCI_PORT_SUB_OPERATIONAL:
1351 sci_port_general_link_up_handler(iport, iphy, true); 1358 sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
1352 return SCI_SUCCESS; 1359 return SCI_SUCCESS;
1353 case SCI_PORT_RESETTING: 1360 case SCI_PORT_RESETTING:
1354 /* TODO We should make sure that the phy that has gone 1361 /* TODO We should make sure that the phy that has gone
@@ -1365,7 +1372,7 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
1365 /* In the resetting state we don't notify the user regarding 1372 /* In the resetting state we don't notify the user regarding
1366 * link up and link down notifications. 1373 * link up and link down notifications.
1367 */ 1374 */
1368 sci_port_general_link_up_handler(iport, iphy, false); 1375 sci_port_general_link_up_handler(iport, iphy, PF_RESUME);
1369 return SCI_SUCCESS; 1376 return SCI_SUCCESS;
1370 default: 1377 default:
1371 dev_warn(sciport_to_dev(iport), 1378 dev_warn(sciport_to_dev(iport),
@@ -1588,14 +1595,14 @@ static const struct sci_base_state sci_port_state_table[] = {
1588 }, 1595 },
1589 [SCI_PORT_SUB_WAITING] = { 1596 [SCI_PORT_SUB_WAITING] = {
1590 .enter_state = sci_port_ready_substate_waiting_enter, 1597 .enter_state = sci_port_ready_substate_waiting_enter,
1598 .exit_state = scic_sds_port_ready_substate_waiting_exit,
1591 }, 1599 },
1592 [SCI_PORT_SUB_OPERATIONAL] = { 1600 [SCI_PORT_SUB_OPERATIONAL] = {
1593 .enter_state = sci_port_ready_substate_operational_enter, 1601 .enter_state = sci_port_ready_substate_operational_enter,
1594 .exit_state = sci_port_ready_substate_operational_exit 1602 .exit_state = sci_port_ready_substate_operational_exit
1595 }, 1603 },
1596 [SCI_PORT_SUB_CONFIGURING] = { 1604 [SCI_PORT_SUB_CONFIGURING] = {
1597 .enter_state = sci_port_ready_substate_configuring_enter, 1605 .enter_state = sci_port_ready_substate_configuring_enter
1598 .exit_state = sci_port_ready_substate_configuring_exit
1599 }, 1606 },
1600 [SCI_PORT_RESETTING] = { 1607 [SCI_PORT_RESETTING] = {
1601 .exit_state = sci_port_resetting_state_exit 1608 .exit_state = sci_port_resetting_state_exit
@@ -1613,6 +1620,7 @@ void sci_port_construct(struct isci_port *iport, u8 index,
1613 iport->logical_port_index = SCIC_SDS_DUMMY_PORT; 1620 iport->logical_port_index = SCIC_SDS_DUMMY_PORT;
1614 iport->physical_port_index = index; 1621 iport->physical_port_index = index;
1615 iport->active_phy_mask = 0; 1622 iport->active_phy_mask = 0;
1623 iport->enabled_phy_mask = 0;
1616 iport->last_active_phy = 0; 1624 iport->last_active_phy = 0;
1617 iport->ready_exit = false; 1625 iport->ready_exit = false;
1618 1626