diff options
author | Christof Schmitt <christof.schmitt@de.ibm.com> | 2008-07-02 04:56:40 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:36 -0400 |
commit | 287ac01acf22ab6aaaf9f5a4919ce2449c8b391c (patch) | |
tree | b8ea35d04aa7d74c68739a67a9e2c8b4151c0017 /drivers | |
parent | c41f8cbddd4e0e72951e0575165dea8ea26f1c4b (diff) |
[SCSI] zfcp: Cleanup code in zfcp_erp.c
Cleanup the code in zfcp_erp.c, move erp internal definititions to
this file and move FSF timeout handling to the FSF layer.
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 45 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 3370 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 25 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 43 |
4 files changed, 1280 insertions, 2203 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 206b6e7a8bfd..67f45fc62f53 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -91,17 +91,11 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) | |||
91 | /* max. number of (data buffer) SBALEs in largest SBAL chain | 91 | /* max. number of (data buffer) SBALEs in largest SBAL chain |
92 | multiplied with number of sectors per 4k block */ | 92 | multiplied with number of sectors per 4k block */ |
93 | 93 | ||
94 | #define ZFCP_TYPE2_RECOVERY_TIME 8 /* seconds */ | ||
95 | |||
96 | /********************* FSF SPECIFIC DEFINES *********************************/ | 94 | /********************* FSF SPECIFIC DEFINES *********************************/ |
97 | 95 | ||
98 | /* ATTENTION: value must not be used by hardware */ | 96 | /* ATTENTION: value must not be used by hardware */ |
99 | #define FSF_QTCB_UNSOLICITED_STATUS 0x6305 | 97 | #define FSF_QTCB_UNSOLICITED_STATUS 0x6305 |
100 | 98 | ||
101 | /* Do 1st retry in 1 second, then double the timeout for each following retry */ | ||
102 | #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 1 | ||
103 | #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 | ||
104 | |||
105 | /* timeout value for "default timer" for fsf requests */ | 99 | /* timeout value for "default timer" for fsf requests */ |
106 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ) | 100 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ) |
107 | 101 | ||
@@ -349,45 +343,6 @@ struct zfcp_rc_entry { | |||
349 | #define ZFCP_STATUS_FSFREQ_RETRY 0x00000800 | 343 | #define ZFCP_STATUS_FSFREQ_RETRY 0x00000800 |
350 | #define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000 | 344 | #define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000 |
351 | 345 | ||
352 | /*********************** ERROR RECOVERY PROCEDURE DEFINES ********************/ | ||
353 | |||
354 | #define ZFCP_MAX_ERPS 3 | ||
355 | |||
356 | #define ZFCP_ERP_FSFREQ_TIMEOUT (30 * HZ) | ||
357 | #define ZFCP_ERP_MEMWAIT_TIMEOUT HZ | ||
358 | |||
359 | #define ZFCP_STATUS_ERP_TIMEDOUT 0x10000000 | ||
360 | #define ZFCP_STATUS_ERP_CLOSE_ONLY 0x01000000 | ||
361 | #define ZFCP_STATUS_ERP_DISMISSING 0x00100000 | ||
362 | #define ZFCP_STATUS_ERP_DISMISSED 0x00200000 | ||
363 | #define ZFCP_STATUS_ERP_LOWMEM 0x00400000 | ||
364 | |||
365 | #define ZFCP_ERP_STEP_UNINITIALIZED 0x00000000 | ||
366 | #define ZFCP_ERP_STEP_FSF_XCONFIG 0x00000001 | ||
367 | #define ZFCP_ERP_STEP_PHYS_PORT_CLOSING 0x00000010 | ||
368 | #define ZFCP_ERP_STEP_PORT_CLOSING 0x00000100 | ||
369 | #define ZFCP_ERP_STEP_NAMESERVER_OPEN 0x00000200 | ||
370 | #define ZFCP_ERP_STEP_NAMESERVER_LOOKUP 0x00000400 | ||
371 | #define ZFCP_ERP_STEP_PORT_OPENING 0x00000800 | ||
372 | #define ZFCP_ERP_STEP_UNIT_CLOSING 0x00001000 | ||
373 | #define ZFCP_ERP_STEP_UNIT_OPENING 0x00002000 | ||
374 | |||
375 | /* Ordered by escalation level (necessary for proper erp-code operation) */ | ||
376 | #define ZFCP_ERP_ACTION_REOPEN_ADAPTER 0x4 | ||
377 | #define ZFCP_ERP_ACTION_REOPEN_PORT_FORCED 0x3 | ||
378 | #define ZFCP_ERP_ACTION_REOPEN_PORT 0x2 | ||
379 | #define ZFCP_ERP_ACTION_REOPEN_UNIT 0x1 | ||
380 | |||
381 | #define ZFCP_ERP_ACTION_RUNNING 0x1 | ||
382 | #define ZFCP_ERP_ACTION_READY 0x2 | ||
383 | |||
384 | #define ZFCP_ERP_SUCCEEDED 0x0 | ||
385 | #define ZFCP_ERP_FAILED 0x1 | ||
386 | #define ZFCP_ERP_CONTINUES 0x2 | ||
387 | #define ZFCP_ERP_EXIT 0x3 | ||
388 | #define ZFCP_ERP_DISMISSED 0x4 | ||
389 | #define ZFCP_ERP_NOMEM 0x5 | ||
390 | |||
391 | /************************* STRUCTURE DEFINITIONS *****************************/ | 346 | /************************* STRUCTURE DEFINITIONS *****************************/ |
392 | 347 | ||
393 | struct zfcp_fsf_req; | 348 | struct zfcp_fsf_req; |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 4d797e5264d9..643ac4bba5b5 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -8,1345 +8,582 @@ | |||
8 | 8 | ||
9 | #include "zfcp_ext.h" | 9 | #include "zfcp_ext.h" |
10 | 10 | ||
11 | static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int, u8, | 11 | #define ZFCP_MAX_ERPS 3 |
12 | void *); | 12 | |
13 | static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int, u8, | 13 | enum zfcp_erp_act_flags { |
14 | void *); | 14 | ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000, |
15 | static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int, u8, void *); | 15 | ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000, |
16 | static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int, u8, void *); | 16 | ZFCP_STATUS_ERP_DISMISSING = 0x00100000, |
17 | 17 | ZFCP_STATUS_ERP_DISMISSED = 0x00200000, | |
18 | static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int, u8, | 18 | ZFCP_STATUS_ERP_LOWMEM = 0x00400000, |
19 | void *); | 19 | }; |
20 | static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int, u8, | ||
21 | void *); | ||
22 | |||
23 | static void zfcp_erp_adapter_block(struct zfcp_adapter *, int); | ||
24 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *); | ||
25 | static void zfcp_erp_port_block(struct zfcp_port *, int); | ||
26 | static void zfcp_erp_port_unblock(struct zfcp_port *); | ||
27 | static void zfcp_erp_unit_block(struct zfcp_unit *, int); | ||
28 | static void zfcp_erp_unit_unblock(struct zfcp_unit *); | ||
29 | |||
30 | static int zfcp_erp_thread(void *); | ||
31 | |||
32 | static int zfcp_erp_strategy(struct zfcp_erp_action *); | ||
33 | |||
34 | static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *); | ||
35 | static int zfcp_erp_strategy_memwait(struct zfcp_erp_action *); | ||
36 | static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *, int); | ||
37 | static int zfcp_erp_strategy_check_unit(struct zfcp_unit *, int); | ||
38 | static int zfcp_erp_strategy_check_port(struct zfcp_port *, int); | ||
39 | static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int); | ||
40 | static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, | ||
41 | struct zfcp_port *, | ||
42 | struct zfcp_unit *, int); | ||
43 | static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); | ||
44 | static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, | ||
45 | struct zfcp_port *, | ||
46 | struct zfcp_unit *, int); | ||
47 | static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *); | ||
48 | static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int); | ||
49 | |||
50 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); | ||
51 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); | ||
52 | static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); | ||
53 | static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); | ||
54 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); | ||
55 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); | ||
56 | static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); | ||
57 | static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *); | ||
58 | static int zfcp_erp_adapter_strategy_open_fsf_statusread( | ||
59 | struct zfcp_erp_action *); | ||
60 | |||
61 | static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *); | ||
62 | static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *); | ||
63 | |||
64 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *); | ||
65 | static int zfcp_erp_port_strategy_clearstati(struct zfcp_port *); | ||
66 | static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *); | ||
67 | static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *); | ||
68 | static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *); | ||
69 | static int zfcp_erp_port_strategy_open_nameserver_wakeup( | ||
70 | struct zfcp_erp_action *); | ||
71 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *); | ||
72 | static int zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *); | ||
73 | static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *); | ||
74 | |||
75 | static int zfcp_erp_unit_strategy(struct zfcp_erp_action *); | ||
76 | static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *); | ||
77 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); | ||
78 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); | ||
79 | |||
80 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); | ||
81 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *); | ||
82 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *); | ||
83 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *); | ||
84 | |||
85 | static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, | ||
86 | struct zfcp_port *, struct zfcp_unit *, | ||
87 | u8 id, void *ref); | ||
88 | static int zfcp_erp_action_dequeue(struct zfcp_erp_action *); | ||
89 | static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *, | ||
90 | struct zfcp_port *, struct zfcp_unit *, | ||
91 | int); | ||
92 | |||
93 | static void zfcp_erp_action_ready(struct zfcp_erp_action *); | ||
94 | static int zfcp_erp_action_exists(struct zfcp_erp_action *); | ||
95 | |||
96 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *); | ||
97 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *); | ||
98 | |||
99 | static void zfcp_erp_memwait_handler(unsigned long); | ||
100 | 20 | ||
101 | /** | 21 | enum zfcp_erp_steps { |
102 | * zfcp_close_fsf - stop FSF operations for an adapter | 22 | ZFCP_ERP_STEP_UNINITIALIZED = 0x0000, |
103 | * | 23 | ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, |
104 | * Dismiss and cleanup all pending fsf_reqs (this wakes up all initiators of | 24 | ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, |
105 | * requests waiting for completion; especially this returns SCSI commands | 25 | ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, |
106 | * with error state). | 26 | ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200, |
107 | */ | 27 | ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400, |
108 | static void zfcp_close_fsf(struct zfcp_adapter *adapter) | 28 | ZFCP_ERP_STEP_PORT_OPENING = 0x0800, |
109 | { | 29 | ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, |
110 | /* close queues to ensure that buffers are not accessed by adapter */ | 30 | ZFCP_ERP_STEP_UNIT_OPENING = 0x2000, |
111 | zfcp_qdio_close(adapter); | 31 | }; |
112 | zfcp_fsf_req_dismiss_all(adapter); | ||
113 | /* reset FSF request sequence number */ | ||
114 | adapter->fsf_req_seq_no = 0; | ||
115 | /* all ports and units are closed */ | ||
116 | zfcp_erp_modify_adapter_status(adapter, 24, NULL, | ||
117 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | ||
118 | } | ||
119 | 32 | ||
120 | /** | 33 | enum zfcp_erp_act_type { |
121 | * zfcp_fsf_request_timeout_handler - called if a request timed out | 34 | ZFCP_ERP_ACTION_REOPEN_UNIT = 1, |
122 | * @data: pointer to adapter for handler function | 35 | ZFCP_ERP_ACTION_REOPEN_PORT = 2, |
123 | * | 36 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, |
124 | * This function needs to be called if requests (ELS, Generic Service, | 37 | ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, |
125 | * or SCSI commands) exceed a certain time limit. The assumption is | 38 | }; |
126 | * that after the time limit the adapter get stuck. So we trigger a reopen of | 39 | |
127 | * the adapter. | 40 | enum zfcp_erp_act_state { |
128 | */ | 41 | ZFCP_ERP_ACTION_RUNNING = 1, |
129 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | 42 | ZFCP_ERP_ACTION_READY = 2, |
130 | { | 43 | }; |
131 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | ||
132 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62, | ||
133 | NULL); | ||
134 | } | ||
135 | 44 | ||
136 | void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) | 45 | enum zfcp_erp_act_result { |
46 | ZFCP_ERP_SUCCEEDED = 0, | ||
47 | ZFCP_ERP_FAILED = 1, | ||
48 | ZFCP_ERP_CONTINUES = 2, | ||
49 | ZFCP_ERP_EXIT = 3, | ||
50 | ZFCP_ERP_DISMISSED = 4, | ||
51 | ZFCP_ERP_NOMEM = 5, | ||
52 | }; | ||
53 | |||
54 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) | ||
137 | { | 55 | { |
138 | fsf_req->timer.function = zfcp_fsf_request_timeout_handler; | 56 | zfcp_erp_modify_adapter_status(adapter, 15, NULL, |
139 | fsf_req->timer.data = (unsigned long) fsf_req->adapter; | 57 | ZFCP_STATUS_COMMON_UNBLOCKED | mask, |
140 | fsf_req->timer.expires = jiffies + timeout; | 58 | ZFCP_CLEAR); |
141 | add_timer(&fsf_req->timer); | ||
142 | } | 59 | } |
143 | 60 | ||
144 | /* | 61 | static int zfcp_erp_action_exists(struct zfcp_erp_action *act) |
145 | * function: | ||
146 | * | ||
147 | * purpose: called if an adapter failed, | ||
148 | * initiates adapter recovery which is done | ||
149 | * asynchronously | ||
150 | * | ||
151 | * returns: 0 - initiated action successfully | ||
152 | * <0 - failed to initiate action | ||
153 | */ | ||
154 | static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, | ||
155 | int clear_mask, u8 id, void *ref) | ||
156 | { | 62 | { |
157 | int retval; | 63 | struct zfcp_erp_action *curr_act; |
158 | |||
159 | zfcp_erp_adapter_block(adapter, clear_mask); | ||
160 | 64 | ||
161 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { | 65 | list_for_each_entry(curr_act, &act->adapter->erp_running_head, list) |
162 | /* ensure propagation of failed status to new devices */ | 66 | if (act == curr_act) |
163 | zfcp_erp_adapter_failed(adapter, 13, NULL); | 67 | return ZFCP_ERP_ACTION_RUNNING; |
164 | retval = -EIO; | 68 | return 0; |
165 | goto out; | ||
166 | } | ||
167 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, | ||
168 | adapter, NULL, NULL, id, ref); | ||
169 | |||
170 | out: | ||
171 | return retval; | ||
172 | } | 69 | } |
173 | 70 | ||
174 | /* | 71 | static void zfcp_erp_action_ready(struct zfcp_erp_action *act) |
175 | * function: | ||
176 | * | ||
177 | * purpose: Wrappper for zfcp_erp_adapter_reopen_internal | ||
178 | * used to ensure the correct locking | ||
179 | * | ||
180 | * returns: 0 - initiated action successfully | ||
181 | * <0 - failed to initiate action | ||
182 | */ | ||
183 | int zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, | ||
184 | u8 id, void *ref) | ||
185 | { | 72 | { |
186 | int retval; | 73 | struct zfcp_adapter *adapter = act->adapter; |
187 | unsigned long flags; | ||
188 | 74 | ||
189 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 75 | list_move(&act->list, &act->adapter->erp_ready_head); |
190 | write_lock(&adapter->erp_lock); | 76 | zfcp_rec_dbf_event_action(146, act); |
191 | retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask, id, ref); | 77 | up(&adapter->erp_ready_sem); |
192 | write_unlock(&adapter->erp_lock); | 78 | zfcp_rec_dbf_event_thread(2, adapter); |
193 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
194 | |||
195 | return retval; | ||
196 | } | 79 | } |
197 | 80 | ||
198 | int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask, | 81 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) |
199 | u8 id, void *ref) | ||
200 | { | 82 | { |
201 | int retval; | 83 | act->status |= ZFCP_STATUS_ERP_DISMISSED; |
202 | 84 | if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING) | |
203 | retval = zfcp_erp_adapter_reopen(adapter, | 85 | zfcp_erp_action_ready(act); |
204 | ZFCP_STATUS_COMMON_RUNNING | | ||
205 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
206 | clear_mask, id, ref); | ||
207 | |||
208 | return retval; | ||
209 | } | 86 | } |
210 | 87 | ||
211 | int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask, u8 id, | 88 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) |
212 | void *ref) | ||
213 | { | 89 | { |
214 | int retval; | 90 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
91 | zfcp_erp_action_dismiss(&unit->erp_action); | ||
92 | } | ||
215 | 93 | ||
216 | retval = zfcp_erp_port_reopen(port, | 94 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) |
217 | ZFCP_STATUS_COMMON_RUNNING | | 95 | { |
218 | ZFCP_STATUS_COMMON_ERP_FAILED | | 96 | struct zfcp_unit *unit; |
219 | clear_mask, id, ref); | ||
220 | 97 | ||
221 | return retval; | 98 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
99 | zfcp_erp_action_dismiss(&port->erp_action); | ||
100 | else | ||
101 | list_for_each_entry(unit, &port->unit_list_head, list) | ||
102 | zfcp_erp_action_dismiss_unit(unit); | ||
222 | } | 103 | } |
223 | 104 | ||
224 | int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask, u8 id, | 105 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) |
225 | void *ref) | ||
226 | { | 106 | { |
227 | int retval; | 107 | struct zfcp_port *port; |
228 | |||
229 | retval = zfcp_erp_unit_reopen(unit, | ||
230 | ZFCP_STATUS_COMMON_RUNNING | | ||
231 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
232 | clear_mask, id, ref); | ||
233 | 108 | ||
234 | return retval; | 109 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE) |
110 | zfcp_erp_action_dismiss(&adapter->erp_action); | ||
111 | else | ||
112 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
113 | zfcp_erp_action_dismiss_port(port); | ||
235 | } | 114 | } |
236 | 115 | ||
237 | /* | 116 | static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, |
238 | * function: | 117 | struct zfcp_port *port, |
239 | * | 118 | struct zfcp_unit *unit) |
240 | * purpose: called if a port failed to be opened normally | ||
241 | * initiates Forced Reopen recovery which is done | ||
242 | * asynchronously | ||
243 | * | ||
244 | * returns: 0 - initiated action successfully | ||
245 | * <0 - failed to initiate action | ||
246 | */ | ||
247 | static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, | ||
248 | int clear_mask, u8 id, | ||
249 | void *ref) | ||
250 | { | 119 | { |
251 | int retval; | 120 | int need = want; |
252 | 121 | int u_status, p_status, a_status; | |
253 | zfcp_erp_port_block(port, clear_mask); | ||
254 | 122 | ||
255 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | 123 | switch (want) { |
256 | retval = -EIO; | 124 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
257 | goto out; | 125 | u_status = atomic_read(&unit->status); |
126 | if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
127 | return 0; | ||
128 | p_status = atomic_read(&port->status); | ||
129 | if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) || | ||
130 | p_status & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
131 | return 0; | ||
132 | if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED)) | ||
133 | need = ZFCP_ERP_ACTION_REOPEN_PORT; | ||
134 | /* fall through */ | ||
135 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
136 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
137 | p_status = atomic_read(&port->status); | ||
138 | if (p_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
139 | return 0; | ||
140 | a_status = atomic_read(&adapter->status); | ||
141 | if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) || | ||
142 | a_status & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
143 | return 0; | ||
144 | if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED)) | ||
145 | need = ZFCP_ERP_ACTION_REOPEN_ADAPTER; | ||
146 | /* fall through */ | ||
147 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
148 | a_status = atomic_read(&adapter->status); | ||
149 | if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE) | ||
150 | return 0; | ||
258 | } | 151 | } |
259 | 152 | ||
260 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, | 153 | return need; |
261 | port->adapter, port, NULL, id, ref); | ||
262 | |||
263 | out: | ||
264 | return retval; | ||
265 | } | 154 | } |
266 | 155 | ||
267 | /* | 156 | static struct zfcp_erp_action *zfcp_erp_setup_act(int need, |
268 | * function: | 157 | struct zfcp_adapter *adapter, |
269 | * | 158 | struct zfcp_port *port, |
270 | * purpose: Wrappper for zfcp_erp_port_forced_reopen_internal | 159 | struct zfcp_unit *unit) |
271 | * used to ensure the correct locking | ||
272 | * | ||
273 | * returns: 0 - initiated action successfully | ||
274 | * <0 - failed to initiate action | ||
275 | */ | ||
276 | int zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask, u8 id, | ||
277 | void *ref) | ||
278 | { | 160 | { |
279 | int retval; | 161 | struct zfcp_erp_action *erp_action; |
280 | unsigned long flags; | 162 | u32 status = 0; |
281 | struct zfcp_adapter *adapter; | ||
282 | |||
283 | adapter = port->adapter; | ||
284 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
285 | write_lock(&adapter->erp_lock); | ||
286 | retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask, id, | ||
287 | ref); | ||
288 | write_unlock(&adapter->erp_lock); | ||
289 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
290 | 163 | ||
291 | return retval; | 164 | switch (need) { |
292 | } | 165 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
166 | zfcp_unit_get(unit); | ||
167 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | ||
168 | erp_action = &unit->erp_action; | ||
169 | if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) | ||
170 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
171 | break; | ||
293 | 172 | ||
294 | /* | 173 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
295 | * function: | 174 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
296 | * | 175 | zfcp_port_get(port); |
297 | * purpose: called if a port is to be opened | 176 | zfcp_erp_action_dismiss_port(port); |
298 | * initiates Reopen recovery which is done | 177 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); |
299 | * asynchronously | 178 | erp_action = &port->erp_action; |
300 | * | 179 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) |
301 | * returns: 0 - initiated action successfully | 180 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; |
302 | * <0 - failed to initiate action | 181 | break; |
303 | */ | ||
304 | static int zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask, | ||
305 | u8 id, void *ref) | ||
306 | { | ||
307 | int retval; | ||
308 | 182 | ||
309 | zfcp_erp_port_block(port, clear_mask); | 183 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
184 | zfcp_adapter_get(adapter); | ||
185 | zfcp_erp_action_dismiss_adapter(adapter); | ||
186 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); | ||
187 | erp_action = &adapter->erp_action; | ||
188 | if (!(atomic_read(&adapter->status) & | ||
189 | ZFCP_STATUS_COMMON_RUNNING)) | ||
190 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
191 | break; | ||
310 | 192 | ||
311 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | 193 | default: |
312 | /* ensure propagation of failed status to new devices */ | 194 | return NULL; |
313 | zfcp_erp_port_failed(port, 14, NULL); | ||
314 | retval = -EIO; | ||
315 | goto out; | ||
316 | } | 195 | } |
317 | 196 | ||
318 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, | 197 | memset(erp_action, 0, sizeof(struct zfcp_erp_action)); |
319 | port->adapter, port, NULL, id, ref); | 198 | erp_action->adapter = adapter; |
199 | erp_action->port = port; | ||
200 | erp_action->unit = unit; | ||
201 | erp_action->action = need; | ||
202 | erp_action->status = status; | ||
320 | 203 | ||
321 | out: | 204 | return erp_action; |
322 | return retval; | ||
323 | } | 205 | } |
324 | 206 | ||
325 | /** | 207 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, |
326 | * zfcp_erp_port_reopen - initiate reopen of a remote port | 208 | struct zfcp_port *port, |
327 | * @port: port to be reopened | 209 | struct zfcp_unit *unit, u8 id, void *ref) |
328 | * @clear_mask: specifies flags in port status to be cleared | ||
329 | * Return: 0 on success, < 0 on error | ||
330 | * | ||
331 | * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures | ||
332 | * correct locking. An error recovery task is initiated to do the reopen. | ||
333 | * To wait for the completion of the reopen zfcp_erp_wait should be used. | ||
334 | */ | ||
335 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask, u8 id, | ||
336 | void *ref) | ||
337 | { | 210 | { |
338 | int retval; | 211 | int retval = 1, need; |
339 | unsigned long flags; | 212 | struct zfcp_erp_action *act = NULL; |
340 | struct zfcp_adapter *adapter = port->adapter; | ||
341 | 213 | ||
342 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 214 | if (!(atomic_read(&adapter->status) & |
343 | write_lock(&adapter->erp_lock); | 215 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP)) |
344 | retval = zfcp_erp_port_reopen_internal(port, clear_mask, id, ref); | 216 | return -EIO; |
345 | write_unlock(&adapter->erp_lock); | 217 | |
346 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 218 | need = zfcp_erp_required_act(want, adapter, port, unit); |
219 | if (!need) | ||
220 | goto out; | ||
347 | 221 | ||
222 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | ||
223 | act = zfcp_erp_setup_act(need, adapter, port, unit); | ||
224 | if (!act) | ||
225 | goto out; | ||
226 | ++adapter->erp_total_count; | ||
227 | list_add_tail(&act->list, &adapter->erp_ready_head); | ||
228 | up(&adapter->erp_ready_sem); | ||
229 | zfcp_rec_dbf_event_thread(1, adapter); | ||
230 | retval = 0; | ||
231 | out: | ||
232 | zfcp_rec_dbf_event_trigger(id, ref, want, need, act, | ||
233 | adapter, port, unit); | ||
348 | return retval; | 234 | return retval; |
349 | } | 235 | } |
350 | 236 | ||
351 | /* | 237 | static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, |
352 | * function: | 238 | int clear_mask, u8 id, void *ref) |
353 | * | ||
354 | * purpose: called if a unit is to be opened | ||
355 | * initiates Reopen recovery which is done | ||
356 | * asynchronously | ||
357 | * | ||
358 | * returns: 0 - initiated action successfully | ||
359 | * <0 - failed to initiate action | ||
360 | */ | ||
361 | static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask, | ||
362 | u8 id, void *ref) | ||
363 | { | 239 | { |
364 | int retval; | 240 | zfcp_erp_adapter_block(adapter, clear_mask); |
365 | struct zfcp_adapter *adapter = unit->port->adapter; | ||
366 | |||
367 | zfcp_erp_unit_block(unit, clear_mask); | ||
368 | 241 | ||
369 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { | 242 | /* ensure propagation of failed status to new devices */ |
370 | retval = -EIO; | 243 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
371 | goto out; | 244 | zfcp_erp_adapter_failed(adapter, 13, NULL); |
245 | return -EIO; | ||
372 | } | 246 | } |
373 | 247 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, | |
374 | retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, | 248 | adapter, NULL, NULL, id, ref); |
375 | adapter, unit->port, unit, id, ref); | ||
376 | out: | ||
377 | return retval; | ||
378 | } | 249 | } |
379 | 250 | ||
380 | /** | 251 | /** |
381 | * zfcp_erp_unit_reopen - initiate reopen of a unit | 252 | * zfcp_erp_adapter_reopen - Reopen adapter. |
382 | * @unit: unit to be reopened | 253 | * @adapter: Adapter to reopen. |
383 | * @clear_mask: specifies flags in unit status to be cleared | 254 | * @clear: Status flags to clear. |
384 | * Return: 0 on success, < 0 on error | 255 | * @id: Id for debug trace event. |
385 | * | 256 | * @ref: Reference for debug trace event. |
386 | * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct | ||
387 | * locking. An error recovery task is initiated to do the reopen. | ||
388 | * To wait for the completion of the reopen zfcp_erp_wait should be used. | ||
389 | */ | 257 | */ |
390 | int zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask, u8 id, | 258 | void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, |
391 | void *ref) | 259 | u8 id, void *ref) |
392 | { | 260 | { |
393 | int retval; | ||
394 | unsigned long flags; | 261 | unsigned long flags; |
395 | struct zfcp_adapter *adapter; | ||
396 | struct zfcp_port *port; | ||
397 | |||
398 | port = unit->port; | ||
399 | adapter = port->adapter; | ||
400 | 262 | ||
401 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 263 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
402 | write_lock(&adapter->erp_lock); | 264 | write_lock(&adapter->erp_lock); |
403 | retval = zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref); | 265 | _zfcp_erp_adapter_reopen(adapter, clear, id, ref); |
404 | write_unlock(&adapter->erp_lock); | 266 | write_unlock(&adapter->erp_lock); |
405 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 267 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
406 | |||
407 | return retval; | ||
408 | } | 268 | } |
409 | 269 | ||
410 | /** | 270 | /** |
411 | * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests | 271 | * zfcp_erp_adapter_shutdown - Shutdown adapter. |
272 | * @adapter: Adapter to shut down. | ||
273 | * @clear: Status flags to clear. | ||
274 | * @id: Id for debug trace event. | ||
275 | * @ref: Reference for debug trace event. | ||
412 | */ | 276 | */ |
413 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) | 277 | void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, |
278 | u8 id, void *ref) | ||
414 | { | 279 | { |
415 | zfcp_erp_modify_adapter_status(adapter, 15, NULL, | 280 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
416 | ZFCP_STATUS_COMMON_UNBLOCKED | | 281 | zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref); |
417 | clear_mask, ZFCP_CLEAR); | ||
418 | } | 282 | } |
419 | 283 | ||
420 | /* FIXME: isn't really atomic */ | 284 | /** |
421 | /* | 285 | * zfcp_erp_port_shutdown - Shutdown port |
422 | * returns the mask which has not been set so far, i.e. | 286 | * @port: Port to shut down. |
423 | * 0 if no bit has been changed, !0 if some bit has been changed | 287 | * @clear: Status flags to clear. |
424 | */ | 288 | * @id: Id for debug trace event. |
425 | static int atomic_test_and_set_mask(unsigned long mask, atomic_t *v) | 289 | * @ref: Reference for debug trace event. |
426 | { | ||
427 | int changed_bits = (atomic_read(v) /*XOR*/^ mask) & mask; | ||
428 | atomic_set_mask(mask, v); | ||
429 | return changed_bits; | ||
430 | } | ||
431 | |||
432 | /* FIXME: isn't really atomic */ | ||
433 | /* | ||
434 | * returns the mask which has not been cleared so far, i.e. | ||
435 | * 0 if no bit has been changed, !0 if some bit has been changed | ||
436 | */ | 290 | */ |
437 | static int atomic_test_and_clear_mask(unsigned long mask, atomic_t *v) | 291 | void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, u8 id, void *ref) |
438 | { | 292 | { |
439 | int changed_bits = atomic_read(v) & mask; | 293 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
440 | atomic_clear_mask(mask, v); | 294 | zfcp_erp_port_reopen(port, clear | flags, id, ref); |
441 | return changed_bits; | ||
442 | } | 295 | } |
443 | 296 | ||
444 | /** | 297 | /** |
445 | * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests | 298 | * zfcp_erp_unit_shutdown - Shutdown unit |
299 | * @unit: Unit to shut down. | ||
300 | * @clear: Status flags to clear. | ||
301 | * @id: Id for debug trace event. | ||
302 | * @ref: Reference for debug trace event. | ||
446 | */ | 303 | */ |
447 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) | 304 | void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, u8 id, void *ref) |
448 | { | 305 | { |
449 | if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | 306 | int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; |
450 | &adapter->status)) | 307 | zfcp_erp_unit_reopen(unit, clear | flags, id, ref); |
451 | zfcp_rec_dbf_event_adapter(16, NULL, adapter); | ||
452 | } | 308 | } |
453 | 309 | ||
454 | /* | 310 | static void zfcp_erp_port_block(struct zfcp_port *port, int clear) |
455 | * function: | ||
456 | * | ||
457 | * purpose: disable I/O, | ||
458 | * return any open requests and clean them up, | ||
459 | * aim: no pending and incoming I/O | ||
460 | * | ||
461 | * returns: | ||
462 | */ | ||
463 | static void | ||
464 | zfcp_erp_port_block(struct zfcp_port *port, int clear_mask) | ||
465 | { | 311 | { |
466 | zfcp_erp_modify_port_status(port, 17, NULL, | 312 | zfcp_erp_modify_port_status(port, 17, NULL, |
467 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | 313 | ZFCP_STATUS_COMMON_UNBLOCKED | clear, |
468 | ZFCP_CLEAR); | 314 | ZFCP_CLEAR); |
469 | } | 315 | } |
470 | 316 | ||
471 | /* | 317 | static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, |
472 | * function: | 318 | int clear, u8 id, void *ref) |
473 | * | ||
474 | * purpose: enable I/O | ||
475 | * | ||
476 | * returns: | ||
477 | */ | ||
478 | static void | ||
479 | zfcp_erp_port_unblock(struct zfcp_port *port) | ||
480 | { | 319 | { |
481 | if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | 320 | zfcp_erp_port_block(port, clear); |
482 | &port->status)) | ||
483 | zfcp_rec_dbf_event_port(18, NULL, port); | ||
484 | } | ||
485 | 321 | ||
486 | /* | 322 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
487 | * function: | 323 | return; |
488 | * | ||
489 | * purpose: disable I/O, | ||
490 | * return any open requests and clean them up, | ||
491 | * aim: no pending and incoming I/O | ||
492 | * | ||
493 | * returns: | ||
494 | */ | ||
495 | static void | ||
496 | zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) | ||
497 | { | ||
498 | zfcp_erp_modify_unit_status(unit, 19, NULL, | ||
499 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | ||
500 | ZFCP_CLEAR); | ||
501 | } | ||
502 | |||
503 | /* | ||
504 | * function: | ||
505 | * | ||
506 | * purpose: enable I/O | ||
507 | * | ||
508 | * returns: | ||
509 | */ | ||
510 | static void | ||
511 | zfcp_erp_unit_unblock(struct zfcp_unit *unit) | ||
512 | { | ||
513 | if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | ||
514 | &unit->status)) | ||
515 | zfcp_rec_dbf_event_unit(20, NULL, unit); | ||
516 | } | ||
517 | |||
518 | static void | ||
519 | zfcp_erp_action_ready(struct zfcp_erp_action *erp_action) | ||
520 | { | ||
521 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
522 | |||
523 | zfcp_erp_action_to_ready(erp_action); | ||
524 | up(&adapter->erp_ready_sem); | ||
525 | zfcp_rec_dbf_event_thread(2, adapter); | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * function: | ||
530 | * | ||
531 | * purpose: | ||
532 | * | ||
533 | * returns: <0 erp_action not found in any list | ||
534 | * ZFCP_ERP_ACTION_READY erp_action is in ready list | ||
535 | * ZFCP_ERP_ACTION_RUNNING erp_action is in running list | ||
536 | * | ||
537 | * locks: erp_lock must be held | ||
538 | */ | ||
539 | static int | ||
540 | zfcp_erp_action_exists(struct zfcp_erp_action *erp_action) | ||
541 | { | ||
542 | int retval = -EINVAL; | ||
543 | struct list_head *entry; | ||
544 | struct zfcp_erp_action *entry_erp_action; | ||
545 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
546 | |||
547 | /* search in running list */ | ||
548 | list_for_each(entry, &adapter->erp_running_head) { | ||
549 | entry_erp_action = | ||
550 | list_entry(entry, struct zfcp_erp_action, list); | ||
551 | if (entry_erp_action == erp_action) { | ||
552 | retval = ZFCP_ERP_ACTION_RUNNING; | ||
553 | goto out; | ||
554 | } | ||
555 | } | ||
556 | /* search in ready list */ | ||
557 | list_for_each(entry, &adapter->erp_ready_head) { | ||
558 | entry_erp_action = | ||
559 | list_entry(entry, struct zfcp_erp_action, list); | ||
560 | if (entry_erp_action == erp_action) { | ||
561 | retval = ZFCP_ERP_ACTION_READY; | ||
562 | goto out; | ||
563 | } | ||
564 | } | ||
565 | |||
566 | out: | ||
567 | return retval; | ||
568 | } | ||
569 | |||
570 | /* | ||
571 | * purpose: checks current status of action (timed out, dismissed, ...) | ||
572 | * and does appropriate preparations (dismiss fsf request, ...) | ||
573 | * | ||
574 | * locks: called under erp_lock (disabled interrupts) | ||
575 | */ | ||
576 | static void | ||
577 | zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | ||
578 | { | ||
579 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
580 | |||
581 | if (erp_action->fsf_req) { | ||
582 | /* take lock to ensure that request is not deleted meanwhile */ | ||
583 | spin_lock(&adapter->req_list_lock); | ||
584 | if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) && | ||
585 | erp_action->fsf_req->erp_action == erp_action) { | ||
586 | /* fsf_req still exists */ | ||
587 | /* dismiss fsf_req of timed out/dismissed erp_action */ | ||
588 | if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | | ||
589 | ZFCP_STATUS_ERP_TIMEDOUT)) { | ||
590 | erp_action->fsf_req->status |= | ||
591 | ZFCP_STATUS_FSFREQ_DISMISSED; | ||
592 | zfcp_rec_dbf_event_action(142, erp_action); | ||
593 | } | ||
594 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
595 | zfcp_rec_dbf_event_action(143, erp_action); | ||
596 | /* | ||
597 | * If fsf_req is neither dismissed nor completed | ||
598 | * then keep it running asynchronously and don't mess | ||
599 | * with the association of erp_action and fsf_req. | ||
600 | */ | ||
601 | if (erp_action->fsf_req->status & | ||
602 | (ZFCP_STATUS_FSFREQ_COMPLETED | | ||
603 | ZFCP_STATUS_FSFREQ_DISMISSED)) { | ||
604 | /* forget about association between fsf_req | ||
605 | and erp_action */ | ||
606 | erp_action->fsf_req = NULL; | ||
607 | } | ||
608 | } else { | ||
609 | /* | ||
610 | * even if this fsf_req has gone, forget about | ||
611 | * association between erp_action and fsf_req | ||
612 | */ | ||
613 | erp_action->fsf_req = NULL; | ||
614 | } | ||
615 | spin_unlock(&adapter->req_list_lock); | ||
616 | } | ||
617 | } | ||
618 | 324 | ||
619 | /** | 325 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, |
620 | * zfcp_erp_async_handler_nolock - complete erp_action | 326 | port->adapter, port, NULL, id, ref); |
621 | * | ||
622 | * Used for normal completion, time-out, dismissal and failure after | ||
623 | * low memory condition. | ||
624 | */ | ||
625 | static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, | ||
626 | unsigned long set_mask) | ||
627 | { | ||
628 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { | ||
629 | erp_action->status |= set_mask; | ||
630 | zfcp_erp_action_ready(erp_action); | ||
631 | } else { | ||
632 | /* action is ready or gone - nothing to do */ | ||
633 | } | ||
634 | } | 327 | } |
635 | 328 | ||
636 | /** | 329 | /** |
637 | * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking | 330 | * zfcp_erp_port_forced_reopen - Forced close of port and open again |
331 | * @port: Port to force close and to reopen. | ||
332 | * @id: Id for debug trace event. | ||
333 | * @ref: Reference for debug trace event. | ||
638 | */ | 334 | */ |
639 | void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, | 335 | void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, u8 id, |
640 | unsigned long set_mask) | 336 | void *ref) |
641 | { | 337 | { |
642 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
643 | unsigned long flags; | 338 | unsigned long flags; |
339 | struct zfcp_adapter *adapter = port->adapter; | ||
644 | 340 | ||
645 | write_lock_irqsave(&adapter->erp_lock, flags); | 341 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
646 | zfcp_erp_async_handler_nolock(erp_action, set_mask); | 342 | write_lock(&adapter->erp_lock); |
647 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 343 | _zfcp_erp_port_forced_reopen(port, clear, id, ref); |
344 | write_unlock(&adapter->erp_lock); | ||
345 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
648 | } | 346 | } |
649 | 347 | ||
650 | /* | 348 | static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, |
651 | * purpose: is called for erp_action which was slept waiting for | 349 | void *ref) |
652 | * memory becoming avaliable, | ||
653 | * will trigger that this action will be continued | ||
654 | */ | ||
655 | static void | ||
656 | zfcp_erp_memwait_handler(unsigned long data) | ||
657 | { | 350 | { |
658 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; | 351 | zfcp_erp_port_block(port, clear); |
659 | |||
660 | zfcp_erp_async_handler(erp_action, 0); | ||
661 | } | ||
662 | 352 | ||
663 | /* | 353 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
664 | * purpose: is called if an asynchronous erp step timed out, | 354 | /* ensure propagation of failed status to new devices */ |
665 | * action gets an appropriate flag and will be processed | 355 | zfcp_erp_port_failed(port, 14, NULL); |
666 | * accordingly | 356 | return -EIO; |
667 | */ | 357 | } |
668 | static void zfcp_erp_timeout_handler(unsigned long data) | ||
669 | { | ||
670 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; | ||
671 | 358 | ||
672 | zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); | 359 | return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, |
360 | port->adapter, port, NULL, id, ref); | ||
673 | } | 361 | } |
674 | 362 | ||
675 | /** | 363 | /** |
676 | * zfcp_erp_action_dismiss - dismiss an erp_action | 364 | * zfcp_erp_port_reopen - trigger remote port recovery |
365 | * @port: port to recover | ||
366 | * @clear_mask: flags in port status to be cleared | ||
677 | * | 367 | * |
678 | * adapter->erp_lock must be held | 368 | * Returns 0 if recovery has been triggered, < 0 if not. |
679 | * | ||
680 | * Dismissal of an erp_action is usually required if an erp_action of | ||
681 | * higher priority is generated. | ||
682 | */ | 369 | */ |
683 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) | 370 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, void *ref) |
684 | { | ||
685 | erp_action->status |= ZFCP_STATUS_ERP_DISMISSED; | ||
686 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) | ||
687 | zfcp_erp_action_ready(erp_action); | ||
688 | } | ||
689 | |||
690 | int | ||
691 | zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | ||
692 | { | 371 | { |
693 | int retval = 0; | 372 | unsigned long flags; |
694 | 373 | int retval; | |
695 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | 374 | struct zfcp_adapter *adapter = port->adapter; |
696 | 375 | ||
697 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | 376 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
698 | if (retval < 0) | 377 | write_lock(&adapter->erp_lock); |
699 | dev_err(&adapter->ccw_device->dev, | 378 | retval = _zfcp_erp_port_reopen(port, clear, id, ref); |
700 | "Creation of ERP thread failed.\n"); | 379 | write_unlock(&adapter->erp_lock); |
701 | else { | 380 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
702 | wait_event(adapter->erp_thread_wqh, | ||
703 | atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, | ||
704 | &adapter->status)); | ||
705 | } | ||
706 | 381 | ||
707 | return (retval < 0); | 382 | return retval; |
708 | } | 383 | } |
709 | 384 | ||
710 | /* | 385 | static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) |
711 | * function: | ||
712 | * | ||
713 | * purpose: | ||
714 | * | ||
715 | * returns: | ||
716 | * | ||
717 | * context: process (i.e. proc-fs or rmmod/insmod) | ||
718 | * | ||
719 | * note: The caller of this routine ensures that the specified | ||
720 | * adapter has been shut down and that this operation | ||
721 | * has been completed. Thus, there are no pending erp_actions | ||
722 | * which would need to be handled here. | ||
723 | */ | ||
724 | int | ||
725 | zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | ||
726 | { | 386 | { |
727 | int retval = 0; | 387 | zfcp_erp_modify_unit_status(unit, 19, NULL, |
728 | 388 | ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, | |
729 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); | 389 | ZFCP_CLEAR); |
730 | up(&adapter->erp_ready_sem); | ||
731 | zfcp_rec_dbf_event_thread_lock(2, adapter); | ||
732 | |||
733 | wait_event(adapter->erp_thread_wqh, | ||
734 | !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, | ||
735 | &adapter->status)); | ||
736 | |||
737 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, | ||
738 | &adapter->status); | ||
739 | |||
740 | return retval; | ||
741 | } | 390 | } |
742 | 391 | ||
743 | /* | 392 | static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, |
744 | * purpose: is run as a kernel thread, | 393 | void *ref) |
745 | * goes through list of error recovery actions of associated adapter | ||
746 | * and delegates single action to execution | ||
747 | * | ||
748 | * returns: 0 | ||
749 | */ | ||
750 | static int | ||
751 | zfcp_erp_thread(void *data) | ||
752 | { | 394 | { |
753 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | 395 | struct zfcp_adapter *adapter = unit->port->adapter; |
754 | struct list_head *next; | ||
755 | struct zfcp_erp_action *erp_action; | ||
756 | unsigned long flags; | ||
757 | |||
758 | daemonize("zfcperp%s", zfcp_get_busid_by_adapter(adapter)); | ||
759 | /* Block all signals */ | ||
760 | siginitsetinv(¤t->blocked, 0); | ||
761 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
762 | wake_up(&adapter->erp_thread_wqh); | ||
763 | |||
764 | while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, | ||
765 | &adapter->status)) { | ||
766 | |||
767 | write_lock_irqsave(&adapter->erp_lock, flags); | ||
768 | next = adapter->erp_ready_head.next; | ||
769 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
770 | 396 | ||
771 | if (next != &adapter->erp_ready_head) { | 397 | zfcp_erp_unit_block(unit, clear); |
772 | erp_action = | ||
773 | list_entry(next, struct zfcp_erp_action, list); | ||
774 | /* | ||
775 | * process action (incl. [re]moving it | ||
776 | * from 'ready' queue) | ||
777 | */ | ||
778 | zfcp_erp_strategy(erp_action); | ||
779 | } | ||
780 | 398 | ||
781 | /* | 399 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) |
782 | * sleep as long as there is nothing to do, i.e. | 400 | return; |
783 | * no action in 'ready' queue to be processed and | ||
784 | * thread is not to be killed | ||
785 | */ | ||
786 | zfcp_rec_dbf_event_thread_lock(4, adapter); | ||
787 | down_interruptible(&adapter->erp_ready_sem); | ||
788 | zfcp_rec_dbf_event_thread_lock(5, adapter); | ||
789 | } | ||
790 | |||
791 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
792 | wake_up(&adapter->erp_thread_wqh); | ||
793 | 401 | ||
794 | return 0; | 402 | zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, |
403 | adapter, unit->port, unit, id, ref); | ||
795 | } | 404 | } |
796 | 405 | ||
797 | /* | 406 | /** |
798 | * function: | 407 | * zfcp_erp_unit_reopen - initiate reopen of a unit |
799 | * | 408 | * @unit: unit to be reopened |
800 | * purpose: drives single error recovery action and schedules higher and | 409 | * @clear_mask: specifies flags in unit status to be cleared |
801 | * subordinate actions, if necessary | 410 | * Return: 0 on success, < 0 on error |
802 | * | ||
803 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
804 | * ZFCP_ERP_SUCCEEDED - action finished successfully (deqd) | ||
805 | * ZFCP_ERP_FAILED - action finished unsuccessfully (deqd) | ||
806 | * ZFCP_ERP_EXIT - action finished (dequeued), offline | ||
807 | * ZFCP_ERP_DISMISSED - action canceled (dequeued) | ||
808 | */ | 411 | */ |
809 | static int | 412 | void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, void *ref) |
810 | zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | ||
811 | { | 413 | { |
812 | int retval = 0; | ||
813 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
814 | struct zfcp_port *port = erp_action->port; | ||
815 | struct zfcp_unit *unit = erp_action->unit; | ||
816 | int action = erp_action->action; | ||
817 | u32 status = erp_action->status; | ||
818 | unsigned long flags; | 414 | unsigned long flags; |
415 | struct zfcp_port *port = unit->port; | ||
416 | struct zfcp_adapter *adapter = port->adapter; | ||
819 | 417 | ||
820 | /* serialise dismissing, timing out, moving, enqueueing */ | ||
821 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 418 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
822 | write_lock(&adapter->erp_lock); | 419 | write_lock(&adapter->erp_lock); |
823 | 420 | _zfcp_erp_unit_reopen(unit, clear, id, ref); | |
824 | /* dequeue dismissed action and leave, if required */ | ||
825 | retval = zfcp_erp_strategy_check_action(erp_action, retval); | ||
826 | if (retval == ZFCP_ERP_DISMISSED) { | ||
827 | goto unlock; | ||
828 | } | ||
829 | |||
830 | /* | ||
831 | * move action to 'running' queue before processing it | ||
832 | * (to avoid a race condition regarding moving the | ||
833 | * action to the 'running' queue and back) | ||
834 | */ | ||
835 | zfcp_erp_action_to_running(erp_action); | ||
836 | |||
837 | /* | ||
838 | * try to process action as far as possible, | ||
839 | * no lock to allow for blocking operations (kmalloc, qdio, ...), | ||
840 | * afterwards the lock is required again for the following reasons: | ||
841 | * - dequeueing of finished action and enqueueing of | ||
842 | * follow-up actions must be atomic so that any other | ||
843 | * reopen-routine does not believe there is nothing to do | ||
844 | * and that it is safe to enqueue something else, | ||
845 | * - we want to force any control thread which is dismissing | ||
846 | * actions to finish this before we decide about | ||
847 | * necessary steps to be taken here further | ||
848 | */ | ||
849 | write_unlock(&adapter->erp_lock); | ||
850 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
851 | retval = zfcp_erp_strategy_do_action(erp_action); | ||
852 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
853 | write_lock(&adapter->erp_lock); | ||
854 | |||
855 | /* | ||
856 | * check for dismissed status again to avoid follow-up actions, | ||
857 | * failing of targets and so on for dismissed actions, | ||
858 | * we go through down() here because there has been an up() | ||
859 | */ | ||
860 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) | ||
861 | retval = ZFCP_ERP_CONTINUES; | ||
862 | |||
863 | switch (retval) { | ||
864 | case ZFCP_ERP_NOMEM: | ||
865 | /* no memory to continue immediately, let it sleep */ | ||
866 | if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) { | ||
867 | ++adapter->erp_low_mem_count; | ||
868 | erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; | ||
869 | } | ||
870 | /* This condition is true if there is no memory available | ||
871 | for any erp_action on this adapter. This implies that there | ||
872 | are no elements in the memory pool(s) left for erp_actions. | ||
873 | This might happen if an erp_action that used a memory pool | ||
874 | element was timed out. | ||
875 | */ | ||
876 | if (adapter->erp_total_count == adapter->erp_low_mem_count) | ||
877 | zfcp_erp_adapter_reopen_internal(adapter, 0, 66, NULL); | ||
878 | else | ||
879 | retval = zfcp_erp_strategy_memwait(erp_action); | ||
880 | goto unlock; | ||
881 | case ZFCP_ERP_CONTINUES: | ||
882 | /* leave since this action runs asynchronously */ | ||
883 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | ||
884 | --adapter->erp_low_mem_count; | ||
885 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; | ||
886 | } | ||
887 | goto unlock; | ||
888 | } | ||
889 | /* ok, finished action (whatever its result is) */ | ||
890 | |||
891 | /* check for unrecoverable targets */ | ||
892 | retval = zfcp_erp_strategy_check_target(erp_action, retval); | ||
893 | |||
894 | /* action must be dequeued (here to allow for further ones) */ | ||
895 | zfcp_erp_action_dequeue(erp_action); | ||
896 | |||
897 | /* | ||
898 | * put this target through the erp mill again if someone has | ||
899 | * requested to change the status of a target being online | ||
900 | * to offline or the other way around | ||
901 | * (old retval is preserved if nothing has to be done here) | ||
902 | */ | ||
903 | retval = zfcp_erp_strategy_statechange(action, status, adapter, | ||
904 | port, unit, retval); | ||
905 | |||
906 | /* | ||
907 | * leave if target is in permanent error state or if | ||
908 | * action is repeated in order to process state change | ||
909 | */ | ||
910 | if (retval == ZFCP_ERP_EXIT) { | ||
911 | goto unlock; | ||
912 | } | ||
913 | |||
914 | /* trigger follow up actions */ | ||
915 | zfcp_erp_strategy_followup_actions(action, adapter, port, unit, retval); | ||
916 | |||
917 | unlock: | ||
918 | write_unlock(&adapter->erp_lock); | 421 | write_unlock(&adapter->erp_lock); |
919 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 422 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
920 | |||
921 | if (retval != ZFCP_ERP_CONTINUES) | ||
922 | zfcp_erp_action_cleanup(action, adapter, port, unit, retval); | ||
923 | |||
924 | /* | ||
925 | * a few tasks remain when the erp queues are empty | ||
926 | * (don't do that if the last action evaluated was dismissed | ||
927 | * since this clearly indicates that there is more to come) : | ||
928 | * - close the name server port if it is open yet | ||
929 | * (enqueues another [probably] final action) | ||
930 | * - otherwise, wake up whoever wants to be woken when we are | ||
931 | * done with erp | ||
932 | */ | ||
933 | if (retval != ZFCP_ERP_DISMISSED) | ||
934 | zfcp_erp_strategy_check_queues(adapter); | ||
935 | |||
936 | return retval; | ||
937 | } | 423 | } |
938 | 424 | ||
939 | /* | 425 | static int status_change_set(unsigned long mask, atomic_t *status) |
940 | * function: | ||
941 | * | ||
942 | * purpose: | ||
943 | * | ||
944 | * returns: ZFCP_ERP_DISMISSED - if action has been dismissed | ||
945 | * retval - otherwise | ||
946 | */ | ||
947 | static int | ||
948 | zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval) | ||
949 | { | 426 | { |
950 | zfcp_erp_strategy_check_fsfreq(erp_action); | 427 | return (atomic_read(status) ^ mask) & mask; |
951 | |||
952 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { | ||
953 | zfcp_erp_action_dequeue(erp_action); | ||
954 | retval = ZFCP_ERP_DISMISSED; | ||
955 | } | ||
956 | |||
957 | return retval; | ||
958 | } | 428 | } |
959 | 429 | ||
960 | static int | 430 | static int status_change_clear(unsigned long mask, atomic_t *status) |
961 | zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) | ||
962 | { | 431 | { |
963 | int retval = ZFCP_ERP_FAILED; | 432 | return atomic_read(status) & mask; |
964 | |||
965 | /* | ||
966 | * try to execute/continue action as far as possible, | ||
967 | * note: no lock in subsequent strategy routines | ||
968 | * (this allows these routine to call schedule, e.g. | ||
969 | * kmalloc with such flags or qdio_initialize & friends) | ||
970 | * Note: in case of timeout, the separate strategies will fail | ||
971 | * anyhow. No need for a special action. Even worse, a nameserver | ||
972 | * failure would not wake up waiting ports without the call. | ||
973 | */ | ||
974 | switch (erp_action->action) { | ||
975 | |||
976 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
977 | retval = zfcp_erp_adapter_strategy(erp_action); | ||
978 | break; | ||
979 | |||
980 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
981 | retval = zfcp_erp_port_forced_strategy(erp_action); | ||
982 | break; | ||
983 | |||
984 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
985 | retval = zfcp_erp_port_strategy(erp_action); | ||
986 | break; | ||
987 | |||
988 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | ||
989 | retval = zfcp_erp_unit_strategy(erp_action); | ||
990 | break; | ||
991 | } | ||
992 | |||
993 | return retval; | ||
994 | } | 433 | } |
995 | 434 | ||
996 | /* | 435 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) |
997 | * function: | ||
998 | * | ||
999 | * purpose: triggers retry of this action after a certain amount of time | ||
1000 | * by means of timer provided by erp_action | ||
1001 | * | ||
1002 | * returns: ZFCP_ERP_CONTINUES - erp_action sleeps in erp running queue | ||
1003 | */ | ||
1004 | static int | ||
1005 | zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) | ||
1006 | { | 436 | { |
1007 | int retval = ZFCP_ERP_CONTINUES; | 437 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) |
1008 | 438 | zfcp_rec_dbf_event_adapter(16, NULL, adapter); | |
1009 | init_timer(&erp_action->timer); | 439 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); |
1010 | erp_action->timer.function = zfcp_erp_memwait_handler; | ||
1011 | erp_action->timer.data = (unsigned long) erp_action; | ||
1012 | erp_action->timer.expires = jiffies + ZFCP_ERP_MEMWAIT_TIMEOUT; | ||
1013 | add_timer(&erp_action->timer); | ||
1014 | |||
1015 | return retval; | ||
1016 | } | 440 | } |
1017 | 441 | ||
1018 | /* | 442 | static void zfcp_erp_port_unblock(struct zfcp_port *port) |
1019 | * function: zfcp_erp_adapter_failed | ||
1020 | * | ||
1021 | * purpose: sets the adapter and all underlying devices to ERP_FAILED | ||
1022 | * | ||
1023 | */ | ||
1024 | void | ||
1025 | zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) | ||
1026 | { | 443 | { |
1027 | zfcp_erp_modify_adapter_status(adapter, id, ref, | 444 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) |
1028 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 445 | zfcp_rec_dbf_event_port(18, NULL, port); |
1029 | dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n"); | 446 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); |
1030 | } | 447 | } |
1031 | 448 | ||
1032 | /* | 449 | static void zfcp_erp_unit_unblock(struct zfcp_unit *unit) |
1033 | * function: zfcp_erp_port_failed | ||
1034 | * | ||
1035 | * purpose: sets the port and all underlying devices to ERP_FAILED | ||
1036 | * | ||
1037 | */ | ||
1038 | void | ||
1039 | zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) | ||
1040 | { | 450 | { |
1041 | zfcp_erp_modify_port_status(port, id, ref, | 451 | if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status)) |
1042 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 452 | zfcp_rec_dbf_event_unit(20, NULL, unit); |
1043 | 453 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); | |
1044 | if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) | ||
1045 | dev_err(&port->adapter->ccw_device->dev, | ||
1046 | "Port ERP failed for WKA port d_id=0x%06x.\n", | ||
1047 | port->d_id); | ||
1048 | else | ||
1049 | dev_err(&port->adapter->ccw_device->dev, | ||
1050 | "Port ERP failed for port wwpn=0x%016Lx.\n", | ||
1051 | port->wwpn); | ||
1052 | } | 454 | } |
1053 | 455 | ||
1054 | /* | 456 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) |
1055 | * function: zfcp_erp_unit_failed | ||
1056 | * | ||
1057 | * purpose: sets the unit to ERP_FAILED | ||
1058 | * | ||
1059 | */ | ||
1060 | void | ||
1061 | zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref) | ||
1062 | { | 457 | { |
1063 | zfcp_erp_modify_unit_status(unit, id, ref, | 458 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); |
1064 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | 459 | zfcp_rec_dbf_event_action(145, erp_action); |
1065 | |||
1066 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
1067 | "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n", | ||
1068 | unit->fcp_lun, unit->port->wwpn); | ||
1069 | } | 460 | } |
1070 | 461 | ||
1071 | /* | 462 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) |
1072 | * function: zfcp_erp_strategy_check_target | ||
1073 | * | ||
1074 | * purpose: increments the erp action count on the device currently in | ||
1075 | * recovery if the action failed or resets the count in case of | ||
1076 | * success. If a maximum count is exceeded the device is marked | ||
1077 | * as ERP_FAILED. | ||
1078 | * The 'blocked' state of a target which has been recovered | ||
1079 | * successfully is reset. | ||
1080 | * | ||
1081 | * returns: ZFCP_ERP_CONTINUES - action continues (not considered) | ||
1082 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
1083 | * ZFCP_ERP_EXIT - action failed and will not continue | ||
1084 | */ | ||
1085 | static int | ||
1086 | zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result) | ||
1087 | { | 463 | { |
1088 | struct zfcp_adapter *adapter = erp_action->adapter; | 464 | struct zfcp_adapter *adapter = act->adapter; |
1089 | struct zfcp_port *port = erp_action->port; | ||
1090 | struct zfcp_unit *unit = erp_action->unit; | ||
1091 | |||
1092 | switch (erp_action->action) { | ||
1093 | 465 | ||
1094 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 466 | if (!act->fsf_req) |
1095 | result = zfcp_erp_strategy_check_unit(unit, result); | 467 | return; |
1096 | break; | ||
1097 | |||
1098 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
1099 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
1100 | result = zfcp_erp_strategy_check_port(port, result); | ||
1101 | break; | ||
1102 | |||
1103 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
1104 | result = zfcp_erp_strategy_check_adapter(adapter, result); | ||
1105 | break; | ||
1106 | } | ||
1107 | 468 | ||
1108 | return result; | 469 | spin_lock(&adapter->req_list_lock); |
470 | if (zfcp_reqlist_find_safe(adapter, act->fsf_req) && | ||
471 | act->fsf_req->erp_action == act) { | ||
472 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | | ||
473 | ZFCP_STATUS_ERP_TIMEDOUT)) { | ||
474 | act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | ||
475 | zfcp_rec_dbf_event_action(142, act); | ||
476 | } | ||
477 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
478 | zfcp_rec_dbf_event_action(143, act); | ||
479 | if (act->fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | | ||
480 | ZFCP_STATUS_FSFREQ_DISMISSED)) | ||
481 | act->fsf_req = NULL; | ||
482 | } else | ||
483 | act->fsf_req = NULL; | ||
484 | spin_unlock(&adapter->req_list_lock); | ||
1109 | } | 485 | } |
1110 | 486 | ||
1111 | static int | 487 | /** |
1112 | zfcp_erp_strategy_statechange(int action, | 488 | * zfcp_erp_notify - Trigger ERP action. |
1113 | u32 status, | 489 | * @erp_action: ERP action to continue. |
1114 | struct zfcp_adapter *adapter, | 490 | * @set_mask: ERP action status flags to set. |
1115 | struct zfcp_port *port, | 491 | */ |
1116 | struct zfcp_unit *unit, int retval) | 492 | void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask) |
1117 | { | 493 | { |
1118 | switch (action) { | 494 | struct zfcp_adapter *adapter = erp_action->adapter; |
1119 | 495 | unsigned long flags; | |
1120 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
1121 | if (zfcp_erp_strategy_statechange_detected(&adapter->status, | ||
1122 | status)) { | ||
1123 | zfcp_erp_adapter_reopen_internal(adapter, | ||
1124 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
1125 | 67, NULL); | ||
1126 | retval = ZFCP_ERP_EXIT; | ||
1127 | } | ||
1128 | break; | ||
1129 | |||
1130 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
1131 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
1132 | if (zfcp_erp_strategy_statechange_detected(&port->status, | ||
1133 | status)) { | ||
1134 | zfcp_erp_port_reopen_internal(port, | ||
1135 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
1136 | 68, NULL); | ||
1137 | retval = ZFCP_ERP_EXIT; | ||
1138 | } | ||
1139 | break; | ||
1140 | 496 | ||
1141 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 497 | write_lock_irqsave(&adapter->erp_lock, flags); |
1142 | if (zfcp_erp_strategy_statechange_detected(&unit->status, | 498 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { |
1143 | status)) { | 499 | erp_action->status |= set_mask; |
1144 | zfcp_erp_unit_reopen_internal(unit, | 500 | zfcp_erp_action_ready(erp_action); |
1145 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
1146 | 69, NULL); | ||
1147 | retval = ZFCP_ERP_EXIT; | ||
1148 | } | ||
1149 | break; | ||
1150 | } | 501 | } |
1151 | 502 | write_unlock_irqrestore(&adapter->erp_lock, flags); | |
1152 | return retval; | ||
1153 | } | 503 | } |
1154 | 504 | ||
1155 | static int | 505 | /** |
1156 | zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) | 506 | * zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request |
507 | * @data: ERP action (from timer data) | ||
508 | */ | ||
509 | void zfcp_erp_timeout_handler(unsigned long data) | ||
1157 | { | 510 | { |
1158 | return | 511 | struct zfcp_erp_action *act = (struct zfcp_erp_action *) data; |
1159 | /* take it online */ | 512 | zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT); |
1160 | (atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && | ||
1161 | (ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)) || | ||
1162 | /* take it offline */ | ||
1163 | (!atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && | ||
1164 | !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)); | ||
1165 | } | 513 | } |
1166 | 514 | ||
1167 | static int | 515 | static void zfcp_erp_memwait_handler(unsigned long data) |
1168 | zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) | ||
1169 | { | 516 | { |
1170 | switch (result) { | 517 | zfcp_erp_notify((struct zfcp_erp_action *)data, 0); |
1171 | case ZFCP_ERP_SUCCEEDED : | ||
1172 | atomic_set(&unit->erp_counter, 0); | ||
1173 | zfcp_erp_unit_unblock(unit); | ||
1174 | break; | ||
1175 | case ZFCP_ERP_FAILED : | ||
1176 | atomic_inc(&unit->erp_counter); | ||
1177 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) | ||
1178 | zfcp_erp_unit_failed(unit, 21, NULL); | ||
1179 | break; | ||
1180 | case ZFCP_ERP_EXIT : | ||
1181 | /* nothing */ | ||
1182 | break; | ||
1183 | } | ||
1184 | |||
1185 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { | ||
1186 | zfcp_erp_unit_block(unit, 0); /* for ZFCP_ERP_SUCCEEDED */ | ||
1187 | result = ZFCP_ERP_EXIT; | ||
1188 | } | ||
1189 | |||
1190 | return result; | ||
1191 | } | 518 | } |
1192 | 519 | ||
1193 | static int | 520 | static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) |
1194 | zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) | ||
1195 | { | 521 | { |
1196 | switch (result) { | 522 | init_timer(&erp_action->timer); |
1197 | case ZFCP_ERP_SUCCEEDED : | 523 | erp_action->timer.function = zfcp_erp_memwait_handler; |
1198 | atomic_set(&port->erp_counter, 0); | 524 | erp_action->timer.data = (unsigned long) erp_action; |
1199 | zfcp_erp_port_unblock(port); | 525 | erp_action->timer.expires = jiffies + HZ; |
1200 | break; | 526 | add_timer(&erp_action->timer); |
1201 | case ZFCP_ERP_FAILED : | ||
1202 | if (atomic_test_mask(ZFCP_STATUS_COMMON_NOESC, &port->status)) { | ||
1203 | zfcp_erp_port_block(port, 0); | ||
1204 | result = ZFCP_ERP_EXIT; | ||
1205 | } | ||
1206 | atomic_inc(&port->erp_counter); | ||
1207 | if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) | ||
1208 | zfcp_erp_port_failed(port, 22, NULL); | ||
1209 | break; | ||
1210 | case ZFCP_ERP_EXIT : | ||
1211 | /* nothing */ | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1215 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | ||
1216 | zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */ | ||
1217 | result = ZFCP_ERP_EXIT; | ||
1218 | } | ||
1219 | |||
1220 | return result; | ||
1221 | } | 527 | } |
1222 | 528 | ||
1223 | static int | 529 | static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, |
1224 | zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result) | 530 | int clear, u8 id, void *ref) |
1225 | { | 531 | { |
1226 | switch (result) { | 532 | struct zfcp_port *port; |
1227 | case ZFCP_ERP_SUCCEEDED : | ||
1228 | atomic_set(&adapter->erp_counter, 0); | ||
1229 | zfcp_erp_adapter_unblock(adapter); | ||
1230 | break; | ||
1231 | case ZFCP_ERP_FAILED : | ||
1232 | atomic_inc(&adapter->erp_counter); | ||
1233 | if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) | ||
1234 | zfcp_erp_adapter_failed(adapter, 23, NULL); | ||
1235 | break; | ||
1236 | case ZFCP_ERP_EXIT : | ||
1237 | /* nothing */ | ||
1238 | break; | ||
1239 | } | ||
1240 | |||
1241 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { | ||
1242 | zfcp_erp_adapter_block(adapter, 0); /* for ZFCP_ERP_SUCCEEDED */ | ||
1243 | result = ZFCP_ERP_EXIT; | ||
1244 | } | ||
1245 | |||
1246 | return result; | ||
1247 | } | ||
1248 | |||
1249 | struct zfcp_erp_add_work { | ||
1250 | struct zfcp_unit *unit; | ||
1251 | struct work_struct work; | ||
1252 | }; | ||
1253 | 533 | ||
1254 | /** | 534 | list_for_each_entry(port, &adapter->port_list_head, list) |
1255 | * zfcp_erp_scsi_scan | 535 | if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)) |
1256 | * @data: pointer to a struct zfcp_erp_add_work | 536 | _zfcp_erp_port_reopen(port, clear, id, ref); |
1257 | * | ||
1258 | * Registers a logical unit with the SCSI stack. | ||
1259 | */ | ||
1260 | static void zfcp_erp_scsi_scan(struct work_struct *work) | ||
1261 | { | ||
1262 | struct zfcp_erp_add_work *p = | ||
1263 | container_of(work, struct zfcp_erp_add_work, work); | ||
1264 | struct zfcp_unit *unit = p->unit; | ||
1265 | struct fc_rport *rport = unit->port->rport; | ||
1266 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | ||
1267 | unit->scsi_lun, 0); | ||
1268 | atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
1269 | zfcp_unit_put(unit); | ||
1270 | kfree(p); | ||
1271 | } | 537 | } |
1272 | 538 | ||
1273 | /** | 539 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, |
1274 | * zfcp_erp_schedule_work | 540 | void *ref) |
1275 | * @unit: pointer to unit which should be registered with SCSI stack | ||
1276 | * | ||
1277 | * Schedules work which registers a unit with the SCSI stack | ||
1278 | */ | ||
1279 | static void | ||
1280 | zfcp_erp_schedule_work(struct zfcp_unit *unit) | ||
1281 | { | 541 | { |
1282 | struct zfcp_erp_add_work *p; | 542 | struct zfcp_unit *unit; |
1283 | |||
1284 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
1285 | if (!p) { | ||
1286 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
1287 | "Out of resources. Could not register unit 0x%016Lx " | ||
1288 | "on port 0x%016Lx with SCSI stack.\n", | ||
1289 | unit->fcp_lun, unit->port->wwpn); | ||
1290 | return; | ||
1291 | } | ||
1292 | 543 | ||
1293 | zfcp_unit_get(unit); | 544 | list_for_each_entry(unit, &port->unit_list_head, list) |
1294 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | 545 | _zfcp_erp_unit_reopen(unit, clear, id, ref); |
1295 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); | ||
1296 | p->unit = unit; | ||
1297 | schedule_work(&p->work); | ||
1298 | } | 546 | } |
1299 | 547 | ||
1300 | /* | 548 | static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act) |
1301 | * function: | ||
1302 | * | ||
1303 | * purpose: remaining things in good cases, | ||
1304 | * escalation in bad cases | ||
1305 | * | ||
1306 | * returns: | ||
1307 | */ | ||
1308 | static int | ||
1309 | zfcp_erp_strategy_followup_actions(int action, | ||
1310 | struct zfcp_adapter *adapter, | ||
1311 | struct zfcp_port *port, | ||
1312 | struct zfcp_unit *unit, int status) | ||
1313 | { | 549 | { |
550 | struct zfcp_adapter *adapter = act->adapter; | ||
551 | struct zfcp_port *port = act->port; | ||
552 | struct zfcp_unit *unit = act->unit; | ||
553 | u32 status = act->status; | ||
554 | |||
1314 | /* initiate follow-up actions depending on success of finished action */ | 555 | /* initiate follow-up actions depending on success of finished action */ |
1315 | switch (action) { | 556 | switch (act->action) { |
1316 | 557 | ||
1317 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 558 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
1318 | if (status == ZFCP_ERP_SUCCEEDED) | 559 | if (status == ZFCP_ERP_SUCCEEDED) |
1319 | zfcp_erp_port_reopen_all_internal(adapter, 0, 70, NULL); | 560 | _zfcp_erp_port_reopen_all(adapter, 0, 70, NULL); |
1320 | else | 561 | else |
1321 | zfcp_erp_adapter_reopen_internal(adapter, 0, 71, NULL); | 562 | _zfcp_erp_adapter_reopen(adapter, 0, 71, NULL); |
1322 | break; | 563 | break; |
1323 | 564 | ||
1324 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 565 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
1325 | if (status == ZFCP_ERP_SUCCEEDED) | 566 | if (status == ZFCP_ERP_SUCCEEDED) |
1326 | zfcp_erp_port_reopen_internal(port, 0, 72, NULL); | 567 | _zfcp_erp_port_reopen(port, 0, 72, NULL); |
1327 | else | 568 | else |
1328 | zfcp_erp_adapter_reopen_internal(adapter, 0, 73, NULL); | 569 | _zfcp_erp_adapter_reopen(adapter, 0, 73, NULL); |
1329 | break; | 570 | break; |
1330 | 571 | ||
1331 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 572 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
1332 | if (status == ZFCP_ERP_SUCCEEDED) | 573 | if (status == ZFCP_ERP_SUCCEEDED) |
1333 | zfcp_erp_unit_reopen_all_internal(port, 0, 74, NULL); | 574 | _zfcp_erp_unit_reopen_all(port, 0, 74, NULL); |
1334 | else | 575 | else |
1335 | zfcp_erp_port_forced_reopen_internal(port, 0, 75, NULL); | 576 | _zfcp_erp_port_forced_reopen(port, 0, 75, NULL); |
1336 | break; | 577 | break; |
1337 | 578 | ||
1338 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 579 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
1339 | /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */ | ||
1340 | if (status != ZFCP_ERP_SUCCEEDED) | 580 | if (status != ZFCP_ERP_SUCCEEDED) |
1341 | zfcp_erp_port_reopen_internal(unit->port, 0, 76, NULL); | 581 | _zfcp_erp_port_reopen(unit->port, 0, 76, NULL); |
1342 | break; | 582 | break; |
1343 | } | 583 | } |
1344 | |||
1345 | return 0; | ||
1346 | } | 584 | } |
1347 | 585 | ||
1348 | static int | 586 | static void zfcp_erp_wakeup(struct zfcp_adapter *adapter) |
1349 | zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) | ||
1350 | { | 587 | { |
1351 | unsigned long flags; | 588 | unsigned long flags; |
1352 | 589 | ||
@@ -1360,1104 +597,622 @@ zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) | |||
1360 | } | 597 | } |
1361 | read_unlock(&adapter->erp_lock); | 598 | read_unlock(&adapter->erp_lock); |
1362 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 599 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
1363 | |||
1364 | return 0; | ||
1365 | } | 600 | } |
1366 | 601 | ||
1367 | /** | 602 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) |
1368 | * zfcp_erp_wait - wait for completion of error recovery on an adapter | ||
1369 | * @adapter: adapter for which to wait for completion of its error recovery | ||
1370 | * Return: 0 | ||
1371 | */ | ||
1372 | int | ||
1373 | zfcp_erp_wait(struct zfcp_adapter *adapter) | ||
1374 | { | 603 | { |
1375 | int retval = 0; | 604 | if (zfcp_qdio_open(act->adapter)) |
1376 | 605 | return ZFCP_ERP_FAILED; | |
1377 | wait_event(adapter->erp_done_wqh, | 606 | init_waitqueue_head(&act->adapter->request_wq); |
1378 | !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | 607 | atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status); |
1379 | &adapter->status)); | 608 | return ZFCP_ERP_SUCCEEDED; |
1380 | |||
1381 | return retval; | ||
1382 | } | 609 | } |
1383 | 610 | ||
1384 | void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id, | 611 | static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) |
1385 | void *ref, u32 mask, int set_or_clear) | ||
1386 | { | 612 | { |
1387 | struct zfcp_port *port; | 613 | struct zfcp_port *port; |
1388 | u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS; | 614 | port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0, |
1389 | 615 | adapter->peer_d_id); | |
1390 | if (set_or_clear == ZFCP_SET) { | 616 | if (IS_ERR(port)) /* error or port already attached */ |
1391 | changed = atomic_test_and_set_mask(mask, &adapter->status); | 617 | return; |
1392 | } else { | 618 | _zfcp_erp_port_reopen(port, 0, 150, NULL); |
1393 | changed = atomic_test_and_clear_mask(mask, &adapter->status); | ||
1394 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
1395 | atomic_set(&adapter->erp_counter, 0); | ||
1396 | } | ||
1397 | if (changed) | ||
1398 | zfcp_rec_dbf_event_adapter(id, ref, adapter); | ||
1399 | |||
1400 | /* Deal with all underlying devices, only pass common_mask */ | ||
1401 | if (common_mask) | ||
1402 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
1403 | zfcp_erp_modify_port_status(port, id, ref, common_mask, | ||
1404 | set_or_clear); | ||
1405 | } | 619 | } |
1406 | 620 | ||
1407 | /* | 621 | static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) |
1408 | * function: zfcp_erp_modify_port_status | ||
1409 | * | ||
1410 | * purpose: sets the port and all underlying devices to ERP_FAILED | ||
1411 | * | ||
1412 | */ | ||
1413 | void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref, | ||
1414 | u32 mask, int set_or_clear) | ||
1415 | { | 622 | { |
1416 | struct zfcp_unit *unit; | 623 | int retries; |
1417 | u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS; | 624 | int sleep = 1; |
1418 | 625 | struct zfcp_adapter *adapter = erp_action->adapter; | |
1419 | if (set_or_clear == ZFCP_SET) { | ||
1420 | changed = atomic_test_and_set_mask(mask, &port->status); | ||
1421 | } else { | ||
1422 | changed = atomic_test_and_clear_mask(mask, &port->status); | ||
1423 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
1424 | atomic_set(&port->erp_counter, 0); | ||
1425 | } | ||
1426 | if (changed) | ||
1427 | zfcp_rec_dbf_event_port(id, ref, port); | ||
1428 | |||
1429 | /* Modify status of all underlying devices, only pass common mask */ | ||
1430 | if (common_mask) | ||
1431 | list_for_each_entry(unit, &port->unit_list_head, list) | ||
1432 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, | ||
1433 | set_or_clear); | ||
1434 | } | ||
1435 | 626 | ||
1436 | /* | 627 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); |
1437 | * function: zfcp_erp_modify_unit_status | ||
1438 | * | ||
1439 | * purpose: sets the unit to ERP_FAILED | ||
1440 | * | ||
1441 | */ | ||
1442 | void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref, | ||
1443 | u32 mask, int set_or_clear) | ||
1444 | { | ||
1445 | u32 changed; | ||
1446 | 628 | ||
1447 | if (set_or_clear == ZFCP_SET) { | 629 | for (retries = 7; retries; retries--) { |
1448 | changed = atomic_test_and_set_mask(mask, &unit->status); | 630 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
1449 | } else { | 631 | &adapter->status); |
1450 | changed = atomic_test_and_clear_mask(mask, &unit->status); | 632 | write_lock_irq(&adapter->erp_lock); |
1451 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { | 633 | zfcp_erp_action_to_running(erp_action); |
1452 | atomic_set(&unit->erp_counter, 0); | 634 | write_unlock_irq(&adapter->erp_lock); |
635 | if (zfcp_fsf_exchange_config_data(erp_action)) { | ||
636 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
637 | &adapter->status); | ||
638 | return ZFCP_ERP_FAILED; | ||
1453 | } | 639 | } |
1454 | } | ||
1455 | if (changed) | ||
1456 | zfcp_rec_dbf_event_unit(id, ref, unit); | ||
1457 | } | ||
1458 | 640 | ||
1459 | /* | 641 | zfcp_rec_dbf_event_thread_lock(6, adapter); |
1460 | * function: | 642 | down(&adapter->erp_ready_sem); |
1461 | * | 643 | zfcp_rec_dbf_event_thread_lock(7, adapter); |
1462 | * purpose: Wrappper for zfcp_erp_port_reopen_all_internal | 644 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) |
1463 | * used to ensure the correct locking | 645 | break; |
1464 | * | ||
1465 | * returns: 0 - initiated action successfully | ||
1466 | * <0 - failed to initiate action | ||
1467 | */ | ||
1468 | int zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask, | ||
1469 | u8 id, void *ref) | ||
1470 | { | ||
1471 | int retval; | ||
1472 | unsigned long flags; | ||
1473 | |||
1474 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
1475 | write_lock(&adapter->erp_lock); | ||
1476 | retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask, id, | ||
1477 | ref); | ||
1478 | write_unlock(&adapter->erp_lock); | ||
1479 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1480 | |||
1481 | return retval; | ||
1482 | } | ||
1483 | 646 | ||
1484 | static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, | 647 | if (!(atomic_read(&adapter->status) & |
1485 | int clear_mask, u8 id, void *ref) | 648 | ZFCP_STATUS_ADAPTER_HOST_CON_INIT)) |
1486 | { | 649 | break; |
1487 | int retval = 0; | ||
1488 | struct zfcp_port *port; | ||
1489 | 650 | ||
1490 | list_for_each_entry(port, &adapter->port_list_head, list) | 651 | ssleep(sleep); |
1491 | if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) | 652 | sleep *= 2; |
1492 | zfcp_erp_port_reopen_internal(port, clear_mask, id, | 653 | } |
1493 | ref); | ||
1494 | 654 | ||
1495 | return retval; | 655 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
1496 | } | 656 | &adapter->status); |
1497 | 657 | ||
1498 | /* | 658 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK)) |
1499 | * function: | 659 | return ZFCP_ERP_FAILED; |
1500 | * | ||
1501 | * purpose: | ||
1502 | * | ||
1503 | * returns: FIXME | ||
1504 | */ | ||
1505 | static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, | ||
1506 | int clear_mask, u8 id, void *ref) | ||
1507 | { | ||
1508 | int retval = 0; | ||
1509 | struct zfcp_unit *unit; | ||
1510 | 660 | ||
1511 | list_for_each_entry(unit, &port->unit_list_head, list) | 661 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) |
1512 | zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref); | 662 | zfcp_erp_enqueue_ptp_port(adapter); |
1513 | 663 | ||
1514 | return retval; | 664 | return ZFCP_ERP_SUCCEEDED; |
1515 | } | 665 | } |
1516 | 666 | ||
1517 | /* | 667 | static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) |
1518 | * function: | ||
1519 | * | ||
1520 | * purpose: this routine executes the 'Reopen Adapter' action | ||
1521 | * (the entire action is processed synchronously, since | ||
1522 | * there are no actions which might be run concurrently | ||
1523 | * per definition) | ||
1524 | * | ||
1525 | * returns: ZFCP_ERP_SUCCEEDED - action finished successfully | ||
1526 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
1527 | */ | ||
1528 | static int | ||
1529 | zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action) | ||
1530 | { | 668 | { |
1531 | int retval; | 669 | int ret; |
1532 | 670 | struct zfcp_adapter *adapter = act->adapter; | |
1533 | retval = zfcp_erp_adapter_strategy_close(erp_action); | ||
1534 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
1535 | retval = ZFCP_ERP_EXIT; | ||
1536 | else | ||
1537 | retval = zfcp_erp_adapter_strategy_open(erp_action); | ||
1538 | 671 | ||
1539 | if (retval == ZFCP_ERP_FAILED) | 672 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); |
1540 | ssleep(ZFCP_TYPE2_RECOVERY_TIME); | ||
1541 | 673 | ||
1542 | return retval; | 674 | write_lock_irq(&adapter->erp_lock); |
1543 | } | 675 | zfcp_erp_action_to_running(act); |
676 | write_unlock_irq(&adapter->erp_lock); | ||
1544 | 677 | ||
1545 | /* | 678 | ret = zfcp_fsf_exchange_port_data(act); |
1546 | * function: | 679 | if (ret == -EOPNOTSUPP) |
1547 | * | 680 | return ZFCP_ERP_SUCCEEDED; |
1548 | * purpose: | 681 | if (ret) |
1549 | * | 682 | return ZFCP_ERP_FAILED; |
1550 | * returns: ZFCP_ERP_SUCCEEDED - action finished successfully | ||
1551 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
1552 | */ | ||
1553 | static int | ||
1554 | zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action) | ||
1555 | { | ||
1556 | int retval; | ||
1557 | 683 | ||
1558 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, | 684 | zfcp_rec_dbf_event_thread_lock(8, adapter); |
1559 | &erp_action->adapter->status); | 685 | down(&adapter->erp_ready_sem); |
1560 | retval = zfcp_erp_adapter_strategy_generic(erp_action, 1); | 686 | zfcp_rec_dbf_event_thread_lock(9, adapter); |
1561 | atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, | 687 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
1562 | &erp_action->adapter->status); | 688 | return ZFCP_ERP_FAILED; |
1563 | 689 | ||
1564 | return retval; | 690 | return ZFCP_ERP_SUCCEEDED; |
1565 | } | 691 | } |
1566 | 692 | ||
1567 | /* | 693 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act) |
1568 | * function: | ||
1569 | * | ||
1570 | * purpose: | ||
1571 | * | ||
1572 | * returns: ZFCP_ERP_SUCCEEDED - action finished successfully | ||
1573 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
1574 | */ | ||
1575 | static int | ||
1576 | zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action) | ||
1577 | { | 694 | { |
1578 | int retval; | 695 | if (zfcp_erp_adapter_strat_fsf_xconf(act) == ZFCP_ERP_FAILED) |
696 | return ZFCP_ERP_FAILED; | ||
1579 | 697 | ||
1580 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, | 698 | if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED) |
1581 | &erp_action->adapter->status); | 699 | return ZFCP_ERP_FAILED; |
1582 | retval = zfcp_erp_adapter_strategy_generic(erp_action, 0); | ||
1583 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, | ||
1584 | &erp_action->adapter->status); | ||
1585 | 700 | ||
1586 | return retval; | 701 | atomic_set(&act->adapter->stat_miss, 16); |
702 | if (zfcp_status_read_refill(act->adapter)) | ||
703 | return ZFCP_ERP_FAILED; | ||
704 | |||
705 | return ZFCP_ERP_SUCCEEDED; | ||
1587 | } | 706 | } |
1588 | 707 | ||
1589 | /* | 708 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act, |
1590 | * function: zfcp_register_adapter | 709 | int close) |
1591 | * | ||
1592 | * purpose: allocate the irq associated with this devno and register | ||
1593 | * the FSF adapter with the SCSI stack | ||
1594 | * | ||
1595 | * returns: | ||
1596 | */ | ||
1597 | static int | ||
1598 | zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close) | ||
1599 | { | 710 | { |
1600 | int retval = ZFCP_ERP_SUCCEEDED; | 711 | int retval = ZFCP_ERP_SUCCEEDED; |
712 | struct zfcp_adapter *adapter = act->adapter; | ||
1601 | 713 | ||
1602 | if (close) | 714 | if (close) |
1603 | goto close_only; | 715 | goto close_only; |
1604 | 716 | ||
1605 | retval = zfcp_erp_adapter_strategy_open_qdio(erp_action); | 717 | retval = zfcp_erp_adapter_strategy_open_qdio(act); |
1606 | if (retval != ZFCP_ERP_SUCCEEDED) | 718 | if (retval != ZFCP_ERP_SUCCEEDED) |
1607 | goto failed_qdio; | 719 | goto failed_qdio; |
1608 | 720 | ||
1609 | retval = zfcp_erp_adapter_strategy_open_fsf(erp_action); | 721 | retval = zfcp_erp_adapter_strategy_open_fsf(act); |
1610 | if (retval != ZFCP_ERP_SUCCEEDED) | 722 | if (retval != ZFCP_ERP_SUCCEEDED) |
1611 | goto failed_openfcp; | 723 | goto failed_openfcp; |
1612 | 724 | ||
1613 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status); | 725 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &act->adapter->status); |
1614 | schedule_work(&erp_action->adapter->scan_work); | 726 | schedule_work(&act->adapter->scan_work); |
1615 | goto out; | 727 | |
728 | return ZFCP_ERP_SUCCEEDED; | ||
1616 | 729 | ||
1617 | close_only: | 730 | close_only: |
1618 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, | 731 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, |
1619 | &erp_action->adapter->status); | 732 | &act->adapter->status); |
1620 | 733 | ||
1621 | failed_openfcp: | 734 | failed_openfcp: |
1622 | zfcp_close_fsf(erp_action->adapter); | 735 | /* close queues to ensure that buffers are not accessed by adapter */ |
736 | zfcp_qdio_close(adapter); | ||
737 | zfcp_fsf_req_dismiss_all(adapter); | ||
738 | adapter->fsf_req_seq_no = 0; | ||
739 | /* all ports and units are closed */ | ||
740 | zfcp_erp_modify_adapter_status(adapter, 24, NULL, | ||
741 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | ||
1623 | failed_qdio: | 742 | failed_qdio: |
1624 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 743 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | |
1625 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | 744 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | |
1626 | ZFCP_STATUS_ADAPTER_XPORT_OK, | 745 | ZFCP_STATUS_ADAPTER_XPORT_OK, |
1627 | &erp_action->adapter->status); | 746 | &act->adapter->status); |
1628 | out: | ||
1629 | return retval; | 747 | return retval; |
1630 | } | 748 | } |
1631 | 749 | ||
1632 | /* | 750 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act) |
1633 | * function: zfcp_qdio_init | ||
1634 | * | ||
1635 | * purpose: setup QDIO operation for specified adapter | ||
1636 | * | ||
1637 | * returns: 0 - successful setup | ||
1638 | * !0 - failed setup | ||
1639 | */ | ||
1640 | static int | ||
1641 | zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) | ||
1642 | { | 751 | { |
1643 | struct zfcp_adapter *adapter = erp_action->adapter; | 752 | int retval; |
1644 | 753 | ||
1645 | if (zfcp_qdio_open(adapter)) | 754 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); |
1646 | return ZFCP_ERP_FAILED; | 755 | zfcp_erp_adapter_strategy_generic(act, 1); /* close */ |
756 | atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); | ||
757 | if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
758 | return ZFCP_ERP_EXIT; | ||
1647 | 759 | ||
1648 | /* initialize waitqueue used to wait for free SBALs in requests queue */ | 760 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); |
1649 | init_waitqueue_head(&adapter->request_wq); | 761 | retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */ |
762 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); | ||
1650 | 763 | ||
1651 | /* ok, we did it - skip all cleanups for different failures */ | 764 | if (retval == ZFCP_ERP_FAILED) |
1652 | atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); | 765 | ssleep(8); |
1653 | return ZFCP_ERP_SUCCEEDED; | ||
1654 | } | ||
1655 | 766 | ||
767 | return retval; | ||
768 | } | ||
1656 | 769 | ||
1657 | static int | 770 | static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act) |
1658 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) | ||
1659 | { | 771 | { |
1660 | int retval; | 772 | int retval; |
1661 | 773 | ||
1662 | retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); | 774 | retval = zfcp_fsf_close_physical_port(act); |
1663 | if (retval == ZFCP_ERP_FAILED) | 775 | if (retval == -ENOMEM) |
1664 | return ZFCP_ERP_FAILED; | 776 | return ZFCP_ERP_NOMEM; |
1665 | 777 | act->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING; | |
1666 | retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 778 | if (retval) |
1667 | if (retval == ZFCP_ERP_FAILED) | ||
1668 | return ZFCP_ERP_FAILED; | 779 | return ZFCP_ERP_FAILED; |
1669 | 780 | ||
1670 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); | 781 | return ZFCP_ERP_CONTINUES; |
1671 | } | 782 | } |
1672 | 783 | ||
1673 | static void zfcp_erp_open_ptp_port(struct zfcp_adapter *adapter) | 784 | static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) |
1674 | { | 785 | { |
1675 | struct zfcp_port *port; | 786 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | |
1676 | port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0, | 787 | ZFCP_STATUS_COMMON_CLOSING | |
1677 | adapter->peer_d_id); | 788 | ZFCP_STATUS_COMMON_ACCESS_DENIED | |
1678 | if (IS_ERR(port)) /* error or port already attached */ | 789 | ZFCP_STATUS_PORT_DID_DID | |
1679 | return; | 790 | ZFCP_STATUS_PORT_PHYS_CLOSING | |
1680 | zfcp_erp_port_reopen_internal(port, 0, 150, NULL); | 791 | ZFCP_STATUS_PORT_INVALID_WWPN, |
792 | &port->status); | ||
1681 | } | 793 | } |
1682 | 794 | ||
1683 | static int | 795 | static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) |
1684 | zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | ||
1685 | { | 796 | { |
1686 | int retries; | 797 | struct zfcp_port *port = erp_action->port; |
1687 | int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP; | 798 | int status = atomic_read(&port->status); |
1688 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
1689 | |||
1690 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); | ||
1691 | 799 | ||
1692 | for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) { | 800 | switch (erp_action->step) { |
1693 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | 801 | case ZFCP_ERP_STEP_UNINITIALIZED: |
1694 | &adapter->status); | 802 | zfcp_erp_port_strategy_clearstati(port); |
1695 | write_lock_irq(&adapter->erp_lock); | 803 | if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) && |
1696 | zfcp_erp_action_to_running(erp_action); | 804 | (status & ZFCP_STATUS_COMMON_OPEN)) |
1697 | write_unlock_irq(&adapter->erp_lock); | 805 | return zfcp_erp_port_forced_strategy_close(erp_action); |
1698 | if (zfcp_fsf_exchange_config_data(erp_action)) { | 806 | else |
1699 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
1700 | &adapter->status); | ||
1701 | return ZFCP_ERP_FAILED; | 807 | return ZFCP_ERP_FAILED; |
1702 | } | ||
1703 | |||
1704 | /* | ||
1705 | * Why this works: | ||
1706 | * Both the normal completion handler as well as the timeout | ||
1707 | * handler will do an 'up' when the 'exchange config data' | ||
1708 | * request completes or times out. Thus, the signal to go on | ||
1709 | * won't be lost utilizing this semaphore. | ||
1710 | * Furthermore, this 'adapter_reopen' action is | ||
1711 | * guaranteed to be the only action being there (highest action | ||
1712 | * which prevents other actions from being created). | ||
1713 | * Resulting from that, the wake signal recognized here | ||
1714 | * _must_ be the one belonging to the 'exchange config | ||
1715 | * data' request. | ||
1716 | */ | ||
1717 | zfcp_rec_dbf_event_thread_lock(6, adapter); | ||
1718 | down(&adapter->erp_ready_sem); | ||
1719 | zfcp_rec_dbf_event_thread_lock(7, adapter); | ||
1720 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
1721 | break; | ||
1722 | |||
1723 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
1724 | &adapter->status)) | ||
1725 | break; | ||
1726 | 808 | ||
1727 | /* sleep a little bit before retry */ | 809 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
1728 | ssleep(sleep); | 810 | if (status & ZFCP_STATUS_PORT_PHYS_OPEN) |
1729 | sleep *= 2; | 811 | return ZFCP_ERP_SUCCEEDED; |
1730 | } | 812 | } |
1731 | 813 | return ZFCP_ERP_FAILED; | |
1732 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | ||
1733 | &adapter->status); | ||
1734 | |||
1735 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, | ||
1736 | &adapter->status)) | ||
1737 | return ZFCP_ERP_FAILED; | ||
1738 | |||
1739 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) | ||
1740 | zfcp_erp_open_ptp_port(adapter); | ||
1741 | |||
1742 | return ZFCP_ERP_SUCCEEDED; | ||
1743 | } | 814 | } |
1744 | 815 | ||
1745 | static int | 816 | static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action) |
1746 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | ||
1747 | { | 817 | { |
1748 | int ret; | 818 | int retval; |
1749 | struct zfcp_adapter *adapter; | ||
1750 | |||
1751 | adapter = erp_action->adapter; | ||
1752 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
1753 | |||
1754 | write_lock_irq(&adapter->erp_lock); | ||
1755 | zfcp_erp_action_to_running(erp_action); | ||
1756 | write_unlock_irq(&adapter->erp_lock); | ||
1757 | 819 | ||
1758 | ret = zfcp_fsf_exchange_port_data(erp_action); | 820 | retval = zfcp_fsf_close_port(erp_action); |
1759 | if (ret == -EOPNOTSUPP) { | 821 | if (retval == -ENOMEM) |
1760 | return ZFCP_ERP_SUCCEEDED; | 822 | return ZFCP_ERP_NOMEM; |
1761 | } else if (ret) { | 823 | erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING; |
824 | if (retval) | ||
1762 | return ZFCP_ERP_FAILED; | 825 | return ZFCP_ERP_FAILED; |
1763 | } | 826 | return ZFCP_ERP_CONTINUES; |
1764 | |||
1765 | ret = ZFCP_ERP_SUCCEEDED; | ||
1766 | zfcp_rec_dbf_event_thread_lock(8, adapter); | ||
1767 | down(&adapter->erp_ready_sem); | ||
1768 | zfcp_rec_dbf_event_thread_lock(9, adapter); | ||
1769 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) | ||
1770 | ret = ZFCP_ERP_FAILED; | ||
1771 | |||
1772 | return ret; | ||
1773 | } | 827 | } |
1774 | 828 | ||
1775 | static int | 829 | static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) |
1776 | zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action | ||
1777 | *erp_action) | ||
1778 | { | 830 | { |
1779 | struct zfcp_adapter *adapter = erp_action->adapter; | 831 | int retval; |
1780 | 832 | ||
1781 | atomic_set(&adapter->stat_miss, 16); | 833 | retval = zfcp_fsf_open_port(erp_action); |
1782 | return zfcp_status_read_refill(adapter); | 834 | if (retval == -ENOMEM) |
835 | return ZFCP_ERP_NOMEM; | ||
836 | erp_action->step = ZFCP_ERP_STEP_PORT_OPENING; | ||
837 | if (retval) | ||
838 | return ZFCP_ERP_FAILED; | ||
839 | return ZFCP_ERP_CONTINUES; | ||
1783 | } | 840 | } |
1784 | 841 | ||
1785 | /* | 842 | static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act) |
1786 | * function: | ||
1787 | * | ||
1788 | * purpose: this routine executes the 'Reopen Physical Port' action | ||
1789 | * | ||
1790 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
1791 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
1792 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
1793 | */ | ||
1794 | static int | ||
1795 | zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) | ||
1796 | { | 843 | { |
1797 | int retval = ZFCP_ERP_FAILED; | 844 | unsigned long flags; |
1798 | struct zfcp_port *port = erp_action->port; | 845 | struct zfcp_adapter *adapter = ns_act->adapter; |
1799 | 846 | struct zfcp_erp_action *act, *tmp; | |
1800 | switch (erp_action->step) { | 847 | int status; |
1801 | |||
1802 | /* | ||
1803 | * FIXME: | ||
1804 | * the ULP spec. begs for waiting for oustanding commands | ||
1805 | */ | ||
1806 | case ZFCP_ERP_STEP_UNINITIALIZED: | ||
1807 | zfcp_erp_port_strategy_clearstati(port); | ||
1808 | /* | ||
1809 | * it would be sufficient to test only the normal open flag | ||
1810 | * since the phys. open flag cannot be set if the normal | ||
1811 | * open flag is unset - however, this is for readabilty ... | ||
1812 | */ | ||
1813 | if (atomic_test_mask((ZFCP_STATUS_PORT_PHYS_OPEN | | ||
1814 | ZFCP_STATUS_COMMON_OPEN), | ||
1815 | &port->status)) { | ||
1816 | retval = | ||
1817 | zfcp_erp_port_forced_strategy_close(erp_action); | ||
1818 | } else | ||
1819 | retval = ZFCP_ERP_FAILED; | ||
1820 | break; | ||
1821 | 848 | ||
1822 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 849 | read_lock_irqsave(&adapter->erp_lock, flags); |
1823 | if (atomic_test_mask(ZFCP_STATUS_PORT_PHYS_OPEN, | 850 | list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) { |
1824 | &port->status)) { | 851 | if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { |
1825 | retval = ZFCP_ERP_FAILED; | 852 | status = atomic_read(&adapter->nameserver_port->status); |
1826 | } else | 853 | if (status & ZFCP_STATUS_COMMON_ERP_FAILED) |
1827 | retval = ZFCP_ERP_SUCCEEDED; | 854 | zfcp_erp_port_failed(act->port, 27, NULL); |
1828 | break; | 855 | zfcp_erp_action_ready(act); |
856 | } | ||
1829 | } | 857 | } |
1830 | 858 | read_unlock_irqrestore(&adapter->erp_lock, flags); | |
1831 | return retval; | ||
1832 | } | 859 | } |
1833 | 860 | ||
1834 | /* | 861 | static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act) |
1835 | * function: | ||
1836 | * | ||
1837 | * purpose: this routine executes the 'Reopen Port' action | ||
1838 | * | ||
1839 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
1840 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
1841 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
1842 | */ | ||
1843 | static int | ||
1844 | zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) | ||
1845 | { | 862 | { |
1846 | int retval = ZFCP_ERP_FAILED; | 863 | int retval; |
1847 | struct zfcp_port *port = erp_action->port; | ||
1848 | |||
1849 | switch (erp_action->step) { | ||
1850 | 864 | ||
1851 | /* | 865 | switch (act->step) { |
1852 | * FIXME: | ||
1853 | * the ULP spec. begs for waiting for oustanding commands | ||
1854 | */ | ||
1855 | case ZFCP_ERP_STEP_UNINITIALIZED: | 866 | case ZFCP_ERP_STEP_UNINITIALIZED: |
1856 | zfcp_erp_port_strategy_clearstati(port); | 867 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
1857 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { | ||
1858 | retval = zfcp_erp_port_strategy_close(erp_action); | ||
1859 | goto out; | ||
1860 | } /* else it's already closed, open it */ | ||
1861 | break; | ||
1862 | |||
1863 | case ZFCP_ERP_STEP_PORT_CLOSING: | 868 | case ZFCP_ERP_STEP_PORT_CLOSING: |
1864 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { | 869 | return zfcp_erp_port_strategy_open_port(act); |
870 | |||
871 | case ZFCP_ERP_STEP_PORT_OPENING: | ||
872 | if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN) | ||
873 | retval = ZFCP_ERP_SUCCEEDED; | ||
874 | else | ||
1865 | retval = ZFCP_ERP_FAILED; | 875 | retval = ZFCP_ERP_FAILED; |
1866 | goto out; | 876 | /* this is needed anyway */ |
1867 | } /* else it's closed now, open it */ | 877 | zfcp_erp_port_strategy_open_ns_wake(act); |
1868 | break; | 878 | return retval; |
1869 | } | ||
1870 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
1871 | retval = ZFCP_ERP_EXIT; | ||
1872 | else | ||
1873 | retval = zfcp_erp_port_strategy_open(erp_action); | ||
1874 | 879 | ||
1875 | out: | 880 | default: |
1876 | return retval; | 881 | return ZFCP_ERP_FAILED; |
882 | } | ||
1877 | } | 883 | } |
1878 | 884 | ||
1879 | static int | 885 | static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act) |
1880 | zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action) | ||
1881 | { | 886 | { |
1882 | int retval; | 887 | int retval; |
1883 | 888 | ||
1884 | if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, | 889 | retval = zfcp_fc_ns_gid_pn_request(act); |
1885 | &erp_action->port->status)) | 890 | if (retval == -ENOMEM) |
1886 | retval = zfcp_erp_port_strategy_open_nameserver(erp_action); | 891 | return ZFCP_ERP_NOMEM; |
1887 | else | 892 | act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; |
1888 | retval = zfcp_erp_port_strategy_open_common(erp_action); | 893 | if (retval) |
1889 | 894 | return ZFCP_ERP_FAILED; | |
1890 | return retval; | 895 | return ZFCP_ERP_CONTINUES; |
1891 | } | 896 | } |
1892 | 897 | ||
1893 | static int | 898 | static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) |
1894 | zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) | ||
1895 | { | 899 | { |
1896 | int retval = 0; | 900 | struct zfcp_adapter *adapter = act->adapter; |
1897 | struct zfcp_adapter *adapter = erp_action->adapter; | 901 | struct zfcp_port *port = act->port; |
1898 | struct zfcp_port *port = erp_action->port; | ||
1899 | 902 | ||
1900 | switch (erp_action->step) { | 903 | if (port->wwpn != adapter->peer_wwpn) { |
904 | dev_err(&adapter->ccw_device->dev, | ||
905 | "Failed to open port 0x%016Lx, " | ||
906 | "Peer WWPN 0x%016Lx does not " | ||
907 | "match.\n", port->wwpn, | ||
908 | adapter->peer_wwpn); | ||
909 | zfcp_erp_port_failed(port, 25, NULL); | ||
910 | return ZFCP_ERP_FAILED; | ||
911 | } | ||
912 | port->d_id = adapter->peer_d_id; | ||
913 | atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); | ||
914 | return zfcp_erp_port_strategy_open_port(act); | ||
915 | } | ||
1901 | 916 | ||
917 | static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) | ||
918 | { | ||
919 | struct zfcp_adapter *adapter = act->adapter; | ||
920 | struct zfcp_port *port = act->port; | ||
921 | struct zfcp_port *ns_port = adapter->nameserver_port; | ||
922 | int p_status = atomic_read(&port->status); | ||
923 | |||
924 | switch (act->step) { | ||
1902 | case ZFCP_ERP_STEP_UNINITIALIZED: | 925 | case ZFCP_ERP_STEP_UNINITIALIZED: |
1903 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 926 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
1904 | case ZFCP_ERP_STEP_PORT_CLOSING: | 927 | case ZFCP_ERP_STEP_PORT_CLOSING: |
1905 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) { | 928 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) |
1906 | if (port->wwpn != adapter->peer_wwpn) { | 929 | return zfcp_erp_open_ptp_port(act); |
1907 | dev_err(&adapter->ccw_device->dev, | 930 | if (!ns_port) { |
1908 | "Failed to open port 0x%016Lx, " | ||
1909 | "Peer WWPN 0x%016Lx does not match.\n", | ||
1910 | port->wwpn, adapter->peer_wwpn); | ||
1911 | zfcp_erp_port_failed(port, 25, NULL); | ||
1912 | retval = ZFCP_ERP_FAILED; | ||
1913 | break; | ||
1914 | } | ||
1915 | port->d_id = adapter->peer_d_id; | ||
1916 | atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); | ||
1917 | retval = zfcp_erp_port_strategy_open_port(erp_action); | ||
1918 | break; | ||
1919 | } | ||
1920 | |||
1921 | if (!adapter->nameserver_port) { | ||
1922 | dev_err(&adapter->ccw_device->dev, | 931 | dev_err(&adapter->ccw_device->dev, |
1923 | "Nameserver port unavailable.\n"); | 932 | "Nameserver port unavailable.\n"); |
1924 | retval = ZFCP_ERP_FAILED; | 933 | return ZFCP_ERP_FAILED; |
1925 | break; | ||
1926 | } | 934 | } |
1927 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, | 935 | if (!(atomic_read(&ns_port->status) & |
1928 | &adapter->nameserver_port->status)) { | 936 | ZFCP_STATUS_COMMON_UNBLOCKED)) { |
1929 | /* nameserver port may live again */ | 937 | /* nameserver port may live again */ |
1930 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, | 938 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, |
1931 | &adapter->nameserver_port->status); | 939 | &ns_port->status); |
1932 | if (zfcp_erp_port_reopen(adapter->nameserver_port, 0, | 940 | if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) { |
1933 | 77, erp_action) >= 0) { | 941 | act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; |
1934 | erp_action->step = | 942 | return ZFCP_ERP_CONTINUES; |
1935 | ZFCP_ERP_STEP_NAMESERVER_OPEN; | 943 | } |
1936 | retval = ZFCP_ERP_CONTINUES; | 944 | return ZFCP_ERP_FAILED; |
1937 | } else | ||
1938 | retval = ZFCP_ERP_FAILED; | ||
1939 | break; | ||
1940 | } | 945 | } |
1941 | /* else nameserver port is already open, fall through */ | 946 | /* else nameserver port is already open, fall through */ |
1942 | case ZFCP_ERP_STEP_NAMESERVER_OPEN: | 947 | case ZFCP_ERP_STEP_NAMESERVER_OPEN: |
1943 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, | 948 | if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN)) |
1944 | &adapter->nameserver_port->status)) | 949 | return ZFCP_ERP_FAILED; |
1945 | retval = ZFCP_ERP_FAILED; | 950 | return zfcp_erp_port_strategy_open_lookup(act); |
1946 | else | ||
1947 | retval = zfcp_erp_port_strategy_open_common_lookup | ||
1948 | (erp_action); | ||
1949 | break; | ||
1950 | 951 | ||
1951 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: | 952 | case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: |
1952 | if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status)) { | 953 | if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { |
1953 | if (atomic_test_mask | 954 | if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { |
1954 | (ZFCP_STATUS_PORT_INVALID_WWPN, &port->status)) { | ||
1955 | zfcp_erp_port_failed(port, 26, NULL); | 955 | zfcp_erp_port_failed(port, 26, NULL); |
1956 | retval = ZFCP_ERP_EXIT; | 956 | return ZFCP_ERP_EXIT; |
1957 | } else | 957 | } |
1958 | retval = ZFCP_ERP_FAILED; | 958 | return ZFCP_ERP_FAILED; |
1959 | } else | 959 | } |
1960 | retval = zfcp_erp_port_strategy_open_port(erp_action); | 960 | return zfcp_erp_port_strategy_open_port(act); |
1961 | break; | ||
1962 | 961 | ||
1963 | case ZFCP_ERP_STEP_PORT_OPENING: | 962 | case ZFCP_ERP_STEP_PORT_OPENING: |
1964 | /* D_ID might have changed during open */ | 963 | /* D_ID might have changed during open */ |
1965 | if (atomic_test_mask((ZFCP_STATUS_COMMON_OPEN | | 964 | if ((p_status & ZFCP_STATUS_COMMON_OPEN) && |
1966 | ZFCP_STATUS_PORT_DID_DID), | 965 | (p_status & ZFCP_STATUS_PORT_DID_DID)) |
1967 | &port->status)) | 966 | return ZFCP_ERP_SUCCEEDED; |
1968 | retval = ZFCP_ERP_SUCCEEDED; | 967 | /* fall through otherwise */ |
1969 | else | ||
1970 | retval = ZFCP_ERP_FAILED; | ||
1971 | break; | ||
1972 | |||
1973 | default: | ||
1974 | /* unknown erp step */ | ||
1975 | retval = ZFCP_ERP_FAILED; | ||
1976 | } | 968 | } |
969 | return ZFCP_ERP_FAILED; | ||
970 | } | ||
1977 | 971 | ||
1978 | return retval; | 972 | static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act) |
973 | { | ||
974 | if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA)) | ||
975 | return zfcp_erp_port_strategy_open_nameserver(act); | ||
976 | return zfcp_erp_port_strategy_open_common(act); | ||
1979 | } | 977 | } |
1980 | 978 | ||
1981 | static int | 979 | static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) |
1982 | zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) | ||
1983 | { | 980 | { |
1984 | int retval; | ||
1985 | struct zfcp_port *port = erp_action->port; | 981 | struct zfcp_port *port = erp_action->port; |
1986 | 982 | ||
1987 | switch (erp_action->step) { | 983 | switch (erp_action->step) { |
1988 | |||
1989 | case ZFCP_ERP_STEP_UNINITIALIZED: | 984 | case ZFCP_ERP_STEP_UNINITIALIZED: |
1990 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 985 | zfcp_erp_port_strategy_clearstati(port); |
1991 | case ZFCP_ERP_STEP_PORT_CLOSING: | 986 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) |
1992 | retval = zfcp_erp_port_strategy_open_port(erp_action); | 987 | return zfcp_erp_port_strategy_close(erp_action); |
1993 | break; | 988 | break; |
1994 | 989 | ||
1995 | case ZFCP_ERP_STEP_PORT_OPENING: | 990 | case ZFCP_ERP_STEP_PORT_CLOSING: |
1996 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) | 991 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) |
1997 | retval = ZFCP_ERP_SUCCEEDED; | 992 | return ZFCP_ERP_FAILED; |
1998 | else | ||
1999 | retval = ZFCP_ERP_FAILED; | ||
2000 | /* this is needed anyway (dont care for retval of wakeup) */ | ||
2001 | zfcp_erp_port_strategy_open_nameserver_wakeup(erp_action); | ||
2002 | break; | 993 | break; |
2003 | |||
2004 | default: | ||
2005 | /* unknown erp step */ | ||
2006 | retval = ZFCP_ERP_FAILED; | ||
2007 | } | 994 | } |
995 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | ||
996 | return ZFCP_ERP_EXIT; | ||
997 | else | ||
998 | return zfcp_erp_port_strategy_open(erp_action); | ||
2008 | 999 | ||
2009 | return retval; | 1000 | return ZFCP_ERP_FAILED; |
2010 | } | ||
2011 | |||
2012 | /* | ||
2013 | * function: | ||
2014 | * | ||
2015 | * purpose: makes the erp thread continue with reopen (physical) port | ||
2016 | * actions which have been paused until the name server port | ||
2017 | * is opened (or failed) | ||
2018 | * | ||
2019 | * returns: 0 (a kind of void retval, its not used) | ||
2020 | */ | ||
2021 | static int | ||
2022 | zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action | ||
2023 | *ns_erp_action) | ||
2024 | { | ||
2025 | int retval = 0; | ||
2026 | unsigned long flags; | ||
2027 | struct zfcp_adapter *adapter = ns_erp_action->adapter; | ||
2028 | struct zfcp_erp_action *erp_action, *tmp; | ||
2029 | |||
2030 | read_lock_irqsave(&adapter->erp_lock, flags); | ||
2031 | list_for_each_entry_safe(erp_action, tmp, &adapter->erp_running_head, | ||
2032 | list) { | ||
2033 | if (erp_action->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { | ||
2034 | if (atomic_test_mask( | ||
2035 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
2036 | &adapter->nameserver_port->status)) | ||
2037 | zfcp_erp_port_failed(erp_action->port, 27, | ||
2038 | NULL); | ||
2039 | zfcp_erp_action_ready(erp_action); | ||
2040 | } | ||
2041 | } | ||
2042 | read_unlock_irqrestore(&adapter->erp_lock, flags); | ||
2043 | |||
2044 | return retval; | ||
2045 | } | ||
2046 | |||
2047 | /* | ||
2048 | * function: | ||
2049 | * | ||
2050 | * purpose: | ||
2051 | * | ||
2052 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
2053 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
2054 | */ | ||
2055 | static int | ||
2056 | zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action) | ||
2057 | { | ||
2058 | int retval; | ||
2059 | |||
2060 | retval = zfcp_fsf_close_physical_port(erp_action); | ||
2061 | if (retval == -ENOMEM) { | ||
2062 | retval = ZFCP_ERP_NOMEM; | ||
2063 | goto out; | ||
2064 | } | ||
2065 | erp_action->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING; | ||
2066 | if (retval != 0) { | ||
2067 | /* could not send 'open', fail */ | ||
2068 | retval = ZFCP_ERP_FAILED; | ||
2069 | goto out; | ||
2070 | } | ||
2071 | retval = ZFCP_ERP_CONTINUES; | ||
2072 | out: | ||
2073 | return retval; | ||
2074 | } | 1001 | } |
2075 | 1002 | ||
2076 | static int | 1003 | static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) |
2077 | zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) | ||
2078 | { | 1004 | { |
2079 | int retval = 0; | ||
2080 | |||
2081 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | | 1005 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | |
2082 | ZFCP_STATUS_COMMON_CLOSING | | 1006 | ZFCP_STATUS_COMMON_CLOSING | |
2083 | ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1007 | ZFCP_STATUS_COMMON_ACCESS_DENIED | |
2084 | ZFCP_STATUS_PORT_DID_DID | | 1008 | ZFCP_STATUS_UNIT_SHARED | |
2085 | ZFCP_STATUS_PORT_PHYS_CLOSING | | 1009 | ZFCP_STATUS_UNIT_READONLY, |
2086 | ZFCP_STATUS_PORT_INVALID_WWPN, | 1010 | &unit->status); |
2087 | &port->status); | ||
2088 | return retval; | ||
2089 | } | ||
2090 | |||
2091 | /* | ||
2092 | * function: | ||
2093 | * | ||
2094 | * purpose: | ||
2095 | * | ||
2096 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
2097 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
2098 | */ | ||
2099 | static int | ||
2100 | zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action) | ||
2101 | { | ||
2102 | int retval; | ||
2103 | |||
2104 | retval = zfcp_fsf_close_port(erp_action); | ||
2105 | if (retval == -ENOMEM) { | ||
2106 | retval = ZFCP_ERP_NOMEM; | ||
2107 | goto out; | ||
2108 | } | ||
2109 | erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING; | ||
2110 | if (retval != 0) { | ||
2111 | /* could not send 'close', fail */ | ||
2112 | retval = ZFCP_ERP_FAILED; | ||
2113 | goto out; | ||
2114 | } | ||
2115 | retval = ZFCP_ERP_CONTINUES; | ||
2116 | out: | ||
2117 | return retval; | ||
2118 | } | 1011 | } |
2119 | 1012 | ||
2120 | /* | 1013 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) |
2121 | * function: | ||
2122 | * | ||
2123 | * purpose: | ||
2124 | * | ||
2125 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
2126 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
2127 | */ | ||
2128 | static int | ||
2129 | zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) | ||
2130 | { | 1014 | { |
2131 | int retval; | 1015 | int retval = zfcp_fsf_close_unit(erp_action); |
2132 | 1016 | if (retval == -ENOMEM) | |
2133 | retval = zfcp_fsf_open_port(erp_action); | 1017 | return ZFCP_ERP_NOMEM; |
2134 | if (retval == -ENOMEM) { | 1018 | erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; |
2135 | retval = ZFCP_ERP_NOMEM; | 1019 | if (retval) |
2136 | goto out; | 1020 | return ZFCP_ERP_FAILED; |
2137 | } | 1021 | return ZFCP_ERP_CONTINUES; |
2138 | erp_action->step = ZFCP_ERP_STEP_PORT_OPENING; | ||
2139 | if (retval != 0) { | ||
2140 | /* could not send 'open', fail */ | ||
2141 | retval = ZFCP_ERP_FAILED; | ||
2142 | goto out; | ||
2143 | } | ||
2144 | retval = ZFCP_ERP_CONTINUES; | ||
2145 | out: | ||
2146 | return retval; | ||
2147 | } | 1022 | } |
2148 | 1023 | ||
2149 | /* | 1024 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) |
2150 | * function: | ||
2151 | * | ||
2152 | * purpose: | ||
2153 | * | ||
2154 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
2155 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
2156 | */ | ||
2157 | static int | ||
2158 | zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action) | ||
2159 | { | 1025 | { |
2160 | int retval; | 1026 | int retval = zfcp_fsf_open_unit(erp_action); |
2161 | 1027 | if (retval == -ENOMEM) | |
2162 | retval = zfcp_fc_ns_gid_pn_request(erp_action); | 1028 | return ZFCP_ERP_NOMEM; |
2163 | if (retval == -ENOMEM) { | 1029 | erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; |
2164 | retval = ZFCP_ERP_NOMEM; | 1030 | if (retval) |
2165 | goto out; | 1031 | return ZFCP_ERP_FAILED; |
2166 | } | 1032 | return ZFCP_ERP_CONTINUES; |
2167 | erp_action->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; | ||
2168 | if (retval != 0) { | ||
2169 | /* could not send nameserver request, fail */ | ||
2170 | retval = ZFCP_ERP_FAILED; | ||
2171 | goto out; | ||
2172 | } | ||
2173 | retval = ZFCP_ERP_CONTINUES; | ||
2174 | out: | ||
2175 | return retval; | ||
2176 | } | 1033 | } |
2177 | 1034 | ||
2178 | /* | 1035 | static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) |
2179 | * function: | ||
2180 | * | ||
2181 | * purpose: this routine executes the 'Reopen Unit' action | ||
2182 | * currently no retries | ||
2183 | * | ||
2184 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
2185 | * ZFCP_ERP_SUCCEEDED - action finished successfully | ||
2186 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
2187 | */ | ||
2188 | static int | ||
2189 | zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action) | ||
2190 | { | 1036 | { |
2191 | int retval = ZFCP_ERP_FAILED; | ||
2192 | struct zfcp_unit *unit = erp_action->unit; | 1037 | struct zfcp_unit *unit = erp_action->unit; |
2193 | 1038 | ||
2194 | switch (erp_action->step) { | 1039 | switch (erp_action->step) { |
2195 | |||
2196 | /* | ||
2197 | * FIXME: | ||
2198 | * the ULP spec. begs for waiting for oustanding commands | ||
2199 | */ | ||
2200 | case ZFCP_ERP_STEP_UNINITIALIZED: | 1040 | case ZFCP_ERP_STEP_UNINITIALIZED: |
2201 | zfcp_erp_unit_strategy_clearstati(unit); | 1041 | zfcp_erp_unit_strategy_clearstati(unit); |
2202 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) { | 1042 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) |
2203 | retval = zfcp_erp_unit_strategy_close(erp_action); | 1043 | return zfcp_erp_unit_strategy_close(erp_action); |
2204 | break; | 1044 | /* already closed, fall through */ |
2205 | } | ||
2206 | /* else it's already closed, fall through */ | ||
2207 | case ZFCP_ERP_STEP_UNIT_CLOSING: | 1045 | case ZFCP_ERP_STEP_UNIT_CLOSING: |
2208 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) | 1046 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) |
2209 | retval = ZFCP_ERP_FAILED; | 1047 | return ZFCP_ERP_FAILED; |
2210 | else | 1048 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) |
2211 | if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) | 1049 | return ZFCP_ERP_EXIT; |
2212 | retval = ZFCP_ERP_EXIT; | 1050 | return zfcp_erp_unit_strategy_open(erp_action); |
2213 | else | ||
2214 | retval = | ||
2215 | zfcp_erp_unit_strategy_open(erp_action); | ||
2216 | break; | ||
2217 | 1051 | ||
2218 | case ZFCP_ERP_STEP_UNIT_OPENING: | 1052 | case ZFCP_ERP_STEP_UNIT_OPENING: |
2219 | if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status)) | 1053 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN) |
2220 | retval = ZFCP_ERP_SUCCEEDED; | 1054 | return ZFCP_ERP_SUCCEEDED; |
2221 | else | ||
2222 | retval = ZFCP_ERP_FAILED; | ||
2223 | break; | ||
2224 | } | 1055 | } |
2225 | 1056 | return ZFCP_ERP_FAILED; | |
2226 | return retval; | ||
2227 | } | 1057 | } |
2228 | 1058 | ||
2229 | static int | 1059 | static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) |
2230 | zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) | ||
2231 | { | 1060 | { |
2232 | int retval = 0; | 1061 | switch (result) { |
2233 | 1062 | case ZFCP_ERP_SUCCEEDED : | |
2234 | atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | | 1063 | atomic_set(&unit->erp_counter, 0); |
2235 | ZFCP_STATUS_COMMON_CLOSING | | 1064 | zfcp_erp_unit_unblock(unit); |
2236 | ZFCP_STATUS_COMMON_ACCESS_DENIED | | 1065 | break; |
2237 | ZFCP_STATUS_UNIT_SHARED | | 1066 | case ZFCP_ERP_FAILED : |
2238 | ZFCP_STATUS_UNIT_READONLY, | 1067 | atomic_inc(&unit->erp_counter); |
2239 | &unit->status); | 1068 | if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) |
1069 | zfcp_erp_unit_failed(unit, 21, NULL); | ||
1070 | break; | ||
1071 | } | ||
2240 | 1072 | ||
2241 | return retval; | 1073 | if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
1074 | zfcp_erp_unit_block(unit, 0); | ||
1075 | result = ZFCP_ERP_EXIT; | ||
1076 | } | ||
1077 | return result; | ||
2242 | } | 1078 | } |
2243 | 1079 | ||
2244 | /* | 1080 | static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) |
2245 | * function: | ||
2246 | * | ||
2247 | * purpose: | ||
2248 | * | ||
2249 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
2250 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
2251 | */ | ||
2252 | static int | ||
2253 | zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) | ||
2254 | { | 1081 | { |
2255 | int retval; | 1082 | switch (result) { |
1083 | case ZFCP_ERP_SUCCEEDED : | ||
1084 | atomic_set(&port->erp_counter, 0); | ||
1085 | zfcp_erp_port_unblock(port); | ||
1086 | break; | ||
2256 | 1087 | ||
2257 | retval = zfcp_fsf_close_unit(erp_action); | 1088 | case ZFCP_ERP_FAILED : |
2258 | if (retval == -ENOMEM) { | 1089 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) { |
2259 | retval = ZFCP_ERP_NOMEM; | 1090 | zfcp_erp_port_block(port, 0); |
2260 | goto out; | 1091 | result = ZFCP_ERP_EXIT; |
2261 | } | 1092 | } |
2262 | erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING; | 1093 | atomic_inc(&port->erp_counter); |
2263 | if (retval != 0) { | 1094 | if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) |
2264 | /* could not send 'close', fail */ | 1095 | zfcp_erp_port_failed(port, 22, NULL); |
2265 | retval = ZFCP_ERP_FAILED; | 1096 | break; |
2266 | goto out; | ||
2267 | } | 1097 | } |
2268 | retval = ZFCP_ERP_CONTINUES; | ||
2269 | 1098 | ||
2270 | out: | 1099 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
2271 | return retval; | 1100 | zfcp_erp_port_block(port, 0); |
1101 | result = ZFCP_ERP_EXIT; | ||
1102 | } | ||
1103 | return result; | ||
2272 | } | 1104 | } |
2273 | 1105 | ||
2274 | /* | 1106 | static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, |
2275 | * function: | 1107 | int result) |
2276 | * | ||
2277 | * purpose: | ||
2278 | * | ||
2279 | * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) | ||
2280 | * ZFCP_ERP_FAILED - action finished unsuccessfully | ||
2281 | */ | ||
2282 | static int | ||
2283 | zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action) | ||
2284 | { | 1108 | { |
2285 | int retval; | 1109 | switch (result) { |
1110 | case ZFCP_ERP_SUCCEEDED : | ||
1111 | atomic_set(&adapter->erp_counter, 0); | ||
1112 | zfcp_erp_adapter_unblock(adapter); | ||
1113 | break; | ||
2286 | 1114 | ||
2287 | retval = zfcp_fsf_open_unit(erp_action); | 1115 | case ZFCP_ERP_FAILED : |
2288 | if (retval == -ENOMEM) { | 1116 | atomic_inc(&adapter->erp_counter); |
2289 | retval = ZFCP_ERP_NOMEM; | 1117 | if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) |
2290 | goto out; | 1118 | zfcp_erp_adapter_failed(adapter, 23, NULL); |
1119 | break; | ||
2291 | } | 1120 | } |
2292 | erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING; | 1121 | |
2293 | if (retval != 0) { | 1122 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { |
2294 | /* could not send 'open', fail */ | 1123 | zfcp_erp_adapter_block(adapter, 0); |
2295 | retval = ZFCP_ERP_FAILED; | 1124 | result = ZFCP_ERP_EXIT; |
2296 | goto out; | ||
2297 | } | 1125 | } |
2298 | retval = ZFCP_ERP_CONTINUES; | 1126 | return result; |
2299 | out: | ||
2300 | return retval; | ||
2301 | } | 1127 | } |
2302 | 1128 | ||
2303 | void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req) | 1129 | static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, |
1130 | int result) | ||
2304 | { | 1131 | { |
2305 | BUG_ON(!fsf_req->erp_action); | 1132 | struct zfcp_adapter *adapter = erp_action->adapter; |
2306 | fsf_req->timer.function = zfcp_erp_timeout_handler; | 1133 | struct zfcp_port *port = erp_action->port; |
2307 | fsf_req->timer.data = (unsigned long) fsf_req->erp_action; | 1134 | struct zfcp_unit *unit = erp_action->unit; |
2308 | fsf_req->timer.expires = jiffies + ZFCP_ERP_FSFREQ_TIMEOUT; | ||
2309 | add_timer(&fsf_req->timer); | ||
2310 | } | ||
2311 | |||
2312 | /* | ||
2313 | * function: | ||
2314 | * | ||
2315 | * purpose: enqueue the specified error recovery action, if needed | ||
2316 | * | ||
2317 | * returns: | ||
2318 | */ | ||
2319 | static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, | ||
2320 | struct zfcp_port *port, | ||
2321 | struct zfcp_unit *unit, u8 id, void *ref) | ||
2322 | { | ||
2323 | int retval = 1, need = want; | ||
2324 | struct zfcp_erp_action *erp_action = NULL; | ||
2325 | u32 status = 0; | ||
2326 | 1135 | ||
2327 | /* | 1136 | switch (erp_action->action) { |
2328 | * We need some rules here which check whether we really need | ||
2329 | * this action or whether we should just drop it. | ||
2330 | * E.g. if there is a unfinished 'Reopen Port' request then we drop a | ||
2331 | * 'Reopen Unit' request for an associated unit since we can't | ||
2332 | * satisfy this request now. A 'Reopen Port' action will trigger | ||
2333 | * 'Reopen Unit' actions when it completes. | ||
2334 | * Thus, there are only actions in the queue which can immediately be | ||
2335 | * executed. This makes the processing of the action queue more | ||
2336 | * efficient. | ||
2337 | */ | ||
2338 | |||
2339 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, | ||
2340 | &adapter->status)) | ||
2341 | return -EIO; | ||
2342 | 1137 | ||
2343 | /* check whether we really need this */ | ||
2344 | switch (want) { | ||
2345 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1138 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
2346 | if (atomic_test_mask | 1139 | result = zfcp_erp_strategy_check_unit(unit, result); |
2347 | (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) { | 1140 | break; |
2348 | goto out; | ||
2349 | } | ||
2350 | if (!atomic_test_mask | ||
2351 | (ZFCP_STATUS_COMMON_RUNNING, &port->status) || | ||
2352 | atomic_test_mask | ||
2353 | (ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { | ||
2354 | goto out; | ||
2355 | } | ||
2356 | if (!atomic_test_mask | ||
2357 | (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) | ||
2358 | need = ZFCP_ERP_ACTION_REOPEN_PORT; | ||
2359 | /* fall through !!! */ | ||
2360 | |||
2361 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
2362 | if (atomic_test_mask | ||
2363 | (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) { | ||
2364 | goto out; | ||
2365 | } | ||
2366 | /* fall through !!! */ | ||
2367 | 1141 | ||
2368 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1142 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
2369 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1143 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
2370 | &port->status)) | 1144 | result = zfcp_erp_strategy_check_port(port, result); |
2371 | goto out; | 1145 | break; |
2372 | if (!atomic_test_mask | ||
2373 | (ZFCP_STATUS_COMMON_RUNNING, &adapter->status) || | ||
2374 | atomic_test_mask | ||
2375 | (ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { | ||
2376 | goto out; | ||
2377 | } | ||
2378 | if (!atomic_test_mask | ||
2379 | (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) | ||
2380 | need = ZFCP_ERP_ACTION_REOPEN_ADAPTER; | ||
2381 | /* fall through !!! */ | ||
2382 | 1146 | ||
2383 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1147 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
2384 | if (atomic_test_mask | 1148 | result = zfcp_erp_strategy_check_adapter(adapter, result); |
2385 | (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) { | ||
2386 | goto out; | ||
2387 | } | ||
2388 | break; | 1149 | break; |
2389 | |||
2390 | default: | ||
2391 | /* unknown erp action */ | ||
2392 | goto out; | ||
2393 | } | 1150 | } |
1151 | return result; | ||
1152 | } | ||
2394 | 1153 | ||
2395 | /* mark adapter to have some error recovery pending */ | 1154 | static int zfcp_erp_strat_change_det(atomic_t *target_status, u32 erp_status) |
2396 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); | 1155 | { |
1156 | int status = atomic_read(target_status); | ||
2397 | 1157 | ||
2398 | /* setup error recovery action */ | 1158 | if ((status & ZFCP_STATUS_COMMON_RUNNING) && |
2399 | switch (need) { | 1159 | (erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY)) |
1160 | return 1; /* take it online */ | ||
2400 | 1161 | ||
2401 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1162 | if (!(status & ZFCP_STATUS_COMMON_RUNNING) && |
2402 | zfcp_unit_get(unit); | 1163 | !(erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY)) |
2403 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | 1164 | return 1; /* take it offline */ |
2404 | erp_action = &unit->erp_action; | 1165 | |
2405 | if (!atomic_test_mask | 1166 | return 0; |
2406 | (ZFCP_STATUS_COMMON_RUNNING, &unit->status)) | 1167 | } |
2407 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 1168 | |
1169 | static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) | ||
1170 | { | ||
1171 | int action = act->action; | ||
1172 | struct zfcp_adapter *adapter = act->adapter; | ||
1173 | struct zfcp_port *port = act->port; | ||
1174 | struct zfcp_unit *unit = act->unit; | ||
1175 | u32 erp_status = act->status; | ||
1176 | |||
1177 | switch (action) { | ||
1178 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
1179 | if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { | ||
1180 | _zfcp_erp_adapter_reopen(adapter, | ||
1181 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
1182 | 67, NULL); | ||
1183 | return ZFCP_ERP_EXIT; | ||
1184 | } | ||
2408 | break; | 1185 | break; |
2409 | 1186 | ||
2410 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
2411 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1187 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
2412 | zfcp_port_get(port); | 1188 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
2413 | zfcp_erp_action_dismiss_port(port); | 1189 | if (zfcp_erp_strat_change_det(&port->status, erp_status)) { |
2414 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); | 1190 | _zfcp_erp_port_reopen(port, |
2415 | erp_action = &port->erp_action; | 1191 | ZFCP_STATUS_COMMON_ERP_FAILED, |
2416 | if (!atomic_test_mask | 1192 | 68, NULL); |
2417 | (ZFCP_STATUS_COMMON_RUNNING, &port->status)) | 1193 | return ZFCP_ERP_EXIT; |
2418 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | 1194 | } |
2419 | break; | 1195 | break; |
2420 | 1196 | ||
2421 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1197 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
2422 | zfcp_adapter_get(adapter); | 1198 | if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { |
2423 | zfcp_erp_action_dismiss_adapter(adapter); | 1199 | _zfcp_erp_unit_reopen(unit, |
2424 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); | 1200 | ZFCP_STATUS_COMMON_ERP_FAILED, |
2425 | erp_action = &adapter->erp_action; | 1201 | 69, NULL); |
2426 | if (!atomic_test_mask | 1202 | return ZFCP_ERP_EXIT; |
2427 | (ZFCP_STATUS_COMMON_RUNNING, &adapter->status)) | 1203 | } |
2428 | status = ZFCP_STATUS_ERP_CLOSE_ONLY; | ||
2429 | break; | 1204 | break; |
2430 | } | 1205 | } |
2431 | 1206 | return ret; | |
2432 | memset(erp_action, 0, sizeof (struct zfcp_erp_action)); | ||
2433 | erp_action->adapter = adapter; | ||
2434 | erp_action->port = port; | ||
2435 | erp_action->unit = unit; | ||
2436 | erp_action->action = need; | ||
2437 | erp_action->status = status; | ||
2438 | |||
2439 | ++adapter->erp_total_count; | ||
2440 | |||
2441 | /* finally put it into 'ready' queue and kick erp thread */ | ||
2442 | list_add_tail(&erp_action->list, &adapter->erp_ready_head); | ||
2443 | up(&adapter->erp_ready_sem); | ||
2444 | zfcp_rec_dbf_event_thread(1, adapter); | ||
2445 | retval = 0; | ||
2446 | out: | ||
2447 | zfcp_rec_dbf_event_trigger(id, ref, want, need, erp_action, | ||
2448 | adapter, port, unit); | ||
2449 | return retval; | ||
2450 | } | 1207 | } |
2451 | 1208 | ||
2452 | static int | 1209 | static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) |
2453 | zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | ||
2454 | { | 1210 | { |
2455 | int retval = 0; | ||
2456 | struct zfcp_adapter *adapter = erp_action->adapter; | 1211 | struct zfcp_adapter *adapter = erp_action->adapter; |
2457 | 1212 | ||
2458 | --adapter->erp_total_count; | 1213 | adapter->erp_total_count--; |
2459 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | 1214 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { |
2460 | --adapter->erp_low_mem_count; | 1215 | adapter->erp_low_mem_count--; |
2461 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; | 1216 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; |
2462 | } | 1217 | } |
2463 | 1218 | ||
@@ -2469,140 +1224,458 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) | |||
2469 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1224 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
2470 | &erp_action->unit->status); | 1225 | &erp_action->unit->status); |
2471 | break; | 1226 | break; |
1227 | |||
2472 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1228 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
2473 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1229 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
2474 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1230 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
2475 | &erp_action->port->status); | 1231 | &erp_action->port->status); |
2476 | break; | 1232 | break; |
1233 | |||
2477 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1234 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
2478 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, | 1235 | atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
2479 | &erp_action->adapter->status); | 1236 | &erp_action->adapter->status); |
2480 | break; | 1237 | break; |
2481 | default: | ||
2482 | /* bug */ | ||
2483 | break; | ||
2484 | } | 1238 | } |
2485 | return retval; | ||
2486 | } | 1239 | } |
2487 | 1240 | ||
2488 | /** | 1241 | struct zfcp_erp_add_work { |
2489 | * zfcp_erp_action_cleanup | 1242 | struct zfcp_unit *unit; |
2490 | * | 1243 | struct work_struct work; |
2491 | * Register unit with scsi stack if appropriate and fix reference counts. | 1244 | }; |
2492 | * Note: Temporary units are not registered with scsi stack. | 1245 | |
2493 | */ | 1246 | static void zfcp_erp_scsi_scan(struct work_struct *work) |
2494 | static void | ||
2495 | zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, | ||
2496 | struct zfcp_port *port, struct zfcp_unit *unit, | ||
2497 | int result) | ||
2498 | { | 1247 | { |
2499 | switch (action) { | 1248 | struct zfcp_erp_add_work *p = |
1249 | container_of(work, struct zfcp_erp_add_work, work); | ||
1250 | struct zfcp_unit *unit = p->unit; | ||
1251 | struct fc_rport *rport = unit->port->rport; | ||
1252 | scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, | ||
1253 | unit->scsi_lun, 0); | ||
1254 | atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
1255 | zfcp_unit_put(unit); | ||
1256 | kfree(p); | ||
1257 | } | ||
1258 | |||
1259 | static void zfcp_erp_schedule_work(struct zfcp_unit *unit) | ||
1260 | { | ||
1261 | struct zfcp_erp_add_work *p; | ||
1262 | |||
1263 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
1264 | if (!p) { | ||
1265 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
1266 | "Out of resources. Could not register unit " | ||
1267 | "0x%016Lx on port 0x%016Lx with SCSI stack.\n", | ||
1268 | unit->fcp_lun, unit->port->wwpn); | ||
1269 | return; | ||
1270 | } | ||
1271 | |||
1272 | zfcp_unit_get(unit); | ||
1273 | atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); | ||
1274 | INIT_WORK(&p->work, zfcp_erp_scsi_scan); | ||
1275 | p->unit = unit; | ||
1276 | schedule_work(&p->work); | ||
1277 | } | ||
1278 | |||
1279 | static void zfcp_erp_rport_register(struct zfcp_port *port) | ||
1280 | { | ||
1281 | struct fc_rport_identifiers ids; | ||
1282 | ids.node_name = port->wwnn; | ||
1283 | ids.port_name = port->wwpn; | ||
1284 | ids.port_id = port->d_id; | ||
1285 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; | ||
1286 | port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); | ||
1287 | if (!port->rport) { | ||
1288 | dev_err(&port->adapter->ccw_device->dev, | ||
1289 | "Failed registration of rport " | ||
1290 | "0x%016Lx.\n", port->wwpn); | ||
1291 | return; | ||
1292 | } | ||
1293 | |||
1294 | scsi_target_unblock(&port->rport->dev); | ||
1295 | port->rport->maxframe_size = port->maxframe_size; | ||
1296 | port->rport->supported_classes = port->supported_classes; | ||
1297 | } | ||
1298 | |||
1299 | static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) | ||
1300 | { | ||
1301 | struct zfcp_port *port; | ||
1302 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
1303 | if (port->rport && !(atomic_read(&port->status) & | ||
1304 | ZFCP_STATUS_PORT_WKA)) { | ||
1305 | fc_remote_port_delete(port->rport); | ||
1306 | port->rport = NULL; | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | ||
1311 | { | ||
1312 | struct zfcp_adapter *adapter = act->adapter; | ||
1313 | struct zfcp_port *port = act->port; | ||
1314 | struct zfcp_unit *unit = act->unit; | ||
1315 | |||
1316 | switch (act->action) { | ||
2500 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1317 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
2501 | if ((result == ZFCP_ERP_SUCCEEDED) | 1318 | if ((result == ZFCP_ERP_SUCCEEDED) && |
2502 | && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, | 1319 | !unit->device && port->rport) { |
2503 | &unit->status)) | ||
2504 | && !unit->device | ||
2505 | && port->rport) { | ||
2506 | atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, | 1320 | atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, |
2507 | &unit->status); | 1321 | &unit->status); |
2508 | if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, | 1322 | if (!(atomic_read(&unit->status) & |
2509 | &unit->status) == 0) | 1323 | ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)) |
2510 | zfcp_erp_schedule_work(unit); | 1324 | zfcp_erp_schedule_work(unit); |
2511 | } | 1325 | } |
2512 | zfcp_unit_put(unit); | 1326 | zfcp_unit_put(unit); |
2513 | break; | 1327 | break; |
1328 | |||
2514 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1329 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
2515 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1330 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
2516 | if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, | 1331 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN) { |
2517 | &port->status)) { | ||
2518 | zfcp_port_put(port); | 1332 | zfcp_port_put(port); |
2519 | break; | 1333 | return; |
2520 | } | ||
2521 | |||
2522 | if ((result == ZFCP_ERP_SUCCEEDED) | ||
2523 | && !port->rport) { | ||
2524 | struct fc_rport_identifiers ids; | ||
2525 | ids.node_name = port->wwnn; | ||
2526 | ids.port_name = port->wwpn; | ||
2527 | ids.port_id = port->d_id; | ||
2528 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; | ||
2529 | port->rport = | ||
2530 | fc_remote_port_add(adapter->scsi_host, 0, &ids); | ||
2531 | if (!port->rport) | ||
2532 | dev_err(&adapter->ccw_device->dev, | ||
2533 | "Failed registration of rport " | ||
2534 | "0x%016Lx.\n", port->wwpn); | ||
2535 | else { | ||
2536 | scsi_target_unblock(&port->rport->dev); | ||
2537 | port->rport->maxframe_size = port->maxframe_size; | ||
2538 | port->rport->supported_classes = | ||
2539 | port->supported_classes; | ||
2540 | } | ||
2541 | } | 1334 | } |
1335 | if ((result == ZFCP_ERP_SUCCEEDED) && !port->rport) | ||
1336 | zfcp_erp_rport_register(port); | ||
2542 | if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { | 1337 | if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { |
2543 | fc_remote_port_delete(port->rport); | 1338 | fc_remote_port_delete(port->rport); |
2544 | port->rport = NULL; | 1339 | port->rport = NULL; |
2545 | } | 1340 | } |
2546 | zfcp_port_put(port); | 1341 | zfcp_port_put(port); |
2547 | break; | 1342 | break; |
1343 | |||
2548 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1344 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
2549 | if (result != ZFCP_ERP_SUCCEEDED) { | 1345 | if (result != ZFCP_ERP_SUCCEEDED) |
2550 | list_for_each_entry(port, &adapter->port_list_head, list) | 1346 | zfcp_erp_rports_del(adapter); |
2551 | if (port->rport && | ||
2552 | !atomic_test_mask(ZFCP_STATUS_PORT_WKA, | ||
2553 | &port->status)) { | ||
2554 | fc_remote_port_delete(port->rport); | ||
2555 | port->rport = NULL; | ||
2556 | } | ||
2557 | } | ||
2558 | zfcp_adapter_put(adapter); | 1347 | zfcp_adapter_put(adapter); |
2559 | break; | 1348 | break; |
2560 | default: | ||
2561 | break; | ||
2562 | } | 1349 | } |
2563 | } | 1350 | } |
2564 | 1351 | ||
1352 | static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) | ||
1353 | { | ||
1354 | switch (erp_action->action) { | ||
1355 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | ||
1356 | return zfcp_erp_adapter_strategy(erp_action); | ||
1357 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | ||
1358 | return zfcp_erp_port_forced_strategy(erp_action); | ||
1359 | case ZFCP_ERP_ACTION_REOPEN_PORT: | ||
1360 | return zfcp_erp_port_strategy(erp_action); | ||
1361 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | ||
1362 | return zfcp_erp_unit_strategy(erp_action); | ||
1363 | } | ||
1364 | return ZFCP_ERP_FAILED; | ||
1365 | } | ||
2565 | 1366 | ||
2566 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | 1367 | static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) |
2567 | { | 1368 | { |
2568 | struct zfcp_port *port; | 1369 | int retval; |
1370 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
1371 | unsigned long flags; | ||
2569 | 1372 | ||
2570 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) | 1373 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
2571 | zfcp_erp_action_dismiss(&adapter->erp_action); | 1374 | write_lock(&adapter->erp_lock); |
2572 | else | 1375 | |
2573 | list_for_each_entry(port, &adapter->port_list_head, list) | 1376 | zfcp_erp_strategy_check_fsfreq(erp_action); |
2574 | zfcp_erp_action_dismiss_port(port); | 1377 | |
1378 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { | ||
1379 | zfcp_erp_action_dequeue(erp_action); | ||
1380 | retval = ZFCP_ERP_DISMISSED; | ||
1381 | goto unlock; | ||
1382 | } | ||
1383 | |||
1384 | zfcp_erp_action_to_running(erp_action); | ||
1385 | |||
1386 | /* no lock to allow for blocking operations */ | ||
1387 | write_unlock(&adapter->erp_lock); | ||
1388 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1389 | retval = zfcp_erp_strategy_do_action(erp_action); | ||
1390 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
1391 | write_lock(&adapter->erp_lock); | ||
1392 | |||
1393 | if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) | ||
1394 | retval = ZFCP_ERP_CONTINUES; | ||
1395 | |||
1396 | switch (retval) { | ||
1397 | case ZFCP_ERP_NOMEM: | ||
1398 | if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) { | ||
1399 | ++adapter->erp_low_mem_count; | ||
1400 | erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; | ||
1401 | } | ||
1402 | if (adapter->erp_total_count == adapter->erp_low_mem_count) | ||
1403 | _zfcp_erp_adapter_reopen(adapter, 0, 66, NULL); | ||
1404 | else { | ||
1405 | zfcp_erp_strategy_memwait(erp_action); | ||
1406 | retval = ZFCP_ERP_CONTINUES; | ||
1407 | } | ||
1408 | goto unlock; | ||
1409 | |||
1410 | case ZFCP_ERP_CONTINUES: | ||
1411 | if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { | ||
1412 | --adapter->erp_low_mem_count; | ||
1413 | erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; | ||
1414 | } | ||
1415 | goto unlock; | ||
1416 | } | ||
1417 | |||
1418 | retval = zfcp_erp_strategy_check_target(erp_action, retval); | ||
1419 | zfcp_erp_action_dequeue(erp_action); | ||
1420 | retval = zfcp_erp_strategy_statechange(erp_action, retval); | ||
1421 | if (retval == ZFCP_ERP_EXIT) | ||
1422 | goto unlock; | ||
1423 | zfcp_erp_strategy_followup_actions(erp_action); | ||
1424 | |||
1425 | unlock: | ||
1426 | write_unlock(&adapter->erp_lock); | ||
1427 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1428 | |||
1429 | if (retval != ZFCP_ERP_CONTINUES) | ||
1430 | zfcp_erp_action_cleanup(erp_action, retval); | ||
1431 | |||
1432 | return retval; | ||
2575 | } | 1433 | } |
2576 | 1434 | ||
2577 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) | 1435 | static int zfcp_erp_thread(void *data) |
2578 | { | 1436 | { |
2579 | struct zfcp_unit *unit; | 1437 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; |
1438 | struct list_head *next; | ||
1439 | struct zfcp_erp_action *act; | ||
1440 | unsigned long flags; | ||
2580 | 1441 | ||
2581 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) | 1442 | daemonize("zfcperp%s", adapter->ccw_device->dev.bus_id); |
2582 | zfcp_erp_action_dismiss(&port->erp_action); | 1443 | /* Block all signals */ |
1444 | siginitsetinv(¤t->blocked, 0); | ||
1445 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
1446 | wake_up(&adapter->erp_thread_wqh); | ||
1447 | |||
1448 | while (!(atomic_read(&adapter->status) & | ||
1449 | ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) { | ||
1450 | write_lock_irqsave(&adapter->erp_lock, flags); | ||
1451 | next = adapter->erp_ready_head.next; | ||
1452 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
1453 | |||
1454 | if (next != &adapter->erp_ready_head) { | ||
1455 | act = list_entry(next, struct zfcp_erp_action, list); | ||
1456 | |||
1457 | /* there is more to come after dismission, no notify */ | ||
1458 | if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED) | ||
1459 | zfcp_erp_wakeup(adapter); | ||
1460 | } | ||
1461 | |||
1462 | zfcp_rec_dbf_event_thread(4, adapter); | ||
1463 | down_interruptible(&adapter->erp_ready_sem); | ||
1464 | zfcp_rec_dbf_event_thread(5, adapter); | ||
1465 | } | ||
1466 | |||
1467 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
1468 | wake_up(&adapter->erp_thread_wqh); | ||
1469 | |||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | /** | ||
1474 | * zfcp_erp_thread_setup - Start ERP thread for adapter | ||
1475 | * @adapter: Adapter to start the ERP thread for | ||
1476 | * | ||
1477 | * Returns 0 on success or error code from kernel_thread() | ||
1478 | */ | ||
1479 | int zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | ||
1480 | { | ||
1481 | int retval; | ||
1482 | |||
1483 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | ||
1484 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | ||
1485 | if (retval < 0) { | ||
1486 | dev_err(&adapter->ccw_device->dev, | ||
1487 | "Creation of ERP thread failed.\n"); | ||
1488 | return retval; | ||
1489 | } | ||
1490 | wait_event(adapter->erp_thread_wqh, | ||
1491 | atomic_read(&adapter->status) & | ||
1492 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP); | ||
1493 | return 0; | ||
1494 | } | ||
1495 | |||
1496 | /** | ||
1497 | * zfcp_erp_thread_kill - Stop ERP thread. | ||
1498 | * @adapter: Adapter where the ERP thread should be stopped. | ||
1499 | * | ||
1500 | * The caller of this routine ensures that the specified adapter has | ||
1501 | * been shut down and that this operation has been completed. Thus, | ||
1502 | * there are no pending erp_actions which would need to be handled | ||
1503 | * here. | ||
1504 | */ | ||
1505 | void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) | ||
1506 | { | ||
1507 | atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); | ||
1508 | up(&adapter->erp_ready_sem); | ||
1509 | zfcp_rec_dbf_event_thread_lock(2, adapter); | ||
1510 | |||
1511 | wait_event(adapter->erp_thread_wqh, | ||
1512 | !(atomic_read(&adapter->status) & | ||
1513 | ZFCP_STATUS_ADAPTER_ERP_THREAD_UP)); | ||
1514 | |||
1515 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, | ||
1516 | &adapter->status); | ||
1517 | } | ||
1518 | |||
1519 | /** | ||
1520 | * zfcp_erp_adapter_failed - Set adapter status to failed. | ||
1521 | * @adapter: Failed adapter. | ||
1522 | * @id: Event id for debug trace. | ||
1523 | * @ref: Reference for debug trace. | ||
1524 | */ | ||
1525 | void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) | ||
1526 | { | ||
1527 | zfcp_erp_modify_adapter_status(adapter, id, ref, | ||
1528 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1529 | dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n"); | ||
1530 | } | ||
1531 | |||
1532 | /** | ||
1533 | * zfcp_erp_port_failed - Set port status to failed. | ||
1534 | * @port: Failed port. | ||
1535 | * @id: Event id for debug trace. | ||
1536 | * @ref: Reference for debug trace. | ||
1537 | */ | ||
1538 | void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) | ||
1539 | { | ||
1540 | zfcp_erp_modify_port_status(port, id, ref, | ||
1541 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); | ||
1542 | |||
1543 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) | ||
1544 | dev_err(&port->adapter->ccw_device->dev, | ||
1545 | "Port ERP failed for WKA port d_id=0x%06x.\n", | ||
1546 | port->d_id); | ||
2583 | else | 1547 | else |
2584 | list_for_each_entry(unit, &port->unit_list_head, list) | 1548 | dev_err(&port->adapter->ccw_device->dev, |
2585 | zfcp_erp_action_dismiss_unit(unit); | 1549 | "Port ERP failed for port wwpn=0x%016Lx.\n", |
1550 | port->wwpn); | ||
2586 | } | 1551 | } |
2587 | 1552 | ||
2588 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | 1553 | /** |
1554 | * zfcp_erp_unit_failed - Set unit status to failed. | ||
1555 | * @unit: Failed unit. | ||
1556 | * @id: Event id for debug trace. | ||
1557 | * @ref: Reference for debug trace. | ||
1558 | */ | ||
1559 | void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref) | ||
2589 | { | 1560 | { |
2590 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) | 1561 | zfcp_erp_modify_unit_status(unit, id, ref, |
2591 | zfcp_erp_action_dismiss(&unit->erp_action); | 1562 | ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); |
1563 | |||
1564 | dev_err(&unit->port->adapter->ccw_device->dev, | ||
1565 | "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n", | ||
1566 | unit->fcp_lun, unit->port->wwpn); | ||
2592 | } | 1567 | } |
2593 | 1568 | ||
2594 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | 1569 | /** |
1570 | * zfcp_erp_wait - wait for completion of error recovery on an adapter | ||
1571 | * @adapter: adapter for which to wait for completion of its error recovery | ||
1572 | */ | ||
1573 | void zfcp_erp_wait(struct zfcp_adapter *adapter) | ||
2595 | { | 1574 | { |
2596 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); | 1575 | wait_event(adapter->erp_done_wqh, |
2597 | zfcp_rec_dbf_event_action(145, erp_action); | 1576 | !(atomic_read(&adapter->status) & |
1577 | ZFCP_STATUS_ADAPTER_ERP_PENDING)); | ||
1578 | } | ||
1579 | |||
1580 | /** | ||
1581 | * zfcp_erp_modify_adapter_status - change adapter status bits | ||
1582 | * @adapter: adapter to change the status | ||
1583 | * @id: id for the debug trace | ||
1584 | * @ref: reference for the debug trace | ||
1585 | * @mask: status bits to change | ||
1586 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
1587 | * | ||
1588 | * Changes in common status bits are propagated to attached ports and units. | ||
1589 | */ | ||
1590 | void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id, | ||
1591 | void *ref, u32 mask, int set_or_clear) | ||
1592 | { | ||
1593 | struct zfcp_port *port; | ||
1594 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | ||
1595 | |||
1596 | if (set_or_clear == ZFCP_SET) { | ||
1597 | if (status_change_set(mask, &adapter->status)) | ||
1598 | zfcp_rec_dbf_event_adapter(id, ref, adapter); | ||
1599 | atomic_set_mask(mask, &adapter->status); | ||
1600 | } else { | ||
1601 | if (status_change_clear(mask, &adapter->status)) | ||
1602 | zfcp_rec_dbf_event_adapter(id, ref, adapter); | ||
1603 | atomic_clear_mask(mask, &adapter->status); | ||
1604 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
1605 | atomic_set(&adapter->erp_counter, 0); | ||
1606 | } | ||
1607 | |||
1608 | if (common_mask) | ||
1609 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
1610 | zfcp_erp_modify_port_status(port, id, ref, common_mask, | ||
1611 | set_or_clear); | ||
1612 | } | ||
1613 | |||
1614 | /** | ||
1615 | * zfcp_erp_modify_port_status - change port status bits | ||
1616 | * @port: port to change the status bits | ||
1617 | * @id: id for the debug trace | ||
1618 | * @ref: reference for the debug trace | ||
1619 | * @mask: status bits to change | ||
1620 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
1621 | * | ||
1622 | * Changes in common status bits are propagated to attached units. | ||
1623 | */ | ||
1624 | void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref, | ||
1625 | u32 mask, int set_or_clear) | ||
1626 | { | ||
1627 | struct zfcp_unit *unit; | ||
1628 | u32 common_mask = mask & ZFCP_COMMON_FLAGS; | ||
1629 | |||
1630 | if (set_or_clear == ZFCP_SET) { | ||
1631 | if (status_change_set(mask, &port->status)) | ||
1632 | zfcp_rec_dbf_event_port(id, ref, port); | ||
1633 | atomic_set_mask(mask, &port->status); | ||
1634 | } else { | ||
1635 | if (status_change_clear(mask, &port->status)) | ||
1636 | zfcp_rec_dbf_event_port(id, ref, port); | ||
1637 | atomic_clear_mask(mask, &port->status); | ||
1638 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
1639 | atomic_set(&port->erp_counter, 0); | ||
1640 | } | ||
1641 | |||
1642 | if (common_mask) | ||
1643 | list_for_each_entry(unit, &port->unit_list_head, list) | ||
1644 | zfcp_erp_modify_unit_status(unit, id, ref, common_mask, | ||
1645 | set_or_clear); | ||
2598 | } | 1646 | } |
2599 | 1647 | ||
2600 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) | 1648 | /** |
1649 | * zfcp_erp_modify_unit_status - change unit status bits | ||
1650 | * @unit: unit to change the status bits | ||
1651 | * @id: id for the debug trace | ||
1652 | * @ref: reference for the debug trace | ||
1653 | * @mask: status bits to change | ||
1654 | * @set_or_clear: ZFCP_SET or ZFCP_CLEAR | ||
1655 | */ | ||
1656 | void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref, | ||
1657 | u32 mask, int set_or_clear) | ||
2601 | { | 1658 | { |
2602 | list_move(&erp_action->list, &erp_action->adapter->erp_ready_head); | 1659 | if (set_or_clear == ZFCP_SET) { |
2603 | zfcp_rec_dbf_event_action(146, erp_action); | 1660 | if (status_change_set(mask, &unit->status)) |
1661 | zfcp_rec_dbf_event_unit(id, ref, unit); | ||
1662 | atomic_set_mask(mask, &unit->status); | ||
1663 | } else { | ||
1664 | if (status_change_clear(mask, &unit->status)) | ||
1665 | zfcp_rec_dbf_event_unit(id, ref, unit); | ||
1666 | atomic_clear_mask(mask, &unit->status); | ||
1667 | if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { | ||
1668 | atomic_set(&unit->erp_counter, 0); | ||
1669 | } | ||
1670 | } | ||
2604 | } | 1671 | } |
2605 | 1672 | ||
1673 | /** | ||
1674 | * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP | ||
1675 | * @port: The "boxed" port. | ||
1676 | * @id: The debug trace id. | ||
1677 | * @id: Reference for the debug trace. | ||
1678 | */ | ||
2606 | void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) | 1679 | void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) |
2607 | { | 1680 | { |
2608 | unsigned long flags; | 1681 | unsigned long flags; |
@@ -2614,6 +1687,12 @@ void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref) | |||
2614 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1687 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
2615 | } | 1688 | } |
2616 | 1689 | ||
1690 | /** | ||
1691 | * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP | ||
1692 | * @port: The "boxed" unit. | ||
1693 | * @id: The debug trace id. | ||
1694 | * @id: Reference for the debug trace. | ||
1695 | */ | ||
2617 | void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) | 1696 | void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) |
2618 | { | 1697 | { |
2619 | zfcp_erp_modify_unit_status(unit, id, ref, | 1698 | zfcp_erp_modify_unit_status(unit, id, ref, |
@@ -2621,6 +1700,15 @@ void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref) | |||
2621 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1700 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
2622 | } | 1701 | } |
2623 | 1702 | ||
1703 | /** | ||
1704 | * zfcp_erp_port_access_denied - Adapter denied access to port. | ||
1705 | * @port: port where access has been denied | ||
1706 | * @id: id for debug trace | ||
1707 | * @ref: reference for debug trace | ||
1708 | * | ||
1709 | * Since the adapter has denied access, stop using the port and the | ||
1710 | * attached units. | ||
1711 | */ | ||
2624 | void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) | 1712 | void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) |
2625 | { | 1713 | { |
2626 | unsigned long flags; | 1714 | unsigned long flags; |
@@ -2632,6 +1720,14 @@ void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref) | |||
2632 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 1720 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
2633 | } | 1721 | } |
2634 | 1722 | ||
1723 | /** | ||
1724 | * zfcp_erp_unit_access_denied - Adapter denied access to unit. | ||
1725 | * @unit: unit where access has been denied | ||
1726 | * @id: id for debug trace | ||
1727 | * @ref: reference for debug trace | ||
1728 | * | ||
1729 | * Since the adapter has denied access, stop using the unit. | ||
1730 | */ | ||
2635 | void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref) | 1731 | void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref) |
2636 | { | 1732 | { |
2637 | zfcp_erp_modify_unit_status(unit, id, ref, | 1733 | zfcp_erp_modify_unit_status(unit, id, ref, |
@@ -2639,33 +1735,26 @@ void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref) | |||
2639 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); | 1735 | ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); |
2640 | } | 1736 | } |
2641 | 1737 | ||
2642 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, | 1738 | static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, |
2643 | void *ref) | 1739 | void *ref) |
2644 | { | 1740 | { |
2645 | struct zfcp_port *port; | 1741 | int status = atomic_read(&unit->status); |
2646 | unsigned long flags; | 1742 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | |
2647 | 1743 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) | |
2648 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
2649 | return; | 1744 | return; |
2650 | 1745 | ||
2651 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1746 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
2652 | if (adapter->nameserver_port) | ||
2653 | zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref); | ||
2654 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
2655 | if (port != adapter->nameserver_port) | ||
2656 | zfcp_erp_port_access_changed(port, id, ref); | ||
2657 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
2658 | } | 1747 | } |
2659 | 1748 | ||
2660 | void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, void *ref) | 1749 | static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, |
1750 | void *ref) | ||
2661 | { | 1751 | { |
2662 | struct zfcp_unit *unit; | 1752 | struct zfcp_unit *unit; |
1753 | int status = atomic_read(&port->status); | ||
2663 | 1754 | ||
2664 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, | 1755 | if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | |
2665 | &port->status) && | 1756 | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { |
2666 | !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, | 1757 | if (!(status & ZFCP_STATUS_PORT_WKA)) |
2667 | &port->status)) { | ||
2668 | if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) | ||
2669 | list_for_each_entry(unit, &port->unit_list_head, list) | 1758 | list_for_each_entry(unit, &port->unit_list_head, list) |
2670 | zfcp_erp_unit_access_changed(unit, id, ref); | 1759 | zfcp_erp_unit_access_changed(unit, id, ref); |
2671 | return; | 1760 | return; |
@@ -2674,13 +1763,26 @@ void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, void *ref) | |||
2674 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1763 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); |
2675 | } | 1764 | } |
2676 | 1765 | ||
2677 | void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, void *ref) | 1766 | /** |
1767 | * zfcp_erp_adapter_access_changed - Process change in adapter ACT | ||
1768 | * @adapter: Adapter where the Access Control Table (ACT) changed | ||
1769 | * @id: Id for debug trace | ||
1770 | * @ref: Reference for debug trace | ||
1771 | */ | ||
1772 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, | ||
1773 | void *ref) | ||
2678 | { | 1774 | { |
2679 | if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, | 1775 | struct zfcp_port *port; |
2680 | &unit->status) && | 1776 | unsigned long flags; |
2681 | !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, | 1777 | |
2682 | &unit->status)) | 1778 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) |
2683 | return; | 1779 | return; |
2684 | 1780 | ||
2685 | zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); | 1781 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
1782 | if (adapter->nameserver_port) | ||
1783 | zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref); | ||
1784 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
1785 | if (port != adapter->nameserver_port) | ||
1786 | zfcp_erp_port_access_changed(port, id, ref); | ||
1787 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
2686 | } | 1788 | } |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 2845693413fb..13eb0a67da66 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -67,8 +67,6 @@ extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *, | |||
67 | struct fsf_qtcb_bottom_port *); | 67 | struct fsf_qtcb_bottom_port *); |
68 | extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | 68 | extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, |
69 | struct zfcp_fsf_cfdc *fsf_cfdc); | 69 | struct zfcp_fsf_cfdc *fsf_cfdc); |
70 | extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); | ||
71 | extern void zfcp_erp_start_timer(struct zfcp_fsf_req *); | ||
72 | extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); | 70 | extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); |
73 | extern int zfcp_fsf_status_read(struct zfcp_adapter *); | 71 | extern int zfcp_fsf_status_read(struct zfcp_adapter *); |
74 | extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); | 72 | extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); |
@@ -103,37 +101,34 @@ extern struct fc_function_template zfcp_transport_functions; | |||
103 | /******************************** ERP ****************************************/ | 101 | /******************************** ERP ****************************************/ |
104 | extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *, | 102 | extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *, |
105 | u32, int); | 103 | u32, int); |
106 | extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *); | 104 | extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *); |
107 | extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *); | 105 | extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *); |
108 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *); | 106 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *); |
109 | 107 | ||
110 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32, | 108 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32, |
111 | int); | 109 | int); |
112 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *); | 110 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *); |
113 | extern int zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *); | 111 | extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *); |
114 | extern int zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *); | 112 | extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *); |
115 | extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *); | 113 | extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *); |
116 | extern int zfcp_erp_port_reopen_all(struct zfcp_adapter *, int, u8, void *); | ||
117 | 114 | ||
118 | extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32, | 115 | extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32, |
119 | int); | 116 | int); |
120 | extern int zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *); | 117 | extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *); |
121 | extern int zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *); | 118 | extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *); |
122 | extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *); | 119 | extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *); |
123 | 120 | ||
124 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); | 121 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); |
125 | extern int zfcp_erp_thread_kill(struct zfcp_adapter *); | 122 | extern void zfcp_erp_thread_kill(struct zfcp_adapter *); |
126 | extern int zfcp_erp_wait(struct zfcp_adapter *); | 123 | extern void zfcp_erp_wait(struct zfcp_adapter *); |
127 | extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); | 124 | extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long); |
128 | 125 | ||
129 | extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref); | 126 | extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref); |
130 | extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref); | 127 | extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref); |
131 | extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref); | 128 | extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref); |
132 | extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8 id, void *ref); | 129 | extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8 id, void *ref); |
133 | extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); | 130 | extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); |
134 | extern void zfcp_erp_port_access_changed(struct zfcp_port *, u8, void *); | 131 | extern void zfcp_erp_timeout_handler(unsigned long); |
135 | extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *); | ||
136 | |||
137 | /******************************** AUX ****************************************/ | 132 | /******************************** AUX ****************************************/ |
138 | extern void zfcp_sg_free_table(struct scatterlist *sg, int count); | 133 | extern void zfcp_sg_free_table(struct scatterlist *sg, int count); |
139 | extern int zfcp_sg_setup_table(struct scatterlist *sg, int count); | 134 | extern int zfcp_sg_setup_table(struct scatterlist *sg, int count); |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e6d815593b49..19c1ca913874 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -8,6 +8,31 @@ | |||
8 | 8 | ||
9 | #include "zfcp_ext.h" | 9 | #include "zfcp_ext.h" |
10 | 10 | ||
11 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | ||
12 | { | ||
13 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | ||
14 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62, | ||
15 | NULL); | ||
16 | } | ||
17 | |||
18 | static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, | ||
19 | unsigned long timeout) | ||
20 | { | ||
21 | fsf_req->timer.function = zfcp_fsf_request_timeout_handler; | ||
22 | fsf_req->timer.data = (unsigned long) fsf_req->adapter; | ||
23 | fsf_req->timer.expires = jiffies + timeout; | ||
24 | add_timer(&fsf_req->timer); | ||
25 | } | ||
26 | |||
27 | static void zfcp_fsf_start_erp_timer(struct zfcp_fsf_req *fsf_req) | ||
28 | { | ||
29 | BUG_ON(!fsf_req->erp_action); | ||
30 | fsf_req->timer.function = zfcp_erp_timeout_handler; | ||
31 | fsf_req->timer.data = (unsigned long) fsf_req->erp_action; | ||
32 | fsf_req->timer.expires = jiffies + 30 * HZ; | ||
33 | add_timer(&fsf_req->timer); | ||
34 | } | ||
35 | |||
11 | /* association between FSF command and FSF QTCB type */ | 36 | /* association between FSF command and FSF QTCB type */ |
12 | static u32 fsf_qtcb_type[] = { | 37 | static u32 fsf_qtcb_type[] = { |
13 | [FSF_QTCB_FCP_CMND] = FSF_IO_COMMAND, | 38 | [FSF_QTCB_FCP_CMND] = FSF_IO_COMMAND, |
@@ -485,7 +510,7 @@ void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) | |||
485 | req->handler(req); | 510 | req->handler(req); |
486 | 511 | ||
487 | if (req->erp_action) | 512 | if (req->erp_action) |
488 | zfcp_erp_async_handler(req->erp_action, 0); | 513 | zfcp_erp_notify(req->erp_action, 0); |
489 | req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; | 514 | req->status |= ZFCP_STATUS_FSFREQ_COMPLETED; |
490 | 515 | ||
491 | if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) | 516 | if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) |
@@ -1108,7 +1133,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1108 | if (erp_action) { | 1133 | if (erp_action) { |
1109 | erp_action->fsf_req = req; | 1134 | erp_action->fsf_req = req; |
1110 | req->erp_action = erp_action; | 1135 | req->erp_action = erp_action; |
1111 | zfcp_erp_start_timer(req); | 1136 | zfcp_fsf_start_erp_timer(req); |
1112 | } else | 1137 | } else |
1113 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); | 1138 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
1114 | 1139 | ||
@@ -1263,7 +1288,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1263 | req->handler = zfcp_fsf_exchange_config_data_handler; | 1288 | req->handler = zfcp_fsf_exchange_config_data_handler; |
1264 | erp_action->fsf_req = req; | 1289 | erp_action->fsf_req = req; |
1265 | 1290 | ||
1266 | zfcp_erp_start_timer(req); | 1291 | zfcp_fsf_start_erp_timer(req); |
1267 | retval = zfcp_fsf_req_send(req); | 1292 | retval = zfcp_fsf_req_send(req); |
1268 | if (retval) { | 1293 | if (retval) { |
1269 | zfcp_fsf_req_free(req); | 1294 | zfcp_fsf_req_free(req); |
@@ -1353,7 +1378,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | |||
1353 | req->erp_action = erp_action; | 1378 | req->erp_action = erp_action; |
1354 | erp_action->fsf_req = req; | 1379 | erp_action->fsf_req = req; |
1355 | 1380 | ||
1356 | zfcp_erp_start_timer(req); | 1381 | zfcp_fsf_start_erp_timer(req); |
1357 | retval = zfcp_fsf_req_send(req); | 1382 | retval = zfcp_fsf_req_send(req); |
1358 | if (retval) { | 1383 | if (retval) { |
1359 | zfcp_fsf_req_free(req); | 1384 | zfcp_fsf_req_free(req); |
@@ -1530,7 +1555,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1530 | erp_action->fsf_req = req; | 1555 | erp_action->fsf_req = req; |
1531 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); | 1556 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); |
1532 | 1557 | ||
1533 | zfcp_erp_start_timer(req); | 1558 | zfcp_fsf_start_erp_timer(req); |
1534 | retval = zfcp_fsf_req_send(req); | 1559 | retval = zfcp_fsf_req_send(req); |
1535 | if (retval) { | 1560 | if (retval) { |
1536 | zfcp_fsf_req_free(req); | 1561 | zfcp_fsf_req_free(req); |
@@ -1601,7 +1626,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
1601 | erp_action->fsf_req = req; | 1626 | erp_action->fsf_req = req; |
1602 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); | 1627 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); |
1603 | 1628 | ||
1604 | zfcp_erp_start_timer(req); | 1629 | zfcp_fsf_start_erp_timer(req); |
1605 | retval = zfcp_fsf_req_send(req); | 1630 | retval = zfcp_fsf_req_send(req); |
1606 | if (retval) { | 1631 | if (retval) { |
1607 | zfcp_fsf_req_free(req); | 1632 | zfcp_fsf_req_free(req); |
@@ -1699,7 +1724,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
1699 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, | 1724 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, |
1700 | &erp_action->port->status); | 1725 | &erp_action->port->status); |
1701 | 1726 | ||
1702 | zfcp_erp_start_timer(req); | 1727 | zfcp_fsf_start_erp_timer(req); |
1703 | retval = zfcp_fsf_req_send(req); | 1728 | retval = zfcp_fsf_req_send(req); |
1704 | if (retval) { | 1729 | if (retval) { |
1705 | zfcp_fsf_req_free(req); | 1730 | zfcp_fsf_req_free(req); |
@@ -1878,7 +1903,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
1878 | 1903 | ||
1879 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); | 1904 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); |
1880 | 1905 | ||
1881 | zfcp_erp_start_timer(req); | 1906 | zfcp_fsf_start_erp_timer(req); |
1882 | retval = zfcp_fsf_req_send(req); | 1907 | retval = zfcp_fsf_req_send(req); |
1883 | if (retval) { | 1908 | if (retval) { |
1884 | zfcp_fsf_req_free(req); | 1909 | zfcp_fsf_req_free(req); |
@@ -1963,7 +1988,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
1963 | erp_action->fsf_req = req; | 1988 | erp_action->fsf_req = req; |
1964 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); | 1989 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); |
1965 | 1990 | ||
1966 | zfcp_erp_start_timer(req); | 1991 | zfcp_fsf_start_erp_timer(req); |
1967 | retval = zfcp_fsf_req_send(req); | 1992 | retval = zfcp_fsf_req_send(req); |
1968 | if (retval) { | 1993 | if (retval) { |
1969 | zfcp_fsf_req_free(req); | 1994 | zfcp_fsf_req_free(req); |