diff options
author | Andreas Herrmann <aherrman@de.ibm.com> | 2006-08-02 05:05:52 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-08-06 12:31:17 -0400 |
commit | f6c0e7a7b3b6db15146877c0cef43b413af5b76e (patch) | |
tree | 2ac31f5ea2cd66eb3aff8c6a4584074be407319d /drivers/s390/scsi | |
parent | fea9d6c7bcd8ff1d60ff74f27ba483b3820b18a3 (diff) |
[SCSI] zfcp: minor erp bug fixes
Bug fixes for zfcp's erp:
- trigger adapter reopen if do_QDIO fails
- avoid erp deadlock if registration of scsi target or remote port hang
- do not treat as error if exchange port data fails
- decrease timeout for target reset and aborts
- mark unit failed if slave_destroy is called
Additionally some code cleanup was done:
- made some functions void when retval is not of interest
- shortened initialization of zfcp's host_template
- corrected some comments
Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 196 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 73 |
4 files changed, 107 insertions, 167 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 72293f3870b5..904d6a7e9312 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -80,7 +80,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) | |||
80 | #define REQUEST_LIST_SIZE 128 | 80 | #define REQUEST_LIST_SIZE 128 |
81 | 81 | ||
82 | /********************* SCSI SPECIFIC DEFINES *********************************/ | 82 | /********************* SCSI SPECIFIC DEFINES *********************************/ |
83 | #define ZFCP_SCSI_ER_TIMEOUT (100*HZ) | 83 | #define ZFCP_SCSI_ER_TIMEOUT (10*HZ) |
84 | 84 | ||
85 | /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ | 85 | /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ |
86 | 86 | ||
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index f74412bd9d6a..7f60b6fdf724 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -64,8 +64,8 @@ static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int); | |||
64 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); | 64 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); |
65 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); | 65 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); |
66 | static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); | 66 | static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); |
67 | static int zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *); | 67 | static void zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *); |
68 | static int zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *); | 68 | static void zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *); |
69 | static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); | 69 | static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); |
70 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); | 70 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); |
71 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); | 71 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); |
@@ -93,10 +93,9 @@ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *); | |||
93 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); | 93 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); |
94 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); | 94 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); |
95 | 95 | ||
96 | static int zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); | 96 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *); |
97 | static int zfcp_erp_action_dismiss_port(struct zfcp_port *); | 97 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *); |
98 | static int zfcp_erp_action_dismiss_unit(struct zfcp_unit *); | 98 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *); |
99 | static int zfcp_erp_action_dismiss(struct zfcp_erp_action *); | ||
100 | 99 | ||
101 | static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, | 100 | static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, |
102 | struct zfcp_port *, struct zfcp_unit *); | 101 | struct zfcp_port *, struct zfcp_unit *); |
@@ -135,29 +134,39 @@ zfcp_fsf_request_timeout_handler(unsigned long data) | |||
135 | zfcp_erp_adapter_reopen(adapter, 0); | 134 | zfcp_erp_adapter_reopen(adapter, 0); |
136 | } | 135 | } |
137 | 136 | ||
138 | /* | 137 | /** |
139 | * function: zfcp_fsf_scsi_er_timeout_handler | 138 | * zfcp_fsf_scsi_er_timeout_handler - timeout handler for scsi eh tasks |
140 | * | 139 | * |
141 | * purpose: This function needs to be called whenever a SCSI error recovery | 140 | * This function needs to be called whenever a SCSI error recovery |
142 | * action (abort/reset) does not return. | 141 | * action (abort/reset) does not return. Re-opening the adapter means |
143 | * Re-opening the adapter means that the command can be returned | 142 | * that the abort/reset command can be returned by zfcp. It won't complete |
144 | * by zfcp (it is guarranteed that it does not return via the | 143 | * via the adapter anymore (because qdio queues are closed). If ERP is |
145 | * adapter anymore). The buffer can then be used again. | 144 | * already running on this adapter it will be stopped. |
146 | * | ||
147 | * returns: sod all | ||
148 | */ | 145 | */ |
149 | void | 146 | void zfcp_fsf_scsi_er_timeout_handler(unsigned long data) |
150 | zfcp_fsf_scsi_er_timeout_handler(unsigned long data) | ||
151 | { | 147 | { |
152 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | 148 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; |
149 | unsigned long flags; | ||
153 | 150 | ||
154 | ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. " | 151 | ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. " |
155 | "Restarting all operations on the adapter %s\n", | 152 | "Restarting all operations on the adapter %s\n", |
156 | zfcp_get_busid_by_adapter(adapter)); | 153 | zfcp_get_busid_by_adapter(adapter)); |
157 | debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout"); | 154 | debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout"); |
158 | zfcp_erp_adapter_reopen(adapter, 0); | ||
159 | 155 | ||
160 | return; | 156 | write_lock_irqsave(&adapter->erp_lock, flags); |
157 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | ||
158 | &adapter->status)) { | ||
159 | zfcp_erp_modify_adapter_status(adapter, | ||
160 | ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, | ||
161 | ZFCP_CLEAR); | ||
162 | zfcp_erp_action_dismiss_adapter(adapter); | ||
163 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
164 | /* dismiss all pending requests including requests for ERP */ | ||
165 | zfcp_fsf_req_dismiss_all(adapter); | ||
166 | adapter->fsf_req_seq_no = 0; | ||
167 | } else | ||
168 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
169 | zfcp_erp_adapter_reopen(adapter, 0); | ||
161 | } | 170 | } |
162 | 171 | ||
163 | /* | 172 | /* |
@@ -670,17 +679,10 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask) | |||
670 | return retval; | 679 | return retval; |
671 | } | 680 | } |
672 | 681 | ||
673 | /* | 682 | /** |
674 | * function: | 683 | * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests |
675 | * | ||
676 | * purpose: disable I/O, | ||
677 | * return any open requests and clean them up, | ||
678 | * aim: no pending and incoming I/O | ||
679 | * | ||
680 | * returns: | ||
681 | */ | 684 | */ |
682 | static void | 685 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) |
683 | zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) | ||
684 | { | 686 | { |
685 | debug_text_event(adapter->erp_dbf, 6, "a_bl"); | 687 | debug_text_event(adapter->erp_dbf, 6, "a_bl"); |
686 | zfcp_erp_modify_adapter_status(adapter, | 688 | zfcp_erp_modify_adapter_status(adapter, |
@@ -688,15 +690,10 @@ zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) | |||
688 | clear_mask, ZFCP_CLEAR); | 690 | clear_mask, ZFCP_CLEAR); |
689 | } | 691 | } |
690 | 692 | ||
691 | /* | 693 | /** |
692 | * function: | 694 | * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests |
693 | * | ||
694 | * purpose: enable I/O | ||
695 | * | ||
696 | * returns: | ||
697 | */ | 695 | */ |
698 | static void | 696 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) |
699 | zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) | ||
700 | { | 697 | { |
701 | debug_text_event(adapter->erp_dbf, 6, "a_ubl"); | 698 | debug_text_event(adapter->erp_dbf, 6, "a_ubl"); |
702 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); | 699 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); |
@@ -897,23 +894,15 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
897 | return retval; | 894 | return retval; |
898 | } | 895 | } |
899 | 896 | ||
900 | /* | 897 | /** |
901 | * purpose: generic handler for asynchronous events related to erp_action events | 898 | * zfcp_erp_async_handler_nolock - complete erp_action |
902 | * (normal completion, time-out, dismissing, retry after | ||
903 | * low memory condition) | ||
904 | * | ||
905 | * note: deletion of timer is not required (e.g. in case of a time-out), | ||
906 | * but a second try does no harm, | ||
907 | * we leave it in here to allow for greater simplification | ||
908 | * | 899 | * |
909 | * returns: 0 - there was an action to handle | 900 | * Used for normal completion, time-out, dismissal and failure after |
910 | * !0 - otherwise | 901 | * low memory condition. |
911 | */ | 902 | */ |
912 | static int | 903 | static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, |
913 | zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, | 904 | unsigned long set_mask) |
914 | unsigned long set_mask) | ||
915 | { | 905 | { |
916 | int retval; | ||
917 | struct zfcp_adapter *adapter = erp_action->adapter; | 906 | struct zfcp_adapter *adapter = erp_action->adapter; |
918 | 907 | ||
919 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { | 908 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { |
@@ -924,43 +913,26 @@ zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, | |||
924 | del_timer(&erp_action->timer); | 913 | del_timer(&erp_action->timer); |
925 | erp_action->status |= set_mask; | 914 | erp_action->status |= set_mask; |
926 | zfcp_erp_action_ready(erp_action); | 915 | zfcp_erp_action_ready(erp_action); |
927 | retval = 0; | ||
928 | } else { | 916 | } else { |
929 | /* action is ready or gone - nothing to do */ | 917 | /* action is ready or gone - nothing to do */ |
930 | debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone"); | 918 | debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone"); |
931 | debug_event(adapter->erp_dbf, 3, &erp_action->action, | 919 | debug_event(adapter->erp_dbf, 3, &erp_action->action, |
932 | sizeof (int)); | 920 | sizeof (int)); |
933 | retval = 1; | ||
934 | } | 921 | } |
935 | |||
936 | return retval; | ||
937 | } | 922 | } |
938 | 923 | ||
939 | /* | 924 | /** |
940 | * purpose: generic handler for asynchronous events related to erp_action | 925 | * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking |
941 | * events (normal completion, time-out, dismissing, retry after | ||
942 | * low memory condition) | ||
943 | * | ||
944 | * note: deletion of timer is not required (e.g. in case of a time-out), | ||
945 | * but a second try does no harm, | ||
946 | * we leave it in here to allow for greater simplification | ||
947 | * | ||
948 | * returns: 0 - there was an action to handle | ||
949 | * !0 - otherwise | ||
950 | */ | 926 | */ |
951 | int | 927 | void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, |
952 | zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, | 928 | unsigned long set_mask) |
953 | unsigned long set_mask) | ||
954 | { | 929 | { |
955 | struct zfcp_adapter *adapter = erp_action->adapter; | 930 | struct zfcp_adapter *adapter = erp_action->adapter; |
956 | unsigned long flags; | 931 | unsigned long flags; |
957 | int retval; | ||
958 | 932 | ||
959 | write_lock_irqsave(&adapter->erp_lock, flags); | 933 | write_lock_irqsave(&adapter->erp_lock, flags); |
960 | retval = zfcp_erp_async_handler_nolock(erp_action, set_mask); | 934 | zfcp_erp_async_handler_nolock(erp_action, set_mask); |
961 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 935 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
962 | |||
963 | return retval; | ||
964 | } | 936 | } |
965 | 937 | ||
966 | /* | 938 | /* |
@@ -997,17 +969,15 @@ zfcp_erp_timeout_handler(unsigned long data) | |||
997 | zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); | 969 | zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); |
998 | } | 970 | } |
999 | 971 | ||
1000 | /* | 972 | /** |
1001 | * purpose: is called for an erp_action which needs to be ended | 973 | * zfcp_erp_action_dismiss - dismiss an erp_action |
1002 | * though not being done, | ||
1003 | * this is usually required if an higher is generated, | ||
1004 | * action gets an appropriate flag and will be processed | ||
1005 | * accordingly | ||
1006 | * | 974 | * |
1007 | * locks: erp_lock held (thus we need to call another handler variant) | 975 | * adapter->erp_lock must be held |
976 | * | ||
977 | * Dismissal of an erp_action is usually required if an erp_action of | ||
978 | * higher priority is generated. | ||
1008 | */ | 979 | */ |
1009 | static int | 980 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) |
1010 | zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) | ||
1011 | { | 981 | { |
1012 | struct zfcp_adapter *adapter = erp_action->adapter; | 982 | struct zfcp_adapter *adapter = erp_action->adapter; |
1013 | 983 | ||
@@ -1015,8 +985,6 @@ zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) | |||
1015 | debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); | 985 | debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); |
1016 | 986 | ||
1017 | zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED); | 987 | zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED); |
1018 | |||
1019 | return 0; | ||
1020 | } | 988 | } |
1021 | 989 | ||
1022 | int | 990 | int |
@@ -2072,18 +2040,12 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) | |||
2072 | return retval; | 2040 | return retval; |
2073 | } | 2041 | } |
2074 | 2042 | ||
2075 | /* | 2043 | /** |
2076 | * function: zfcp_qdio_cleanup | 2044 | * zfcp_erp_adapter_strategy_close_qdio - close qdio queues for an adapter |
2077 | * | ||
2078 | * purpose: cleans up QDIO operation for the specified adapter | ||
2079 | * | ||
2080 | * returns: 0 - successful cleanup | ||
2081 | * !0 - failed cleanup | ||
2082 | */ | 2045 | */ |
2083 | int | 2046 | static void |
2084 | zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | 2047 | zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) |
2085 | { | 2048 | { |
2086 | int retval = ZFCP_ERP_SUCCEEDED; | ||
2087 | int first_used; | 2049 | int first_used; |
2088 | int used_count; | 2050 | int used_count; |
2089 | struct zfcp_adapter *adapter = erp_action->adapter; | 2051 | struct zfcp_adapter *adapter = erp_action->adapter; |
@@ -2092,15 +2054,13 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
2092 | ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO " | 2054 | ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO " |
2093 | "queues on adapter %s\n", | 2055 | "queues on adapter %s\n", |
2094 | zfcp_get_busid_by_adapter(adapter)); | 2056 | zfcp_get_busid_by_adapter(adapter)); |
2095 | retval = ZFCP_ERP_FAILED; | 2057 | return; |
2096 | goto out; | ||
2097 | } | 2058 | } |
2098 | 2059 | ||
2099 | /* | 2060 | /* |
2100 | * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that | 2061 | * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that |
2101 | * do_QDIO won't be called while qdio_shutdown is in progress. | 2062 | * do_QDIO won't be called while qdio_shutdown is in progress. |
2102 | */ | 2063 | */ |
2103 | |||
2104 | write_lock_irq(&adapter->request_queue.queue_lock); | 2064 | write_lock_irq(&adapter->request_queue.queue_lock); |
2105 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); | 2065 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); |
2106 | write_unlock_irq(&adapter->request_queue.queue_lock); | 2066 | write_unlock_irq(&adapter->request_queue.queue_lock); |
@@ -2132,8 +2092,6 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
2132 | adapter->request_queue.free_index = 0; | 2092 | adapter->request_queue.free_index = 0; |
2133 | atomic_set(&adapter->request_queue.free_count, 0); | 2093 | atomic_set(&adapter->request_queue.free_count, 0); |
2134 | adapter->request_queue.distance_from_int = 0; | 2094 | adapter->request_queue.distance_from_int = 0; |
2135 | out: | ||
2136 | return retval; | ||
2137 | } | 2095 | } |
2138 | 2096 | ||
2139 | static int | 2097 | static int |
@@ -2256,11 +2214,11 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | |||
2256 | "%s)\n", zfcp_get_busid_by_adapter(adapter)); | 2214 | "%s)\n", zfcp_get_busid_by_adapter(adapter)); |
2257 | ret = ZFCP_ERP_FAILED; | 2215 | ret = ZFCP_ERP_FAILED; |
2258 | } | 2216 | } |
2259 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) { | 2217 | |
2260 | ZFCP_LOG_INFO("error: exchange port data failed (adapter " | 2218 | /* don't treat as error for the sake of compatibility */ |
2219 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) | ||
2220 | ZFCP_LOG_INFO("warning: exchange port data failed (adapter " | ||
2261 | "%s\n", zfcp_get_busid_by_adapter(adapter)); | 2221 | "%s\n", zfcp_get_busid_by_adapter(adapter)); |
2262 | ret = ZFCP_ERP_FAILED; | ||
2263 | } | ||
2264 | 2222 | ||
2265 | return ret; | 2223 | return ret; |
2266 | } | 2224 | } |
@@ -2290,18 +2248,12 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action | |||
2290 | return retval; | 2248 | return retval; |
2291 | } | 2249 | } |
2292 | 2250 | ||
2293 | /* | 2251 | /** |
2294 | * function: zfcp_fsf_cleanup | 2252 | * zfcp_erp_adapter_strategy_close_fsf - stop FSF operations for an adapter |
2295 | * | ||
2296 | * purpose: cleanup FSF operation for specified adapter | ||
2297 | * | ||
2298 | * returns: 0 - FSF operation successfully cleaned up | ||
2299 | * !0 - failed to cleanup FSF operation for this adapter | ||
2300 | */ | 2253 | */ |
2301 | static int | 2254 | static void |
2302 | zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) | 2255 | zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) |
2303 | { | 2256 | { |
2304 | int retval = ZFCP_ERP_SUCCEEDED; | ||
2305 | struct zfcp_adapter *adapter = erp_action->adapter; | 2257 | struct zfcp_adapter *adapter = erp_action->adapter; |
2306 | 2258 | ||
2307 | /* | 2259 | /* |
@@ -2315,8 +2267,6 @@ zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) | |||
2315 | /* all ports and units are closed */ | 2267 | /* all ports and units are closed */ |
2316 | zfcp_erp_modify_adapter_status(adapter, | 2268 | zfcp_erp_modify_adapter_status(adapter, |
2317 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | 2269 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); |
2318 | |||
2319 | return retval; | ||
2320 | } | 2270 | } |
2321 | 2271 | ||
2322 | /* | 2272 | /* |
@@ -3291,10 +3241,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, | |||
3291 | } | 3241 | } |
3292 | 3242 | ||
3293 | 3243 | ||
3294 | static int | 3244 | void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) |
3295 | zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | ||
3296 | { | 3245 | { |
3297 | int retval = 0; | ||
3298 | struct zfcp_port *port; | 3246 | struct zfcp_port *port; |
3299 | 3247 | ||
3300 | debug_text_event(adapter->erp_dbf, 5, "a_actab"); | 3248 | debug_text_event(adapter->erp_dbf, 5, "a_actab"); |
@@ -3303,14 +3251,10 @@ zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | |||
3303 | else | 3251 | else |
3304 | list_for_each_entry(port, &adapter->port_list_head, list) | 3252 | list_for_each_entry(port, &adapter->port_list_head, list) |
3305 | zfcp_erp_action_dismiss_port(port); | 3253 | zfcp_erp_action_dismiss_port(port); |
3306 | |||
3307 | return retval; | ||
3308 | } | 3254 | } |
3309 | 3255 | ||
3310 | static int | 3256 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) |
3311 | zfcp_erp_action_dismiss_port(struct zfcp_port *port) | ||
3312 | { | 3257 | { |
3313 | int retval = 0; | ||
3314 | struct zfcp_unit *unit; | 3258 | struct zfcp_unit *unit; |
3315 | struct zfcp_adapter *adapter = port->adapter; | 3259 | struct zfcp_adapter *adapter = port->adapter; |
3316 | 3260 | ||
@@ -3321,22 +3265,16 @@ zfcp_erp_action_dismiss_port(struct zfcp_port *port) | |||
3321 | else | 3265 | else |
3322 | list_for_each_entry(unit, &port->unit_list_head, list) | 3266 | list_for_each_entry(unit, &port->unit_list_head, list) |
3323 | zfcp_erp_action_dismiss_unit(unit); | 3267 | zfcp_erp_action_dismiss_unit(unit); |
3324 | |||
3325 | return retval; | ||
3326 | } | 3268 | } |
3327 | 3269 | ||
3328 | static int | 3270 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) |
3329 | zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | ||
3330 | { | 3271 | { |
3331 | int retval = 0; | ||
3332 | struct zfcp_adapter *adapter = unit->port->adapter; | 3272 | struct zfcp_adapter *adapter = unit->port->adapter; |
3333 | 3273 | ||
3334 | debug_text_event(adapter->erp_dbf, 5, "u_actab"); | 3274 | debug_text_event(adapter->erp_dbf, 5, "u_actab"); |
3335 | debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); | 3275 | debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); |
3336 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) | 3276 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) |
3337 | zfcp_erp_action_dismiss(&unit->erp_action); | 3277 | zfcp_erp_action_dismiss(&unit->erp_action); |
3338 | |||
3339 | return retval; | ||
3340 | } | 3278 | } |
3341 | 3279 | ||
3342 | static inline void | 3280 | static inline void |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 04bb3a9d90a8..146d7a2b4c4a 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -139,6 +139,7 @@ extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int); | |||
139 | extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int); | 139 | extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int); |
140 | extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int); | 140 | extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int); |
141 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *); | 141 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *); |
142 | extern void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); | ||
142 | 143 | ||
143 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int); | 144 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int); |
144 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int); | 145 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int); |
@@ -155,7 +156,7 @@ extern void zfcp_erp_unit_failed(struct zfcp_unit *); | |||
155 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); | 156 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); |
156 | extern int zfcp_erp_thread_kill(struct zfcp_adapter *); | 157 | extern int zfcp_erp_thread_kill(struct zfcp_adapter *); |
157 | extern int zfcp_erp_wait(struct zfcp_adapter *); | 158 | extern int zfcp_erp_wait(struct zfcp_adapter *); |
158 | extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); | 159 | extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); |
159 | 160 | ||
160 | extern int zfcp_test_link(struct zfcp_port *); | 161 | extern int zfcp_test_link(struct zfcp_port *); |
161 | 162 | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 671f4a6a5d18..1bb55086db9f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -30,7 +30,6 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *, | |||
30 | void (*done) (struct scsi_cmnd *)); | 30 | void (*done) (struct scsi_cmnd *)); |
31 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); | 31 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); |
32 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); | 32 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); |
33 | static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); | ||
34 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); | 33 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); |
35 | static int zfcp_task_management_function(struct zfcp_unit *, u8, | 34 | static int zfcp_task_management_function(struct zfcp_unit *, u8, |
36 | struct scsi_cmnd *); | 35 | struct scsi_cmnd *); |
@@ -46,30 +45,22 @@ struct zfcp_data zfcp_data = { | |||
46 | .scsi_host_template = { | 45 | .scsi_host_template = { |
47 | .name = ZFCP_NAME, | 46 | .name = ZFCP_NAME, |
48 | .proc_name = "zfcp", | 47 | .proc_name = "zfcp", |
49 | .proc_info = NULL, | ||
50 | .detect = NULL, | ||
51 | .slave_alloc = zfcp_scsi_slave_alloc, | 48 | .slave_alloc = zfcp_scsi_slave_alloc, |
52 | .slave_configure = zfcp_scsi_slave_configure, | 49 | .slave_configure = zfcp_scsi_slave_configure, |
53 | .slave_destroy = zfcp_scsi_slave_destroy, | 50 | .slave_destroy = zfcp_scsi_slave_destroy, |
54 | .queuecommand = zfcp_scsi_queuecommand, | 51 | .queuecommand = zfcp_scsi_queuecommand, |
55 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, | 52 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, |
56 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, | 53 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, |
57 | .eh_bus_reset_handler = zfcp_scsi_eh_bus_reset_handler, | 54 | .eh_bus_reset_handler = zfcp_scsi_eh_host_reset_handler, |
58 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, | 55 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, |
59 | .can_queue = 4096, | 56 | .can_queue = 4096, |
60 | .this_id = -1, | 57 | .this_id = -1, |
61 | /* | ||
62 | * FIXME: | ||
63 | * one less? can zfcp_create_sbale cope with it? | ||
64 | */ | ||
65 | .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, | 58 | .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, |
66 | .cmd_per_lun = 1, | 59 | .cmd_per_lun = 1, |
67 | .unchecked_isa_dma = 0, | ||
68 | .use_clustering = 1, | 60 | .use_clustering = 1, |
69 | .sdev_attrs = zfcp_sysfs_sdev_attrs, | 61 | .sdev_attrs = zfcp_sysfs_sdev_attrs, |
70 | }, | 62 | }, |
71 | .driver_version = ZFCP_VERSION, | 63 | .driver_version = ZFCP_VERSION, |
72 | /* rest initialised with zeros */ | ||
73 | }; | 64 | }; |
74 | 65 | ||
75 | /* Find start of Response Information in FCP response unit*/ | 66 | /* Find start of Response Information in FCP response unit*/ |
@@ -176,8 +167,14 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) | |||
176 | return retval; | 167 | return retval; |
177 | } | 168 | } |
178 | 169 | ||
179 | static void | 170 | /** |
180 | zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | 171 | * zfcp_scsi_slave_destroy - called when scsi device is removed |
172 | * | ||
173 | * Remove reference to associated scsi device for an zfcp_unit. | ||
174 | * Mark zfcp_unit as failed. The scsi device might be deleted via sysfs | ||
175 | * or a scan for this device might have failed. | ||
176 | */ | ||
177 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | ||
181 | { | 178 | { |
182 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 179 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; |
183 | 180 | ||
@@ -185,6 +182,7 @@ zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | |||
185 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); | 182 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); |
186 | sdpnt->hostdata = NULL; | 183 | sdpnt->hostdata = NULL; |
187 | unit->device = NULL; | 184 | unit->device = NULL; |
185 | zfcp_erp_unit_failed(unit); | ||
188 | zfcp_unit_put(unit); | 186 | zfcp_unit_put(unit); |
189 | } else { | 187 | } else { |
190 | ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " | 188 | ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " |
@@ -549,35 +547,38 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, | |||
549 | } | 547 | } |
550 | 548 | ||
551 | /** | 549 | /** |
552 | * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) | 550 | * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset |
551 | * | ||
552 | * If ERP is already running it will be stopped. | ||
553 | */ | 553 | */ |
554 | int | 554 | int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
555 | zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) | ||
556 | { | 555 | { |
557 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; | 556 | struct zfcp_unit *unit; |
558 | struct zfcp_adapter *adapter = unit->port->adapter; | 557 | struct zfcp_adapter *adapter; |
559 | 558 | unsigned long flags; | |
560 | ZFCP_LOG_NORMAL("bus reset because of problems with " | ||
561 | "unit 0x%016Lx\n", unit->fcp_lun); | ||
562 | zfcp_erp_adapter_reopen(adapter, 0); | ||
563 | zfcp_erp_wait(adapter); | ||
564 | |||
565 | return SUCCESS; | ||
566 | } | ||
567 | 559 | ||
568 | /** | 560 | unit = (struct zfcp_unit*) scpnt->device->hostdata; |
569 | * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) | 561 | adapter = unit->port->adapter; |
570 | */ | ||
571 | int | ||
572 | zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | ||
573 | { | ||
574 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; | ||
575 | struct zfcp_adapter *adapter = unit->port->adapter; | ||
576 | 562 | ||
577 | ZFCP_LOG_NORMAL("host reset because of problems with " | 563 | ZFCP_LOG_NORMAL("host/bus reset because of problems with " |
578 | "unit 0x%016Lx\n", unit->fcp_lun); | 564 | "unit 0x%016Lx\n", unit->fcp_lun); |
579 | zfcp_erp_adapter_reopen(adapter, 0); | 565 | |
580 | zfcp_erp_wait(adapter); | 566 | write_lock_irqsave(&adapter->erp_lock, flags); |
567 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | ||
568 | &adapter->status)) { | ||
569 | zfcp_erp_modify_adapter_status(adapter, | ||
570 | ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, | ||
571 | ZFCP_CLEAR); | ||
572 | zfcp_erp_action_dismiss_adapter(adapter); | ||
573 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
574 | zfcp_fsf_req_dismiss_all(adapter); | ||
575 | adapter->fsf_req_seq_no = 0; | ||
576 | zfcp_erp_adapter_reopen(adapter, 0); | ||
577 | } else { | ||
578 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
579 | zfcp_erp_adapter_reopen(adapter, 0); | ||
580 | zfcp_erp_wait(adapter); | ||
581 | } | ||
581 | 582 | ||
582 | return SUCCESS; | 583 | return SUCCESS; |
583 | } | 584 | } |