diff options
Diffstat (limited to 'drivers/scsi/isci/port.c')
-rw-r--r-- | drivers/scsi/isci/port.c | 409 |
1 files changed, 189 insertions, 220 deletions
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index e386066825b2..2ea3d0fe091d 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c | |||
@@ -61,6 +61,8 @@ | |||
61 | #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) | 61 | #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) |
62 | #define SCU_DUMMY_INDEX (0xFFFF) | 62 | #define SCU_DUMMY_INDEX (0xFFFF) |
63 | 63 | ||
64 | static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[]; | ||
65 | |||
64 | static void isci_port_change_state(struct isci_port *iport, enum isci_status status) | 66 | static void isci_port_change_state(struct isci_port *iport, enum isci_status status) |
65 | { | 67 | { |
66 | unsigned long flags; | 68 | unsigned long flags; |
@@ -856,6 +858,40 @@ static void scic_sds_port_invalid_link_up(struct scic_sds_port *sci_port, | |||
856 | } | 858 | } |
857 | } | 859 | } |
858 | 860 | ||
861 | static bool is_port_ready_state(enum scic_sds_port_states state) | ||
862 | { | ||
863 | switch (state) { | ||
864 | case SCI_BASE_PORT_STATE_READY: | ||
865 | case SCIC_SDS_PORT_READY_SUBSTATE_WAITING: | ||
866 | case SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL: | ||
867 | case SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING: | ||
868 | return true; | ||
869 | default: | ||
870 | return false; | ||
871 | } | ||
872 | } | ||
873 | |||
874 | /* flag dummy rnc hanling when exiting a ready state */ | ||
875 | static void port_state_machine_change(struct scic_sds_port *sci_port, | ||
876 | enum scic_sds_port_states state) | ||
877 | { | ||
878 | struct sci_base_state_machine *sm = &sci_port->state_machine; | ||
879 | enum scic_sds_port_states old_state = sm->current_state_id; | ||
880 | |||
881 | if (is_port_ready_state(old_state) && !is_port_ready_state(state)) | ||
882 | sci_port->ready_exit = true; | ||
883 | |||
884 | sci_base_state_machine_change_state(sm, state); | ||
885 | sci_port->ready_exit = false; | ||
886 | } | ||
887 | |||
888 | static void port_state_machine_stop(struct scic_sds_port *sci_port) | ||
889 | { | ||
890 | sci_port->ready_exit = true; | ||
891 | sci_base_state_machine_stop(&sci_port->state_machine); | ||
892 | sci_port->ready_exit = false; | ||
893 | } | ||
894 | |||
859 | /** | 895 | /** |
860 | * scic_sds_port_general_link_up_handler - phy can be assigned to port? | 896 | * scic_sds_port_general_link_up_handler - phy can be assigned to port? |
861 | * @sci_port: scic_sds_port object for which has a phy that has gone link up. | 897 | * @sci_port: scic_sds_port object for which has a phy that has gone link up. |
@@ -891,7 +927,7 @@ static void scic_sds_port_general_link_up_handler(struct scic_sds_port *sci_port | |||
891 | 927 | ||
892 | scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); | 928 | scic_sds_port_activate_phy(sci_port, sci_phy, do_notify_user); |
893 | if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) | 929 | if (sm->current_state_id == SCI_BASE_PORT_STATE_RESETTING) |
894 | sci_base_state_machine_change_state(sm, SCI_BASE_PORT_STATE_READY); | 930 | port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_READY); |
895 | } else | 931 | } else |
896 | scic_sds_port_invalid_link_up(sci_port, sci_phy); | 932 | scic_sds_port_invalid_link_up(sci_port, sci_phy); |
897 | } | 933 | } |
@@ -1025,46 +1061,33 @@ static void scic_sds_port_timeout_handler(void *port) | |||
1025 | struct scic_sds_port *sci_port = port; | 1061 | struct scic_sds_port *sci_port = port; |
1026 | u32 current_state; | 1062 | u32 current_state; |
1027 | 1063 | ||
1028 | current_state = sci_base_state_machine_get_state( | 1064 | current_state = sci_base_state_machine_get_state(&sci_port->state_machine); |
1029 | &sci_port->state_machine); | ||
1030 | 1065 | ||
1031 | if (current_state == SCI_BASE_PORT_STATE_RESETTING) { | 1066 | if (current_state == SCI_BASE_PORT_STATE_RESETTING) { |
1032 | /* | 1067 | /* if the port is still in the resetting state then the timeout |
1033 | * if the port is still in the resetting state then the | 1068 | * fired before the reset completed. |
1034 | * timeout fired before the reset completed. | ||
1035 | */ | 1069 | */ |
1036 | sci_base_state_machine_change_state( | 1070 | port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_FAILED); |
1037 | &sci_port->state_machine, | ||
1038 | SCI_BASE_PORT_STATE_FAILED); | ||
1039 | } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { | 1071 | } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { |
1040 | /* | 1072 | /* if the port is stopped then the start request failed In this |
1041 | * if the port is stopped then the start request failed | 1073 | * case stay in the stopped state. |
1042 | * In this case stay in the stopped state. | ||
1043 | */ | 1074 | */ |
1044 | dev_err(sciport_to_dev(sci_port), | 1075 | dev_err(sciport_to_dev(sci_port), |
1045 | "%s: SCIC Port 0x%p failed to stop before tiemout.\n", | 1076 | "%s: SCIC Port 0x%p failed to stop before tiemout.\n", |
1046 | __func__, | 1077 | __func__, |
1047 | sci_port); | 1078 | sci_port); |
1048 | } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { | 1079 | } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { |
1049 | /* | 1080 | /* if the port is still stopping then the stop has not completed */ |
1050 | * if the port is still stopping then the stop has not | 1081 | isci_port_stop_complete(sci_port->owning_controller, |
1051 | * completed | 1082 | sci_port, |
1052 | */ | 1083 | SCI_FAILURE_TIMEOUT); |
1053 | isci_port_stop_complete( | ||
1054 | scic_sds_port_get_controller(sci_port), | ||
1055 | sci_port, | ||
1056 | SCI_FAILURE_TIMEOUT); | ||
1057 | } else { | 1084 | } else { |
1058 | /* | 1085 | /* The port is in the ready state and we have a timer |
1059 | * The port is in the ready state and we have a timer | ||
1060 | * reporting a timeout this should not happen. | 1086 | * reporting a timeout this should not happen. |
1061 | */ | 1087 | */ |
1062 | dev_err(sciport_to_dev(sci_port), | 1088 | dev_err(sciport_to_dev(sci_port), |
1063 | "%s: SCIC Port 0x%p is processing a timeout operation " | 1089 | "%s: SCIC Port 0x%p is processing a timeout operation " |
1064 | "in state %d.\n", | 1090 | "in state %d.\n", __func__, sci_port, current_state); |
1065 | __func__, | ||
1066 | sci_port, | ||
1067 | current_state); | ||
1068 | } | 1091 | } |
1069 | } | 1092 | } |
1070 | 1093 | ||
@@ -1160,14 +1183,9 @@ static void scic_port_enable_broadcast_change_notification(struct scic_sds_port | |||
1160 | * object. This function will transition the ready substate machine to its | 1183 | * object. This function will transition the ready substate machine to its |
1161 | * final state. enum sci_status SCI_SUCCESS | 1184 | * final state. enum sci_status SCI_SUCCESS |
1162 | */ | 1185 | */ |
1163 | static enum sci_status scic_sds_port_ready_substate_stop_handler( | 1186 | static enum sci_status scic_sds_port_ready_substate_stop_handler(struct scic_sds_port *sci_port) |
1164 | struct scic_sds_port *port) | ||
1165 | { | 1187 | { |
1166 | sci_base_state_machine_change_state( | 1188 | port_state_machine_change(sci_port, SCI_BASE_PORT_STATE_STOPPING); |
1167 | &port->state_machine, | ||
1168 | SCI_BASE_PORT_STATE_STOPPING | ||
1169 | ); | ||
1170 | |||
1171 | return SCI_SUCCESS; | 1189 | return SCI_SUCCESS; |
1172 | } | 1190 | } |
1173 | 1191 | ||
@@ -1186,48 +1204,40 @@ static enum sci_status scic_sds_port_ready_substate_complete_io_handler( | |||
1186 | return SCI_SUCCESS; | 1204 | return SCI_SUCCESS; |
1187 | } | 1205 | } |
1188 | 1206 | ||
1189 | static enum sci_status scic_sds_port_ready_substate_add_phy_handler( | 1207 | static enum sci_status scic_sds_port_ready_substate_add_phy_handler(struct scic_sds_port *sci_port, |
1190 | struct scic_sds_port *port, | 1208 | struct scic_sds_phy *sci_phy) |
1191 | struct scic_sds_phy *phy) | ||
1192 | { | 1209 | { |
1193 | enum sci_status status; | 1210 | enum sci_status status; |
1194 | 1211 | ||
1195 | status = scic_sds_port_set_phy(port, phy); | 1212 | status = scic_sds_port_set_phy(sci_port, sci_phy); |
1196 | 1213 | ||
1197 | if (status == SCI_SUCCESS) { | 1214 | if (status != SCI_SUCCESS) |
1198 | scic_sds_port_general_link_up_handler(port, phy, true); | 1215 | return status; |
1199 | |||
1200 | port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; | ||
1201 | 1216 | ||
1202 | sci_base_state_machine_change_state( | 1217 | scic_sds_port_general_link_up_handler(sci_port, sci_phy, true); |
1203 | &port->ready_substate_machine, | 1218 | sci_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; |
1204 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | 1219 | port_state_machine_change(sci_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); |
1205 | ); | ||
1206 | } | ||
1207 | 1220 | ||
1208 | return status; | 1221 | return status; |
1209 | } | 1222 | } |
1210 | 1223 | ||
1211 | 1224 | ||
1212 | static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( | 1225 | static enum sci_status scic_sds_port_ready_substate_remove_phy_handler(struct scic_sds_port *port, |
1213 | struct scic_sds_port *port, | 1226 | struct scic_sds_phy *phy) |
1214 | struct scic_sds_phy *phy) | ||
1215 | { | 1227 | { |
1216 | enum sci_status status; | 1228 | enum sci_status status; |
1217 | 1229 | ||
1218 | status = scic_sds_port_clear_phy(port, phy); | 1230 | status = scic_sds_port_clear_phy(port, phy); |
1219 | 1231 | ||
1220 | if (status == SCI_SUCCESS) { | 1232 | if (status != SCI_SUCCESS) |
1221 | scic_sds_port_deactivate_phy(port, phy, true); | 1233 | return status; |
1222 | 1234 | ||
1223 | port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; | 1235 | scic_sds_port_deactivate_phy(port, phy, true); |
1224 | 1236 | ||
1225 | sci_base_state_machine_change_state( | 1237 | port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; |
1226 | &port->ready_substate_machine, | ||
1227 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1228 | ); | ||
1229 | } | ||
1230 | 1238 | ||
1239 | port_state_machine_change(port, | ||
1240 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); | ||
1231 | return status; | 1241 | return status; |
1232 | } | 1242 | } |
1233 | 1243 | ||
@@ -1255,10 +1265,8 @@ static void scic_sds_port_ready_waiting_substate_link_up_handler( | |||
1255 | * it and continue. */ | 1265 | * it and continue. */ |
1256 | scic_sds_port_activate_phy(sci_port, sci_phy, true); | 1266 | scic_sds_port_activate_phy(sci_port, sci_phy, true); |
1257 | 1267 | ||
1258 | sci_base_state_machine_change_state( | 1268 | port_state_machine_change(sci_port, |
1259 | &sci_port->ready_substate_machine, | 1269 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); |
1260 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1261 | ); | ||
1262 | } | 1270 | } |
1263 | 1271 | ||
1264 | /* | 1272 | /* |
@@ -1317,9 +1325,8 @@ sci_status scic_sds_port_ready_operational_substate_reset_handler( | |||
1317 | port->not_ready_reason = | 1325 | port->not_ready_reason = |
1318 | SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; | 1326 | SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; |
1319 | 1327 | ||
1320 | sci_base_state_machine_change_state( | 1328 | port_state_machine_change(port, |
1321 | &port->state_machine, | 1329 | SCI_BASE_PORT_STATE_RESETTING); |
1322 | SCI_BASE_PORT_STATE_RESETTING); | ||
1323 | } | 1330 | } |
1324 | } | 1331 | } |
1325 | 1332 | ||
@@ -1365,8 +1372,8 @@ static void scic_sds_port_ready_operational_substate_link_down_handler( | |||
1365 | * the port to the WAITING state until such time as a phy goes | 1372 | * the port to the WAITING state until such time as a phy goes |
1366 | * link up. */ | 1373 | * link up. */ |
1367 | if (sci_port->active_phy_mask == 0) | 1374 | if (sci_port->active_phy_mask == 0) |
1368 | sci_base_state_machine_change_state(&sci_port->ready_substate_machine, | 1375 | port_state_machine_change(sci_port, |
1369 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING); | 1376 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING); |
1370 | } | 1377 | } |
1371 | 1378 | ||
1372 | /* | 1379 | /* |
@@ -1406,10 +1413,8 @@ static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( | |||
1406 | /* | 1413 | /* |
1407 | * Re-enter the configuring state since this may be the last phy in | 1414 | * Re-enter the configuring state since this may be the last phy in |
1408 | * the port. */ | 1415 | * the port. */ |
1409 | sci_base_state_machine_change_state( | 1416 | port_state_machine_change(port, |
1410 | &port->ready_substate_machine, | 1417 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); |
1411 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1412 | ); | ||
1413 | } | 1418 | } |
1414 | 1419 | ||
1415 | return status; | 1420 | return status; |
@@ -1427,17 +1432,15 @@ static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handl | |||
1427 | 1432 | ||
1428 | status = scic_sds_port_clear_phy(port, phy); | 1433 | status = scic_sds_port_clear_phy(port, phy); |
1429 | 1434 | ||
1430 | if (status == SCI_SUCCESS) { | 1435 | if (status != SCI_SUCCESS) |
1431 | scic_sds_port_deactivate_phy(port, phy, true); | 1436 | return status; |
1437 | scic_sds_port_deactivate_phy(port, phy, true); | ||
1432 | 1438 | ||
1433 | /* | 1439 | /* Re-enter the configuring state since this may be the last phy in |
1434 | * Re-enter the configuring state since this may be the last phy in | 1440 | * the port |
1435 | * the port. */ | 1441 | */ |
1436 | sci_base_state_machine_change_state( | 1442 | port_state_machine_change(port, |
1437 | &port->ready_substate_machine, | 1443 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); |
1438 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1439 | ); | ||
1440 | } | ||
1441 | 1444 | ||
1442 | return status; | 1445 | return status; |
1443 | } | 1446 | } |
@@ -1460,10 +1463,8 @@ scic_sds_port_ready_configuring_substate_complete_io_handler( | |||
1460 | scic_sds_port_decrement_request_count(port); | 1463 | scic_sds_port_decrement_request_count(port); |
1461 | 1464 | ||
1462 | if (port->started_request_count == 0) { | 1465 | if (port->started_request_count == 0) { |
1463 | sci_base_state_machine_change_state( | 1466 | port_state_machine_change(port, |
1464 | &port->ready_substate_machine, | 1467 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); |
1465 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1466 | ); | ||
1467 | } | 1468 | } |
1468 | 1469 | ||
1469 | return SCI_SUCCESS; | 1470 | return SCI_SUCCESS; |
@@ -1567,61 +1568,6 @@ static enum sci_status scic_sds_port_default_complete_io_handler(struct scic_sds | |||
1567 | return default_port_handler(sci_port, __func__); | 1568 | return default_port_handler(sci_port, __func__); |
1568 | } | 1569 | } |
1569 | 1570 | ||
1570 | static struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[] = { | ||
1571 | [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { | ||
1572 | .start_handler = scic_sds_port_default_start_handler, | ||
1573 | .stop_handler = scic_sds_port_ready_substate_stop_handler, | ||
1574 | .destruct_handler = scic_sds_port_default_destruct_handler, | ||
1575 | .reset_handler = scic_sds_port_default_reset_handler, | ||
1576 | .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, | ||
1577 | .remove_phy_handler = scic_sds_port_default_remove_phy_handler, | ||
1578 | .frame_handler = scic_sds_port_default_frame_handler, | ||
1579 | .event_handler = scic_sds_port_default_event_handler, | ||
1580 | .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, | ||
1581 | .link_down_handler = scic_sds_port_default_link_down_handler, | ||
1582 | .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, | ||
1583 | .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, | ||
1584 | }, | ||
1585 | [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { | ||
1586 | .start_handler = scic_sds_port_default_start_handler, | ||
1587 | .stop_handler = scic_sds_port_ready_substate_stop_handler, | ||
1588 | .destruct_handler = scic_sds_port_default_destruct_handler, | ||
1589 | .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, | ||
1590 | .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, | ||
1591 | .remove_phy_handler = scic_sds_port_ready_substate_remove_phy_handler, | ||
1592 | .frame_handler = scic_sds_port_default_frame_handler, | ||
1593 | .event_handler = scic_sds_port_default_event_handler, | ||
1594 | .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, | ||
1595 | .link_down_handler = scic_sds_port_ready_operational_substate_link_down_handler, | ||
1596 | .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, | ||
1597 | .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, | ||
1598 | }, | ||
1599 | [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { | ||
1600 | .start_handler = scic_sds_port_default_start_handler, | ||
1601 | .stop_handler = scic_sds_port_ready_substate_stop_handler, | ||
1602 | .destruct_handler = scic_sds_port_default_destruct_handler, | ||
1603 | .reset_handler = scic_sds_port_default_reset_handler, | ||
1604 | .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, | ||
1605 | .remove_phy_handler = scic_sds_port_ready_configuring_substate_remove_phy_handler, | ||
1606 | .frame_handler = scic_sds_port_default_frame_handler, | ||
1607 | .event_handler = scic_sds_port_default_event_handler, | ||
1608 | .link_up_handler = scic_sds_port_default_link_up_handler, | ||
1609 | .link_down_handler = scic_sds_port_default_link_down_handler, | ||
1610 | .start_io_handler = scic_sds_port_default_start_io_handler, | ||
1611 | .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler | ||
1612 | } | ||
1613 | }; | ||
1614 | |||
1615 | /** | ||
1616 | * scic_sds_port_set_ready_state_handlers() - | ||
1617 | * | ||
1618 | * This macro sets the port ready substate handlers. | ||
1619 | */ | ||
1620 | #define scic_sds_port_set_ready_state_handlers(port, state_id) \ | ||
1621 | scic_sds_port_set_state_handlers(\ | ||
1622 | port, &scic_sds_port_ready_substate_handler_table[(state_id)] \ | ||
1623 | ) | ||
1624 | |||
1625 | /* | 1571 | /* |
1626 | * ****************************************************************************** | 1572 | * ****************************************************************************** |
1627 | * * PORT STATE PRIVATE METHODS | 1573 | * * PORT STATE PRIVATE METHODS |
@@ -1729,7 +1675,7 @@ static void scic_sds_port_ready_substate_waiting_enter(void *object) | |||
1729 | { | 1675 | { |
1730 | struct scic_sds_port *sci_port = object; | 1676 | struct scic_sds_port *sci_port = object; |
1731 | 1677 | ||
1732 | scic_sds_port_set_ready_state_handlers( | 1678 | scic_sds_port_set_base_state_handlers( |
1733 | sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING | 1679 | sci_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING |
1734 | ); | 1680 | ); |
1735 | 1681 | ||
@@ -1739,10 +1685,8 @@ static void scic_sds_port_ready_substate_waiting_enter(void *object) | |||
1739 | 1685 | ||
1740 | if (sci_port->active_phy_mask != 0) { | 1686 | if (sci_port->active_phy_mask != 0) { |
1741 | /* At least one of the phys on the port is ready */ | 1687 | /* At least one of the phys on the port is ready */ |
1742 | sci_base_state_machine_change_state( | 1688 | port_state_machine_change(sci_port, |
1743 | &sci_port->ready_substate_machine, | 1689 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); |
1744 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1745 | ); | ||
1746 | } | 1690 | } |
1747 | } | 1691 | } |
1748 | 1692 | ||
@@ -1763,7 +1707,7 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) | |||
1763 | struct isci_host *ihost = scic_to_ihost(scic); | 1707 | struct isci_host *ihost = scic_to_ihost(scic); |
1764 | struct isci_port *iport = sci_port_to_iport(sci_port); | 1708 | struct isci_port *iport = sci_port_to_iport(sci_port); |
1765 | 1709 | ||
1766 | scic_sds_port_set_ready_state_handlers( | 1710 | scic_sds_port_set_base_state_handlers( |
1767 | sci_port, | 1711 | sci_port, |
1768 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); | 1712 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); |
1769 | 1713 | ||
@@ -1788,6 +1732,31 @@ static void scic_sds_port_ready_substate_operational_enter(void *object) | |||
1788 | scic_sds_port_post_dummy_request(sci_port); | 1732 | scic_sds_port_post_dummy_request(sci_port); |
1789 | } | 1733 | } |
1790 | 1734 | ||
1735 | static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) | ||
1736 | { | ||
1737 | struct scic_sds_controller *scic = sci_port->owning_controller; | ||
1738 | u8 phys_index = sci_port->physical_port_index; | ||
1739 | union scu_remote_node_context *rnc; | ||
1740 | u16 rni = sci_port->reserved_rni; | ||
1741 | u32 command; | ||
1742 | |||
1743 | rnc = &scic->remote_node_context_table[rni]; | ||
1744 | |||
1745 | rnc->ssp.is_valid = false; | ||
1746 | |||
1747 | /* ensure the preceding tc abort request has reached the | ||
1748 | * controller and give it ample time to act before posting the rnc | ||
1749 | * invalidate | ||
1750 | */ | ||
1751 | readl(&scic->smu_registers->interrupt_status); /* flush */ | ||
1752 | udelay(10); | ||
1753 | |||
1754 | command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | | ||
1755 | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; | ||
1756 | |||
1757 | scic_sds_controller_post_request(scic, command); | ||
1758 | } | ||
1759 | |||
1791 | /** | 1760 | /** |
1792 | * | 1761 | * |
1793 | * @object: This is the object which is cast to a struct scic_sds_port object. | 1762 | * @object: This is the object which is cast to a struct scic_sds_port object. |
@@ -1811,6 +1780,9 @@ static void scic_sds_port_ready_substate_operational_exit(void *object) | |||
1811 | scic_sds_port_abort_dummy_request(sci_port); | 1780 | scic_sds_port_abort_dummy_request(sci_port); |
1812 | 1781 | ||
1813 | isci_port_not_ready(ihost, iport); | 1782 | isci_port_not_ready(ihost, iport); |
1783 | |||
1784 | if (sci_port->ready_exit) | ||
1785 | scic_sds_port_invalidate_dummy_remote_node(sci_port); | ||
1814 | } | 1786 | } |
1815 | 1787 | ||
1816 | /* | 1788 | /* |
@@ -1833,20 +1805,18 @@ static void scic_sds_port_ready_substate_configuring_enter(void *object) | |||
1833 | struct isci_host *ihost = scic_to_ihost(scic); | 1805 | struct isci_host *ihost = scic_to_ihost(scic); |
1834 | struct isci_port *iport = sci_port_to_iport(sci_port); | 1806 | struct isci_port *iport = sci_port_to_iport(sci_port); |
1835 | 1807 | ||
1836 | scic_sds_port_set_ready_state_handlers( | 1808 | scic_sds_port_set_base_state_handlers( |
1837 | sci_port, | 1809 | sci_port, |
1838 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); | 1810 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING); |
1839 | 1811 | ||
1840 | if (sci_port->active_phy_mask == 0) { | 1812 | if (sci_port->active_phy_mask == 0) { |
1841 | isci_port_not_ready(ihost, iport); | 1813 | isci_port_not_ready(ihost, iport); |
1842 | 1814 | ||
1843 | sci_base_state_machine_change_state( | 1815 | port_state_machine_change(sci_port, |
1844 | &sci_port->ready_substate_machine, | 1816 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING); |
1845 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING); | ||
1846 | } else if (sci_port->started_request_count == 0) | 1817 | } else if (sci_port->started_request_count == 0) |
1847 | sci_base_state_machine_change_state( | 1818 | port_state_machine_change(sci_port, |
1848 | &sci_port->ready_substate_machine, | 1819 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); |
1849 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL); | ||
1850 | } | 1820 | } |
1851 | 1821 | ||
1852 | static void scic_sds_port_ready_substate_configuring_exit(void *object) | 1822 | static void scic_sds_port_ready_substate_configuring_exit(void *object) |
@@ -1854,24 +1824,12 @@ static void scic_sds_port_ready_substate_configuring_exit(void *object) | |||
1854 | struct scic_sds_port *sci_port = object; | 1824 | struct scic_sds_port *sci_port = object; |
1855 | 1825 | ||
1856 | scic_sds_port_suspend_port_task_scheduler(sci_port); | 1826 | scic_sds_port_suspend_port_task_scheduler(sci_port); |
1827 | if (sci_port->ready_exit) | ||
1828 | scic_sds_port_invalidate_dummy_remote_node(sci_port); | ||
1857 | } | 1829 | } |
1858 | 1830 | ||
1859 | /* --------------------------------------------------------------------------- */ | 1831 | /* --------------------------------------------------------------------------- */ |
1860 | 1832 | ||
1861 | static const struct sci_base_state scic_sds_port_ready_substate_table[] = { | ||
1862 | [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { | ||
1863 | .enter_state = scic_sds_port_ready_substate_waiting_enter, | ||
1864 | }, | ||
1865 | [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { | ||
1866 | .enter_state = scic_sds_port_ready_substate_operational_enter, | ||
1867 | .exit_state = scic_sds_port_ready_substate_operational_exit | ||
1868 | }, | ||
1869 | [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { | ||
1870 | .enter_state = scic_sds_port_ready_substate_configuring_enter, | ||
1871 | .exit_state = scic_sds_port_ready_substate_configuring_exit | ||
1872 | }, | ||
1873 | }; | ||
1874 | |||
1875 | /** | 1833 | /** |
1876 | * | 1834 | * |
1877 | * @port: This is the struct scic_sds_port object on which the io request count will | 1835 | * @port: This is the struct scic_sds_port object on which the io request count will |
@@ -1970,9 +1928,8 @@ scic_sds_port_stopped_state_start_handler(struct scic_sds_port *sci_port) | |||
1970 | * silicon. | 1928 | * silicon. |
1971 | */ | 1929 | */ |
1972 | if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { | 1930 | if (scic_sds_port_is_phy_mask_valid(sci_port, phy_mask) == true) { |
1973 | sci_base_state_machine_change_state( | 1931 | port_state_machine_change(sci_port, |
1974 | &sci_port->state_machine, | 1932 | SCI_BASE_PORT_STATE_READY); |
1975 | SCI_BASE_PORT_STATE_READY); | ||
1976 | 1933 | ||
1977 | return SCI_SUCCESS; | 1934 | return SCI_SUCCESS; |
1978 | } else | 1935 | } else |
@@ -2003,10 +1960,9 @@ static enum sci_status scic_sds_port_stopped_state_stop_handler( | |||
2003 | * struct scic_sds_port can be destroyed. This function causes the port object to | 1960 | * struct scic_sds_port can be destroyed. This function causes the port object to |
2004 | * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS | 1961 | * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS |
2005 | */ | 1962 | */ |
2006 | static enum sci_status scic_sds_port_stopped_state_destruct_handler( | 1963 | static enum sci_status scic_sds_port_stopped_state_destruct_handler(struct scic_sds_port *port) |
2007 | struct scic_sds_port *port) | ||
2008 | { | 1964 | { |
2009 | sci_base_state_machine_stop(&port->state_machine); | 1965 | port_state_machine_stop(port); |
2010 | 1966 | ||
2011 | return SCI_SUCCESS; | 1967 | return SCI_SUCCESS; |
2012 | } | 1968 | } |
@@ -2087,10 +2043,9 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( | |||
2087 | { | 2043 | { |
2088 | scic_sds_port_decrement_request_count(sci_port); | 2044 | scic_sds_port_decrement_request_count(sci_port); |
2089 | 2045 | ||
2090 | if (sci_port->started_request_count == 0) { | 2046 | if (sci_port->started_request_count == 0) |
2091 | sci_base_state_machine_change_state(&sci_port->state_machine, | 2047 | port_state_machine_change(sci_port, |
2092 | SCI_BASE_PORT_STATE_STOPPED); | 2048 | SCI_BASE_PORT_STATE_STOPPED); |
2093 | } | ||
2094 | 2049 | ||
2095 | return SCI_SUCCESS; | 2050 | return SCI_SUCCESS; |
2096 | } | 2051 | } |
@@ -2110,10 +2065,8 @@ static enum sci_status scic_sds_port_stopping_state_complete_io_handler( | |||
2110 | static enum sci_status scic_sds_port_reset_state_stop_handler( | 2065 | static enum sci_status scic_sds_port_reset_state_stop_handler( |
2111 | struct scic_sds_port *port) | 2066 | struct scic_sds_port *port) |
2112 | { | 2067 | { |
2113 | sci_base_state_machine_change_state( | 2068 | port_state_machine_change(port, |
2114 | &port->state_machine, | 2069 | SCI_BASE_PORT_STATE_STOPPING); |
2115 | SCI_BASE_PORT_STATE_STOPPING | ||
2116 | ); | ||
2117 | 2070 | ||
2118 | return SCI_SUCCESS; | 2071 | return SCI_SUCCESS; |
2119 | } | 2072 | } |
@@ -2201,6 +2154,48 @@ static struct scic_sds_port_state_handler scic_sds_port_state_handler_table[] = | |||
2201 | .start_io_handler = scic_sds_port_default_start_io_handler, | 2154 | .start_io_handler = scic_sds_port_default_start_io_handler, |
2202 | .complete_io_handler = scic_sds_port_general_complete_io_handler | 2155 | .complete_io_handler = scic_sds_port_general_complete_io_handler |
2203 | }, | 2156 | }, |
2157 | [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { | ||
2158 | .start_handler = scic_sds_port_default_start_handler, | ||
2159 | .stop_handler = scic_sds_port_ready_substate_stop_handler, | ||
2160 | .destruct_handler = scic_sds_port_default_destruct_handler, | ||
2161 | .reset_handler = scic_sds_port_default_reset_handler, | ||
2162 | .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, | ||
2163 | .remove_phy_handler = scic_sds_port_default_remove_phy_handler, | ||
2164 | .frame_handler = scic_sds_port_default_frame_handler, | ||
2165 | .event_handler = scic_sds_port_default_event_handler, | ||
2166 | .link_up_handler = scic_sds_port_ready_waiting_substate_link_up_handler, | ||
2167 | .link_down_handler = scic_sds_port_default_link_down_handler, | ||
2168 | .start_io_handler = scic_sds_port_ready_waiting_substate_start_io_handler, | ||
2169 | .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, | ||
2170 | }, | ||
2171 | [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { | ||
2172 | .start_handler = scic_sds_port_default_start_handler, | ||
2173 | .stop_handler = scic_sds_port_ready_substate_stop_handler, | ||
2174 | .destruct_handler = scic_sds_port_default_destruct_handler, | ||
2175 | .reset_handler = scic_sds_port_ready_operational_substate_reset_handler, | ||
2176 | .add_phy_handler = scic_sds_port_ready_substate_add_phy_handler, | ||
2177 | .remove_phy_handler = scic_sds_port_ready_substate_remove_phy_handler, | ||
2178 | .frame_handler = scic_sds_port_default_frame_handler, | ||
2179 | .event_handler = scic_sds_port_default_event_handler, | ||
2180 | .link_up_handler = scic_sds_port_ready_operational_substate_link_up_handler, | ||
2181 | .link_down_handler = scic_sds_port_ready_operational_substate_link_down_handler, | ||
2182 | .start_io_handler = scic_sds_port_ready_operational_substate_start_io_handler, | ||
2183 | .complete_io_handler = scic_sds_port_ready_substate_complete_io_handler, | ||
2184 | }, | ||
2185 | [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { | ||
2186 | .start_handler = scic_sds_port_default_start_handler, | ||
2187 | .stop_handler = scic_sds_port_ready_substate_stop_handler, | ||
2188 | .destruct_handler = scic_sds_port_default_destruct_handler, | ||
2189 | .reset_handler = scic_sds_port_default_reset_handler, | ||
2190 | .add_phy_handler = scic_sds_port_ready_configuring_substate_add_phy_handler, | ||
2191 | .remove_phy_handler = scic_sds_port_ready_configuring_substate_remove_phy_handler, | ||
2192 | .frame_handler = scic_sds_port_default_frame_handler, | ||
2193 | .event_handler = scic_sds_port_default_event_handler, | ||
2194 | .link_up_handler = scic_sds_port_default_link_up_handler, | ||
2195 | .link_down_handler = scic_sds_port_default_link_down_handler, | ||
2196 | .start_io_handler = scic_sds_port_default_start_io_handler, | ||
2197 | .complete_io_handler = scic_sds_port_ready_configuring_substate_complete_io_handler | ||
2198 | }, | ||
2204 | [SCI_BASE_PORT_STATE_RESETTING] = { | 2199 | [SCI_BASE_PORT_STATE_RESETTING] = { |
2205 | .start_handler = scic_sds_port_default_start_handler, | 2200 | .start_handler = scic_sds_port_default_start_handler, |
2206 | .stop_handler = scic_sds_port_reset_state_stop_handler, | 2201 | .stop_handler = scic_sds_port_reset_state_stop_handler, |
@@ -2299,31 +2294,6 @@ static void scic_sds_port_post_dummy_remote_node(struct scic_sds_port *sci_port) | |||
2299 | scic_sds_controller_post_request(scic, command); | 2294 | scic_sds_controller_post_request(scic, command); |
2300 | } | 2295 | } |
2301 | 2296 | ||
2302 | static void scic_sds_port_invalidate_dummy_remote_node(struct scic_sds_port *sci_port) | ||
2303 | { | ||
2304 | struct scic_sds_controller *scic = sci_port->owning_controller; | ||
2305 | u8 phys_index = sci_port->physical_port_index; | ||
2306 | union scu_remote_node_context *rnc; | ||
2307 | u16 rni = sci_port->reserved_rni; | ||
2308 | u32 command; | ||
2309 | |||
2310 | rnc = &scic->remote_node_context_table[rni]; | ||
2311 | |||
2312 | rnc->ssp.is_valid = false; | ||
2313 | |||
2314 | /* ensure the preceding tc abort request has reached the | ||
2315 | * controller and give it ample time to act before posting the rnc | ||
2316 | * invalidate | ||
2317 | */ | ||
2318 | readl(&scic->smu_registers->interrupt_status); /* flush */ | ||
2319 | udelay(10); | ||
2320 | |||
2321 | command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | | ||
2322 | phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni; | ||
2323 | |||
2324 | scic_sds_controller_post_request(scic, command); | ||
2325 | } | ||
2326 | |||
2327 | /* | 2297 | /* |
2328 | * ****************************************************************************** | 2298 | * ****************************************************************************** |
2329 | * * PORT STATE METHODS | 2299 | * * PORT STATE METHODS |
@@ -2404,15 +2374,8 @@ static void scic_sds_port_ready_state_enter(void *object) | |||
2404 | scic_sds_port_post_dummy_remote_node(sci_port); | 2374 | scic_sds_port_post_dummy_remote_node(sci_port); |
2405 | 2375 | ||
2406 | /* Start the ready substate machine */ | 2376 | /* Start the ready substate machine */ |
2407 | sci_base_state_machine_start(&sci_port->ready_substate_machine); | 2377 | port_state_machine_change(sci_port, |
2408 | } | 2378 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING); |
2409 | |||
2410 | static void scic_sds_port_ready_state_exit(void *object) | ||
2411 | { | ||
2412 | struct scic_sds_port *sci_port = object; | ||
2413 | |||
2414 | sci_base_state_machine_stop(&sci_port->ready_substate_machine); | ||
2415 | scic_sds_port_invalidate_dummy_remote_node(sci_port); | ||
2416 | } | 2379 | } |
2417 | 2380 | ||
2418 | /** | 2381 | /** |
@@ -2516,7 +2479,17 @@ static const struct sci_base_state scic_sds_port_state_table[] = { | |||
2516 | }, | 2479 | }, |
2517 | [SCI_BASE_PORT_STATE_READY] = { | 2480 | [SCI_BASE_PORT_STATE_READY] = { |
2518 | .enter_state = scic_sds_port_ready_state_enter, | 2481 | .enter_state = scic_sds_port_ready_state_enter, |
2519 | .exit_state = scic_sds_port_ready_state_exit | 2482 | }, |
2483 | [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { | ||
2484 | .enter_state = scic_sds_port_ready_substate_waiting_enter, | ||
2485 | }, | ||
2486 | [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { | ||
2487 | .enter_state = scic_sds_port_ready_substate_operational_enter, | ||
2488 | .exit_state = scic_sds_port_ready_substate_operational_exit | ||
2489 | }, | ||
2490 | [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { | ||
2491 | .enter_state = scic_sds_port_ready_substate_configuring_enter, | ||
2492 | .exit_state = scic_sds_port_ready_substate_configuring_exit | ||
2520 | }, | 2493 | }, |
2521 | [SCI_BASE_PORT_STATE_RESETTING] = { | 2494 | [SCI_BASE_PORT_STATE_RESETTING] = { |
2522 | .enter_state = scic_sds_port_resetting_state_enter, | 2495 | .enter_state = scic_sds_port_resetting_state_enter, |
@@ -2537,14 +2510,10 @@ void scic_sds_port_construct(struct scic_sds_port *sci_port, u8 index, | |||
2537 | 2510 | ||
2538 | sci_base_state_machine_start(&sci_port->state_machine); | 2511 | sci_base_state_machine_start(&sci_port->state_machine); |
2539 | 2512 | ||
2540 | sci_base_state_machine_construct(&sci_port->ready_substate_machine, | ||
2541 | sci_port, | ||
2542 | scic_sds_port_ready_substate_table, | ||
2543 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING); | ||
2544 | |||
2545 | sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; | 2513 | sci_port->logical_port_index = SCIC_SDS_DUMMY_PORT; |
2546 | sci_port->physical_port_index = index; | 2514 | sci_port->physical_port_index = index; |
2547 | sci_port->active_phy_mask = 0; | 2515 | sci_port->active_phy_mask = 0; |
2516 | sci_port->ready_exit = false; | ||
2548 | 2517 | ||
2549 | sci_port->owning_controller = scic; | 2518 | sci_port->owning_controller = scic; |
2550 | 2519 | ||