diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-18 15:35:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-18 15:35:17 -0500 |
commit | d71f5be276bf79eda14c40f3cafcf827326f10cb (patch) | |
tree | 581dadb90b06b950882a8eb75deee23d3370a4ab /drivers/scsi/isci/port.c | |
parent | 92b5abbb44e05cdbc4483219f30a435dd871a8ea (diff) | |
parent | 76ffe8a3f766358a0ade543153625b3e4e66159d (diff) |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
SCSI updates on 20120118
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (49 commits)
[SCSI] libfc: remove redundant timer init for fcp
[SCSI] fcoe: Move fcoe_debug_logging from fcoe.h to fcoe.c
[SCSI] libfc: Declare local functions static
[SCSI] fcoe: fix regression on offload em matching function for initiator/target
[SCSI] qla4xxx: Update driver version to 5.02.00-k12
[SCSI] qla4xxx: Cleanup modinfo display
[SCSI] qla4xxx: Update license
[SCSI] qla4xxx: Clear the RISC interrupt bit during FW init
[SCSI] qla4xxx: Added error logging for firmware abort
[SCSI] qla4xxx: Disable generating pause frames in case of FW hung
[SCSI] qla4xxx: Temperature monitoring for ISP82XX core.
[SCSI] megaraid: fix sparse warnings
[SCSI] sg: convert to kstrtoul_from_user()
[SCSI] don't change sdev starvation list order without request dispatched
[SCSI] isci: fix, prevent port from getting stuck in the 'configuring' state
[SCSI] isci: fix start OOB
[SCSI] isci: fix io failures while wide port links are coming up
[SCSI] isci: allow more time for wide port targets
[SCSI] isci: enable wide port targets
[SCSI] isci: Fix IO fails when pull cable from phy in x4 wideport in MPC mode.
...
Diffstat (limited to 'drivers/scsi/isci/port.c')
-rw-r--r-- | drivers/scsi/isci/port.c | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index ac7f27749f97..7c6ac58a5c4c 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c | |||
@@ -114,7 +114,7 @@ static u32 sci_port_get_phys(struct isci_port *iport) | |||
114 | * value is returned if the specified port is not valid. When this value is | 114 | * value is returned if the specified port is not valid. When this value is |
115 | * returned, no data is copied to the properties output parameter. | 115 | * returned, no data is copied to the properties output parameter. |
116 | */ | 116 | */ |
117 | static enum sci_status sci_port_get_properties(struct isci_port *iport, | 117 | enum sci_status sci_port_get_properties(struct isci_port *iport, |
118 | struct sci_port_properties *prop) | 118 | struct sci_port_properties *prop) |
119 | { | 119 | { |
120 | if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT) | 120 | if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT) |
@@ -647,19 +647,26 @@ void sci_port_setup_transports(struct isci_port *iport, u32 device_id) | |||
647 | } | 647 | } |
648 | } | 648 | } |
649 | 649 | ||
650 | static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy, | 650 | static 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 | |||
656 | static 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,14 +676,19 @@ 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 | ||
675 | iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; | 683 | iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; |
676 | 684 | ||
677 | /* Re-assign the phy back to the LP as if it were a narrow port */ | 685 | /* Re-assign the phy back to the LP as if it were a narrow port for APC |
678 | writel(iphy->phy_index, | 686 | * mode. For MPC mode, the phy will remain in the port. |
679 | &iport->port_pe_configuration_register[iphy->phy_index]); | 687 | */ |
688 | if (iport->owning_controller->oem_parameters.controller.mode_type == | ||
689 | SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) | ||
690 | writel(iphy->phy_index, | ||
691 | &iport->port_pe_configuration_register[iphy->phy_index]); | ||
680 | 692 | ||
681 | if (do_notify_user == true) | 693 | if (do_notify_user == true) |
682 | isci_port_link_down(ihost, iphy, iport); | 694 | isci_port_link_down(ihost, iphy, iport); |
@@ -701,18 +713,16 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i | |||
701 | * 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? |
702 | * @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. |
703 | * @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. |
704 | * @do_notify_user: This parameter specifies whether to inform the user (via | 716 | * @flags: PF_RESUME, PF_NOTIFY to sci_port_activate_phy |
705 | * sci_port_link_up()) as to the fact that a new phy as become ready. | ||
706 | * | 717 | * |
707 | * Determine if this phy can be assigned to this | 718 | * Determine if this phy can be assigned to this port . If the phy is |
708 | * 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. |
709 | * 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 |
710 | * 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. |
711 | * the same port. none | ||
712 | */ | 722 | */ |
713 | static void sci_port_general_link_up_handler(struct isci_port *iport, | 723 | static void sci_port_general_link_up_handler(struct isci_port *iport, |
714 | struct isci_phy *iphy, | 724 | struct isci_phy *iphy, |
715 | bool do_notify_user) | 725 | u8 flags) |
716 | { | 726 | { |
717 | struct sci_sas_address port_sas_address; | 727 | struct sci_sas_address port_sas_address; |
718 | struct sci_sas_address phy_sas_address; | 728 | struct sci_sas_address phy_sas_address; |
@@ -730,7 +740,7 @@ static void sci_port_general_link_up_handler(struct isci_port *iport, | |||
730 | iport->active_phy_mask == 0) { | 740 | iport->active_phy_mask == 0) { |
731 | struct sci_base_state_machine *sm = &iport->sm; | 741 | struct sci_base_state_machine *sm = &iport->sm; |
732 | 742 | ||
733 | sci_port_activate_phy(iport, iphy, do_notify_user); | 743 | sci_port_activate_phy(iport, iphy, flags); |
734 | if (sm->current_state_id == SCI_PORT_RESETTING) | 744 | if (sm->current_state_id == SCI_PORT_RESETTING) |
735 | port_state_machine_change(iport, SCI_PORT_READY); | 745 | port_state_machine_change(iport, SCI_PORT_READY); |
736 | } else | 746 | } else |
@@ -781,11 +791,16 @@ bool sci_port_link_detected( | |||
781 | struct isci_phy *iphy) | 791 | struct isci_phy *iphy) |
782 | { | 792 | { |
783 | if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) && | 793 | if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) && |
784 | (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && | 794 | (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) { |
785 | sci_port_is_wide(iport)) { | 795 | if (sci_port_is_wide(iport)) { |
786 | sci_port_invalid_link_up(iport, iphy); | 796 | sci_port_invalid_link_up(iport, iphy); |
787 | 797 | return false; | |
788 | 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 | } | ||
789 | } | 804 | } |
790 | 805 | ||
791 | return true; | 806 | return true; |
@@ -975,6 +990,13 @@ static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine | |||
975 | } | 990 | } |
976 | } | 991 | } |
977 | 992 | ||
993 | static 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 | |||
978 | static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) | 1000 | static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) |
979 | { | 1001 | { |
980 | u32 index; | 1002 | u32 index; |
@@ -988,13 +1010,13 @@ static void sci_port_ready_substate_operational_enter(struct sci_base_state_mach | |||
988 | writel(iport->physical_port_index, | 1010 | writel(iport->physical_port_index, |
989 | &iport->port_pe_configuration_register[ | 1011 | &iport->port_pe_configuration_register[ |
990 | 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]); | ||
991 | } | 1015 | } |
992 | } | 1016 | } |
993 | 1017 | ||
994 | sci_port_update_viit_entry(iport); | 1018 | sci_port_update_viit_entry(iport); |
995 | 1019 | ||
996 | sci_port_resume_port_task_scheduler(iport); | ||
997 | |||
998 | /* | 1020 | /* |
999 | * 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 |
1000 | * io correctly | 1022 | * io correctly |
@@ -1061,20 +1083,9 @@ static void sci_port_ready_substate_configuring_enter(struct sci_base_state_mach | |||
1061 | if (iport->active_phy_mask == 0) { | 1083 | if (iport->active_phy_mask == 0) { |
1062 | isci_port_not_ready(ihost, iport); | 1084 | isci_port_not_ready(ihost, iport); |
1063 | 1085 | ||
1064 | port_state_machine_change(iport, | 1086 | port_state_machine_change(iport, SCI_PORT_SUB_WAITING); |
1065 | SCI_PORT_SUB_WAITING); | 1087 | } else |
1066 | } else if (iport->started_request_count == 0) | 1088 | port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); |
1067 | port_state_machine_change(iport, | ||
1068 | SCI_PORT_SUB_OPERATIONAL); | ||
1069 | } | ||
1070 | |||
1071 | static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm) | ||
1072 | { | ||
1073 | struct isci_port *iport = container_of(sm, typeof(*iport), sm); | ||
1074 | |||
1075 | sci_port_suspend_port_task_scheduler(iport); | ||
1076 | if (iport->ready_exit) | ||
1077 | sci_port_invalidate_dummy_remote_node(iport); | ||
1078 | } | 1089 | } |
1079 | 1090 | ||
1080 | enum sci_status sci_port_start(struct isci_port *iport) | 1091 | enum sci_status sci_port_start(struct isci_port *iport) |
@@ -1252,7 +1263,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport, | |||
1252 | if (status != SCI_SUCCESS) | 1263 | if (status != SCI_SUCCESS) |
1253 | return status; | 1264 | return status; |
1254 | 1265 | ||
1255 | sci_port_general_link_up_handler(iport, iphy, true); | 1266 | sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME); |
1256 | iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; | 1267 | iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; |
1257 | port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); | 1268 | port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); |
1258 | 1269 | ||
@@ -1262,7 +1273,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport, | |||
1262 | 1273 | ||
1263 | if (status != SCI_SUCCESS) | 1274 | if (status != SCI_SUCCESS) |
1264 | return status; | 1275 | return status; |
1265 | sci_port_general_link_up_handler(iport, iphy, true); | 1276 | sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY); |
1266 | 1277 | ||
1267 | /* 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 |
1268 | * the port. | 1279 | * the port. |
@@ -1338,13 +1349,13 @@ enum sci_status sci_port_link_up(struct isci_port *iport, | |||
1338 | /* 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 |
1339 | * can just enable it and continue | 1350 | * can just enable it and continue |
1340 | */ | 1351 | */ |
1341 | sci_port_activate_phy(iport, iphy, true); | 1352 | sci_port_activate_phy(iport, iphy, PF_NOTIFY|PF_RESUME); |
1342 | 1353 | ||
1343 | port_state_machine_change(iport, | 1354 | port_state_machine_change(iport, |
1344 | SCI_PORT_SUB_OPERATIONAL); | 1355 | SCI_PORT_SUB_OPERATIONAL); |
1345 | return SCI_SUCCESS; | 1356 | return SCI_SUCCESS; |
1346 | case SCI_PORT_SUB_OPERATIONAL: | 1357 | case SCI_PORT_SUB_OPERATIONAL: |
1347 | sci_port_general_link_up_handler(iport, iphy, true); | 1358 | sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME); |
1348 | return SCI_SUCCESS; | 1359 | return SCI_SUCCESS; |
1349 | case SCI_PORT_RESETTING: | 1360 | case SCI_PORT_RESETTING: |
1350 | /* TODO We should make sure that the phy that has gone | 1361 | /* TODO We should make sure that the phy that has gone |
@@ -1361,7 +1372,7 @@ enum sci_status sci_port_link_up(struct isci_port *iport, | |||
1361 | /* In the resetting state we don't notify the user regarding | 1372 | /* In the resetting state we don't notify the user regarding |
1362 | * link up and link down notifications. | 1373 | * link up and link down notifications. |
1363 | */ | 1374 | */ |
1364 | sci_port_general_link_up_handler(iport, iphy, false); | 1375 | sci_port_general_link_up_handler(iport, iphy, PF_RESUME); |
1365 | return SCI_SUCCESS; | 1376 | return SCI_SUCCESS; |
1366 | default: | 1377 | default: |
1367 | dev_warn(sciport_to_dev(iport), | 1378 | dev_warn(sciport_to_dev(iport), |
@@ -1584,14 +1595,14 @@ static const struct sci_base_state sci_port_state_table[] = { | |||
1584 | }, | 1595 | }, |
1585 | [SCI_PORT_SUB_WAITING] = { | 1596 | [SCI_PORT_SUB_WAITING] = { |
1586 | .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, | ||
1587 | }, | 1599 | }, |
1588 | [SCI_PORT_SUB_OPERATIONAL] = { | 1600 | [SCI_PORT_SUB_OPERATIONAL] = { |
1589 | .enter_state = sci_port_ready_substate_operational_enter, | 1601 | .enter_state = sci_port_ready_substate_operational_enter, |
1590 | .exit_state = sci_port_ready_substate_operational_exit | 1602 | .exit_state = sci_port_ready_substate_operational_exit |
1591 | }, | 1603 | }, |
1592 | [SCI_PORT_SUB_CONFIGURING] = { | 1604 | [SCI_PORT_SUB_CONFIGURING] = { |
1593 | .enter_state = sci_port_ready_substate_configuring_enter, | 1605 | .enter_state = sci_port_ready_substate_configuring_enter |
1594 | .exit_state = sci_port_ready_substate_configuring_exit | ||
1595 | }, | 1606 | }, |
1596 | [SCI_PORT_RESETTING] = { | 1607 | [SCI_PORT_RESETTING] = { |
1597 | .exit_state = sci_port_resetting_state_exit | 1608 | .exit_state = sci_port_resetting_state_exit |
@@ -1609,6 +1620,7 @@ void sci_port_construct(struct isci_port *iport, u8 index, | |||
1609 | iport->logical_port_index = SCIC_SDS_DUMMY_PORT; | 1620 | iport->logical_port_index = SCIC_SDS_DUMMY_PORT; |
1610 | iport->physical_port_index = index; | 1621 | iport->physical_port_index = index; |
1611 | iport->active_phy_mask = 0; | 1622 | iport->active_phy_mask = 0; |
1623 | iport->enabled_phy_mask = 0; | ||
1612 | iport->last_active_phy = 0; | 1624 | iport->last_active_phy = 0; |
1613 | iport->ready_exit = false; | 1625 | iport->ready_exit = false; |
1614 | 1626 | ||