diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_erp.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 149 |
1 files changed, 40 insertions, 109 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index b18c6dd37294..e7d3bce51429 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -23,7 +23,6 @@ enum zfcp_erp_steps { | |||
23 | ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, | 23 | ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, |
24 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, | 24 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, |
25 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, | 25 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, |
26 | ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200, | ||
27 | ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400, | 26 | ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400, |
28 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, | 27 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, |
29 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, | 28 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, |
@@ -532,8 +531,7 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, | |||
532 | struct zfcp_port *port; | 531 | struct zfcp_port *port; |
533 | 532 | ||
534 | list_for_each_entry(port, &adapter->port_list_head, list) | 533 | list_for_each_entry(port, &adapter->port_list_head, list) |
535 | if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)) | 534 | _zfcp_erp_port_reopen(port, clear, id, ref); |
536 | _zfcp_erp_port_reopen(port, clear, id, ref); | ||
537 | } | 535 | } |
538 | 536 | ||
539 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, | 537 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, |
@@ -777,7 +775,6 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act) | |||
777 | static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) | 775 | static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) |
778 | { | 776 | { |
779 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 777 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
780 | ZFCP_STATUS_PORT_DID_DID | | ||
781 | ZFCP_STATUS_PORT_PHYS_CLOSING | | 778 | ZFCP_STATUS_PORT_PHYS_CLOSING | |
782 | ZFCP_STATUS_PORT_INVALID_WWPN, | 779 | ZFCP_STATUS_PORT_INVALID_WWPN, |
783 | &port->status); | 780 | &port->status); |
@@ -830,62 +827,6 @@ static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) | |||
830 | return ZFCP_ERP_CONTINUES; | 827 | return ZFCP_ERP_CONTINUES; |
831 | } | 828 | } |
832 | 829 | ||
833 | static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act) | ||
834 | { | ||
835 | unsigned long flags; | ||
836 | struct zfcp_adapter *adapter = ns_act->adapter; | ||
837 | struct zfcp_erp_action *act, *tmp; | ||
838 | int status; | ||
839 | |||
840 | read_lock_irqsave(&adapter->erp_lock, flags); | ||
841 | list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) { | ||
842 | if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { | ||
843 | status = atomic_read(&adapter->nameserver_port->status); | ||
844 | if (status & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
845 | zfcp_erp_port_failed(act->port, 27, NULL); | ||
846 | zfcp_erp_action_ready(act); | ||
847 | } | ||
848 | } | ||
849 | read_unlock_irqrestore(&adapter->erp_lock, flags); | ||
850 | } | ||
851 | |||
852 | static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act) | ||
853 | { | ||
854 | int retval; | ||
855 | |||
856 | switch (act->step) { | ||
857 | case ZFCP_ERP_STEP_UNINITIALIZED: | ||
858 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | ||
859 | case ZFCP_ERP_STEP_PORT_CLOSING: | ||
860 | return zfcp_erp_port_strategy_open_port(act); | ||
861 | |||
862 | case ZFCP_ERP_STEP_PORT_OPENING: | ||
863 | if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN) | ||
864 | retval = ZFCP_ERP_SUCCEEDED; | ||
865 | else | ||
866 | retval = ZFCP_ERP_FAILED; | ||
867 | /* this is needed anyway */ | ||
868 | zfcp_erp_port_strategy_open_ns_wake(act); | ||
869 | return retval; | ||
870 | |||
871 | default: | ||
872 | return ZFCP_ERP_FAILED; | ||
873 | } | ||
874 | } | ||
875 | |||
876 | static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act) | ||
877 | { | ||
878 | int retval; | ||
879 | |||
880 | retval = zfcp_fc_ns_gid_pn_request(act); | ||
881 | if (retval == -ENOMEM) | ||
882 | return ZFCP_ERP_NOMEM; | ||
883 | act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; | ||
884 | if (retval) | ||
885 | return ZFCP_ERP_FAILED; | ||
886 | return ZFCP_ERP_CONTINUES; | ||
887 | } | ||
888 | |||
889 | static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) | 830 | static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) |
890 | { | 831 | { |
891 | struct zfcp_adapter *adapter = act->adapter; | 832 | struct zfcp_adapter *adapter = act->adapter; |
@@ -900,11 +841,25 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) | |||
900 | return zfcp_erp_port_strategy_open_port(act); | 841 | return zfcp_erp_port_strategy_open_port(act); |
901 | } | 842 | } |
902 | 843 | ||
844 | void zfcp_erp_port_strategy_open_lookup(struct work_struct *work) | ||
845 | { | ||
846 | int retval; | ||
847 | struct zfcp_port *port = container_of(work, struct zfcp_port, | ||
848 | gid_pn_work); | ||
849 | |||
850 | retval = zfcp_fc_ns_gid_pn(&port->erp_action); | ||
851 | if (retval == -ENOMEM) | ||
852 | zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM); | ||
853 | port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; | ||
854 | if (retval) | ||
855 | zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED); | ||
856 | |||
857 | } | ||
858 | |||
903 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | 859 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) |
904 | { | 860 | { |
905 | struct zfcp_adapter *adapter = act->adapter; | 861 | struct zfcp_adapter *adapter = act->adapter; |
906 | struct zfcp_port *port = act->port; | 862 | struct zfcp_port *port = act->port; |
907 | struct zfcp_port *ns_port = adapter->nameserver_port; | ||
908 | int p_status = atomic_read(&port->status); | 863 | int p_status = atomic_read(&port->status); |
909 | 864 | ||
910 | switch (act->step) { | 865 | switch (act->step) { |
@@ -913,29 +868,10 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | |||
913 | case ZFCP_ERP_STEP_PORT_CLOSING: | 868 | case ZFCP_ERP_STEP_PORT_CLOSING: |
914 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) | 869 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) |
915 | return zfcp_erp_open_ptp_port(act); | 870 | return zfcp_erp_open_ptp_port(act); |
916 | if (!ns_port) { | 871 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { |
917 | dev_err(&adapter->ccw_device->dev, | 872 | schedule_work(&port->gid_pn_work); |
918 | "Attaching the name server port to the " | 873 | return ZFCP_ERP_CONTINUES; |
919 | "FCP device failed\n"); | ||
920 | return ZFCP_ERP_FAILED; | ||
921 | } | ||
922 | if (!(atomic_read(&ns_port->status) & | ||
923 | ZFCP_STATUS_COMMON_UNBLOCKED)) { | ||
924 | /* nameserver port may live again */ | ||
925 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, | ||
926 | &ns_port->status); | ||
927 | if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) { | ||
928 | act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; | ||
929 | return ZFCP_ERP_CONTINUES; | ||
930 | } | ||
931 | return ZFCP_ERP_FAILED; | ||
932 | } | 874 | } |
933 | /* else nameserver port is already open, fall through */ | ||
934 | case ZFCP_ERP_STEP_NAMESERVER_OPEN: | ||
935 | if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
936 | return ZFCP_ERP_FAILED; | ||
937 | return zfcp_erp_port_strategy_open_lookup(act); | ||
938 | |||
939 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: | 875 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: |
940 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { | 876 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { |
941 | if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { | 877 | if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { |
@@ -948,25 +884,26 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | |||
948 | 884 | ||
949 | case ZFCP_ERP_STEP_PORT_OPENING: | 885 | case ZFCP_ERP_STEP_PORT_OPENING: |
950 | /* D_ID might have changed during open */ | 886 | /* D_ID might have changed during open */ |
951 | if ((p_status & ZFCP_STATUS_COMMON_OPEN) && | 887 | if (p_status & ZFCP_STATUS_COMMON_OPEN) { |
952 | (p_status & ZFCP_STATUS_PORT_DID_DID)) | 888 | if (p_status & ZFCP_STATUS_PORT_DID_DID) |
953 | return ZFCP_ERP_SUCCEEDED; | 889 | return ZFCP_ERP_SUCCEEDED; |
890 | else { | ||
891 | act->step = ZFCP_ERP_STEP_PORT_CLOSING; | ||
892 | return ZFCP_ERP_CONTINUES; | ||
893 | } | ||
954 | /* fall through otherwise */ | 894 | /* fall through otherwise */ |
895 | } | ||
955 | } | 896 | } |
956 | return ZFCP_ERP_FAILED; | 897 | return ZFCP_ERP_FAILED; |
957 | } | 898 | } |
958 | 899 | ||
959 | static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act) | ||
960 | { | ||
961 | if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA)) | ||
962 | return zfcp_erp_port_strategy_open_nameserver(act); | ||
963 | return zfcp_erp_port_strategy_open_common(act); | ||
964 | } | ||
965 | |||
966 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) | 900 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) |
967 | { | 901 | { |
968 | struct zfcp_port *port = erp_action->port; | 902 | struct zfcp_port *port = erp_action->port; |
969 | 903 | ||
904 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) | ||
905 | goto close_init_done; | ||
906 | |||
970 | switch (erp_action->step) { | 907 | switch (erp_action->step) { |
971 | case ZFCP_ERP_STEP_UNINITIALIZED: | 908 | case ZFCP_ERP_STEP_UNINITIALIZED: |
972 | zfcp_erp_port_strategy_clearstati(port); | 909 | zfcp_erp_port_strategy_clearstati(port); |
@@ -979,12 +916,12 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) | |||
979 | return ZFCP_ERP_FAILED; | 916 | return ZFCP_ERP_FAILED; |
980 | break; | 917 | break; |
981 | } | 918 | } |
919 | |||
920 | close_init_done: | ||
982 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | 921 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) |
983 | return ZFCP_ERP_EXIT; | 922 | return ZFCP_ERP_EXIT; |
984 | else | ||
985 | return zfcp_erp_port_strategy_open(erp_action); | ||
986 | 923 | ||
987 | return ZFCP_ERP_FAILED; | 924 | return zfcp_erp_port_strategy_open_common(erp_action); |
988 | } | 925 | } |
989 | 926 | ||
990 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) | 927 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) |
@@ -1296,12 +1233,10 @@ static void zfcp_erp_rport_register(struct zfcp_port *port) | |||
1296 | static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) | 1233 | static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) |
1297 | { | 1234 | { |
1298 | struct zfcp_port *port; | 1235 | struct zfcp_port *port; |
1299 | list_for_each_entry(port, &adapter->port_list_head, list) | 1236 | list_for_each_entry(port, &adapter->port_list_head, list) { |
1300 | if (port->rport && !(atomic_read(&port->status) & | 1237 | fc_remote_port_delete(port->rport); |
1301 | ZFCP_STATUS_PORT_WKA)) { | 1238 | port->rport = NULL; |
1302 | fc_remote_port_delete(port->rport); | 1239 | } |
1303 | port->rport = NULL; | ||
1304 | } | ||
1305 | } | 1240 | } |
1306 | 1241 | ||
1307 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | 1242 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) |
@@ -1737,9 +1672,8 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, | |||
1737 | 1672 | ||
1738 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1673 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | |
1739 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { | 1674 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { |
1740 | if (!(status & ZFCP_STATUS_PORT_WKA)) | 1675 | list_for_each_entry(unit, &port->unit_list_head, list) |
1741 | list_for_each_entry(unit, &port->unit_list_head, list) | 1676 | zfcp_erp_unit_access_changed(unit, id, ref); |
1742 | zfcp_erp_unit_access_changed(unit, id, ref); | ||
1743 | return; | 1677 | return; |
1744 | } | 1678 | } |
1745 | 1679 | ||
@@ -1762,10 +1696,7 @@ void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, | |||
1762 | return; | 1696 | return; |
1763 | 1697 | ||
1764 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1698 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
1765 | if (adapter->nameserver_port) | ||
1766 | zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref); | ||
1767 | list_for_each_entry(port, &adapter->port_list_head, list) | 1699 | list_for_each_entry(port, &adapter->port_list_head, list) |
1768 | if (port != adapter->nameserver_port) | 1700 | zfcp_erp_port_access_changed(port, id, ref); |
1769 | zfcp_erp_port_access_changed(port, id, ref); | ||
1770 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 1701 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
1771 | } | 1702 | } |