]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/s390/scsi/zfcp_erp.c
[SCSI] zfcp: Update status read mempool
[net-next-2.6.git] / drivers / s390 / scsi / zfcp_erp.c
CommitLineData
41fa2ada 1/*
553448f6 2 * zfcp device driver
1da177e4 3 *
553448f6 4 * Error Recovery Procedures (ERP).
41fa2ada 5 *
615f59e0 6 * Copyright IBM Corporation 2002, 2010
1da177e4
LT
7 */
8
ecf39d42
CS
9#define KMSG_COMPONENT "zfcp"
10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11
347c6a96 12#include <linux/kthread.h>
1da177e4 13#include "zfcp_ext.h"
b6bd2fb9 14#include "zfcp_reqlist.h"
1da177e4 15
287ac01a
CS
16#define ZFCP_MAX_ERPS 3
17
18enum zfcp_erp_act_flags {
19 ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000,
20 ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000,
21 ZFCP_STATUS_ERP_DISMISSING = 0x00100000,
22 ZFCP_STATUS_ERP_DISMISSED = 0x00200000,
23 ZFCP_STATUS_ERP_LOWMEM = 0x00400000,
24};
1da177e4 25
287ac01a
CS
26enum zfcp_erp_steps {
27 ZFCP_ERP_STEP_UNINITIALIZED = 0x0000,
28 ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001,
29 ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
30 ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
287ac01a
CS
31 ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
32 ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000,
33 ZFCP_ERP_STEP_UNIT_OPENING = 0x2000,
34};
35
36enum zfcp_erp_act_type {
37 ZFCP_ERP_ACTION_REOPEN_UNIT = 1,
38 ZFCP_ERP_ACTION_REOPEN_PORT = 2,
39 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
40 ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4,
41};
42
43enum zfcp_erp_act_state {
44 ZFCP_ERP_ACTION_RUNNING = 1,
45 ZFCP_ERP_ACTION_READY = 2,
46};
47
48enum zfcp_erp_act_result {
49 ZFCP_ERP_SUCCEEDED = 0,
50 ZFCP_ERP_FAILED = 1,
51 ZFCP_ERP_CONTINUES = 2,
52 ZFCP_ERP_EXIT = 3,
53 ZFCP_ERP_DISMISSED = 4,
54 ZFCP_ERP_NOMEM = 5,
55};
56
57static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
1da177e4 58{
5ffd51a5 59 zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL,
287ac01a
CS
60 ZFCP_STATUS_COMMON_UNBLOCKED | mask,
61 ZFCP_CLEAR);
2abbe866 62}
1da177e4 63
287ac01a 64static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
2abbe866 65{
287ac01a
CS
66 struct zfcp_erp_action *curr_act;
67
68 list_for_each_entry(curr_act, &act->adapter->erp_running_head, list)
69 if (act == curr_act)
70 return ZFCP_ERP_ACTION_RUNNING;
71 return 0;
1da177e4
LT
72}
73
287ac01a 74static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
2abbe866 75{
287ac01a
CS
76 struct zfcp_adapter *adapter = act->adapter;
77
78 list_move(&act->list, &act->adapter->erp_ready_head);
5771710b 79 zfcp_dbf_rec_action("erardy1", act);
347c6a96 80 wake_up(&adapter->erp_ready_wq);
5771710b 81 zfcp_dbf_rec_thread("erardy2", adapter->dbf);
2abbe866
AH
82}
83
287ac01a 84static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
1da177e4 85{
287ac01a
CS
86 act->status |= ZFCP_STATUS_ERP_DISMISSED;
87 if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING)
88 zfcp_erp_action_ready(act);
89}
1da177e4 90
287ac01a
CS
91static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
92{
93 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
94 zfcp_erp_action_dismiss(&unit->erp_action);
95}
1da177e4 96
287ac01a
CS
97static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
98{
99 struct zfcp_unit *unit;
1da177e4 100
287ac01a
CS
101 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
102 zfcp_erp_action_dismiss(&port->erp_action);
ecf0c772
SS
103 else {
104 read_lock(&port->unit_list_lock);
105 list_for_each_entry(unit, &port->unit_list, list)
106 zfcp_erp_action_dismiss_unit(unit);
107 read_unlock(&port->unit_list_lock);
108 }
1da177e4
LT
109}
110
287ac01a 111static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
1da177e4 112{
287ac01a 113 struct zfcp_port *port;
1da177e4 114
287ac01a
CS
115 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
116 zfcp_erp_action_dismiss(&adapter->erp_action);
ecf0c772
SS
117 else {
118 read_lock(&adapter->port_list_lock);
119 list_for_each_entry(port, &adapter->port_list, list)
287ac01a 120 zfcp_erp_action_dismiss_port(port);
ecf0c772
SS
121 read_unlock(&adapter->port_list_lock);
122 }
1da177e4
LT
123}
124
287ac01a
CS
125static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
126 struct zfcp_port *port,
127 struct zfcp_unit *unit)
1da177e4 128{
287ac01a
CS
129 int need = want;
130 int u_status, p_status, a_status;
1da177e4 131
287ac01a
CS
132 switch (want) {
133 case ZFCP_ERP_ACTION_REOPEN_UNIT:
134 u_status = atomic_read(&unit->status);
135 if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE)
136 return 0;
137 p_status = atomic_read(&port->status);
138 if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
139 p_status & ZFCP_STATUS_COMMON_ERP_FAILED)
140 return 0;
141 if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED))
142 need = ZFCP_ERP_ACTION_REOPEN_PORT;
143 /* fall through */
144 case ZFCP_ERP_ACTION_REOPEN_PORT:
145 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
146 p_status = atomic_read(&port->status);
147 if (p_status & ZFCP_STATUS_COMMON_ERP_INUSE)
148 return 0;
149 a_status = atomic_read(&adapter->status);
150 if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
151 a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
152 return 0;
153 if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED))
154 need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
155 /* fall through */
156 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
157 a_status = atomic_read(&adapter->status);
158 if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE)
159 return 0;
143bb6bf
CS
160 if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) &&
161 !(a_status & ZFCP_STATUS_COMMON_OPEN))
162 return 0; /* shutdown requested for closed adapter */
287ac01a 163 }
1da177e4 164
287ac01a 165 return need;
1da177e4
LT
166}
167
287ac01a
CS
168static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
169 struct zfcp_adapter *adapter,
170 struct zfcp_port *port,
171 struct zfcp_unit *unit)
1da177e4 172{
287ac01a
CS
173 struct zfcp_erp_action *erp_action;
174 u32 status = 0;
1da177e4 175
287ac01a
CS
176 switch (need) {
177 case ZFCP_ERP_ACTION_REOPEN_UNIT:
615f59e0 178 if (!get_device(&unit->dev))
6b183334 179 return NULL;
287ac01a
CS
180 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
181 erp_action = &unit->erp_action;
182 if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING))
183 status = ZFCP_STATUS_ERP_CLOSE_ONLY;
184 break;
1da177e4 185
287ac01a
CS
186 case ZFCP_ERP_ACTION_REOPEN_PORT:
187 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
615f59e0 188 if (!get_device(&port->dev))
6b183334 189 return NULL;
287ac01a
CS
190 zfcp_erp_action_dismiss_port(port);
191 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
192 erp_action = &port->erp_action;
193 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
194 status = ZFCP_STATUS_ERP_CLOSE_ONLY;
195 break;
1da177e4 196
287ac01a 197 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
f3450c7b 198 kref_get(&adapter->ref);
287ac01a
CS
199 zfcp_erp_action_dismiss_adapter(adapter);
200 atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
201 erp_action = &adapter->erp_action;
202 if (!(atomic_read(&adapter->status) &
203 ZFCP_STATUS_COMMON_RUNNING))
204 status = ZFCP_STATUS_ERP_CLOSE_ONLY;
205 break;
206
207 default:
208 return NULL;
209 }
1da177e4 210
287ac01a
CS
211 memset(erp_action, 0, sizeof(struct zfcp_erp_action));
212 erp_action->adapter = adapter;
213 erp_action->port = port;
214 erp_action->unit = unit;
215 erp_action->action = need;
216 erp_action->status = status;
1da177e4 217
287ac01a 218 return erp_action;
1da177e4
LT
219}
220
287ac01a
CS
221static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
222 struct zfcp_port *port,
5ffd51a5 223 struct zfcp_unit *unit, char *id, void *ref)
1da177e4 224{
287ac01a
CS
225 int retval = 1, need;
226 struct zfcp_erp_action *act = NULL;
1da177e4 227
347c6a96 228 if (!adapter->erp_thread)
287ac01a 229 return -EIO;
1da177e4 230
287ac01a
CS
231 need = zfcp_erp_required_act(want, adapter, port, unit);
232 if (!need)
1da177e4 233 goto out;
1da177e4 234
287ac01a
CS
235 atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
236 act = zfcp_erp_setup_act(need, adapter, port, unit);
237 if (!act)
238 goto out;
239 ++adapter->erp_total_count;
240 list_add_tail(&act->list, &adapter->erp_ready_head);
347c6a96 241 wake_up(&adapter->erp_ready_wq);
5771710b 242 zfcp_dbf_rec_thread("eracte1", adapter->dbf);
287ac01a 243 retval = 0;
1da177e4 244 out:
5771710b 245 zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit);
1da177e4
LT
246 return retval;
247}
248
287ac01a 249static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
5ffd51a5 250 int clear_mask, char *id, void *ref)
287ac01a
CS
251{
252 zfcp_erp_adapter_block(adapter, clear_mask);
a2fa0aed 253 zfcp_scsi_schedule_rports_block(adapter);
287ac01a
CS
254
255 /* ensure propagation of failed status to new devices */
256 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
5ffd51a5 257 zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
287ac01a
CS
258 return -EIO;
259 }
260 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
261 adapter, NULL, NULL, id, ref);
262}
263
264/**
265 * zfcp_erp_adapter_reopen - Reopen adapter.
266 * @adapter: Adapter to reopen.
267 * @clear: Status flags to clear.
268 * @id: Id for debug trace event.
269 * @ref: Reference for debug trace event.
1da177e4 270 */
287ac01a 271void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
5ffd51a5 272 char *id, void *ref)
1da177e4 273{
1da177e4 274 unsigned long flags;
1da177e4 275
ecf0c772
SS
276 zfcp_erp_adapter_block(adapter, clear);
277 zfcp_scsi_schedule_rports_block(adapter);
278
279 write_lock_irqsave(&adapter->erp_lock, flags);
280 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
281 zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
282 else
283 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
284 NULL, NULL, id, ref);
285 write_unlock_irqrestore(&adapter->erp_lock, flags);
287ac01a 286}
1da177e4 287
287ac01a
CS
288/**
289 * zfcp_erp_adapter_shutdown - Shutdown adapter.
290 * @adapter: Adapter to shut down.
291 * @clear: Status flags to clear.
292 * @id: Id for debug trace event.
293 * @ref: Reference for debug trace event.
294 */
295void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear,
5ffd51a5 296 char *id, void *ref)
287ac01a
CS
297{
298 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
299 zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref);
1da177e4
LT
300}
301
287ac01a
CS
302/**
303 * zfcp_erp_port_shutdown - Shutdown port
304 * @port: Port to shut down.
305 * @clear: Status flags to clear.
306 * @id: Id for debug trace event.
307 * @ref: Reference for debug trace event.
1da177e4 308 */
5ffd51a5
SS
309void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id,
310 void *ref)
1da177e4 311{
287ac01a
CS
312 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
313 zfcp_erp_port_reopen(port, clear | flags, id, ref);
314}
315
316/**
317 * zfcp_erp_unit_shutdown - Shutdown unit
318 * @unit: Unit to shut down.
319 * @clear: Status flags to clear.
320 * @id: Id for debug trace event.
321 * @ref: Reference for debug trace event.
322 */
5ffd51a5
SS
323void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id,
324 void *ref)
287ac01a
CS
325{
326 int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
327 zfcp_erp_unit_reopen(unit, clear | flags, id, ref);
328}
329
330static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
331{
5ffd51a5 332 zfcp_erp_modify_port_status(port, "erpblk1", NULL,
287ac01a
CS
333 ZFCP_STATUS_COMMON_UNBLOCKED | clear,
334 ZFCP_CLEAR);
335}
336
337static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
5ffd51a5 338 int clear, char *id, void *ref)
287ac01a
CS
339{
340 zfcp_erp_port_block(port, clear);
a2fa0aed 341 zfcp_scsi_schedule_rport_block(port);
287ac01a
CS
342
343 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
344 return;
1da177e4 345
287ac01a
CS
346 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
347 port->adapter, port, NULL, id, ref);
348}
349
350/**
351 * zfcp_erp_port_forced_reopen - Forced close of port and open again
352 * @port: Port to force close and to reopen.
353 * @id: Id for debug trace event.
354 * @ref: Reference for debug trace event.
355 */
5ffd51a5 356void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id,
287ac01a
CS
357 void *ref)
358{
359 unsigned long flags;
360 struct zfcp_adapter *adapter = port->adapter;
361
ecf0c772 362 write_lock_irqsave(&adapter->erp_lock, flags);
287ac01a 363 _zfcp_erp_port_forced_reopen(port, clear, id, ref);
ecf0c772 364 write_unlock_irqrestore(&adapter->erp_lock, flags);
287ac01a
CS
365}
366
5ffd51a5 367static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
287ac01a
CS
368 void *ref)
369{
370 zfcp_erp_port_block(port, clear);
a2fa0aed 371 zfcp_scsi_schedule_rport_block(port);
1da177e4 372
287ac01a 373 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1da177e4 374 /* ensure propagation of failed status to new devices */
5ffd51a5 375 zfcp_erp_port_failed(port, "erpreo1", NULL);
287ac01a 376 return -EIO;
1da177e4
LT
377 }
378
287ac01a
CS
379 return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
380 port->adapter, port, NULL, id, ref);
1da177e4
LT
381}
382
383/**
287ac01a
CS
384 * zfcp_erp_port_reopen - trigger remote port recovery
385 * @port: port to recover
386 * @clear_mask: flags in port status to be cleared
1da177e4 387 *
287ac01a 388 * Returns 0 if recovery has been triggered, < 0 if not.
1da177e4 389 */
5ffd51a5 390int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref)
1da177e4 391{
287ac01a 392 int retval;
ecf0c772 393 unsigned long flags;
1da177e4
LT
394 struct zfcp_adapter *adapter = port->adapter;
395
ecf0c772 396 write_lock_irqsave(&adapter->erp_lock, flags);
287ac01a 397 retval = _zfcp_erp_port_reopen(port, clear, id, ref);
ecf0c772 398 write_unlock_irqrestore(&adapter->erp_lock, flags);
1da177e4
LT
399
400 return retval;
401}
402
287ac01a
CS
403static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
404{
5ffd51a5 405 zfcp_erp_modify_unit_status(unit, "erublk1", NULL,
287ac01a
CS
406 ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
407 ZFCP_CLEAR);
408}
409
5ffd51a5 410static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
287ac01a 411 void *ref)
1da177e4 412{
1da177e4
LT
413 struct zfcp_adapter *adapter = unit->port->adapter;
414
287ac01a 415 zfcp_erp_unit_block(unit, clear);
1da177e4 416
287ac01a
CS
417 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
418 return;
1da177e4 419
287ac01a
CS
420 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
421 adapter, unit->port, unit, id, ref);
1da177e4
LT
422}
423
424/**
425 * zfcp_erp_unit_reopen - initiate reopen of a unit
426 * @unit: unit to be reopened
427 * @clear_mask: specifies flags in unit status to be cleared
428 * Return: 0 on success, < 0 on error
1da177e4 429 */
5ffd51a5
SS
430void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
431 void *ref)
1da177e4 432{
1da177e4 433 unsigned long flags;
287ac01a
CS
434 struct zfcp_port *port = unit->port;
435 struct zfcp_adapter *adapter = port->adapter;
1da177e4 436
ecf0c772 437 write_lock_irqsave(&adapter->erp_lock, flags);
287ac01a 438 _zfcp_erp_unit_reopen(unit, clear, id, ref);
ecf0c772 439 write_unlock_irqrestore(&adapter->erp_lock, flags);
1da177e4
LT
440}
441
287ac01a 442static int status_change_set(unsigned long mask, atomic_t *status)
1da177e4 443{
287ac01a 444 return (atomic_read(status) ^ mask) & mask;
1da177e4
LT
445}
446
287ac01a 447static int status_change_clear(unsigned long mask, atomic_t *status)
698ec016 448{
287ac01a 449 return atomic_read(status) & mask;
698ec016
MP
450}
451
287ac01a 452static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
698ec016 453{
287ac01a 454 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
5771710b 455 zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf);
287ac01a 456 atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
698ec016
MP
457}
458
287ac01a 459static void zfcp_erp_port_unblock(struct zfcp_port *port)
1da177e4 460{
287ac01a 461 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
5771710b 462 zfcp_dbf_rec_port("erpubl1", NULL, port);
287ac01a 463 atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
1da177e4
LT
464}
465
287ac01a 466static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
1da177e4 467{
287ac01a 468 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
5771710b 469 zfcp_dbf_rec_unit("eruubl1", NULL, unit);
287ac01a 470 atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
1da177e4
LT
471}
472
287ac01a 473static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
1da177e4 474{
287ac01a 475 list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
5771710b 476 zfcp_dbf_rec_action("erator1", erp_action);
1da177e4
LT
477}
478
287ac01a 479static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
1da177e4 480{
287ac01a 481 struct zfcp_adapter *adapter = act->adapter;
e60a6d69 482 struct zfcp_fsf_req *req;
1da177e4 483
e60a6d69 484 if (!act->fsf_req_id)
287ac01a 485 return;
1da177e4 486
b6bd2fb9
CS
487 spin_lock(&adapter->req_list->lock);
488 req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id);
e60a6d69 489 if (req && req->erp_action == act) {
287ac01a
CS
490 if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
491 ZFCP_STATUS_ERP_TIMEDOUT)) {
e60a6d69 492 req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
5771710b 493 zfcp_dbf_rec_action("erscf_1", act);
e60a6d69 494 req->erp_action = NULL;
1da177e4 495 }
287ac01a 496 if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
5771710b 497 zfcp_dbf_rec_action("erscf_2", act);
e60a6d69
CS
498 if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
499 act->fsf_req_id = 0;
287ac01a 500 } else
e60a6d69 501 act->fsf_req_id = 0;
b6bd2fb9 502 spin_unlock(&adapter->req_list->lock);
1da177e4
LT
503}
504
287ac01a
CS
505/**
506 * zfcp_erp_notify - Trigger ERP action.
507 * @erp_action: ERP action to continue.
508 * @set_mask: ERP action status flags to set.
1da177e4 509 */
287ac01a 510void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask)
1da177e4 511{
1da177e4 512 struct zfcp_adapter *adapter = erp_action->adapter;
287ac01a 513 unsigned long flags;
1da177e4 514
287ac01a 515 write_lock_irqsave(&adapter->erp_lock, flags);
1da177e4 516 if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
1da177e4
LT
517 erp_action->status |= set_mask;
518 zfcp_erp_action_ready(erp_action);
1da177e4 519 }
1da177e4 520 write_unlock_irqrestore(&adapter->erp_lock, flags);
1da177e4
LT
521}
522
287ac01a
CS
523/**
524 * zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request
525 * @data: ERP action (from timer data)
1da177e4 526 */
287ac01a 527void zfcp_erp_timeout_handler(unsigned long data)
1da177e4 528{
287ac01a
CS
529 struct zfcp_erp_action *act = (struct zfcp_erp_action *) data;
530 zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT);
1da177e4
LT
531}
532
287ac01a 533static void zfcp_erp_memwait_handler(unsigned long data)
1da177e4 534{
287ac01a 535 zfcp_erp_notify((struct zfcp_erp_action *)data, 0);
1da177e4
LT
536}
537
287ac01a 538static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
1da177e4 539{
287ac01a
CS
540 init_timer(&erp_action->timer);
541 erp_action->timer.function = zfcp_erp_memwait_handler;
542 erp_action->timer.data = (unsigned long) erp_action;
543 erp_action->timer.expires = jiffies + HZ;
544 add_timer(&erp_action->timer);
1da177e4
LT
545}
546
287ac01a 547static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
5ffd51a5 548 int clear, char *id, void *ref)
1da177e4 549{
287ac01a 550 struct zfcp_port *port;
1da177e4 551
ecf0c772
SS
552 read_lock(&adapter->port_list_lock);
553 list_for_each_entry(port, &adapter->port_list, list)
5ab944f9 554 _zfcp_erp_port_reopen(port, clear, id, ref);
ecf0c772 555 read_unlock(&adapter->port_list_lock);
1da177e4
LT
556}
557
5ffd51a5
SS
558static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
559 char *id, void *ref)
1da177e4 560{
287ac01a 561 struct zfcp_unit *unit;
1da177e4 562
ecf0c772
SS
563 read_lock(&port->unit_list_lock);
564 list_for_each_entry(unit, &port->unit_list, list)
287ac01a 565 _zfcp_erp_unit_reopen(unit, clear, id, ref);
ecf0c772 566 read_unlock(&port->unit_list_lock);
1da177e4
LT
567}
568
85600f7f 569static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
1da177e4 570{
287ac01a 571 switch (act->action) {
287ac01a 572 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
85600f7f 573 _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL);
287ac01a 574 break;
287ac01a 575 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
85600f7f 576 _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL);
287ac01a 577 break;
287ac01a 578 case ZFCP_ERP_ACTION_REOPEN_PORT:
85600f7f 579 _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
287ac01a 580 break;
287ac01a 581 case ZFCP_ERP_ACTION_REOPEN_UNIT:
85600f7f
CS
582 _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL);
583 break;
584 }
585}
586
587static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act)
588{
589 switch (act->action) {
590 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
591 _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL);
592 break;
593 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
594 _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
595 break;
596 case ZFCP_ERP_ACTION_REOPEN_PORT:
597 _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL);
287ac01a 598 break;
1da177e4 599 }
1da177e4
LT
600}
601
287ac01a 602static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
1da177e4 603{
1da177e4
LT
604 unsigned long flags;
605
ecf0c772 606 read_lock_irqsave(&adapter->erp_lock, flags);
287ac01a
CS
607 if (list_empty(&adapter->erp_ready_head) &&
608 list_empty(&adapter->erp_running_head)) {
609 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
610 &adapter->status);
611 wake_up(&adapter->erp_done_wqh);
1da177e4 612 }
ecf0c772 613 read_unlock_irqrestore(&adapter->erp_lock, flags);
287ac01a 614}
1da177e4 615
287ac01a
CS
616static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
617{
564e1c86
SS
618 struct zfcp_qdio *qdio = act->adapter->qdio;
619
620 if (zfcp_qdio_open(qdio))
287ac01a 621 return ZFCP_ERP_FAILED;
564e1c86 622 init_waitqueue_head(&qdio->req_q_wq);
287ac01a
CS
623 atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status);
624 return ZFCP_ERP_SUCCEEDED;
625}
1da177e4 626
287ac01a
CS
627static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter)
628{
629 struct zfcp_port *port;
630 port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0,
631 adapter->peer_d_id);
632 if (IS_ERR(port)) /* error or port already attached */
633 return;
5ffd51a5 634 _zfcp_erp_port_reopen(port, 0, "ereptp1", NULL);
287ac01a 635}
1da177e4 636
287ac01a
CS
637static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
638{
639 int retries;
640 int sleep = 1;
641 struct zfcp_adapter *adapter = erp_action->adapter;
1da177e4 642
287ac01a
CS
643 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
644
645 for (retries = 7; retries; retries--) {
646 atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
647 &adapter->status);
648 write_lock_irq(&adapter->erp_lock);
649 zfcp_erp_action_to_running(erp_action);
650 write_unlock_irq(&adapter->erp_lock);
651 if (zfcp_fsf_exchange_config_data(erp_action)) {
652 atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
653 &adapter->status);
654 return ZFCP_ERP_FAILED;
1da177e4 655 }
1da177e4 656
5771710b 657 zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf);
347c6a96
CS
658 wait_event(adapter->erp_ready_wq,
659 !list_empty(&adapter->erp_ready_head));
5771710b 660 zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf);
287ac01a
CS
661 if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
662 break;
1da177e4 663
287ac01a
CS
664 if (!(atomic_read(&adapter->status) &
665 ZFCP_STATUS_ADAPTER_HOST_CON_INIT))
666 break;
1da177e4 667
287ac01a
CS
668 ssleep(sleep);
669 sleep *= 2;
1da177e4
LT
670 }
671
287ac01a
CS
672 atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
673 &adapter->status);
1da177e4 674
287ac01a
CS
675 if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK))
676 return ZFCP_ERP_FAILED;
41fa2ada 677
287ac01a
CS
678 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
679 zfcp_erp_enqueue_ptp_port(adapter);
1da177e4 680
287ac01a 681 return ZFCP_ERP_SUCCEEDED;
1da177e4
LT
682}
683
287ac01a 684static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
1da177e4 685{
287ac01a
CS
686 int ret;
687 struct zfcp_adapter *adapter = act->adapter;
1da177e4 688
287ac01a
CS
689 write_lock_irq(&adapter->erp_lock);
690 zfcp_erp_action_to_running(act);
691 write_unlock_irq(&adapter->erp_lock);
692
693 ret = zfcp_fsf_exchange_port_data(act);
694 if (ret == -EOPNOTSUPP)
695 return ZFCP_ERP_SUCCEEDED;
696 if (ret)
697 return ZFCP_ERP_FAILED;
698
5771710b 699 zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf);
347c6a96
CS
700 wait_event(adapter->erp_ready_wq,
701 !list_empty(&adapter->erp_ready_head));
5771710b 702 zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf);
287ac01a
CS
703 if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
704 return ZFCP_ERP_FAILED;
705
706 return ZFCP_ERP_SUCCEEDED;
1da177e4
LT
707}
708
287ac01a 709static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
1da177e4 710{
287ac01a
CS
711 if (zfcp_erp_adapter_strat_fsf_xconf(act) == ZFCP_ERP_FAILED)
712 return ZFCP_ERP_FAILED;
1da177e4 713
287ac01a
CS
714 if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
715 return ZFCP_ERP_FAILED;
1da177e4 716
8d88cf3f
CS
717 if (mempool_resize(act->adapter->pool.status_read_data,
718 act->adapter->stat_read_buf_num, GFP_KERNEL))
719 return ZFCP_ERP_FAILED;
720
721 if (mempool_resize(act->adapter->pool.status_read_req,
722 act->adapter->stat_read_buf_num, GFP_KERNEL))
723 return ZFCP_ERP_FAILED;
724
64deb6ef 725 atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
287ac01a
CS
726 if (zfcp_status_read_refill(act->adapter))
727 return ZFCP_ERP_FAILED;
1da177e4 728
287ac01a
CS
729 return ZFCP_ERP_SUCCEEDED;
730}
1da177e4 731
cf13c082 732static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
287ac01a 733{
287ac01a 734 struct zfcp_adapter *adapter = act->adapter;
1da177e4 735
287ac01a 736 /* close queues to ensure that buffers are not accessed by adapter */
564e1c86 737 zfcp_qdio_close(adapter->qdio);
287ac01a
CS
738 zfcp_fsf_req_dismiss_all(adapter);
739 adapter->fsf_req_seq_no = 0;
55c770fa 740 zfcp_fc_wka_ports_force_offline(adapter->gs);
287ac01a 741 /* all ports and units are closed */
5ffd51a5 742 zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
287ac01a 743 ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
cf13c082 744
287ac01a 745 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
cf13c082 746 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
1da177e4
LT
747}
748
cf13c082 749static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act)
1da177e4 750{
cf13c082 751 struct zfcp_adapter *adapter = act->adapter;
1da177e4 752
cf13c082
SS
753 if (zfcp_erp_adapter_strategy_open_qdio(act)) {
754 atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
755 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
756 &adapter->status);
757 return ZFCP_ERP_FAILED;
758 }
287ac01a 759
cf13c082
SS
760 if (zfcp_erp_adapter_strategy_open_fsf(act)) {
761 zfcp_erp_adapter_strategy_close(act);
762 return ZFCP_ERP_FAILED;
763 }
764
765 atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &adapter->status);
766
767 return ZFCP_ERP_SUCCEEDED;
768}
287ac01a 769
cf13c082
SS
770static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act)
771{
772 struct zfcp_adapter *adapter = act->adapter;
773
774 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN) {
775 zfcp_erp_adapter_strategy_close(act);
776 if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
777 return ZFCP_ERP_EXIT;
778 }
779
780 if (zfcp_erp_adapter_strategy_open(act)) {
287ac01a 781 ssleep(8);
cf13c082
SS
782 return ZFCP_ERP_FAILED;
783 }
1da177e4 784
cf13c082 785 return ZFCP_ERP_SUCCEEDED;
1da177e4
LT
786}
787
287ac01a 788static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
1da177e4 789{
287ac01a
CS
790 int retval;
791
792 retval = zfcp_fsf_close_physical_port(act);
793 if (retval == -ENOMEM)
794 return ZFCP_ERP_NOMEM;
795 act->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
796 if (retval)
797 return ZFCP_ERP_FAILED;
798
799 return ZFCP_ERP_CONTINUES;
1da177e4
LT
800}
801
287ac01a 802static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
1da177e4 803{
a5b11dda 804 atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status);
287ac01a 805}
1da177e4 806
287ac01a
CS
807static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
808{
809 struct zfcp_port *port = erp_action->port;
810 int status = atomic_read(&port->status);
811
812 switch (erp_action->step) {
813 case ZFCP_ERP_STEP_UNINITIALIZED:
814 zfcp_erp_port_strategy_clearstati(port);
815 if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
816 (status & ZFCP_STATUS_COMMON_OPEN))
817 return zfcp_erp_port_forced_strategy_close(erp_action);
818 else
819 return ZFCP_ERP_FAILED;
820
821 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
ddb3e0c1 822 if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN))
287ac01a
CS
823 return ZFCP_ERP_SUCCEEDED;
824 }
825 return ZFCP_ERP_FAILED;
1da177e4
LT
826}
827
287ac01a 828static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
1da177e4 829{
287ac01a 830 int retval;
1da177e4 831
287ac01a
CS
832 retval = zfcp_fsf_close_port(erp_action);
833 if (retval == -ENOMEM)
834 return ZFCP_ERP_NOMEM;
835 erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
836 if (retval)
837 return ZFCP_ERP_FAILED;
838 return ZFCP_ERP_CONTINUES;
1da177e4
LT
839}
840
287ac01a 841static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
1da177e4 842{
287ac01a 843 int retval;
1da177e4 844
287ac01a
CS
845 retval = zfcp_fsf_open_port(erp_action);
846 if (retval == -ENOMEM)
847 return ZFCP_ERP_NOMEM;
848 erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
849 if (retval)
850 return ZFCP_ERP_FAILED;
851 return ZFCP_ERP_CONTINUES;
852}
1da177e4 853
287ac01a 854static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
1da177e4 855{
287ac01a
CS
856 struct zfcp_adapter *adapter = act->adapter;
857 struct zfcp_port *port = act->port;
1da177e4 858
287ac01a 859 if (port->wwpn != adapter->peer_wwpn) {
5ffd51a5 860 zfcp_erp_port_failed(port, "eroptp1", NULL);
287ac01a
CS
861 return ZFCP_ERP_FAILED;
862 }
863 port->d_id = adapter->peer_d_id;
287ac01a
CS
864 return zfcp_erp_port_strategy_open_port(act);
865}
866
867static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
868{
869 struct zfcp_adapter *adapter = act->adapter;
870 struct zfcp_port *port = act->port;
287ac01a
CS
871 int p_status = atomic_read(&port->status);
872
873 switch (act->step) {
874 case ZFCP_ERP_STEP_UNINITIALIZED:
875 case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
876 case ZFCP_ERP_STEP_PORT_CLOSING:
877 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
878 return zfcp_erp_open_ptp_port(act);
b98478d7 879 if (!port->d_id) {
934aeb58 880 zfcp_fc_trigger_did_lookup(port);
799b76d0 881 return ZFCP_ERP_EXIT;
287ac01a 882 }
287ac01a
CS
883 return zfcp_erp_port_strategy_open_port(act);
884
885 case ZFCP_ERP_STEP_PORT_OPENING:
886 /* D_ID might have changed during open */
5ab944f9 887 if (p_status & ZFCP_STATUS_COMMON_OPEN) {
934aeb58
CS
888 if (!port->d_id) {
889 zfcp_fc_trigger_did_lookup(port);
890 return ZFCP_ERP_EXIT;
5ab944f9 891 }
934aeb58 892 return ZFCP_ERP_SUCCEEDED;
5ab944f9 893 }
ea460a81
SS
894 if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) {
895 port->d_id = 0;
896 _zfcp_erp_port_reopen(port, 0, "erpsoc1", NULL);
897 return ZFCP_ERP_EXIT;
898 }
899 /* fall through otherwise */
287ac01a
CS
900 }
901 return ZFCP_ERP_FAILED;
902}
903
287ac01a
CS
904static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
905{
906 struct zfcp_port *port = erp_action->port;
934aeb58 907 int p_status = atomic_read(&port->status);
287ac01a 908
934aeb58
CS
909 if ((p_status & ZFCP_STATUS_COMMON_NOESC) &&
910 !(p_status & ZFCP_STATUS_COMMON_OPEN))
5ab944f9
SS
911 goto close_init_done;
912
287ac01a
CS
913 switch (erp_action->step) {
914 case ZFCP_ERP_STEP_UNINITIALIZED:
915 zfcp_erp_port_strategy_clearstati(port);
934aeb58 916 if (p_status & ZFCP_STATUS_COMMON_OPEN)
287ac01a 917 return zfcp_erp_port_strategy_close(erp_action);
1da177e4
LT
918 break;
919
287ac01a 920 case ZFCP_ERP_STEP_PORT_CLOSING:
934aeb58 921 if (p_status & ZFCP_STATUS_COMMON_OPEN)
287ac01a 922 return ZFCP_ERP_FAILED;
1da177e4
LT
923 break;
924 }
5ab944f9
SS
925
926close_init_done:
287ac01a
CS
927 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
928 return ZFCP_ERP_EXIT;
1da177e4 929
5ab944f9 930 return zfcp_erp_port_strategy_open_common(erp_action);
287ac01a
CS
931}
932
933static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
934{
44cc76f2 935 atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
287ac01a
CS
936 ZFCP_STATUS_UNIT_SHARED |
937 ZFCP_STATUS_UNIT_READONLY,
938 &unit->status);
939}
940
941static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
942{
943 int retval = zfcp_fsf_close_unit(erp_action);
944 if (retval == -ENOMEM)
945 return ZFCP_ERP_NOMEM;
946 erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
947 if (retval)
948 return ZFCP_ERP_FAILED;
949 return ZFCP_ERP_CONTINUES;
950}
951
952static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
953{
954 int retval = zfcp_fsf_open_unit(erp_action);
955 if (retval == -ENOMEM)
956 return ZFCP_ERP_NOMEM;
957 erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
958 if (retval)
959 return ZFCP_ERP_FAILED;
960 return ZFCP_ERP_CONTINUES;
1da177e4
LT
961}
962
287ac01a 963static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
1da177e4 964{
287ac01a
CS
965 struct zfcp_unit *unit = erp_action->unit;
966
967 switch (erp_action->step) {
968 case ZFCP_ERP_STEP_UNINITIALIZED:
969 zfcp_erp_unit_strategy_clearstati(unit);
970 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
971 return zfcp_erp_unit_strategy_close(erp_action);
972 /* already closed, fall through */
973 case ZFCP_ERP_STEP_UNIT_CLOSING:
974 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
975 return ZFCP_ERP_FAILED;
976 if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
977 return ZFCP_ERP_EXIT;
978 return zfcp_erp_unit_strategy_open(erp_action);
979
980 case ZFCP_ERP_STEP_UNIT_OPENING:
981 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
982 return ZFCP_ERP_SUCCEEDED;
983 }
984 return ZFCP_ERP_FAILED;
1da177e4
LT
985}
986
287ac01a 987static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
1da177e4 988{
1da177e4
LT
989 switch (result) {
990 case ZFCP_ERP_SUCCEEDED :
991 atomic_set(&unit->erp_counter, 0);
992 zfcp_erp_unit_unblock(unit);
993 break;
994 case ZFCP_ERP_FAILED :
995 atomic_inc(&unit->erp_counter);
ff3b24fa
CS
996 if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
997 dev_err(&unit->port->adapter->ccw_device->dev,
998 "ERP failed for unit 0x%016Lx on "
999 "port 0x%016Lx\n",
7ba58c9c
SS
1000 (unsigned long long)unit->fcp_lun,
1001 (unsigned long long)unit->port->wwpn);
5ffd51a5 1002 zfcp_erp_unit_failed(unit, "erusck1", NULL);
ff3b24fa 1003 }
1da177e4 1004 break;
1da177e4
LT
1005 }
1006
287ac01a
CS
1007 if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1008 zfcp_erp_unit_block(unit, 0);
1da177e4
LT
1009 result = ZFCP_ERP_EXIT;
1010 }
1da177e4
LT
1011 return result;
1012}
1013
287ac01a 1014static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
1da177e4 1015{
1da177e4
LT
1016 switch (result) {
1017 case ZFCP_ERP_SUCCEEDED :
1018 atomic_set(&port->erp_counter, 0);
1019 zfcp_erp_port_unblock(port);
1020 break;
287ac01a 1021
1da177e4 1022 case ZFCP_ERP_FAILED :
287ac01a 1023 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) {
cc8c2829
SS
1024 zfcp_erp_port_block(port, 0);
1025 result = ZFCP_ERP_EXIT;
1026 }
1da177e4 1027 atomic_inc(&port->erp_counter);
ff3b24fa
CS
1028 if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
1029 dev_err(&port->adapter->ccw_device->dev,
1030 "ERP failed for remote port 0x%016Lx\n",
7ba58c9c 1031 (unsigned long long)port->wwpn);
5ffd51a5 1032 zfcp_erp_port_failed(port, "erpsck1", NULL);
ff3b24fa 1033 }
1da177e4 1034 break;
1da177e4
LT
1035 }
1036
287ac01a
CS
1037 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1038 zfcp_erp_port_block(port, 0);
1da177e4
LT
1039 result = ZFCP_ERP_EXIT;
1040 }
1da177e4
LT
1041 return result;
1042}
1043
287ac01a
CS
1044static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
1045 int result)
1da177e4 1046{
1da177e4
LT
1047 switch (result) {
1048 case ZFCP_ERP_SUCCEEDED :
1049 atomic_set(&adapter->erp_counter, 0);
1050 zfcp_erp_adapter_unblock(adapter);
1051 break;
287ac01a 1052
1da177e4
LT
1053 case ZFCP_ERP_FAILED :
1054 atomic_inc(&adapter->erp_counter);
ff3b24fa
CS
1055 if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
1056 dev_err(&adapter->ccw_device->dev,
1057 "ERP cannot recover an error "
1058 "on the FCP device\n");
5ffd51a5 1059 zfcp_erp_adapter_failed(adapter, "erasck1", NULL);
ff3b24fa 1060 }
1da177e4 1061 break;
1da177e4
LT
1062 }
1063
287ac01a
CS
1064 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
1065 zfcp_erp_adapter_block(adapter, 0);
1da177e4
LT
1066 result = ZFCP_ERP_EXIT;
1067 }
1da177e4
LT
1068 return result;
1069}
1070
287ac01a
CS
1071static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action,
1072 int result)
5f852be9 1073{
287ac01a
CS
1074 struct zfcp_adapter *adapter = erp_action->adapter;
1075 struct zfcp_port *port = erp_action->port;
1076 struct zfcp_unit *unit = erp_action->unit;
1077
1078 switch (erp_action->action) {
1079
1080 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1081 result = zfcp_erp_strategy_check_unit(unit, result);
1082 break;
1083
1084 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1085 case ZFCP_ERP_ACTION_REOPEN_PORT:
1086 result = zfcp_erp_strategy_check_port(port, result);
1087 break;
1088
1089 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1090 result = zfcp_erp_strategy_check_adapter(adapter, result);
1091 break;
1092 }
1093 return result;
5f852be9
CS
1094}
1095
287ac01a 1096static int zfcp_erp_strat_change_det(atomic_t *target_status, u32 erp_status)
5f852be9 1097{
287ac01a 1098 int status = atomic_read(target_status);
5f852be9 1099
287ac01a
CS
1100 if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
1101 (erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
1102 return 1; /* take it online */
5f852be9 1103
287ac01a
CS
1104 if (!(status & ZFCP_STATUS_COMMON_RUNNING) &&
1105 !(erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
1106 return 1; /* take it offline */
1107
1108 return 0;
5f852be9
CS
1109}
1110
287ac01a 1111static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
1da177e4 1112{
287ac01a
CS
1113 int action = act->action;
1114 struct zfcp_adapter *adapter = act->adapter;
1115 struct zfcp_port *port = act->port;
1116 struct zfcp_unit *unit = act->unit;
1117 u32 erp_status = act->status;
1da177e4 1118
287ac01a 1119 switch (action) {
1da177e4 1120 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
287ac01a
CS
1121 if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) {
1122 _zfcp_erp_adapter_reopen(adapter,
1123 ZFCP_STATUS_COMMON_ERP_FAILED,
5ffd51a5 1124 "ersscg1", NULL);
287ac01a
CS
1125 return ZFCP_ERP_EXIT;
1126 }
1da177e4
LT
1127 break;
1128
1129 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1da177e4 1130 case ZFCP_ERP_ACTION_REOPEN_PORT:
287ac01a
CS
1131 if (zfcp_erp_strat_change_det(&port->status, erp_status)) {
1132 _zfcp_erp_port_reopen(port,
1133 ZFCP_STATUS_COMMON_ERP_FAILED,
5ffd51a5 1134 "ersscg2", NULL);
287ac01a
CS
1135 return ZFCP_ERP_EXIT;
1136 }
1da177e4
LT
1137 break;
1138
1139 case ZFCP_ERP_ACTION_REOPEN_UNIT:
287ac01a
CS
1140 if (zfcp_erp_strat_change_det(&unit->status, erp_status)) {
1141 _zfcp_erp_unit_reopen(unit,
1142 ZFCP_STATUS_COMMON_ERP_FAILED,
5ffd51a5 1143 "ersscg3", NULL);
287ac01a
CS
1144 return ZFCP_ERP_EXIT;
1145 }
1da177e4
LT
1146 break;
1147 }
287ac01a 1148 return ret;
1da177e4
LT
1149}
1150
287ac01a 1151static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
1da177e4 1152{
287ac01a 1153 struct zfcp_adapter *adapter = erp_action->adapter;
1da177e4 1154
287ac01a
CS
1155 adapter->erp_total_count--;
1156 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
1157 adapter->erp_low_mem_count--;
1158 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
507e4969 1159 }
1da177e4 1160
287ac01a 1161 list_del(&erp_action->list);
5771710b 1162 zfcp_dbf_rec_action("eractd1", erp_action);
1da177e4 1163
287ac01a
CS
1164 switch (erp_action->action) {
1165 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1166 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1167 &erp_action->unit->status);
1168 break;
1da177e4 1169
287ac01a
CS
1170 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1171 case ZFCP_ERP_ACTION_REOPEN_PORT:
1172 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1173 &erp_action->port->status);
1174 break;
1da177e4 1175
287ac01a
CS
1176 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1177 atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1178 &erp_action->adapter->status);
1179 break;
1180 }
1da177e4
LT
1181}
1182
287ac01a 1183static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1da177e4 1184{
287ac01a
CS
1185 struct zfcp_adapter *adapter = act->adapter;
1186 struct zfcp_port *port = act->port;
1187 struct zfcp_unit *unit = act->unit;
1da177e4 1188
287ac01a
CS
1189 switch (act->action) {
1190 case ZFCP_ERP_ACTION_REOPEN_UNIT:
a2fa0aed 1191 if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
615f59e0 1192 get_device(&unit->dev);
92d5193b
SS
1193 if (scsi_queue_work(unit->port->adapter->scsi_host,
1194 &unit->scsi_work) <= 0)
615f59e0 1195 put_device(&unit->dev);
287ac01a 1196 }
615f59e0 1197 put_device(&unit->dev);
287ac01a 1198 break;
1da177e4 1199
287ac01a
CS
1200 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1201 case ZFCP_ERP_ACTION_REOPEN_PORT:
a2fa0aed
CS
1202 if (result == ZFCP_ERP_SUCCEEDED)
1203 zfcp_scsi_schedule_rport_register(port);
615f59e0 1204 put_device(&port->dev);
287ac01a
CS
1205 break;
1206
1207 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
a2fa0aed 1208 if (result == ZFCP_ERP_SUCCEEDED) {
bd43a42b 1209 register_service_level(&adapter->service_level);
9eae07ef 1210 queue_work(adapter->work_queue, &adapter->scan_work);
a2fa0aed
CS
1211 } else
1212 unregister_service_level(&adapter->service_level);
f3450c7b 1213 kref_put(&adapter->ref, zfcp_adapter_release);
287ac01a
CS
1214 break;
1215 }
1da177e4
LT
1216}
1217
287ac01a 1218static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
1da177e4 1219{
287ac01a
CS
1220 switch (erp_action->action) {
1221 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1222 return zfcp_erp_adapter_strategy(erp_action);
1223 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1224 return zfcp_erp_port_forced_strategy(erp_action);
1225 case ZFCP_ERP_ACTION_REOPEN_PORT:
1226 return zfcp_erp_port_strategy(erp_action);
1227 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1228 return zfcp_erp_unit_strategy(erp_action);
1229 }
1230 return ZFCP_ERP_FAILED;
1da177e4
LT
1231}
1232
287ac01a 1233static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
1da177e4
LT
1234{
1235 int retval;
287ac01a 1236 unsigned long flags;
ecf0c772 1237 struct zfcp_adapter *adapter = erp_action->adapter;
1da177e4 1238
f3450c7b 1239 kref_get(&adapter->ref);
1da177e4 1240
f3450c7b 1241 write_lock_irqsave(&adapter->erp_lock, flags);
287ac01a 1242 zfcp_erp_strategy_check_fsfreq(erp_action);
1da177e4 1243
287ac01a
CS
1244 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
1245 zfcp_erp_action_dequeue(erp_action);
1246 retval = ZFCP_ERP_DISMISSED;
1247 goto unlock;
22753fa5 1248 }
1da177e4 1249
2f8f3ed5 1250 zfcp_erp_action_to_running(erp_action);
1da177e4 1251
287ac01a 1252 /* no lock to allow for blocking operations */
ecf0c772 1253 write_unlock_irqrestore(&adapter->erp_lock, flags);
287ac01a 1254 retval = zfcp_erp_strategy_do_action(erp_action);
ecf0c772 1255 write_lock_irqsave(&adapter->erp_lock, flags);
1da177e4 1256
287ac01a
CS
1257 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
1258 retval = ZFCP_ERP_CONTINUES;
cc8c2829 1259
287ac01a
CS
1260 switch (retval) {
1261 case ZFCP_ERP_NOMEM:
1262 if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {
1263 ++adapter->erp_low_mem_count;
1264 erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
1da177e4 1265 }
287ac01a 1266 if (adapter->erp_total_count == adapter->erp_low_mem_count)
5ffd51a5 1267 _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1", NULL);
287ac01a
CS
1268 else {
1269 zfcp_erp_strategy_memwait(erp_action);
1270 retval = ZFCP_ERP_CONTINUES;
1da177e4 1271 }
287ac01a 1272 goto unlock;
1da177e4 1273
287ac01a
CS
1274 case ZFCP_ERP_CONTINUES:
1275 if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
1276 --adapter->erp_low_mem_count;
1277 erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
1da177e4 1278 }
287ac01a 1279 goto unlock;
1da177e4
LT
1280 }
1281
287ac01a
CS
1282 retval = zfcp_erp_strategy_check_target(erp_action, retval);
1283 zfcp_erp_action_dequeue(erp_action);
1284 retval = zfcp_erp_strategy_statechange(erp_action, retval);
1285 if (retval == ZFCP_ERP_EXIT)
1286 goto unlock;
85600f7f
CS
1287 if (retval == ZFCP_ERP_SUCCEEDED)
1288 zfcp_erp_strategy_followup_success(erp_action);
1289 if (retval == ZFCP_ERP_FAILED)
1290 zfcp_erp_strategy_followup_failed(erp_action);
1da177e4 1291
287ac01a 1292 unlock:
ecf0c772 1293 write_unlock_irqrestore(&adapter->erp_lock, flags);
1da177e4 1294
287ac01a
CS
1295 if (retval != ZFCP_ERP_CONTINUES)
1296 zfcp_erp_action_cleanup(erp_action, retval);
1da177e4 1297
f3450c7b 1298 kref_put(&adapter->ref, zfcp_adapter_release);
1da177e4
LT
1299 return retval;
1300}
1301
287ac01a 1302static int zfcp_erp_thread(void *data)
1da177e4 1303{
287ac01a
CS
1304 struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
1305 struct list_head *next;
1306 struct zfcp_erp_action *act;
1307 unsigned long flags;
94ab4b38 1308
347c6a96 1309 for (;;) {
5771710b 1310 zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf);
347c6a96
CS
1311 wait_event_interruptible(adapter->erp_ready_wq,
1312 !list_empty(&adapter->erp_ready_head) ||
1313 kthread_should_stop());
5771710b 1314 zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf);
94ab4b38 1315
347c6a96
CS
1316 if (kthread_should_stop())
1317 break;
1318
287ac01a
CS
1319 write_lock_irqsave(&adapter->erp_lock, flags);
1320 next = adapter->erp_ready_head.next;
1321 write_unlock_irqrestore(&adapter->erp_lock, flags);
1da177e4 1322
287ac01a
CS
1323 if (next != &adapter->erp_ready_head) {
1324 act = list_entry(next, struct zfcp_erp_action, list);
1da177e4 1325
287ac01a
CS
1326 /* there is more to come after dismission, no notify */
1327 if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
1328 zfcp_erp_wakeup(adapter);
1da177e4 1329 }
1da177e4
LT
1330 }
1331
287ac01a
CS
1332 return 0;
1333}
1da177e4 1334
287ac01a
CS
1335/**
1336 * zfcp_erp_thread_setup - Start ERP thread for adapter
1337 * @adapter: Adapter to start the ERP thread for
1338 *
1339 * Returns 0 on success or error code from kernel_thread()
1340 */
1341int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
1342{
347c6a96 1343 struct task_struct *thread;
1da177e4 1344
347c6a96
CS
1345 thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
1346 dev_name(&adapter->ccw_device->dev));
1347 if (IS_ERR(thread)) {
287ac01a 1348 dev_err(&adapter->ccw_device->dev,
ff3b24fa 1349 "Creating an ERP thread for the FCP device failed.\n");
347c6a96 1350 return PTR_ERR(thread);
1da177e4 1351 }
347c6a96
CS
1352
1353 adapter->erp_thread = thread;
287ac01a
CS
1354 return 0;
1355}
1da177e4 1356
287ac01a
CS
1357/**
1358 * zfcp_erp_thread_kill - Stop ERP thread.
1359 * @adapter: Adapter where the ERP thread should be stopped.
1360 *
1361 * The caller of this routine ensures that the specified adapter has
1362 * been shut down and that this operation has been completed. Thus,
1363 * there are no pending erp_actions which would need to be handled
1364 * here.
1365 */
1366void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
1367{
347c6a96
CS
1368 kthread_stop(adapter->erp_thread);
1369 adapter->erp_thread = NULL;
143bb6bf
CS
1370 WARN_ON(!list_empty(&adapter->erp_ready_head));
1371 WARN_ON(!list_empty(&adapter->erp_running_head));
1da177e4
LT
1372}
1373
287ac01a
CS
1374/**
1375 * zfcp_erp_adapter_failed - Set adapter status to failed.
1376 * @adapter: Failed adapter.
1377 * @id: Event id for debug trace.
1378 * @ref: Reference for debug trace.
1379 */
5ffd51a5 1380void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref)
1da177e4 1381{
287ac01a
CS
1382 zfcp_erp_modify_adapter_status(adapter, id, ref,
1383 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
287ac01a 1384}
1da177e4 1385
287ac01a
CS
1386/**
1387 * zfcp_erp_port_failed - Set port status to failed.
1388 * @port: Failed port.
1389 * @id: Event id for debug trace.
1390 * @ref: Reference for debug trace.
1391 */
5ffd51a5 1392void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref)
287ac01a
CS
1393{
1394 zfcp_erp_modify_port_status(port, id, ref,
1395 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
1da177e4
LT
1396}
1397
1398/**
287ac01a
CS
1399 * zfcp_erp_unit_failed - Set unit status to failed.
1400 * @unit: Failed unit.
1401 * @id: Event id for debug trace.
1402 * @ref: Reference for debug trace.
1da177e4 1403 */
5ffd51a5 1404void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref)
1da177e4 1405{
287ac01a
CS
1406 zfcp_erp_modify_unit_status(unit, id, ref,
1407 ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
1da177e4
LT
1408}
1409
287ac01a
CS
1410/**
1411 * zfcp_erp_wait - wait for completion of error recovery on an adapter
1412 * @adapter: adapter for which to wait for completion of its error recovery
1413 */
1414void zfcp_erp_wait(struct zfcp_adapter *adapter)
1415{
1416 wait_event(adapter->erp_done_wqh,
1417 !(atomic_read(&adapter->status) &
1418 ZFCP_STATUS_ADAPTER_ERP_PENDING));
1419}
1da177e4 1420
287ac01a
CS
1421/**
1422 * zfcp_erp_modify_adapter_status - change adapter status bits
1423 * @adapter: adapter to change the status
1424 * @id: id for the debug trace
1425 * @ref: reference for the debug trace
1426 * @mask: status bits to change
1427 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
1428 *
1429 * Changes in common status bits are propagated to attached ports and units.
1430 */
5ffd51a5 1431void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
287ac01a 1432 void *ref, u32 mask, int set_or_clear)
1da177e4 1433{
1da177e4 1434 struct zfcp_port *port;
ecf0c772 1435 unsigned long flags;
287ac01a 1436 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1da177e4 1437
287ac01a
CS
1438 if (set_or_clear == ZFCP_SET) {
1439 if (status_change_set(mask, &adapter->status))
5771710b 1440 zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
287ac01a
CS
1441 atomic_set_mask(mask, &adapter->status);
1442 } else {
1443 if (status_change_clear(mask, &adapter->status))
5771710b 1444 zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
287ac01a
CS
1445 atomic_clear_mask(mask, &adapter->status);
1446 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
1447 atomic_set(&adapter->erp_counter, 0);
1448 }
1449
ecf0c772
SS
1450 if (common_mask) {
1451 read_lock_irqsave(&adapter->port_list_lock, flags);
1452 list_for_each_entry(port, &adapter->port_list, list)
287ac01a
CS
1453 zfcp_erp_modify_port_status(port, id, ref, common_mask,
1454 set_or_clear);
ecf0c772
SS
1455 read_unlock_irqrestore(&adapter->port_list_lock, flags);
1456 }
1da177e4
LT
1457}
1458
287ac01a
CS
1459/**
1460 * zfcp_erp_modify_port_status - change port status bits
1461 * @port: port to change the status bits
1462 * @id: id for the debug trace
1463 * @ref: reference for the debug trace
1464 * @mask: status bits to change
1465 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
1466 *
1467 * Changes in common status bits are propagated to attached units.
1468 */
5ffd51a5 1469void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
287ac01a 1470 u32 mask, int set_or_clear)
1da177e4 1471{
1da177e4 1472 struct zfcp_unit *unit;
ecf0c772 1473 unsigned long flags;
287ac01a 1474 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1da177e4 1475
287ac01a
CS
1476 if (set_or_clear == ZFCP_SET) {
1477 if (status_change_set(mask, &port->status))
5771710b 1478 zfcp_dbf_rec_port(id, ref, port);
287ac01a
CS
1479 atomic_set_mask(mask, &port->status);
1480 } else {
1481 if (status_change_clear(mask, &port->status))
5771710b 1482 zfcp_dbf_rec_port(id, ref, port);
287ac01a
CS
1483 atomic_clear_mask(mask, &port->status);
1484 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
1485 atomic_set(&port->erp_counter, 0);
1486 }
1da177e4 1487
ecf0c772
SS
1488 if (common_mask) {
1489 read_lock_irqsave(&port->unit_list_lock, flags);
1490 list_for_each_entry(unit, &port->unit_list, list)
287ac01a
CS
1491 zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
1492 set_or_clear);
ecf0c772
SS
1493 read_unlock_irqrestore(&port->unit_list_lock, flags);
1494 }
1da177e4
LT
1495}
1496
287ac01a
CS
1497/**
1498 * zfcp_erp_modify_unit_status - change unit status bits
1499 * @unit: unit to change the status bits
1500 * @id: id for the debug trace
1501 * @ref: reference for the debug trace
1502 * @mask: status bits to change
1503 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
1504 */
5ffd51a5 1505void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
287ac01a 1506 u32 mask, int set_or_clear)
1da177e4 1507{
287ac01a
CS
1508 if (set_or_clear == ZFCP_SET) {
1509 if (status_change_set(mask, &unit->status))
5771710b 1510 zfcp_dbf_rec_unit(id, ref, unit);
287ac01a
CS
1511 atomic_set_mask(mask, &unit->status);
1512 } else {
1513 if (status_change_clear(mask, &unit->status))
5771710b 1514 zfcp_dbf_rec_unit(id, ref, unit);
287ac01a
CS
1515 atomic_clear_mask(mask, &unit->status);
1516 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
1517 atomic_set(&unit->erp_counter, 0);
1518 }
1519 }
1da177e4
LT
1520}
1521
287ac01a
CS
1522/**
1523 * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP
1524 * @port: The "boxed" port.
1525 * @id: The debug trace id.
1526 * @id: Reference for the debug trace.
1527 */
5ffd51a5 1528void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref)
d736a27b 1529{
698ec016
MP
1530 zfcp_erp_modify_port_status(port, id, ref,
1531 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
9467a9b3 1532 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
d736a27b
AH
1533}
1534
287ac01a
CS
1535/**
1536 * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP
1537 * @port: The "boxed" unit.
1538 * @id: The debug trace id.
1539 * @id: Reference for the debug trace.
1540 */
5ffd51a5 1541void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref)
d736a27b 1542{
698ec016
MP
1543 zfcp_erp_modify_unit_status(unit, id, ref,
1544 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
9467a9b3 1545 zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
d736a27b
AH
1546}
1547
287ac01a
CS
1548/**
1549 * zfcp_erp_port_access_denied - Adapter denied access to port.
1550 * @port: port where access has been denied
1551 * @id: id for debug trace
1552 * @ref: reference for debug trace
1553 *
1554 * Since the adapter has denied access, stop using the port and the
1555 * attached units.
1556 */
5ffd51a5 1557void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref)
1da177e4 1558{
698ec016
MP
1559 zfcp_erp_modify_port_status(port, id, ref,
1560 ZFCP_STATUS_COMMON_ERP_FAILED |
1561 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
1da177e4
LT
1562}
1563
287ac01a
CS
1564/**
1565 * zfcp_erp_unit_access_denied - Adapter denied access to unit.
1566 * @unit: unit where access has been denied
1567 * @id: id for debug trace
1568 * @ref: reference for debug trace
1569 *
1570 * Since the adapter has denied access, stop using the unit.
1571 */
5ffd51a5 1572void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref)
1da177e4 1573{
698ec016
MP
1574 zfcp_erp_modify_unit_status(unit, id, ref,
1575 ZFCP_STATUS_COMMON_ERP_FAILED |
1576 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
1da177e4
LT
1577}
1578
5ffd51a5 1579static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id,
287ac01a 1580 void *ref)
1da177e4 1581{
287ac01a
CS
1582 int status = atomic_read(&unit->status);
1583 if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
1584 ZFCP_STATUS_COMMON_ACCESS_BOXED)))
aef4a983
MS
1585 return;
1586
287ac01a 1587 zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
1da177e4
LT
1588}
1589
5ffd51a5 1590static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
287ac01a 1591 void *ref)
1da177e4 1592{
1da177e4 1593 struct zfcp_unit *unit;
ecf0c772 1594 unsigned long flags;
287ac01a 1595 int status = atomic_read(&port->status);
1da177e4 1596
287ac01a
CS
1597 if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
1598 ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
ecf0c772
SS
1599 read_lock_irqsave(&port->unit_list_lock, flags);
1600 list_for_each_entry(unit, &port->unit_list, list)
5ab944f9 1601 zfcp_erp_unit_access_changed(unit, id, ref);
ecf0c772 1602 read_unlock_irqrestore(&port->unit_list_lock, flags);
1da177e4
LT
1603 return;
1604 }
1605
553448f6 1606 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
1da177e4
LT
1607}
1608
287ac01a
CS
1609/**
1610 * zfcp_erp_adapter_access_changed - Process change in adapter ACT
1611 * @adapter: Adapter where the Access Control Table (ACT) changed
1612 * @id: Id for debug trace
1613 * @ref: Reference for debug trace
1614 */
5ffd51a5 1615void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id,
287ac01a 1616 void *ref)
1da177e4 1617{
287ac01a 1618 unsigned long flags;
ecf0c772 1619 struct zfcp_port *port;
287ac01a
CS
1620
1621 if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
1da177e4
LT
1622 return;
1623
ecf0c772
SS
1624 read_lock_irqsave(&adapter->port_list_lock, flags);
1625 list_for_each_entry(port, &adapter->port_list, list)
5ab944f9 1626 zfcp_erp_port_access_changed(port, id, ref);
ecf0c772 1627 read_unlock_irqrestore(&adapter->port_list_lock, flags);
1da177e4 1628}