blob: b18c6dd37294d101f2104d0d29dac67f9e3d0d01 [file] [log] [blame]
Swen Schillig41fa2ad2007-09-07 09:15:31 +02001/*
Christof Schmitt553448f2008-06-10 18:20:58 +02002 * zfcp device driver
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Christof Schmitt553448f2008-06-10 18:20:58 +02004 * Error Recovery Procedures (ERP).
Swen Schillig41fa2ad2007-09-07 09:15:31 +02005 *
Christof Schmitt553448f2008-06-10 18:20:58 +02006 * Copyright IBM Corporation 2002, 2008
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include "zfcp_ext.h"
10
Christof Schmitt287ac012008-07-02 10:56:40 +020011#define ZFCP_MAX_ERPS 3
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
Christof Schmitt287ac012008-07-02 10:56:40 +020013enum zfcp_erp_act_flags {
14 ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000,
15 ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000,
16 ZFCP_STATUS_ERP_DISMISSING = 0x00100000,
17 ZFCP_STATUS_ERP_DISMISSED = 0x00200000,
18 ZFCP_STATUS_ERP_LOWMEM = 0x00400000,
19};
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Christof Schmitt287ac012008-07-02 10:56:40 +020021enum zfcp_erp_steps {
22 ZFCP_ERP_STEP_UNINITIALIZED = 0x0000,
23 ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001,
24 ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
25 ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
26 ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200,
27 ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400,
28 ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
29 ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000,
30 ZFCP_ERP_STEP_UNIT_OPENING = 0x2000,
31};
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
Christof Schmitt287ac012008-07-02 10:56:40 +020033enum zfcp_erp_act_type {
34 ZFCP_ERP_ACTION_REOPEN_UNIT = 1,
35 ZFCP_ERP_ACTION_REOPEN_PORT = 2,
36 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
37 ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4,
38};
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Christof Schmitt287ac012008-07-02 10:56:40 +020040enum zfcp_erp_act_state {
41 ZFCP_ERP_ACTION_RUNNING = 1,
42 ZFCP_ERP_ACTION_READY = 2,
43};
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Christof Schmitt287ac012008-07-02 10:56:40 +020045enum 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};
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Christof Schmitt287ac012008-07-02 10:56:40 +020054static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
Andreas Herrmann2abbe862006-09-18 22:29:56 +020055{
Christof Schmitt287ac012008-07-02 10:56:40 +020056 zfcp_erp_modify_adapter_status(adapter, 15, NULL,
57 ZFCP_STATUS_COMMON_UNBLOCKED | mask,
58 ZFCP_CLEAR);
Andreas Herrmann2abbe862006-09-18 22:29:56 +020059}
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Christof Schmitt287ac012008-07-02 10:56:40 +020061static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -070062{
Christof Schmitt287ac012008-07-02 10:56:40 +020063 struct zfcp_erp_action *curr_act;
64
65 list_for_each_entry(curr_act, &act->adapter->erp_running_head, list)
66 if (act == curr_act)
67 return ZFCP_ERP_ACTION_RUNNING;
68 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069}
70
Christof Schmitt287ac012008-07-02 10:56:40 +020071static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
Christof Schmitt287ac012008-07-02 10:56:40 +020073 struct zfcp_adapter *adapter = act->adapter;
74
75 list_move(&act->list, &act->adapter->erp_ready_head);
76 zfcp_rec_dbf_event_action(146, act);
77 up(&adapter->erp_ready_sem);
78 zfcp_rec_dbf_event_thread(2, adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079}
80
Christof Schmitt287ac012008-07-02 10:56:40 +020081static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -070082{
Christof Schmitt287ac012008-07-02 10:56:40 +020083 act->status |= ZFCP_STATUS_ERP_DISMISSED;
84 if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING)
85 zfcp_erp_action_ready(act);
86}
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Christof Schmitt287ac012008-07-02 10:56:40 +020088static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
89{
90 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
91 zfcp_erp_action_dismiss(&unit->erp_action);
92}
93
94static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
95{
96 struct zfcp_unit *unit;
97
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);
103}
104
105static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
106{
107 struct zfcp_port *port;
108
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);
114}
115
116static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
117 struct zfcp_port *port,
118 struct zfcp_unit *unit)
119{
120 int need = want;
121 int u_status, p_status, a_status;
122
123 switch (want) {
124 case ZFCP_ERP_ACTION_REOPEN_UNIT:
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;
151 }
152
153 return need;
154}
155
156static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
157 struct zfcp_adapter *adapter,
158 struct zfcp_port *port,
159 struct zfcp_unit *unit)
160{
161 struct zfcp_erp_action *erp_action;
162 u32 status = 0;
163
164 switch (need) {
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;
172
173 case ZFCP_ERP_ACTION_REOPEN_PORT:
174 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
175 zfcp_port_get(port);
176 zfcp_erp_action_dismiss_port(port);
177 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
178 erp_action = &port->erp_action;
179 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
180 status = ZFCP_STATUS_ERP_CLOSE_ONLY;
181 break;
182
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;
192
193 default:
194 return NULL;
195 }
196
197 memset(erp_action, 0, sizeof(struct zfcp_erp_action));
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;
203
204 return erp_action;
205}
206
207static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
208 struct zfcp_port *port,
209 struct zfcp_unit *unit, u8 id, void *ref)
210{
211 int retval = 1, need;
212 struct zfcp_erp_action *act = NULL;
213
214 if (!(atomic_read(&adapter->status) &
215 ZFCP_STATUS_ADAPTER_ERP_THREAD_UP))
216 return -EIO;
217
218 need = zfcp_erp_required_act(want, adapter, port, unit);
219 if (!need)
220 goto out;
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);
234 return retval;
235}
236
237static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
238 int clear_mask, u8 id, void *ref)
239{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 zfcp_erp_adapter_block(adapter, clear_mask);
241
Christof Schmitt287ac012008-07-02 10:56:40 +0200242 /* ensure propagation of failed status to new devices */
243 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
Martin Peschke1f6f7122008-04-18 12:51:55 +0200244 zfcp_erp_adapter_failed(adapter, 13, NULL);
Christof Schmitt287ac012008-07-02 10:56:40 +0200245 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200247 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
248 adapter, NULL, NULL, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249}
250
251/**
Christof Schmitt287ac012008-07-02 10:56:40 +0200252 * zfcp_erp_adapter_reopen - Reopen adapter.
253 * @adapter: Adapter to reopen.
254 * @clear: Status flags to clear.
255 * @id: Id for debug trace event.
256 * @ref: Reference for debug trace event.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 */
Christof Schmitt287ac012008-07-02 10:56:40 +0200258void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
259 u8 id, void *ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
Christof Schmitt287ac012008-07-02 10:56:40 +0200261 unsigned long flags;
262
263 read_lock_irqsave(&zfcp_data.config_lock, flags);
264 write_lock(&adapter->erp_lock);
265 _zfcp_erp_adapter_reopen(adapter, clear, id, ref);
266 write_unlock(&adapter->erp_lock);
267 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
268}
269
270/**
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.
276 */
277void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear,
278 u8 id, void *ref)
279{
280 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
281 zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref);
282}
283
284/**
285 * zfcp_erp_port_shutdown - Shutdown port
286 * @port: Port to shut down.
287 * @clear: Status flags to clear.
288 * @id: Id for debug trace event.
289 * @ref: Reference for debug trace event.
290 */
291void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, u8 id, void *ref)
292{
293 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
294 zfcp_erp_port_reopen(port, clear | flags, id, ref);
295}
296
297/**
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.
303 */
304void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, u8 id, void *ref)
305{
306 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
307 zfcp_erp_unit_reopen(unit, clear | flags, id, ref);
308}
309
310static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
311{
312 zfcp_erp_modify_port_status(port, 17, NULL,
313 ZFCP_STATUS_COMMON_UNBLOCKED | clear,
314 ZFCP_CLEAR);
315}
316
317static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
318 int clear, u8 id, void *ref)
319{
320 zfcp_erp_port_block(port, clear);
321
322 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
323 return;
324
325 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
326 port->adapter, port, NULL, id, ref);
327}
328
329/**
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.
334 */
335void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, u8 id,
336 void *ref)
337{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 unsigned long flags;
339 struct zfcp_adapter *adapter = port->adapter;
340
341 read_lock_irqsave(&zfcp_data.config_lock, flags);
342 write_lock(&adapter->erp_lock);
Christof Schmitt287ac012008-07-02 10:56:40 +0200343 _zfcp_erp_port_forced_reopen(port, clear, id, ref);
344 write_unlock(&adapter->erp_lock);
345 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
346}
347
348static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id,
349 void *ref)
350{
351 zfcp_erp_port_block(port, clear);
352
353 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
354 /* ensure propagation of failed status to new devices */
355 zfcp_erp_port_failed(port, 14, NULL);
356 return -EIO;
357 }
358
359 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
360 port->adapter, port, NULL, id, ref);
361}
362
363/**
364 * zfcp_erp_port_reopen - trigger remote port recovery
365 * @port: port to recover
366 * @clear_mask: flags in port status to be cleared
367 *
368 * Returns 0 if recovery has been triggered, < 0 if not.
369 */
370int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, void *ref)
371{
372 unsigned long flags;
373 int retval;
374 struct zfcp_adapter *adapter = port->adapter;
375
376 read_lock_irqsave(&zfcp_data.config_lock, flags);
377 write_lock(&adapter->erp_lock);
378 retval = _zfcp_erp_port_reopen(port, clear, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 write_unlock(&adapter->erp_lock);
380 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
381
382 return retval;
383}
384
Christof Schmitt287ac012008-07-02 10:56:40 +0200385static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
Christof Schmitt287ac012008-07-02 10:56:40 +0200387 zfcp_erp_modify_unit_status(unit, 19, NULL,
388 ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
389 ZFCP_CLEAR);
390}
391
392static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id,
393 void *ref)
394{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 struct zfcp_adapter *adapter = unit->port->adapter;
396
Christof Schmitt287ac012008-07-02 10:56:40 +0200397 zfcp_erp_unit_block(unit, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Christof Schmitt287ac012008-07-02 10:56:40 +0200399 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
400 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Christof Schmitt287ac012008-07-02 10:56:40 +0200402 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
403 adapter, unit->port, unit, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404}
405
406/**
407 * zfcp_erp_unit_reopen - initiate reopen of a unit
408 * @unit: unit to be reopened
409 * @clear_mask: specifies flags in unit status to be cleared
410 * Return: 0 on success, < 0 on error
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 */
Christof Schmitt287ac012008-07-02 10:56:40 +0200412void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, u8 id, void *ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 unsigned long flags;
Christof Schmitt287ac012008-07-02 10:56:40 +0200415 struct zfcp_port *port = unit->port;
416 struct zfcp_adapter *adapter = port->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
418 read_lock_irqsave(&zfcp_data.config_lock, flags);
419 write_lock(&adapter->erp_lock);
Christof Schmitt287ac012008-07-02 10:56:40 +0200420 _zfcp_erp_unit_reopen(unit, clear, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 write_unlock(&adapter->erp_lock);
422 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423}
424
Christof Schmitt287ac012008-07-02 10:56:40 +0200425static int status_change_set(unsigned long mask, atomic_t *status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
Christof Schmitt287ac012008-07-02 10:56:40 +0200427 return (atomic_read(status) ^ mask) & mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428}
429
Christof Schmitt287ac012008-07-02 10:56:40 +0200430static int status_change_clear(unsigned long mask, atomic_t *status)
Martin Peschke698ec0162008-03-27 14:22:02 +0100431{
Christof Schmitt287ac012008-07-02 10:56:40 +0200432 return atomic_read(status) & mask;
Martin Peschke698ec0162008-03-27 14:22:02 +0100433}
434
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200435static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
Christof Schmitt287ac012008-07-02 10:56:40 +0200437 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
Martin Peschke1f6f7122008-04-18 12:51:55 +0200438 zfcp_rec_dbf_event_adapter(16, NULL, adapter);
Christof Schmitt287ac012008-07-02 10:56:40 +0200439 atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440}
441
Christof Schmitt287ac012008-07-02 10:56:40 +0200442static void zfcp_erp_port_unblock(struct zfcp_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
Christof Schmitt287ac012008-07-02 10:56:40 +0200444 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
Martin Peschke1f6f7122008-04-18 12:51:55 +0200445 zfcp_rec_dbf_event_port(18, NULL, port);
Christof Schmitt287ac012008-07-02 10:56:40 +0200446 atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447}
448
Christof Schmitt287ac012008-07-02 10:56:40 +0200449static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450{
Christof Schmitt287ac012008-07-02 10:56:40 +0200451 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
Martin Peschke1f6f7122008-04-18 12:51:55 +0200452 zfcp_rec_dbf_event_unit(20, NULL, unit);
Christof Schmitt287ac012008-07-02 10:56:40 +0200453 atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454}
455
Christof Schmitt287ac012008-07-02 10:56:40 +0200456static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
Christof Schmitt287ac012008-07-02 10:56:40 +0200458 list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
459 zfcp_rec_dbf_event_action(145, erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460}
461
Christof Schmitt287ac012008-07-02 10:56:40 +0200462static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
Christof Schmitt287ac012008-07-02 10:56:40 +0200464 struct zfcp_adapter *adapter = act->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
Christof Schmitt287ac012008-07-02 10:56:40 +0200466 if (!act->fsf_req)
467 return;
468
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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 }
Christof Schmitt287ac012008-07-02 10:56:40 +0200477 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485}
486
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200487/**
Christof Schmitt287ac012008-07-02 10:56:40 +0200488 * zfcp_erp_notify - Trigger ERP action.
489 * @erp_action: ERP action to continue.
490 * @set_mask: ERP action status flags to set.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 */
Christof Schmitt287ac012008-07-02 10:56:40 +0200492void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
494 struct zfcp_adapter *adapter = erp_action->adapter;
495 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497 write_lock_irqsave(&adapter->erp_lock, flags);
Christof Schmitt287ac012008-07-02 10:56:40 +0200498 if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
499 erp_action->status |= set_mask;
500 zfcp_erp_action_ready(erp_action);
501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 write_unlock_irqrestore(&adapter->erp_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503}
504
Andreas Herrmannf6c0e7a2006-08-02 11:05:52 +0200505/**
Christof Schmitt287ac012008-07-02 10:56:40 +0200506 * zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request
507 * @data: ERP action (from timer data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 */
Christof Schmitt287ac012008-07-02 10:56:40 +0200509void zfcp_erp_timeout_handler(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510{
Christof Schmitt287ac012008-07-02 10:56:40 +0200511 struct zfcp_erp_action *act = (struct zfcp_erp_action *) data;
512 zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513}
514
Christof Schmitt287ac012008-07-02 10:56:40 +0200515static void zfcp_erp_memwait_handler(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
Christof Schmitt287ac012008-07-02 10:56:40 +0200517 zfcp_erp_notify((struct zfcp_erp_action *)data, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518}
519
Christof Schmitt287ac012008-07-02 10:56:40 +0200520static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 init_timer(&erp_action->timer);
523 erp_action->timer.function = zfcp_erp_memwait_handler;
524 erp_action->timer.data = (unsigned long) erp_action;
Christof Schmitt287ac012008-07-02 10:56:40 +0200525 erp_action->timer.expires = jiffies + HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 add_timer(&erp_action->timer);
Christof Schmitt287ac012008-07-02 10:56:40 +0200527}
528
529static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
530 int clear, u8 id, void *ref)
531{
532 struct zfcp_port *port;
533
534 list_for_each_entry(port, &adapter->port_list_head, list)
535 if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA))
536 _zfcp_erp_port_reopen(port, clear, id, ref);
537}
538
539static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id,
540 void *ref)
541{
542 struct zfcp_unit *unit;
543
544 list_for_each_entry(unit, &port->unit_list_head, list)
545 _zfcp_erp_unit_reopen(unit, clear, id, ref);
546}
547
548static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act)
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
555 /* initiate follow-up actions depending on success of finished action */
556 switch (act->action) {
557
558 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
559 if (status == ZFCP_ERP_SUCCEEDED)
560 _zfcp_erp_port_reopen_all(adapter, 0, 70, NULL);
561 else
562 _zfcp_erp_adapter_reopen(adapter, 0, 71, NULL);
563 break;
564
565 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
566 if (status == ZFCP_ERP_SUCCEEDED)
567 _zfcp_erp_port_reopen(port, 0, 72, NULL);
568 else
569 _zfcp_erp_adapter_reopen(adapter, 0, 73, NULL);
570 break;
571
572 case ZFCP_ERP_ACTION_REOPEN_PORT:
573 if (status == ZFCP_ERP_SUCCEEDED)
574 _zfcp_erp_unit_reopen_all(port, 0, 74, NULL);
575 else
576 _zfcp_erp_port_forced_reopen(port, 0, 75, NULL);
577 break;
578
579 case ZFCP_ERP_ACTION_REOPEN_UNIT:
580 if (status != ZFCP_ERP_SUCCEEDED)
581 _zfcp_erp_port_reopen(unit->port, 0, 76, NULL);
582 break;
583 }
584}
585
586static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
587{
588 unsigned long flags;
589
590 read_lock_irqsave(&zfcp_data.config_lock, flags);
591 read_lock(&adapter->erp_lock);
592 if (list_empty(&adapter->erp_ready_head) &&
593 list_empty(&adapter->erp_running_head)) {
594 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
595 &adapter->status);
596 wake_up(&adapter->erp_done_wqh);
597 }
598 read_unlock(&adapter->erp_lock);
599 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
600}
601
602static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
603{
604 if (zfcp_qdio_open(act->adapter))
605 return ZFCP_ERP_FAILED;
606 init_waitqueue_head(&act->adapter->request_wq);
607 atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status);
608 return ZFCP_ERP_SUCCEEDED;
609}
610
611static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter)
612{
613 struct zfcp_port *port;
614 port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0,
615 adapter->peer_d_id);
616 if (IS_ERR(port)) /* error or port already attached */
617 return;
618 _zfcp_erp_port_reopen(port, 0, 150, NULL);
619}
620
621static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
622{
623 int retries;
624 int sleep = 1;
625 struct zfcp_adapter *adapter = erp_action->adapter;
626
627 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
628
629 for (retries = 7; retries; retries--) {
630 atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
631 &adapter->status);
632 write_lock_irq(&adapter->erp_lock);
633 zfcp_erp_action_to_running(erp_action);
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;
639 }
640
641 zfcp_rec_dbf_event_thread_lock(6, adapter);
642 down(&adapter->erp_ready_sem);
643 zfcp_rec_dbf_event_thread_lock(7, adapter);
644 if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
645 break;
646
647 if (!(atomic_read(&adapter->status) &
648 ZFCP_STATUS_ADAPTER_HOST_CON_INIT))
649 break;
650
651 ssleep(sleep);
652 sleep *= 2;
653 }
654
655 atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
656 &adapter->status);
657
658 if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK))
659 return ZFCP_ERP_FAILED;
660
661 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
662 zfcp_erp_enqueue_ptp_port(adapter);
663
664 return ZFCP_ERP_SUCCEEDED;
665}
666
667static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
668{
669 int ret;
670 struct zfcp_adapter *adapter = act->adapter;
671
Christof Schmitt287ac012008-07-02 10:56:40 +0200672 write_lock_irq(&adapter->erp_lock);
673 zfcp_erp_action_to_running(act);
674 write_unlock_irq(&adapter->erp_lock);
675
676 ret = zfcp_fsf_exchange_port_data(act);
677 if (ret == -EOPNOTSUPP)
678 return ZFCP_ERP_SUCCEEDED;
679 if (ret)
680 return ZFCP_ERP_FAILED;
681
682 zfcp_rec_dbf_event_thread_lock(8, adapter);
683 down(&adapter->erp_ready_sem);
684 zfcp_rec_dbf_event_thread_lock(9, adapter);
685 if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
686 return ZFCP_ERP_FAILED;
687
688 return ZFCP_ERP_SUCCEEDED;
689}
690
691static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
692{
693 if (zfcp_erp_adapter_strat_fsf_xconf(act) == ZFCP_ERP_FAILED)
694 return ZFCP_ERP_FAILED;
695
696 if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
697 return ZFCP_ERP_FAILED;
698
699 atomic_set(&act->adapter->stat_miss, 16);
700 if (zfcp_status_read_refill(act->adapter))
701 return ZFCP_ERP_FAILED;
702
703 return ZFCP_ERP_SUCCEEDED;
704}
705
706static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act,
707 int close)
708{
709 int retval = ZFCP_ERP_SUCCEEDED;
710 struct zfcp_adapter *adapter = act->adapter;
711
712 if (close)
713 goto close_only;
714
715 retval = zfcp_erp_adapter_strategy_open_qdio(act);
716 if (retval != ZFCP_ERP_SUCCEEDED)
717 goto failed_qdio;
718
719 retval = zfcp_erp_adapter_strategy_open_fsf(act);
720 if (retval != ZFCP_ERP_SUCCEEDED)
721 goto failed_openfcp;
722
723 atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &act->adapter->status);
724 schedule_work(&act->adapter->scan_work);
725
726 return ZFCP_ERP_SUCCEEDED;
727
728 close_only:
729 atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
730 &act->adapter->status);
731
732 failed_openfcp:
733 /* close queues to ensure that buffers are not accessed by adapter */
734 zfcp_qdio_close(adapter);
735 zfcp_fsf_req_dismiss_all(adapter);
736 adapter->fsf_req_seq_no = 0;
737 /* all ports and units are closed */
738 zfcp_erp_modify_adapter_status(adapter, 24, NULL,
739 ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
740 failed_qdio:
741 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
Swen Schillig44cc76f2008-10-01 12:42:16 +0200742 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
Christof Schmitt287ac012008-07-02 10:56:40 +0200743 &act->adapter->status);
744 return retval;
745}
746
747static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act)
748{
749 int retval;
750
Christof Schmitt287ac012008-07-02 10:56:40 +0200751 zfcp_erp_adapter_strategy_generic(act, 1); /* close */
Christof Schmitt287ac012008-07-02 10:56:40 +0200752 if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
753 return ZFCP_ERP_EXIT;
754
Christof Schmitt287ac012008-07-02 10:56:40 +0200755 retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */
Christof Schmitt287ac012008-07-02 10:56:40 +0200756
757 if (retval == ZFCP_ERP_FAILED)
758 ssleep(8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759
760 return retval;
761}
762
Christof Schmitt287ac012008-07-02 10:56:40 +0200763static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764{
Christof Schmitt287ac012008-07-02 10:56:40 +0200765 int retval;
766
767 retval = zfcp_fsf_close_physical_port(act);
768 if (retval == -ENOMEM)
769 return ZFCP_ERP_NOMEM;
770 act->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
771 if (retval)
772 return ZFCP_ERP_FAILED;
773
774 return ZFCP_ERP_CONTINUES;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775}
776
Christof Schmitt287ac012008-07-02 10:56:40 +0200777static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778{
Swen Schillig44cc76f2008-10-01 12:42:16 +0200779 atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
Christof Schmitt287ac012008-07-02 10:56:40 +0200780 ZFCP_STATUS_PORT_DID_DID |
781 ZFCP_STATUS_PORT_PHYS_CLOSING |
782 ZFCP_STATUS_PORT_INVALID_WWPN,
783 &port->status);
784}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Christof Schmitt287ac012008-07-02 10:56:40 +0200786static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
787{
788 struct zfcp_port *port = erp_action->port;
789 int status = atomic_read(&port->status);
790
791 switch (erp_action->step) {
792 case ZFCP_ERP_STEP_UNINITIALIZED:
793 zfcp_erp_port_strategy_clearstati(port);
794 if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
795 (status & ZFCP_STATUS_COMMON_OPEN))
796 return zfcp_erp_port_forced_strategy_close(erp_action);
797 else
798 return ZFCP_ERP_FAILED;
799
800 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
801 if (status & ZFCP_STATUS_PORT_PHYS_OPEN)
802 return ZFCP_ERP_SUCCEEDED;
803 }
804 return ZFCP_ERP_FAILED;
805}
806
807static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
808{
809 int retval;
810
811 retval = zfcp_fsf_close_port(erp_action);
812 if (retval == -ENOMEM)
813 return ZFCP_ERP_NOMEM;
814 erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
815 if (retval)
816 return ZFCP_ERP_FAILED;
817 return ZFCP_ERP_CONTINUES;
818}
819
820static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
821{
822 int retval;
823
824 retval = zfcp_fsf_open_port(erp_action);
825 if (retval == -ENOMEM)
826 return ZFCP_ERP_NOMEM;
827 erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
828 if (retval)
829 return ZFCP_ERP_FAILED;
830 return ZFCP_ERP_CONTINUES;
831}
832
833static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act)
834{
835 unsigned long flags;
836 struct zfcp_adapter *adapter = ns_act->adapter;
837 struct zfcp_erp_action *act, *tmp;
838 int status;
839
840 read_lock_irqsave(&adapter->erp_lock, flags);
841 list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) {
842 if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) {
843 status = atomic_read(&adapter->nameserver_port->status);
844 if (status & ZFCP_STATUS_COMMON_ERP_FAILED)
845 zfcp_erp_port_failed(act->port, 27, NULL);
846 zfcp_erp_action_ready(act);
847 }
848 }
849 read_unlock_irqrestore(&adapter->erp_lock, flags);
850}
851
852static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act)
853{
854 int retval;
855
856 switch (act->step) {
857 case ZFCP_ERP_STEP_UNINITIALIZED:
858 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
859 case ZFCP_ERP_STEP_PORT_CLOSING:
860 return zfcp_erp_port_strategy_open_port(act);
861
862 case ZFCP_ERP_STEP_PORT_OPENING:
863 if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN)
864 retval = ZFCP_ERP_SUCCEEDED;
865 else
866 retval = ZFCP_ERP_FAILED;
867 /* this is needed anyway */
868 zfcp_erp_port_strategy_open_ns_wake(act);
869 return retval;
870
871 default:
872 return ZFCP_ERP_FAILED;
873 }
874}
875
876static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act)
877{
878 int retval;
879
880 retval = zfcp_fc_ns_gid_pn_request(act);
881 if (retval == -ENOMEM)
882 return ZFCP_ERP_NOMEM;
883 act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
884 if (retval)
885 return ZFCP_ERP_FAILED;
886 return ZFCP_ERP_CONTINUES;
887}
888
889static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
890{
891 struct zfcp_adapter *adapter = act->adapter;
892 struct zfcp_port *port = act->port;
893
894 if (port->wwpn != adapter->peer_wwpn) {
Christof Schmitt287ac012008-07-02 10:56:40 +0200895 zfcp_erp_port_failed(port, 25, NULL);
896 return ZFCP_ERP_FAILED;
897 }
898 port->d_id = adapter->peer_d_id;
899 atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
900 return zfcp_erp_port_strategy_open_port(act);
901}
902
903static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
904{
905 struct zfcp_adapter *adapter = act->adapter;
906 struct zfcp_port *port = act->port;
907 struct zfcp_port *ns_port = adapter->nameserver_port;
908 int p_status = atomic_read(&port->status);
909
910 switch (act->step) {
911 case ZFCP_ERP_STEP_UNINITIALIZED:
912 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
913 case ZFCP_ERP_STEP_PORT_CLOSING:
914 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
915 return zfcp_erp_open_ptp_port(act);
916 if (!ns_port) {
917 dev_err(&adapter->ccw_device->dev,
Christof Schmittff3b24f2008-10-01 12:42:15 +0200918 "Attaching the name server port to the "
919 "FCP device failed\n");
Christof Schmitt287ac012008-07-02 10:56:40 +0200920 return ZFCP_ERP_FAILED;
921 }
922 if (!(atomic_read(&ns_port->status) &
923 ZFCP_STATUS_COMMON_UNBLOCKED)) {
924 /* nameserver port may live again */
925 atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
926 &ns_port->status);
927 if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) {
928 act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN;
929 return ZFCP_ERP_CONTINUES;
930 }
931 return ZFCP_ERP_FAILED;
932 }
933 /* else nameserver port is already open, fall through */
934 case ZFCP_ERP_STEP_NAMESERVER_OPEN:
935 if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN))
936 return ZFCP_ERP_FAILED;
937 return zfcp_erp_port_strategy_open_lookup(act);
938
939 case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
940 if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) {
941 if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) {
942 zfcp_erp_port_failed(port, 26, NULL);
943 return ZFCP_ERP_EXIT;
944 }
945 return ZFCP_ERP_FAILED;
946 }
947 return zfcp_erp_port_strategy_open_port(act);
948
949 case ZFCP_ERP_STEP_PORT_OPENING:
950 /* D_ID might have changed during open */
951 if ((p_status & ZFCP_STATUS_COMMON_OPEN) &&
952 (p_status & ZFCP_STATUS_PORT_DID_DID))
953 return ZFCP_ERP_SUCCEEDED;
954 /* fall through otherwise */
955 }
956 return ZFCP_ERP_FAILED;
957}
958
959static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act)
960{
961 if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA))
962 return zfcp_erp_port_strategy_open_nameserver(act);
963 return zfcp_erp_port_strategy_open_common(act);
964}
965
966static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
967{
968 struct zfcp_port *port = erp_action->port;
969
970 switch (erp_action->step) {
971 case ZFCP_ERP_STEP_UNINITIALIZED:
972 zfcp_erp_port_strategy_clearstati(port);
973 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)
974 return zfcp_erp_port_strategy_close(erp_action);
975 break;
976
977 case ZFCP_ERP_STEP_PORT_CLOSING:
978 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)
979 return ZFCP_ERP_FAILED;
980 break;
981 }
982 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
983 return ZFCP_ERP_EXIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 else
Christof Schmitt287ac012008-07-02 10:56:40 +0200985 return zfcp_erp_port_strategy_open(erp_action);
986
987 return ZFCP_ERP_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988}
989
Christof Schmitt287ac012008-07-02 10:56:40 +0200990static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991{
Swen Schillig44cc76f2008-10-01 12:42:16 +0200992 atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
Christof Schmitt287ac012008-07-02 10:56:40 +0200993 ZFCP_STATUS_UNIT_SHARED |
994 ZFCP_STATUS_UNIT_READONLY,
995 &unit->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996}
997
Christof Schmitt287ac012008-07-02 10:56:40 +0200998static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
999{
1000 int retval = zfcp_fsf_close_unit(erp_action);
1001 if (retval == -ENOMEM)
1002 return ZFCP_ERP_NOMEM;
1003 erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
1004 if (retval)
1005 return ZFCP_ERP_FAILED;
1006 return ZFCP_ERP_CONTINUES;
1007}
1008
1009static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
1010{
1011 int retval = zfcp_fsf_open_unit(erp_action);
1012 if (retval == -ENOMEM)
1013 return ZFCP_ERP_NOMEM;
1014 erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
1015 if (retval)
1016 return ZFCP_ERP_FAILED;
1017 return ZFCP_ERP_CONTINUES;
1018}
1019
1020static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
1021{
1022 struct zfcp_unit *unit = erp_action->unit;
1023
1024 switch (erp_action->step) {
1025 case ZFCP_ERP_STEP_UNINITIALIZED:
1026 zfcp_erp_unit_strategy_clearstati(unit);
1027 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
1028 return zfcp_erp_unit_strategy_close(erp_action);
1029 /* already closed, fall through */
1030 case ZFCP_ERP_STEP_UNIT_CLOSING:
1031 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
1032 return ZFCP_ERP_FAILED;
1033 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
1034 return ZFCP_ERP_EXIT;
1035 return zfcp_erp_unit_strategy_open(erp_action);
1036
1037 case ZFCP_ERP_STEP_UNIT_OPENING:
1038 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
1039 return ZFCP_ERP_SUCCEEDED;
1040 }
1041 return ZFCP_ERP_FAILED;
1042}
1043
1044static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
1045{
1046 switch (result) {
1047 case ZFCP_ERP_SUCCEEDED :
1048 atomic_set(&unit->erp_counter, 0);
1049 zfcp_erp_unit_unblock(unit);
1050 break;
1051 case ZFCP_ERP_FAILED :
1052 atomic_inc(&unit->erp_counter);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001053 if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
1054 dev_err(&unit->port->adapter->ccw_device->dev,
1055 "ERP failed for unit 0x%016Lx on "
1056 "port 0x%016Lx\n",
1057 unit->fcp_lun, unit->port->wwpn);
Christof Schmitt287ac012008-07-02 10:56:40 +02001058 zfcp_erp_unit_failed(unit, 21, NULL);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001059 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001060 break;
1061 }
1062
1063 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1064 zfcp_erp_unit_block(unit, 0);
1065 result = ZFCP_ERP_EXIT;
1066 }
1067 return result;
1068}
1069
1070static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
1071{
1072 switch (result) {
1073 case ZFCP_ERP_SUCCEEDED :
1074 atomic_set(&port->erp_counter, 0);
1075 zfcp_erp_port_unblock(port);
1076 break;
1077
1078 case ZFCP_ERP_FAILED :
1079 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) {
1080 zfcp_erp_port_block(port, 0);
1081 result = ZFCP_ERP_EXIT;
1082 }
1083 atomic_inc(&port->erp_counter);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001084 if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
1085 dev_err(&port->adapter->ccw_device->dev,
1086 "ERP failed for remote port 0x%016Lx\n",
1087 port->wwpn);
Christof Schmitt287ac012008-07-02 10:56:40 +02001088 zfcp_erp_port_failed(port, 22, NULL);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001089 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001090 break;
1091 }
1092
1093 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1094 zfcp_erp_port_block(port, 0);
1095 result = ZFCP_ERP_EXIT;
1096 }
1097 return result;
1098}
1099
1100static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
1101 int result)
1102{
1103 switch (result) {
1104 case ZFCP_ERP_SUCCEEDED :
1105 atomic_set(&adapter->erp_counter, 0);
1106 zfcp_erp_adapter_unblock(adapter);
1107 break;
1108
1109 case ZFCP_ERP_FAILED :
1110 atomic_inc(&adapter->erp_counter);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001111 if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
1112 dev_err(&adapter->ccw_device->dev,
1113 "ERP cannot recover an error "
1114 "on the FCP device\n");
Christof Schmitt287ac012008-07-02 10:56:40 +02001115 zfcp_erp_adapter_failed(adapter, 23, NULL);
Christof Schmittff3b24f2008-10-01 12:42:15 +02001116 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001117 break;
1118 }
1119
1120 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1121 zfcp_erp_adapter_block(adapter, 0);
1122 result = ZFCP_ERP_EXIT;
1123 }
1124 return result;
1125}
1126
1127static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action,
1128 int result)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
1130 struct zfcp_adapter *adapter = erp_action->adapter;
1131 struct zfcp_port *port = erp_action->port;
1132 struct zfcp_unit *unit = erp_action->unit;
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 switch (erp_action->action) {
1135
1136 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1137 result = zfcp_erp_strategy_check_unit(unit, result);
1138 break;
1139
1140 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1141 case ZFCP_ERP_ACTION_REOPEN_PORT:
1142 result = zfcp_erp_strategy_check_port(port, result);
1143 break;
1144
1145 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1146 result = zfcp_erp_strategy_check_adapter(adapter, result);
1147 break;
1148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 return result;
1150}
1151
Christof Schmitt287ac012008-07-02 10:56:40 +02001152static int zfcp_erp_strat_change_det(atomic_t *target_status, u32 erp_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
Christof Schmitt287ac012008-07-02 10:56:40 +02001154 int status = atomic_read(target_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155
Christof Schmitt287ac012008-07-02 10:56:40 +02001156 if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
1157 (erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
1158 return 1; /* take it online */
1159
1160 if (!(status & ZFCP_STATUS_COMMON_RUNNING) &&
1161 !(erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
1162 return 1; /* take it offline */
1163
1164 return 0;
1165}
1166
1167static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
1168{
1169 int action = act->action;
1170 struct zfcp_adapter *adapter = act->adapter;
1171 struct zfcp_port *port = act->port;
1172 struct zfcp_unit *unit = act->unit;
1173 u32 erp_status = act->status;
1174
1175 switch (action) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Christof Schmitt287ac012008-07-02 10:56:40 +02001177 if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) {
1178 _zfcp_erp_adapter_reopen(adapter,
1179 ZFCP_STATUS_COMMON_ERP_FAILED,
1180 67, NULL);
1181 return ZFCP_ERP_EXIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 }
1183 break;
1184
1185 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1186 case ZFCP_ERP_ACTION_REOPEN_PORT:
Christof Schmitt287ac012008-07-02 10:56:40 +02001187 if (zfcp_erp_strat_change_det(&port->status, erp_status)) {
1188 _zfcp_erp_port_reopen(port,
1189 ZFCP_STATUS_COMMON_ERP_FAILED,
1190 68, NULL);
1191 return ZFCP_ERP_EXIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 }
1193 break;
1194
1195 case ZFCP_ERP_ACTION_REOPEN_UNIT:
Christof Schmitt287ac012008-07-02 10:56:40 +02001196 if (zfcp_erp_strat_change_det(&unit->status, erp_status)) {
1197 _zfcp_erp_unit_reopen(unit,
1198 ZFCP_STATUS_COMMON_ERP_FAILED,
1199 69, NULL);
1200 return ZFCP_ERP_EXIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 }
1202 break;
1203 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001204 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
Christof Schmitt287ac012008-07-02 10:56:40 +02001207static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208{
Christof Schmitt287ac012008-07-02 10:56:40 +02001209 struct zfcp_adapter *adapter = erp_action->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
Christof Schmitt287ac012008-07-02 10:56:40 +02001211 adapter->erp_total_count--;
1212 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
1213 adapter->erp_low_mem_count--;
1214 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 }
1216
Christof Schmitt287ac012008-07-02 10:56:40 +02001217 list_del(&erp_action->list);
1218 zfcp_rec_dbf_event_action(144, erp_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Christof Schmitt287ac012008-07-02 10:56:40 +02001220 switch (erp_action->action) {
1221 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1222 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1223 &erp_action->unit->status);
1224 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Christof Schmitt287ac012008-07-02 10:56:40 +02001226 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1227 case ZFCP_ERP_ACTION_REOPEN_PORT:
1228 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1229 &erp_action->port->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 break;
Christof Schmitt287ac012008-07-02 10:56:40 +02001231
1232 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1233 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1234 &erp_action->adapter->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 break;
1236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237}
1238
Christof Schmitt5f852be2007-05-08 11:16:52 +02001239struct zfcp_erp_add_work {
1240 struct zfcp_unit *unit;
1241 struct work_struct work;
1242};
1243
Christof Schmitt5f852be2007-05-08 11:16:52 +02001244static void zfcp_erp_scsi_scan(struct work_struct *work)
1245{
1246 struct zfcp_erp_add_work *p =
1247 container_of(work, struct zfcp_erp_add_work, work);
1248 struct zfcp_unit *unit = p->unit;
1249 struct fc_rport *rport = unit->port->rport;
1250 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
1251 unit->scsi_lun, 0);
1252 atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
Christof Schmitt5f852be2007-05-08 11:16:52 +02001253 zfcp_unit_put(unit);
1254 kfree(p);
1255}
1256
Christof Schmitt287ac012008-07-02 10:56:40 +02001257static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
Christof Schmitt5f852be2007-05-08 11:16:52 +02001258{
1259 struct zfcp_erp_add_work *p;
1260
Swen Schillig0d661322007-07-18 10:55:08 +02001261 p = kzalloc(sizeof(*p), GFP_KERNEL);
Christof Schmitt5f852be2007-05-08 11:16:52 +02001262 if (!p) {
Christof Schmitt553448f2008-06-10 18:20:58 +02001263 dev_err(&unit->port->adapter->ccw_device->dev,
Christof Schmittff3b24f2008-10-01 12:42:15 +02001264 "Registering unit 0x%016Lx on port 0x%016Lx failed\n",
Christof Schmitt553448f2008-06-10 18:20:58 +02001265 unit->fcp_lun, unit->port->wwpn);
Christof Schmitt5f852be2007-05-08 11:16:52 +02001266 return;
1267 }
1268
1269 zfcp_unit_get(unit);
Christof Schmitt5f852be2007-05-08 11:16:52 +02001270 atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
1271 INIT_WORK(&p->work, zfcp_erp_scsi_scan);
1272 p->unit = unit;
1273 schedule_work(&p->work);
1274}
1275
Christof Schmitt287ac012008-07-02 10:56:40 +02001276static void zfcp_erp_rport_register(struct zfcp_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277{
Christof Schmitt287ac012008-07-02 10:56:40 +02001278 struct fc_rport_identifiers ids;
1279 ids.node_name = port->wwnn;
1280 ids.port_name = port->wwpn;
1281 ids.port_id = port->d_id;
1282 ids.roles = FC_RPORT_ROLE_FCP_TARGET;
1283 port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
1284 if (!port->rport) {
1285 dev_err(&port->adapter->ccw_device->dev,
Christof Schmittff3b24f2008-10-01 12:42:15 +02001286 "Registering port 0x%016Lx failed\n",
1287 port->wwpn);
Swen Schilligcc8c2822008-06-10 18:21:00 +02001288 return;
Christof Schmitt287ac012008-07-02 10:56:40 +02001289 }
1290
1291 scsi_target_unblock(&port->rport->dev);
1292 port->rport->maxframe_size = port->maxframe_size;
1293 port->rport->supported_classes = port->supported_classes;
Swen Schilligcc8c2822008-06-10 18:21:00 +02001294}
1295
Christof Schmitt287ac012008-07-02 10:56:40 +02001296static void zfcp_erp_rports_del(struct zfcp_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297{
Christof Schmitt287ac012008-07-02 10:56:40 +02001298 struct zfcp_port *port;
1299 list_for_each_entry(port, &adapter->port_list_head, list)
1300 if (port->rport && !(atomic_read(&port->status) &
1301 ZFCP_STATUS_PORT_WKA)) {
1302 fc_remote_port_delete(port->rport);
1303 port->rport = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305}
1306
Christof Schmitt287ac012008-07-02 10:56:40 +02001307static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02001308{
Christof Schmitt287ac012008-07-02 10:56:40 +02001309 struct zfcp_adapter *adapter = act->adapter;
1310 struct zfcp_port *port = act->port;
1311 struct zfcp_unit *unit = act->unit;
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02001312
Christof Schmitt287ac012008-07-02 10:56:40 +02001313 switch (act->action) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 case ZFCP_ERP_ACTION_REOPEN_UNIT:
Christof Schmitt287ac012008-07-02 10:56:40 +02001315 if ((result == ZFCP_ERP_SUCCEEDED) &&
1316 !unit->device && port->rport) {
Andreas Herrmannad58f7d2006-03-10 00:56:16 +01001317 atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
1318 &unit->status);
Christof Schmitt287ac012008-07-02 10:56:40 +02001319 if (!(atomic_read(&unit->status) &
1320 ZFCP_STATUS_UNIT_SCSI_WORK_PENDING))
Christof Schmitt5f852be2007-05-08 11:16:52 +02001321 zfcp_erp_schedule_work(unit);
Andreas Herrmannad58f7d2006-03-10 00:56:16 +01001322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 zfcp_unit_put(unit);
1324 break;
Christof Schmitt287ac012008-07-02 10:56:40 +02001325
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1327 case ZFCP_ERP_ACTION_REOPEN_PORT:
Christof Schmitt287ac012008-07-02 10:56:40 +02001328 if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN) {
Andreas Herrmann338151e2006-05-22 18:25:56 +02001329 zfcp_port_put(port);
Christof Schmitt287ac012008-07-02 10:56:40 +02001330 return;
Andreas Herrmann338151e2006-05-22 18:25:56 +02001331 }
Christof Schmitt287ac012008-07-02 10:56:40 +02001332 if ((result == ZFCP_ERP_SUCCEEDED) && !port->rport)
1333 zfcp_erp_rport_register(port);
Andreas Herrmann338151e2006-05-22 18:25:56 +02001334 if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) {
1335 fc_remote_port_delete(port->rport);
1336 port->rport = NULL;
1337 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 zfcp_port_put(port);
1339 break;
Christof Schmitt287ac012008-07-02 10:56:40 +02001340
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
Christof Schmitt287ac012008-07-02 10:56:40 +02001342 if (result != ZFCP_ERP_SUCCEEDED)
1343 zfcp_erp_rports_del(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 zfcp_adapter_put(adapter);
1345 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 }
1347}
1348
Christof Schmitt287ac012008-07-02 10:56:40 +02001349static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
1350{
1351 switch (erp_action->action) {
1352 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1353 return zfcp_erp_adapter_strategy(erp_action);
1354 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1355 return zfcp_erp_port_forced_strategy(erp_action);
1356 case ZFCP_ERP_ACTION_REOPEN_PORT:
1357 return zfcp_erp_port_strategy(erp_action);
1358 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1359 return zfcp_erp_unit_strategy(erp_action);
1360 }
1361 return ZFCP_ERP_FAILED;
1362}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Christof Schmitt287ac012008-07-02 10:56:40 +02001364static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
1365{
1366 int retval;
1367 struct zfcp_adapter *adapter = erp_action->adapter;
1368 unsigned long flags;
1369
1370 read_lock_irqsave(&zfcp_data.config_lock, flags);
1371 write_lock(&adapter->erp_lock);
1372
1373 zfcp_erp_strategy_check_fsfreq(erp_action);
1374
1375 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
1376 zfcp_erp_action_dequeue(erp_action);
1377 retval = ZFCP_ERP_DISMISSED;
1378 goto unlock;
1379 }
1380
1381 zfcp_erp_action_to_running(erp_action);
1382
1383 /* no lock to allow for blocking operations */
1384 write_unlock(&adapter->erp_lock);
1385 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1386 retval = zfcp_erp_strategy_do_action(erp_action);
1387 read_lock_irqsave(&zfcp_data.config_lock, flags);
1388 write_lock(&adapter->erp_lock);
1389
1390 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
1391 retval = ZFCP_ERP_CONTINUES;
1392
1393 switch (retval) {
1394 case ZFCP_ERP_NOMEM:
1395 if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {
1396 ++adapter->erp_low_mem_count;
1397 erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
1398 }
1399 if (adapter->erp_total_count == adapter->erp_low_mem_count)
1400 _zfcp_erp_adapter_reopen(adapter, 0, 66, NULL);
1401 else {
1402 zfcp_erp_strategy_memwait(erp_action);
1403 retval = ZFCP_ERP_CONTINUES;
1404 }
1405 goto unlock;
1406
1407 case ZFCP_ERP_CONTINUES:
1408 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
1409 --adapter->erp_low_mem_count;
1410 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
1411 }
1412 goto unlock;
1413 }
1414
1415 retval = zfcp_erp_strategy_check_target(erp_action, retval);
1416 zfcp_erp_action_dequeue(erp_action);
1417 retval = zfcp_erp_strategy_statechange(erp_action, retval);
1418 if (retval == ZFCP_ERP_EXIT)
1419 goto unlock;
1420 zfcp_erp_strategy_followup_actions(erp_action);
1421
1422 unlock:
1423 write_unlock(&adapter->erp_lock);
1424 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1425
1426 if (retval != ZFCP_ERP_CONTINUES)
1427 zfcp_erp_action_cleanup(erp_action, retval);
1428
1429 return retval;
1430}
1431
1432static int zfcp_erp_thread(void *data)
1433{
1434 struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
1435 struct list_head *next;
1436 struct zfcp_erp_action *act;
1437 unsigned long flags;
1438
1439 daemonize("zfcperp%s", adapter->ccw_device->dev.bus_id);
1440 /* Block all signals */
1441 siginitsetinv(&current->blocked, 0);
1442 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
1443 wake_up(&adapter->erp_thread_wqh);
1444
1445 while (!(atomic_read(&adapter->status) &
1446 ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) {
1447 write_lock_irqsave(&adapter->erp_lock, flags);
1448 next = adapter->erp_ready_head.next;
1449 write_unlock_irqrestore(&adapter->erp_lock, flags);
1450
1451 if (next != &adapter->erp_ready_head) {
1452 act = list_entry(next, struct zfcp_erp_action, list);
1453
1454 /* there is more to come after dismission, no notify */
1455 if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
1456 zfcp_erp_wakeup(adapter);
1457 }
1458
1459 zfcp_rec_dbf_event_thread(4, adapter);
1460 down_interruptible(&adapter->erp_ready_sem);
1461 zfcp_rec_dbf_event_thread(5, adapter);
1462 }
1463
1464 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
1465 wake_up(&adapter->erp_thread_wqh);
1466
1467 return 0;
1468}
1469
1470/**
1471 * zfcp_erp_thread_setup - Start ERP thread for adapter
1472 * @adapter: Adapter to start the ERP thread for
1473 *
1474 * Returns 0 on success or error code from kernel_thread()
1475 */
1476int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
1477{
1478 int retval;
1479
1480 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
1481 retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
1482 if (retval < 0) {
1483 dev_err(&adapter->ccw_device->dev,
Christof Schmittff3b24f2008-10-01 12:42:15 +02001484 "Creating an ERP thread for the FCP device failed.\n");
Christof Schmitt287ac012008-07-02 10:56:40 +02001485 return retval;
1486 }
1487 wait_event(adapter->erp_thread_wqh,
1488 atomic_read(&adapter->status) &
1489 ZFCP_STATUS_ADAPTER_ERP_THREAD_UP);
1490 return 0;
1491}
1492
1493/**
1494 * zfcp_erp_thread_kill - Stop ERP thread.
1495 * @adapter: Adapter where the ERP thread should be stopped.
1496 *
1497 * The caller of this routine ensures that the specified adapter has
1498 * been shut down and that this operation has been completed. Thus,
1499 * there are no pending erp_actions which would need to be handled
1500 * here.
1501 */
1502void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
1503{
1504 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
1505 up(&adapter->erp_ready_sem);
1506 zfcp_rec_dbf_event_thread_lock(2, adapter);
1507
1508 wait_event(adapter->erp_thread_wqh,
1509 !(atomic_read(&adapter->status) &
1510 ZFCP_STATUS_ADAPTER_ERP_THREAD_UP));
1511
1512 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
1513 &adapter->status);
1514}
1515
1516/**
1517 * zfcp_erp_adapter_failed - Set adapter status to failed.
1518 * @adapter: Failed adapter.
1519 * @id: Event id for debug trace.
1520 * @ref: Reference for debug trace.
1521 */
1522void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref)
1523{
1524 zfcp_erp_modify_adapter_status(adapter, id, ref,
1525 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
Christof Schmitt287ac012008-07-02 10:56:40 +02001526}
1527
1528/**
1529 * zfcp_erp_port_failed - Set port status to failed.
1530 * @port: Failed port.
1531 * @id: Event id for debug trace.
1532 * @ref: Reference for debug trace.
1533 */
1534void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref)
1535{
1536 zfcp_erp_modify_port_status(port, id, ref,
1537 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
Christof Schmitt287ac012008-07-02 10:56:40 +02001538}
1539
1540/**
1541 * zfcp_erp_unit_failed - Set unit status to failed.
1542 * @unit: Failed unit.
1543 * @id: Event id for debug trace.
1544 * @ref: Reference for debug trace.
1545 */
1546void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref)
1547{
1548 zfcp_erp_modify_unit_status(unit, id, ref,
1549 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
Christof Schmitt287ac012008-07-02 10:56:40 +02001550}
1551
1552/**
1553 * zfcp_erp_wait - wait for completion of error recovery on an adapter
1554 * @adapter: adapter for which to wait for completion of its error recovery
1555 */
1556void zfcp_erp_wait(struct zfcp_adapter *adapter)
1557{
1558 wait_event(adapter->erp_done_wqh,
1559 !(atomic_read(&adapter->status) &
1560 ZFCP_STATUS_ADAPTER_ERP_PENDING));
1561}
1562
1563/**
1564 * zfcp_erp_modify_adapter_status - change adapter status bits
1565 * @adapter: adapter to change the status
1566 * @id: id for the debug trace
1567 * @ref: reference for the debug trace
1568 * @mask: status bits to change
1569 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
1570 *
1571 * Changes in common status bits are propagated to attached ports and units.
1572 */
1573void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id,
1574 void *ref, u32 mask, int set_or_clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 struct zfcp_port *port;
Christof Schmitt287ac012008-07-02 10:56:40 +02001577 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
Christof Schmitt287ac012008-07-02 10:56:40 +02001579 if (set_or_clear == ZFCP_SET) {
1580 if (status_change_set(mask, &adapter->status))
1581 zfcp_rec_dbf_event_adapter(id, ref, adapter);
1582 atomic_set_mask(mask, &adapter->status);
1583 } else {
1584 if (status_change_clear(mask, &adapter->status))
1585 zfcp_rec_dbf_event_adapter(id, ref, adapter);
1586 atomic_clear_mask(mask, &adapter->status);
1587 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
1588 atomic_set(&adapter->erp_counter, 0);
1589 }
1590
1591 if (common_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 list_for_each_entry(port, &adapter->port_list_head, list)
Christof Schmitt287ac012008-07-02 10:56:40 +02001593 zfcp_erp_modify_port_status(port, id, ref, common_mask,
1594 set_or_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595}
1596
Christof Schmitt287ac012008-07-02 10:56:40 +02001597/**
1598 * zfcp_erp_modify_port_status - change port status bits
1599 * @port: port to change the status bits
1600 * @id: id for the debug trace
1601 * @ref: reference for the debug trace
1602 * @mask: status bits to change
1603 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
1604 *
1605 * Changes in common status bits are propagated to attached units.
1606 */
1607void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref,
1608 u32 mask, int set_or_clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 struct zfcp_unit *unit;
Christof Schmitt287ac012008-07-02 10:56:40 +02001611 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Christof Schmitt287ac012008-07-02 10:56:40 +02001613 if (set_or_clear == ZFCP_SET) {
1614 if (status_change_set(mask, &port->status))
1615 zfcp_rec_dbf_event_port(id, ref, port);
1616 atomic_set_mask(mask, &port->status);
1617 } else {
1618 if (status_change_clear(mask, &port->status))
1619 zfcp_rec_dbf_event_port(id, ref, port);
1620 atomic_clear_mask(mask, &port->status);
1621 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
1622 atomic_set(&port->erp_counter, 0);
1623 }
1624
1625 if (common_mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 list_for_each_entry(unit, &port->unit_list_head, list)
Christof Schmitt287ac012008-07-02 10:56:40 +02001627 zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
1628 set_or_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629}
1630
Christof Schmitt287ac012008-07-02 10:56:40 +02001631/**
1632 * zfcp_erp_modify_unit_status - change unit status bits
1633 * @unit: unit to change the status bits
1634 * @id: id for the debug trace
1635 * @ref: reference for the debug trace
1636 * @mask: status bits to change
1637 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
1638 */
1639void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref,
1640 u32 mask, int set_or_clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641{
Christof Schmitt287ac012008-07-02 10:56:40 +02001642 if (set_or_clear == ZFCP_SET) {
1643 if (status_change_set(mask, &unit->status))
1644 zfcp_rec_dbf_event_unit(id, ref, unit);
1645 atomic_set_mask(mask, &unit->status);
1646 } else {
1647 if (status_change_clear(mask, &unit->status))
1648 zfcp_rec_dbf_event_unit(id, ref, unit);
1649 atomic_clear_mask(mask, &unit->status);
1650 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
1651 atomic_set(&unit->erp_counter, 0);
1652 }
1653 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654}
1655
Christof Schmitt287ac012008-07-02 10:56:40 +02001656/**
1657 * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP
1658 * @port: The "boxed" port.
1659 * @id: The debug trace id.
1660 * @id: Reference for the debug trace.
1661 */
Martin Peschke1f6f7122008-04-18 12:51:55 +02001662void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref)
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001663{
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001664 unsigned long flags;
1665
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001666 read_lock_irqsave(&zfcp_data.config_lock, flags);
Martin Peschke698ec0162008-03-27 14:22:02 +01001667 zfcp_erp_modify_port_status(port, id, ref,
1668 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001669 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
Martin Peschke9467a9b2008-03-27 14:22:03 +01001670 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001671}
1672
Christof Schmitt287ac012008-07-02 10:56:40 +02001673/**
1674 * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP
1675 * @port: The "boxed" unit.
1676 * @id: The debug trace id.
1677 * @id: Reference for the debug trace.
1678 */
Martin Peschke1f6f7122008-04-18 12:51:55 +02001679void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref)
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001680{
Martin Peschke698ec0162008-03-27 14:22:02 +01001681 zfcp_erp_modify_unit_status(unit, id, ref,
1682 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
Martin Peschke9467a9b2008-03-27 14:22:03 +01001683 zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
Andreas Herrmannd736a27b2005-06-13 13:23:57 +02001684}
1685
Christof Schmitt287ac012008-07-02 10:56:40 +02001686/**
1687 * zfcp_erp_port_access_denied - Adapter denied access to port.
1688 * @port: port where access has been denied
1689 * @id: id for debug trace
1690 * @ref: reference for debug trace
1691 *
1692 * Since the adapter has denied access, stop using the port and the
1693 * attached units.
1694 */
Martin Peschke1f6f7122008-04-18 12:51:55 +02001695void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 unsigned long flags;
1698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 read_lock_irqsave(&zfcp_data.config_lock, flags);
Martin Peschke698ec0162008-03-27 14:22:02 +01001700 zfcp_erp_modify_port_status(port, id, ref,
1701 ZFCP_STATUS_COMMON_ERP_FAILED |
1702 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1704}
1705
Christof Schmitt287ac012008-07-02 10:56:40 +02001706/**
1707 * zfcp_erp_unit_access_denied - Adapter denied access to unit.
1708 * @unit: unit where access has been denied
1709 * @id: id for debug trace
1710 * @ref: reference for debug trace
1711 *
1712 * Since the adapter has denied access, stop using the unit.
1713 */
Martin Peschke1f6f7122008-04-18 12:51:55 +02001714void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715{
Martin Peschke698ec0162008-03-27 14:22:02 +01001716 zfcp_erp_modify_unit_status(unit, id, ref,
1717 ZFCP_STATUS_COMMON_ERP_FAILED |
1718 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719}
1720
Christof Schmitt287ac012008-07-02 10:56:40 +02001721static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id,
1722 void *ref)
1723{
1724 int status = atomic_read(&unit->status);
1725 if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
1726 ZFCP_STATUS_COMMON_ACCESS_BOXED)))
1727 return;
1728
1729 zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
1730}
1731
1732static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id,
1733 void *ref)
1734{
1735 struct zfcp_unit *unit;
1736 int status = atomic_read(&port->status);
1737
1738 if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
1739 ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
1740 if (!(status & ZFCP_STATUS_PORT_WKA))
1741 list_for_each_entry(unit, &port->unit_list_head, list)
1742 zfcp_erp_unit_access_changed(unit, id, ref);
1743 return;
1744 }
1745
1746 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
1747}
1748
1749/**
1750 * zfcp_erp_adapter_access_changed - Process change in adapter ACT
1751 * @adapter: Adapter where the Access Control Table (ACT) changed
1752 * @id: Id for debug trace
1753 * @ref: Reference for debug trace
1754 */
Martin Peschke9467a9b2008-03-27 14:22:03 +01001755void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
Martin Peschke1f6f7122008-04-18 12:51:55 +02001756 void *ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757{
1758 struct zfcp_port *port;
1759 unsigned long flags;
1760
Maxim Shchetyninaef4a982005-09-13 21:51:16 +02001761 if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
1762 return;
1763
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 read_lock_irqsave(&zfcp_data.config_lock, flags);
6f71d9b2005-04-10 23:04:28 -05001765 if (adapter->nameserver_port)
Martin Peschke9467a9b2008-03-27 14:22:03 +01001766 zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 list_for_each_entry(port, &adapter->port_list_head, list)
1768 if (port != adapter->nameserver_port)
Martin Peschke9467a9b2008-03-27 14:22:03 +01001769 zfcp_erp_port_access_changed(port, id, ref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1771}