zfcp_erp.c 45.3 KB
Newer Older
S
Swen Schillig 已提交
1
/*
C
Christof Schmitt 已提交
2
 * zfcp device driver
L
Linus Torvalds 已提交
3
 *
C
Christof Schmitt 已提交
4
 * Error Recovery Procedures (ERP).
S
Swen Schillig 已提交
5
 *
6
 * Copyright IBM Corp. 2002, 2016
L
Linus Torvalds 已提交
7 8
 */

9 10 11
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

12
#include <linux/kthread.h>
L
Linus Torvalds 已提交
13
#include "zfcp_ext.h"
14
#include "zfcp_reqlist.h"
L
Linus Torvalds 已提交
15

16 17 18 19 20 21 22 23
#define ZFCP_MAX_ERPS                   3

enum zfcp_erp_act_flags {
	ZFCP_STATUS_ERP_TIMEDOUT	= 0x10000000,
	ZFCP_STATUS_ERP_CLOSE_ONLY	= 0x01000000,
	ZFCP_STATUS_ERP_DISMISSING	= 0x00100000,
	ZFCP_STATUS_ERP_DISMISSED	= 0x00200000,
	ZFCP_STATUS_ERP_LOWMEM		= 0x00400000,
24
	ZFCP_STATUS_ERP_NO_REF		= 0x00800000,
25
};
L
Linus Torvalds 已提交
26

27 28 29 30 31 32
enum zfcp_erp_steps {
	ZFCP_ERP_STEP_UNINITIALIZED	= 0x0000,
	ZFCP_ERP_STEP_FSF_XCONFIG	= 0x0001,
	ZFCP_ERP_STEP_PHYS_PORT_CLOSING	= 0x0010,
	ZFCP_ERP_STEP_PORT_CLOSING	= 0x0100,
	ZFCP_ERP_STEP_PORT_OPENING	= 0x0800,
33 34
	ZFCP_ERP_STEP_LUN_CLOSING	= 0x1000,
	ZFCP_ERP_STEP_LUN_OPENING	= 0x2000,
35 36 37
};

enum zfcp_erp_act_type {
38
	ZFCP_ERP_ACTION_REOPEN_LUN         = 1,
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
	ZFCP_ERP_ACTION_REOPEN_PORT	   = 2,
	ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
	ZFCP_ERP_ACTION_REOPEN_ADAPTER     = 4,
};

enum zfcp_erp_act_state {
	ZFCP_ERP_ACTION_RUNNING = 1,
	ZFCP_ERP_ACTION_READY   = 2,
};

enum zfcp_erp_act_result {
	ZFCP_ERP_SUCCEEDED = 0,
	ZFCP_ERP_FAILED    = 1,
	ZFCP_ERP_CONTINUES = 2,
	ZFCP_ERP_EXIT      = 3,
	ZFCP_ERP_DISMISSED = 4,
	ZFCP_ERP_NOMEM     = 5,
};

static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
L
Linus Torvalds 已提交
59
{
60 61
	zfcp_erp_clear_adapter_status(adapter,
				       ZFCP_STATUS_COMMON_UNBLOCKED | mask);
62
}
L
Linus Torvalds 已提交
63

64
static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
65
{
66 67 68 69 70 71
	struct zfcp_erp_action *curr_act;

	list_for_each_entry(curr_act, &act->adapter->erp_running_head, list)
		if (act == curr_act)
			return ZFCP_ERP_ACTION_RUNNING;
	return 0;
L
Linus Torvalds 已提交
72 73
}

74
static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
75
{
76 77 78
	struct zfcp_adapter *adapter = act->adapter;

	list_move(&act->list, &act->adapter->erp_ready_head);
79
	zfcp_dbf_rec_run("erardy1", act);
80
	wake_up(&adapter->erp_ready_wq);
81
	zfcp_dbf_rec_run("erardy2", act);
82 83
}

84
static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
85
{
86 87 88 89
	act->status |= ZFCP_STATUS_ERP_DISMISSED;
	if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING)
		zfcp_erp_action_ready(act);
}
L
Linus Torvalds 已提交
90

91
static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev)
92
{
93 94 95 96
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
		zfcp_erp_action_dismiss(&zfcp_sdev->erp_action);
97
}
L
Linus Torvalds 已提交
98

99 100
static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
{
101
	struct scsi_device *sdev;
L
Linus Torvalds 已提交
102

103 104
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
		zfcp_erp_action_dismiss(&port->erp_action);
105 106 107
	else {
		spin_lock(port->adapter->scsi_host->host_lock);
		__shost_for_each_device(sdev, port->adapter->scsi_host)
108 109
			if (sdev_to_zfcp(sdev)->port == port)
				zfcp_erp_action_dismiss_lun(sdev);
110 111
		spin_unlock(port->adapter->scsi_host->host_lock);
	}
L
Linus Torvalds 已提交
112 113
}

114
static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
115
{
116
	struct zfcp_port *port;
L
Linus Torvalds 已提交
117

118 119
	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
		zfcp_erp_action_dismiss(&adapter->erp_action);
120 121 122
	else {
		read_lock(&adapter->port_list_lock);
		list_for_each_entry(port, &adapter->port_list, list)
123
		    zfcp_erp_action_dismiss_port(port);
124 125
		read_unlock(&adapter->port_list_lock);
	}
L
Linus Torvalds 已提交
126 127
}

128 129
static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
				 struct zfcp_port *port,
130
				 struct scsi_device *sdev)
L
Linus Torvalds 已提交
131
{
132
	int need = want;
133 134
	int l_status, p_status, a_status;
	struct zfcp_scsi_dev *zfcp_sdev;
L
Linus Torvalds 已提交
135

136
	switch (want) {
137 138 139 140
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		zfcp_sdev = sdev_to_zfcp(sdev);
		l_status = atomic_read(&zfcp_sdev->status);
		if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE)
141 142 143 144 145 146 147 148 149
			return 0;
		p_status = atomic_read(&port->status);
		if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
		      p_status & ZFCP_STATUS_COMMON_ERP_FAILED)
			return 0;
		if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED))
			need = ZFCP_ERP_ACTION_REOPEN_PORT;
		/* fall through */
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
150 151 152 153 154
		p_status = atomic_read(&port->status);
		if (!(p_status & ZFCP_STATUS_COMMON_OPEN))
			need = ZFCP_ERP_ACTION_REOPEN_PORT;
		/* fall through */
	case ZFCP_ERP_ACTION_REOPEN_PORT:
155 156 157 158 159 160 161
		p_status = atomic_read(&port->status);
		if (p_status & ZFCP_STATUS_COMMON_ERP_INUSE)
			return 0;
		a_status = atomic_read(&adapter->status);
		if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
		      a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
			return 0;
162 163
		if (p_status & ZFCP_STATUS_COMMON_NOESC)
			return need;
164 165 166 167 168 169 170
		if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED))
			need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
		/* fall through */
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		a_status = atomic_read(&adapter->status);
		if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE)
			return 0;
171 172 173
		if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) &&
		    !(a_status & ZFCP_STATUS_COMMON_OPEN))
			return 0; /* shutdown requested for closed adapter */
174
	}
L
Linus Torvalds 已提交
175

176
	return need;
L
Linus Torvalds 已提交
177 178
}

179
static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
180 181
						  struct zfcp_adapter *adapter,
						  struct zfcp_port *port,
182
						  struct scsi_device *sdev)
L
Linus Torvalds 已提交
183
{
184
	struct zfcp_erp_action *erp_action;
185
	struct zfcp_scsi_dev *zfcp_sdev;
L
Linus Torvalds 已提交
186

187
	switch (need) {
188 189
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		zfcp_sdev = sdev_to_zfcp(sdev);
190
		if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
191
			if (scsi_device_get(sdev))
192
				return NULL;
193
		atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE,
194 195
				&zfcp_sdev->status);
		erp_action = &zfcp_sdev->erp_action;
196 197 198
		memset(erp_action, 0, sizeof(struct zfcp_erp_action));
		erp_action->port = port;
		erp_action->sdev = sdev;
199 200
		if (!(atomic_read(&zfcp_sdev->status) &
		      ZFCP_STATUS_COMMON_RUNNING))
201
			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
202
		break;
L
Linus Torvalds 已提交
203

204 205
	case ZFCP_ERP_ACTION_REOPEN_PORT:
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
206
		if (!get_device(&port->dev))
207
			return NULL;
208
		zfcp_erp_action_dismiss_port(port);
209
		atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
210
		erp_action = &port->erp_action;
211 212
		memset(erp_action, 0, sizeof(struct zfcp_erp_action));
		erp_action->port = port;
213
		if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
214
			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
215
		break;
L
Linus Torvalds 已提交
216

217
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
218
		kref_get(&adapter->ref);
219
		zfcp_erp_action_dismiss_adapter(adapter);
220
		atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
221
		erp_action = &adapter->erp_action;
222
		memset(erp_action, 0, sizeof(struct zfcp_erp_action));
223 224
		if (!(atomic_read(&adapter->status) &
		      ZFCP_STATUS_COMMON_RUNNING))
225
			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
226 227 228 229 230
		break;

	default:
		return NULL;
	}
L
Linus Torvalds 已提交
231

232 233
	erp_action->adapter = adapter;
	erp_action->action = need;
234
	erp_action->status = act_status;
L
Linus Torvalds 已提交
235

236
	return erp_action;
L
Linus Torvalds 已提交
237 238
}

239 240
static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
				   struct zfcp_port *port,
241
				   struct scsi_device *sdev,
242
				   char *id, u32 act_status)
L
Linus Torvalds 已提交
243
{
244
	int retval = 1, need;
245
	struct zfcp_erp_action *act;
L
Linus Torvalds 已提交
246

247
	if (!adapter->erp_thread)
248
		return -EIO;
L
Linus Torvalds 已提交
249

250
	need = zfcp_erp_required_act(want, adapter, port, sdev);
251
	if (!need)
L
Linus Torvalds 已提交
252 253
		goto out;

254
	act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
255 256
	if (!act)
		goto out;
257
	atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
258 259
	++adapter->erp_total_count;
	list_add_tail(&act->list, &adapter->erp_ready_head);
260
	wake_up(&adapter->erp_ready_wq);
261
	retval = 0;
L
Linus Torvalds 已提交
262
 out:
263
	zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need);
L
Linus Torvalds 已提交
264 265 266
	return retval;
}

267
static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
268
				    int clear_mask, char *id)
269 270
{
	zfcp_erp_adapter_block(adapter, clear_mask);
271
	zfcp_scsi_schedule_rports_block(adapter);
272 273 274

	/* ensure propagation of failed status to new devices */
	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
275 276
		zfcp_erp_set_adapter_status(adapter,
					    ZFCP_STATUS_COMMON_ERP_FAILED);
277 278 279
		return -EIO;
	}
	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
280
				       adapter, NULL, NULL, id, 0);
281 282 283 284 285 286 287
}

/**
 * zfcp_erp_adapter_reopen - Reopen adapter.
 * @adapter: Adapter to reopen.
 * @clear: Status flags to clear.
 * @id: Id for debug trace event.
L
Linus Torvalds 已提交
288
 */
289
void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id)
L
Linus Torvalds 已提交
290 291 292
{
	unsigned long flags;

293 294 295 296 297
	zfcp_erp_adapter_block(adapter, clear);
	zfcp_scsi_schedule_rports_block(adapter);

	write_lock_irqsave(&adapter->erp_lock, flags);
	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
298 299
		zfcp_erp_set_adapter_status(adapter,
					    ZFCP_STATUS_COMMON_ERP_FAILED);
300 301
	else
		zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
302
					NULL, NULL, id, 0);
303
	write_unlock_irqrestore(&adapter->erp_lock, flags);
304
}
L
Linus Torvalds 已提交
305

306 307 308 309 310 311 312
/**
 * zfcp_erp_adapter_shutdown - Shutdown adapter.
 * @adapter: Adapter to shut down.
 * @clear: Status flags to clear.
 * @id: Id for debug trace event.
 */
void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear,
313
			       char *id)
314 315
{
	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
316
	zfcp_erp_adapter_reopen(adapter, clear | flags, id);
L
Linus Torvalds 已提交
317 318
}

319 320 321 322 323
/**
 * zfcp_erp_port_shutdown - Shutdown port
 * @port: Port to shut down.
 * @clear: Status flags to clear.
 * @id: Id for debug trace event.
L
Linus Torvalds 已提交
324
 */
325
void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id)
L
Linus Torvalds 已提交
326
{
327
	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
328
	zfcp_erp_port_reopen(port, clear | flags, id);
329 330 331 332
}

static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
{
333 334
	zfcp_erp_clear_port_status(port,
				    ZFCP_STATUS_COMMON_UNBLOCKED | clear);
335 336
}

337 338
static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear,
					 char *id)
339 340
{
	zfcp_erp_port_block(port, clear);
341
	zfcp_scsi_schedule_rport_block(port);
342 343 344

	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
		return;
L
Linus Torvalds 已提交
345

346
	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
347
				port->adapter, port, NULL, id, 0);
348 349 350 351 352
}

/**
 * zfcp_erp_port_forced_reopen - Forced close of port and open again
 * @port: Port to force close and to reopen.
353
 * @clear: Status flags to clear.
354 355
 * @id: Id for debug trace event.
 */
356
void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id)
357 358 359 360
{
	unsigned long flags;
	struct zfcp_adapter *adapter = port->adapter;

361
	write_lock_irqsave(&adapter->erp_lock, flags);
362
	_zfcp_erp_port_forced_reopen(port, clear, id);
363
	write_unlock_irqrestore(&adapter->erp_lock, flags);
364 365
}

366
static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
367 368
{
	zfcp_erp_port_block(port, clear);
369
	zfcp_scsi_schedule_rport_block(port);
L
Linus Torvalds 已提交
370

371
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
L
Linus Torvalds 已提交
372
		/* ensure propagation of failed status to new devices */
373
		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
374
		return -EIO;
L
Linus Torvalds 已提交
375 376
	}

377
	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
378
				       port->adapter, port, NULL, id, 0);
L
Linus Torvalds 已提交
379 380 381
}

/**
382 383 384
 * zfcp_erp_port_reopen - trigger remote port recovery
 * @port: port to recover
 * @clear_mask: flags in port status to be cleared
385
 * @id: Id for debug trace event.
L
Linus Torvalds 已提交
386
 *
387
 * Returns 0 if recovery has been triggered, < 0 if not.
L
Linus Torvalds 已提交
388
 */
389
int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
L
Linus Torvalds 已提交
390
{
391
	int retval;
392
	unsigned long flags;
L
Linus Torvalds 已提交
393 394
	struct zfcp_adapter *adapter = port->adapter;

395
	write_lock_irqsave(&adapter->erp_lock, flags);
396
	retval = _zfcp_erp_port_reopen(port, clear, id);
397
	write_unlock_irqrestore(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
398 399 400 401

	return retval;
}

402
static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask)
403
{
404 405
	zfcp_erp_clear_lun_status(sdev,
				  ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask);
406 407
}

408
static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
409
				 u32 act_status)
L
Linus Torvalds 已提交
410
{
411 412
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
L
Linus Torvalds 已提交
413

414
	zfcp_erp_lun_block(sdev, clear);
L
Linus Torvalds 已提交
415

416
	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
417
		return;
L
Linus Torvalds 已提交
418

419
	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
420
				zfcp_sdev->port, sdev, id, act_status);
L
Linus Torvalds 已提交
421 422 423
}

/**
424 425 426
 * zfcp_erp_lun_reopen - initiate reopen of a LUN
 * @sdev: SCSI device / LUN to be reopened
 * @clear_mask: specifies flags in LUN status to be cleared
427 428
 * @id: Id for debug trace event.
 *
L
Linus Torvalds 已提交
429 430
 * Return: 0 on success, < 0 on error
 */
431
void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id)
L
Linus Torvalds 已提交
432 433
{
	unsigned long flags;
434 435
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
	struct zfcp_port *port = zfcp_sdev->port;
436
	struct zfcp_adapter *adapter = port->adapter;
L
Linus Torvalds 已提交
437

438
	write_lock_irqsave(&adapter->erp_lock, flags);
439
	_zfcp_erp_lun_reopen(sdev, clear, id, 0);
440 441 442 443
	write_unlock_irqrestore(&adapter->erp_lock, flags);
}

/**
444 445
 * zfcp_erp_lun_shutdown - Shutdown LUN
 * @sdev: SCSI device / LUN to shut down.
446 447 448
 * @clear: Status flags to clear.
 * @id: Id for debug trace event.
 */
449
void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id)
450 451
{
	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
452
	zfcp_erp_lun_reopen(sdev, clear | flags, id);
453 454 455
}

/**
456 457
 * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion
 * @sdev: SCSI device / LUN to shut down.
458 459
 * @id: Id for debug trace event.
 *
460
 * Do not acquire a reference for the LUN when creating the ERP
461
 * action. It is safe, because this function waits for the ERP to
462 463
 * complete first. This allows to shutdown the LUN, even when the SCSI
 * device is in the state SDEV_DEL when scsi_device_get will fail.
464
 */
465
void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id)
466 467
{
	unsigned long flags;
468 469
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
	struct zfcp_port *port = zfcp_sdev->port;
470 471 472 473
	struct zfcp_adapter *adapter = port->adapter;
	int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;

	write_lock_irqsave(&adapter->erp_lock, flags);
474
	_zfcp_erp_lun_reopen(sdev, clear, id, ZFCP_STATUS_ERP_NO_REF);
475
	write_unlock_irqrestore(&adapter->erp_lock, flags);
476 477

	zfcp_erp_wait(adapter);
L
Linus Torvalds 已提交
478 479
}

480
static int status_change_set(unsigned long mask, atomic_t *status)
L
Linus Torvalds 已提交
481
{
482
	return (atomic_read(status) ^ mask) & mask;
L
Linus Torvalds 已提交
483 484
}

485
static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
486
{
487
	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
488
		zfcp_dbf_rec_run("eraubl1", &adapter->erp_action);
489
	atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
490 491
}

492
static void zfcp_erp_port_unblock(struct zfcp_port *port)
L
Linus Torvalds 已提交
493
{
494
	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
495
		zfcp_dbf_rec_run("erpubl1", &port->erp_action);
496
	atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
L
Linus Torvalds 已提交
497 498
}

499
static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
L
Linus Torvalds 已提交
500
{
501 502 503
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
504
		zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action);
505
	atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
L
Linus Torvalds 已提交
506 507
}

508
static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
509
{
510
	list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
511
	zfcp_dbf_rec_run("erator1", erp_action);
L
Linus Torvalds 已提交
512 513
}

514
static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
515
{
516
	struct zfcp_adapter *adapter = act->adapter;
517
	struct zfcp_fsf_req *req;
L
Linus Torvalds 已提交
518

519
	if (!act->fsf_req_id)
520
		return;
L
Linus Torvalds 已提交
521

522 523
	spin_lock(&adapter->req_list->lock);
	req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id);
524
	if (req && req->erp_action == act) {
525 526
		if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
				   ZFCP_STATUS_ERP_TIMEDOUT)) {
527
			req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
528
			zfcp_dbf_rec_run("erscf_1", act);
529
			req->erp_action = NULL;
L
Linus Torvalds 已提交
530
		}
531
		if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
532
			zfcp_dbf_rec_run("erscf_2", act);
533 534
		if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
			act->fsf_req_id = 0;
535
	} else
536
		act->fsf_req_id = 0;
537
	spin_unlock(&adapter->req_list->lock);
L
Linus Torvalds 已提交
538 539
}

540 541 542 543
/**
 * zfcp_erp_notify - Trigger ERP action.
 * @erp_action: ERP action to continue.
 * @set_mask: ERP action status flags to set.
L
Linus Torvalds 已提交
544
 */
545
void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask)
L
Linus Torvalds 已提交
546 547
{
	struct zfcp_adapter *adapter = erp_action->adapter;
548
	unsigned long flags;
L
Linus Torvalds 已提交
549

550
	write_lock_irqsave(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
551 552 553 554 555 556 557
	if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
		erp_action->status |= set_mask;
		zfcp_erp_action_ready(erp_action);
	}
	write_unlock_irqrestore(&adapter->erp_lock, flags);
}

558 559 560
/**
 * zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request
 * @data: ERP action (from timer data)
L
Linus Torvalds 已提交
561
 */
562
void zfcp_erp_timeout_handler(unsigned long data)
L
Linus Torvalds 已提交
563
{
564 565
	struct zfcp_erp_action *act = (struct zfcp_erp_action *) data;
	zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT);
L
Linus Torvalds 已提交
566 567
}

568
static void zfcp_erp_memwait_handler(unsigned long data)
L
Linus Torvalds 已提交
569
{
570
	zfcp_erp_notify((struct zfcp_erp_action *)data, 0);
L
Linus Torvalds 已提交
571 572
}

573
static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
574
{
575 576 577 578 579
	init_timer(&erp_action->timer);
	erp_action->timer.function = zfcp_erp_memwait_handler;
	erp_action->timer.data = (unsigned long) erp_action;
	erp_action->timer.expires = jiffies + HZ;
	add_timer(&erp_action->timer);
L
Linus Torvalds 已提交
580 581
}

582
static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
583
				      int clear, char *id)
L
Linus Torvalds 已提交
584
{
585
	struct zfcp_port *port;
L
Linus Torvalds 已提交
586

587 588
	read_lock(&adapter->port_list_lock);
	list_for_each_entry(port, &adapter->port_list, list)
589
		_zfcp_erp_port_reopen(port, clear, id);
590
	read_unlock(&adapter->port_list_lock);
L
Linus Torvalds 已提交
591 592
}

593
static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
594
				     char *id)
L
Linus Torvalds 已提交
595
{
596
	struct scsi_device *sdev;
L
Linus Torvalds 已提交
597

598 599
	spin_lock(port->adapter->scsi_host->host_lock);
	__shost_for_each_device(sdev, port->adapter->scsi_host)
600
		if (sdev_to_zfcp(sdev)->port == port)
601
			_zfcp_erp_lun_reopen(sdev, clear, id, 0);
602
	spin_unlock(port->adapter->scsi_host->host_lock);
L
Linus Torvalds 已提交
603 604
}

605
static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
606
{
607 608
	switch (act->action) {
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
609
		_zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1");
610 611
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
612
		_zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2");
613 614
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT:
615
		_zfcp_erp_port_reopen(act->port, 0, "ersff_3");
616
		break;
617
	case ZFCP_ERP_ACTION_REOPEN_LUN:
618
		_zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", 0);
619 620 621 622 623 624 625 626
		break;
	}
}

static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act)
{
	switch (act->action) {
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
627
		_zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1");
628 629
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
630
		_zfcp_erp_port_reopen(act->port, 0, "ersfs_2");
631 632
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT:
633
		_zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3");
634
		break;
L
Linus Torvalds 已提交
635 636 637
	}
}

638
static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
639 640 641
{
	unsigned long flags;

642
	read_lock_irqsave(&adapter->erp_lock, flags);
643 644
	if (list_empty(&adapter->erp_ready_head) &&
	    list_empty(&adapter->erp_running_head)) {
645
			atomic_andnot(ZFCP_STATUS_ADAPTER_ERP_PENDING,
646 647
					  &adapter->status);
			wake_up(&adapter->erp_done_wqh);
L
Linus Torvalds 已提交
648
	}
649
	read_unlock_irqrestore(&adapter->erp_lock, flags);
650
}
L
Linus Torvalds 已提交
651

652 653 654 655 656 657 658
static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter)
{
	struct zfcp_port *port;
	port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0,
				 adapter->peer_d_id);
	if (IS_ERR(port)) /* error or port already attached */
		return;
659
	_zfcp_erp_port_reopen(port, 0, "ereptp1");
660
}
L
Linus Torvalds 已提交
661

662 663 664 665 666
static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
{
	int retries;
	int sleep = 1;
	struct zfcp_adapter *adapter = erp_action->adapter;
L
Linus Torvalds 已提交
667

668
	atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
669 670

	for (retries = 7; retries; retries--) {
671
		atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
672 673 674 675 676
				  &adapter->status);
		write_lock_irq(&adapter->erp_lock);
		zfcp_erp_action_to_running(erp_action);
		write_unlock_irq(&adapter->erp_lock);
		if (zfcp_fsf_exchange_config_data(erp_action)) {
677
			atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
678 679
					  &adapter->status);
			return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
680 681
		}

682 683
		wait_event(adapter->erp_ready_wq,
			   !list_empty(&adapter->erp_ready_head));
684 685
		if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
			break;
L
Linus Torvalds 已提交
686

687 688 689
		if (!(atomic_read(&adapter->status) &
		      ZFCP_STATUS_ADAPTER_HOST_CON_INIT))
			break;
L
Linus Torvalds 已提交
690

691 692
		ssleep(sleep);
		sleep *= 2;
L
Linus Torvalds 已提交
693 694
	}

695
	atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
696
			  &adapter->status);
L
Linus Torvalds 已提交
697

698 699
	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK))
		return ZFCP_ERP_FAILED;
S
Swen Schillig 已提交
700

701 702
	if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
		zfcp_erp_enqueue_ptp_port(adapter);
L
Linus Torvalds 已提交
703

704
	return ZFCP_ERP_SUCCEEDED;
L
Linus Torvalds 已提交
705 706
}

707
static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
708
{
709 710
	int ret;
	struct zfcp_adapter *adapter = act->adapter;
L
Linus Torvalds 已提交
711

712 713 714 715 716 717 718 719 720 721
	write_lock_irq(&adapter->erp_lock);
	zfcp_erp_action_to_running(act);
	write_unlock_irq(&adapter->erp_lock);

	ret = zfcp_fsf_exchange_port_data(act);
	if (ret == -EOPNOTSUPP)
		return ZFCP_ERP_SUCCEEDED;
	if (ret)
		return ZFCP_ERP_FAILED;

722
	zfcp_dbf_rec_run("erasox1", act);
723 724
	wait_event(adapter->erp_ready_wq,
		   !list_empty(&adapter->erp_ready_head));
725
	zfcp_dbf_rec_run("erasox2", act);
726 727 728 729
	if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
		return ZFCP_ERP_FAILED;

	return ZFCP_ERP_SUCCEEDED;
L
Linus Torvalds 已提交
730 731
}

732
static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
733
{
734 735
	if (zfcp_erp_adapter_strat_fsf_xconf(act) == ZFCP_ERP_FAILED)
		return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
736

737 738
	if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
		return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
739

740
	if (mempool_resize(act->adapter->pool.sr_data,
741
			   act->adapter->stat_read_buf_num))
742 743 744
		return ZFCP_ERP_FAILED;

	if (mempool_resize(act->adapter->pool.status_read_req,
745
			   act->adapter->stat_read_buf_num))
746 747
		return ZFCP_ERP_FAILED;

748
	atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
749 750
	if (zfcp_status_read_refill(act->adapter))
		return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
751

752 753
	return ZFCP_ERP_SUCCEEDED;
}
L
Linus Torvalds 已提交
754

755
static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
756 757
{
	struct zfcp_adapter *adapter = act->adapter;
L
Linus Torvalds 已提交
758

759
	/* close queues to ensure that buffers are not accessed by adapter */
760
	zfcp_qdio_close(adapter->qdio);
761 762
	zfcp_fsf_req_dismiss_all(adapter);
	adapter->fsf_req_seq_no = 0;
763
	zfcp_fc_wka_ports_force_offline(adapter->gs);
764
	/* all ports and LUNs are closed */
765
	zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN);
766

767
	atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
768
			  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
L
Linus Torvalds 已提交
769 770
}

771
static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
772
{
773
	struct zfcp_adapter *adapter = act->adapter;
L
Linus Torvalds 已提交
774

775
	if (zfcp_qdio_open(adapter->qdio)) {
776
		atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
777 778 779 780
				  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
				  &adapter->status);
		return ZFCP_ERP_FAILED;
	}
781

782 783 784 785 786
	if (zfcp_erp_adapter_strategy_open_fsf(act)) {
		zfcp_erp_adapter_strategy_close(act);
		return ZFCP_ERP_FAILED;
	}

787
	atomic_or(ZFCP_STATUS_COMMON_OPEN, &adapter->status);
788 789 790

	return ZFCP_ERP_SUCCEEDED;
}
791

792 793 794 795 796 797 798 799 800 801 802
static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act)
{
	struct zfcp_adapter *adapter = act->adapter;

	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN) {
		zfcp_erp_adapter_strategy_close(act);
		if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
			return ZFCP_ERP_EXIT;
	}

	if (zfcp_erp_adapter_strategy_open(act)) {
803
		ssleep(8);
804 805
		return ZFCP_ERP_FAILED;
	}
L
Linus Torvalds 已提交
806

807
	return ZFCP_ERP_SUCCEEDED;
L
Linus Torvalds 已提交
808 809
}

810
static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
811
{
812 813 814 815 816 817 818 819 820 821
	int retval;

	retval = zfcp_fsf_close_physical_port(act);
	if (retval == -ENOMEM)
		return ZFCP_ERP_NOMEM;
	act->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
	if (retval)
		return ZFCP_ERP_FAILED;

	return ZFCP_ERP_CONTINUES;
L
Linus Torvalds 已提交
822 823
}

824 825 826 827 828 829 830 831 832 833 834 835 836 837
static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
{
	struct zfcp_port *port = erp_action->port;
	int status = atomic_read(&port->status);

	switch (erp_action->step) {
	case ZFCP_ERP_STEP_UNINITIALIZED:
		if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
		    (status & ZFCP_STATUS_COMMON_OPEN))
			return zfcp_erp_port_forced_strategy_close(erp_action);
		else
			return ZFCP_ERP_FAILED;

	case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
838
		if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN))
839 840 841
			return ZFCP_ERP_SUCCEEDED;
	}
	return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
842 843
}

844
static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
845
{
846
	int retval;
L
Linus Torvalds 已提交
847

848 849 850 851 852 853 854
	retval = zfcp_fsf_close_port(erp_action);
	if (retval == -ENOMEM)
		return ZFCP_ERP_NOMEM;
	erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
	if (retval)
		return ZFCP_ERP_FAILED;
	return ZFCP_ERP_CONTINUES;
L
Linus Torvalds 已提交
855 856
}

857
static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
858
{
859
	int retval;
L
Linus Torvalds 已提交
860

861 862 863 864 865 866 867 868
	retval = zfcp_fsf_open_port(erp_action);
	if (retval == -ENOMEM)
		return ZFCP_ERP_NOMEM;
	erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
	if (retval)
		return ZFCP_ERP_FAILED;
	return ZFCP_ERP_CONTINUES;
}
L
Linus Torvalds 已提交
869

870
static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
871
{
872 873
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
L
Linus Torvalds 已提交
874

875
	if (port->wwpn != adapter->peer_wwpn) {
876
		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
		return ZFCP_ERP_FAILED;
	}
	port->d_id = adapter->peer_d_id;
	return zfcp_erp_port_strategy_open_port(act);
}

static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
{
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
	int p_status = atomic_read(&port->status);

	switch (act->step) {
	case ZFCP_ERP_STEP_UNINITIALIZED:
	case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
	case ZFCP_ERP_STEP_PORT_CLOSING:
		if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
			return zfcp_erp_open_ptp_port(act);
895
		if (!port->d_id) {
896
			zfcp_fc_trigger_did_lookup(port);
897
			return ZFCP_ERP_EXIT;
898 899 900 901 902
		}
		return zfcp_erp_port_strategy_open_port(act);

	case ZFCP_ERP_STEP_PORT_OPENING:
		/* D_ID might have changed during open */
903
		if (p_status & ZFCP_STATUS_COMMON_OPEN) {
904 905 906
			if (!port->d_id) {
				zfcp_fc_trigger_did_lookup(port);
				return ZFCP_ERP_EXIT;
907
			}
908
			return ZFCP_ERP_SUCCEEDED;
909
		}
910 911
		if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) {
			port->d_id = 0;
912
			return ZFCP_ERP_FAILED;
913 914
		}
		/* fall through otherwise */
915 916 917 918 919 920 921
	}
	return ZFCP_ERP_FAILED;
}

static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
{
	struct zfcp_port *port = erp_action->port;
922
	int p_status = atomic_read(&port->status);
923

924 925
	if ((p_status & ZFCP_STATUS_COMMON_NOESC) &&
	    !(p_status & ZFCP_STATUS_COMMON_OPEN))
926 927
		goto close_init_done;

928 929
	switch (erp_action->step) {
	case ZFCP_ERP_STEP_UNINITIALIZED:
930
		if (p_status & ZFCP_STATUS_COMMON_OPEN)
931
			return zfcp_erp_port_strategy_close(erp_action);
L
Linus Torvalds 已提交
932 933
		break;

934
	case ZFCP_ERP_STEP_PORT_CLOSING:
935
		if (p_status & ZFCP_STATUS_COMMON_OPEN)
936
			return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
937 938
		break;
	}
939 940

close_init_done:
941 942
	if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
		return ZFCP_ERP_EXIT;
L
Linus Torvalds 已提交
943

944
	return zfcp_erp_port_strategy_open_common(erp_action);
945 946
}

947
static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev)
948
{
949 950
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

951
	atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_DENIED,
952
			  &zfcp_sdev->status);
953 954
}

955
static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action)
956
{
957
	int retval = zfcp_fsf_close_lun(erp_action);
958 959
	if (retval == -ENOMEM)
		return ZFCP_ERP_NOMEM;
960
	erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING;
961 962 963 964 965
	if (retval)
		return ZFCP_ERP_FAILED;
	return ZFCP_ERP_CONTINUES;
}

966
static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action)
967
{
968
	int retval = zfcp_fsf_open_lun(erp_action);
969 970
	if (retval == -ENOMEM)
		return ZFCP_ERP_NOMEM;
971
	erp_action->step = ZFCP_ERP_STEP_LUN_OPENING;
972 973 974
	if (retval)
		return  ZFCP_ERP_FAILED;
	return ZFCP_ERP_CONTINUES;
L
Linus Torvalds 已提交
975 976
}

977
static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
978
{
979 980
	struct scsi_device *sdev = erp_action->sdev;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
981 982 983

	switch (erp_action->step) {
	case ZFCP_ERP_STEP_UNINITIALIZED:
984 985 986
		zfcp_erp_lun_strategy_clearstati(sdev);
		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
			return zfcp_erp_lun_strategy_close(erp_action);
987
		/* already closed, fall through */
988 989
	case ZFCP_ERP_STEP_LUN_CLOSING:
		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
990 991 992
			return ZFCP_ERP_FAILED;
		if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
			return ZFCP_ERP_EXIT;
993
		return zfcp_erp_lun_strategy_open(erp_action);
994

995 996
	case ZFCP_ERP_STEP_LUN_OPENING:
		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
997 998 999
			return ZFCP_ERP_SUCCEEDED;
	}
	return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
1000 1001
}

1002
static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result)
L
Linus Torvalds 已提交
1003
{
1004 1005
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

L
Linus Torvalds 已提交
1006 1007
	switch (result) {
	case ZFCP_ERP_SUCCEEDED :
1008 1009
		atomic_set(&zfcp_sdev->erp_counter, 0);
		zfcp_erp_lun_unblock(sdev);
L
Linus Torvalds 已提交
1010 1011
		break;
	case ZFCP_ERP_FAILED :
1012 1013 1014 1015
		atomic_inc(&zfcp_sdev->erp_counter);
		if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) {
			dev_err(&zfcp_sdev->port->adapter->ccw_device->dev,
				"ERP failed for LUN 0x%016Lx on "
1016
				"port 0x%016Lx\n",
1017 1018
				(unsigned long long)zfcp_scsi_dev_lun(sdev),
				(unsigned long long)zfcp_sdev->port->wwpn);
1019 1020
			zfcp_erp_set_lun_status(sdev,
						ZFCP_STATUS_COMMON_ERP_FAILED);
1021
		}
L
Linus Torvalds 已提交
1022 1023 1024
		break;
	}

1025 1026
	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
		zfcp_erp_lun_block(sdev, 0);
L
Linus Torvalds 已提交
1027 1028 1029 1030 1031
		result = ZFCP_ERP_EXIT;
	}
	return result;
}

1032
static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
L
Linus Torvalds 已提交
1033 1034 1035 1036 1037 1038
{
	switch (result) {
	case ZFCP_ERP_SUCCEEDED :
		atomic_set(&port->erp_counter, 0);
		zfcp_erp_port_unblock(port);
		break;
1039

L
Linus Torvalds 已提交
1040
	case ZFCP_ERP_FAILED :
1041
		if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) {
1042 1043 1044
			zfcp_erp_port_block(port, 0);
			result = ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1045
		atomic_inc(&port->erp_counter);
1046 1047 1048
		if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
			dev_err(&port->adapter->ccw_device->dev,
				"ERP failed for remote port 0x%016Lx\n",
1049
				(unsigned long long)port->wwpn);
1050 1051
			zfcp_erp_set_port_status(port,
					 ZFCP_STATUS_COMMON_ERP_FAILED);
1052
		}
L
Linus Torvalds 已提交
1053 1054 1055
		break;
	}

1056 1057
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
		zfcp_erp_port_block(port, 0);
L
Linus Torvalds 已提交
1058 1059 1060 1061 1062
		result = ZFCP_ERP_EXIT;
	}
	return result;
}

1063 1064
static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
					   int result)
L
Linus Torvalds 已提交
1065 1066 1067 1068 1069 1070
{
	switch (result) {
	case ZFCP_ERP_SUCCEEDED :
		atomic_set(&adapter->erp_counter, 0);
		zfcp_erp_adapter_unblock(adapter);
		break;
1071

L
Linus Torvalds 已提交
1072 1073
	case ZFCP_ERP_FAILED :
		atomic_inc(&adapter->erp_counter);
1074 1075 1076 1077
		if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
			dev_err(&adapter->ccw_device->dev,
				"ERP cannot recover an error "
				"on the FCP device\n");
1078 1079
			zfcp_erp_set_adapter_status(adapter,
					    ZFCP_STATUS_COMMON_ERP_FAILED);
1080
		}
L
Linus Torvalds 已提交
1081 1082 1083
		break;
	}

1084 1085
	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
		zfcp_erp_adapter_block(adapter, 0);
L
Linus Torvalds 已提交
1086 1087 1088 1089 1090
		result = ZFCP_ERP_EXIT;
	}
	return result;
}

1091 1092
static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action,
					  int result)
1093
{
1094 1095
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_port *port = erp_action->port;
1096
	struct scsi_device *sdev = erp_action->sdev;
1097 1098 1099

	switch (erp_action->action) {

1100 1101
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		result = zfcp_erp_strategy_check_lun(sdev, result);
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
		break;

	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
	case ZFCP_ERP_ACTION_REOPEN_PORT:
		result = zfcp_erp_strategy_check_port(port, result);
		break;

	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		result = zfcp_erp_strategy_check_adapter(adapter, result);
		break;
	}
	return result;
1114 1115
}

1116
static int zfcp_erp_strat_change_det(atomic_t *target_status, u32 erp_status)
1117
{
1118
	int status = atomic_read(target_status);
1119

1120 1121 1122
	if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
	    (erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
		return 1; /* take it online */
1123

1124 1125 1126 1127 1128
	if (!(status & ZFCP_STATUS_COMMON_RUNNING) &&
	    !(erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
		return 1; /* take it offline */

	return 0;
1129 1130
}

1131
static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
L
Linus Torvalds 已提交
1132
{
1133 1134 1135
	int action = act->action;
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
1136 1137
	struct scsi_device *sdev = act->sdev;
	struct zfcp_scsi_dev *zfcp_sdev;
1138
	u32 erp_status = act->status;
L
Linus Torvalds 已提交
1139

1140
	switch (action) {
L
Linus Torvalds 已提交
1141
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1142 1143 1144
		if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) {
			_zfcp_erp_adapter_reopen(adapter,
						 ZFCP_STATUS_COMMON_ERP_FAILED,
1145
						 "ersscg1");
1146 1147
			return ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1148 1149 1150 1151
		break;

	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
	case ZFCP_ERP_ACTION_REOPEN_PORT:
1152 1153 1154
		if (zfcp_erp_strat_change_det(&port->status, erp_status)) {
			_zfcp_erp_port_reopen(port,
					      ZFCP_STATUS_COMMON_ERP_FAILED,
1155
					      "ersscg2");
1156 1157
			return ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1158 1159
		break;

1160 1161 1162 1163 1164
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		zfcp_sdev = sdev_to_zfcp(sdev);
		if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) {
			_zfcp_erp_lun_reopen(sdev,
					     ZFCP_STATUS_COMMON_ERP_FAILED,
1165
					     "ersscg3", 0);
1166 1167
			return ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1168 1169
		break;
	}
1170
	return ret;
L
Linus Torvalds 已提交
1171 1172
}

1173
static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1174
{
1175
	struct zfcp_adapter *adapter = erp_action->adapter;
1176
	struct zfcp_scsi_dev *zfcp_sdev;
L
Linus Torvalds 已提交
1177

1178 1179 1180 1181
	adapter->erp_total_count--;
	if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
		adapter->erp_low_mem_count--;
		erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
1182
	}
L
Linus Torvalds 已提交
1183

1184
	list_del(&erp_action->list);
1185
	zfcp_dbf_rec_run("eractd1", erp_action);
L
Linus Torvalds 已提交
1186

1187
	switch (erp_action->action) {
1188 1189
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
1190
		atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
1191
				  &zfcp_sdev->status);
1192
		break;
L
Linus Torvalds 已提交
1193

1194 1195
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
	case ZFCP_ERP_ACTION_REOPEN_PORT:
1196
		atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
1197 1198
				  &erp_action->port->status);
		break;
L
Linus Torvalds 已提交
1199

1200
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1201
		atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
1202 1203 1204
				  &erp_action->adapter->status);
		break;
	}
L
Linus Torvalds 已提交
1205 1206
}

1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262
/**
 * zfcp_erp_try_rport_unblock - unblock rport if no more/new recovery
 * @port: zfcp_port whose fc_rport we should try to unblock
 */
static void zfcp_erp_try_rport_unblock(struct zfcp_port *port)
{
	unsigned long flags;
	struct zfcp_adapter *adapter = port->adapter;
	int port_status;
	struct Scsi_Host *shost = adapter->scsi_host;
	struct scsi_device *sdev;

	write_lock_irqsave(&adapter->erp_lock, flags);
	port_status = atomic_read(&port->status);
	if ((port_status & ZFCP_STATUS_COMMON_UNBLOCKED)    == 0 ||
	    (port_status & (ZFCP_STATUS_COMMON_ERP_INUSE |
			    ZFCP_STATUS_COMMON_ERP_FAILED)) != 0) {
		/* new ERP of severity >= port triggered elsewhere meanwhile or
		 * local link down (adapter erp_failed but not clear unblock)
		 */
		zfcp_dbf_rec_run_lvl(4, "ertru_p", &port->erp_action);
		write_unlock_irqrestore(&adapter->erp_lock, flags);
		return;
	}
	spin_lock(shost->host_lock);
	__shost_for_each_device(sdev, shost) {
		struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
		int lun_status;

		if (zsdev->port != port)
			continue;
		/* LUN under port of interest */
		lun_status = atomic_read(&zsdev->status);
		if ((lun_status & ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
			continue; /* unblock rport despite failed LUNs */
		/* LUN recovery not given up yet [maybe follow-up pending] */
		if ((lun_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
		    (lun_status & ZFCP_STATUS_COMMON_ERP_INUSE) != 0) {
			/* LUN blocked:
			 * not yet unblocked [LUN recovery pending]
			 * or meanwhile blocked [new LUN recovery triggered]
			 */
			zfcp_dbf_rec_run_lvl(4, "ertru_l", &zsdev->erp_action);
			spin_unlock(shost->host_lock);
			write_unlock_irqrestore(&adapter->erp_lock, flags);
			return;
		}
	}
	/* now port has no child or all children have completed recovery,
	 * and no ERP of severity >= port was meanwhile triggered elsewhere
	 */
	zfcp_scsi_schedule_rport_register(port);
	spin_unlock(shost->host_lock);
	write_unlock_irqrestore(&adapter->erp_lock, flags);
}

1263
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
L
Linus Torvalds 已提交
1264
{
1265 1266
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
1267
	struct scsi_device *sdev = act->sdev;
L
Linus Torvalds 已提交
1268

1269
	switch (act->action) {
1270
	case ZFCP_ERP_ACTION_REOPEN_LUN:
1271
		if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
1272
			scsi_device_put(sdev);
1273
		zfcp_erp_try_rport_unblock(port);
1274
		break;
L
Linus Torvalds 已提交
1275

1276
	case ZFCP_ERP_ACTION_REOPEN_PORT:
1277 1278 1279 1280 1281 1282 1283
		/* This switch case might also happen after a forced reopen
		 * was successfully done and thus overwritten with a new
		 * non-forced reopen at `ersfs_2'. In this case, we must not
		 * do the clean-up of the non-forced version.
		 */
		if (act->step != ZFCP_ERP_STEP_UNINITIALIZED)
			if (result == ZFCP_ERP_SUCCEEDED)
1284
				zfcp_erp_try_rport_unblock(port);
1285 1286
		/* fall through */
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1287
		put_device(&port->dev);
1288 1289 1290
		break;

	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1291
		if (result == ZFCP_ERP_SUCCEEDED) {
1292
			register_service_level(&adapter->service_level);
1293
			zfcp_fc_conditional_port_scan(adapter);
1294
			queue_work(adapter->work_queue, &adapter->ns_up_work);
1295 1296
		} else
			unregister_service_level(&adapter->service_level);
1297

1298
		kref_put(&adapter->ref, zfcp_adapter_release);
1299 1300
		break;
	}
L
Linus Torvalds 已提交
1301 1302
}

1303
static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1304
{
1305 1306 1307 1308 1309 1310 1311
	switch (erp_action->action) {
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		return zfcp_erp_adapter_strategy(erp_action);
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
		return zfcp_erp_port_forced_strategy(erp_action);
	case ZFCP_ERP_ACTION_REOPEN_PORT:
		return zfcp_erp_port_strategy(erp_action);
1312 1313
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		return zfcp_erp_lun_strategy(erp_action);
1314 1315
	}
	return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
1316 1317
}

1318
static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1319 1320
{
	int retval;
1321
	unsigned long flags;
1322
	struct zfcp_adapter *adapter = erp_action->adapter;
L
Linus Torvalds 已提交
1323

1324
	kref_get(&adapter->ref);
L
Linus Torvalds 已提交
1325

1326
	write_lock_irqsave(&adapter->erp_lock, flags);
1327
	zfcp_erp_strategy_check_fsfreq(erp_action);
L
Linus Torvalds 已提交
1328

1329 1330 1331 1332
	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
		zfcp_erp_action_dequeue(erp_action);
		retval = ZFCP_ERP_DISMISSED;
		goto unlock;
1333
	}
L
Linus Torvalds 已提交
1334

1335 1336 1337 1338 1339
	if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
		retval = ZFCP_ERP_FAILED;
		goto check_target;
	}

1340
	zfcp_erp_action_to_running(erp_action);
L
Linus Torvalds 已提交
1341

1342
	/* no lock to allow for blocking operations */
1343
	write_unlock_irqrestore(&adapter->erp_lock, flags);
1344
	retval = zfcp_erp_strategy_do_action(erp_action);
1345
	write_lock_irqsave(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1346

1347 1348
	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
		retval = ZFCP_ERP_CONTINUES;
1349

1350 1351 1352 1353 1354
	switch (retval) {
	case ZFCP_ERP_NOMEM:
		if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {
			++adapter->erp_low_mem_count;
			erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
L
Linus Torvalds 已提交
1355
		}
1356
		if (adapter->erp_total_count == adapter->erp_low_mem_count)
1357
			_zfcp_erp_adapter_reopen(adapter, 0, "erstgy1");
1358 1359 1360
		else {
			zfcp_erp_strategy_memwait(erp_action);
			retval = ZFCP_ERP_CONTINUES;
L
Linus Torvalds 已提交
1361
		}
1362
		goto unlock;
L
Linus Torvalds 已提交
1363

1364 1365 1366 1367
	case ZFCP_ERP_CONTINUES:
		if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
			--adapter->erp_low_mem_count;
			erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
L
Linus Torvalds 已提交
1368
		}
1369
		goto unlock;
L
Linus Torvalds 已提交
1370 1371
	}

1372
check_target:
1373 1374 1375 1376 1377
	retval = zfcp_erp_strategy_check_target(erp_action, retval);
	zfcp_erp_action_dequeue(erp_action);
	retval = zfcp_erp_strategy_statechange(erp_action, retval);
	if (retval == ZFCP_ERP_EXIT)
		goto unlock;
1378 1379 1380 1381
	if (retval == ZFCP_ERP_SUCCEEDED)
		zfcp_erp_strategy_followup_success(erp_action);
	if (retval == ZFCP_ERP_FAILED)
		zfcp_erp_strategy_followup_failed(erp_action);
L
Linus Torvalds 已提交
1382

1383
 unlock:
1384
	write_unlock_irqrestore(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1385

1386 1387
	if (retval != ZFCP_ERP_CONTINUES)
		zfcp_erp_action_cleanup(erp_action, retval);
L
Linus Torvalds 已提交
1388

1389
	kref_put(&adapter->ref, zfcp_adapter_release);
L
Linus Torvalds 已提交
1390 1391 1392
	return retval;
}

1393
static int zfcp_erp_thread(void *data)
L
Linus Torvalds 已提交
1394
{
1395 1396 1397 1398
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
	struct list_head *next;
	struct zfcp_erp_action *act;
	unsigned long flags;
1399

1400 1401 1402 1403
	for (;;) {
		wait_event_interruptible(adapter->erp_ready_wq,
			   !list_empty(&adapter->erp_ready_head) ||
			   kthread_should_stop());
1404

1405 1406 1407
		if (kthread_should_stop())
			break;

1408 1409 1410
		write_lock_irqsave(&adapter->erp_lock, flags);
		next = adapter->erp_ready_head.next;
		write_unlock_irqrestore(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1411

1412 1413
		if (next != &adapter->erp_ready_head) {
			act = list_entry(next, struct zfcp_erp_action, list);
L
Linus Torvalds 已提交
1414

1415 1416 1417
			/* there is more to come after dismission, no notify */
			if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
				zfcp_erp_wakeup(adapter);
L
Linus Torvalds 已提交
1418 1419 1420
		}
	}

1421 1422
	return 0;
}
L
Linus Torvalds 已提交
1423

1424 1425 1426 1427 1428 1429 1430 1431
/**
 * zfcp_erp_thread_setup - Start ERP thread for adapter
 * @adapter: Adapter to start the ERP thread for
 *
 * Returns 0 on success or error code from kernel_thread()
 */
int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
{
1432
	struct task_struct *thread;
L
Linus Torvalds 已提交
1433

1434 1435 1436
	thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
			     dev_name(&adapter->ccw_device->dev));
	if (IS_ERR(thread)) {
1437
		dev_err(&adapter->ccw_device->dev,
1438
			"Creating an ERP thread for the FCP device failed.\n");
1439
		return PTR_ERR(thread);
L
Linus Torvalds 已提交
1440
	}
1441 1442

	adapter->erp_thread = thread;
1443 1444
	return 0;
}
L
Linus Torvalds 已提交
1445

1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
/**
 * zfcp_erp_thread_kill - Stop ERP thread.
 * @adapter: Adapter where the ERP thread should be stopped.
 *
 * The caller of this routine ensures that the specified adapter has
 * been shut down and that this operation has been completed. Thus,
 * there are no pending erp_actions which would need to be handled
 * here.
 */
void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
{
1457 1458
	kthread_stop(adapter->erp_thread);
	adapter->erp_thread = NULL;
1459 1460
	WARN_ON(!list_empty(&adapter->erp_ready_head));
	WARN_ON(!list_empty(&adapter->erp_running_head));
L
Linus Torvalds 已提交
1461 1462
}

1463
/**
1464 1465
 * zfcp_erp_wait - wait for completion of error recovery on an adapter
 * @adapter: adapter for which to wait for completion of its error recovery
1466
 */
1467
void zfcp_erp_wait(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
1468
{
1469 1470 1471
	wait_event(adapter->erp_done_wqh,
		   !(atomic_read(&adapter->status) &
			ZFCP_STATUS_ADAPTER_ERP_PENDING));
1472
}
L
Linus Torvalds 已提交
1473

1474
/**
1475 1476 1477 1478 1479
 * zfcp_erp_set_adapter_status - set adapter status bits
 * @adapter: adapter to change the status
 * @mask: status bits to change
 *
 * Changes in common status bits are propagated to attached ports and LUNs.
1480
 */
1481
void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
1482
{
1483 1484 1485 1486
	struct zfcp_port *port;
	struct scsi_device *sdev;
	unsigned long flags;
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
L
Linus Torvalds 已提交
1487

1488
	atomic_or(mask, &adapter->status);
L
Linus Torvalds 已提交
1489

1490 1491 1492 1493 1494
	if (!common_mask)
		return;

	read_lock_irqsave(&adapter->port_list_lock, flags);
	list_for_each_entry(port, &adapter->port_list, list)
1495
		atomic_or(common_mask, &port->status);
1496 1497
	read_unlock_irqrestore(&adapter->port_list_lock, flags);

1498 1499
	spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, adapter->scsi_host)
1500
		atomic_or(common_mask, &sdev_to_zfcp(sdev)->status);
1501
	spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
1502
}
L
Linus Torvalds 已提交
1503

1504
/**
1505
 * zfcp_erp_clear_adapter_status - clear adapter status bits
1506 1507 1508
 * @adapter: adapter to change the status
 * @mask: status bits to change
 *
1509
 * Changes in common status bits are propagated to attached ports and LUNs.
1510
 */
1511
void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
L
Linus Torvalds 已提交
1512 1513
{
	struct zfcp_port *port;
1514
	struct scsi_device *sdev;
1515
	unsigned long flags;
1516
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1517
	u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
L
Linus Torvalds 已提交
1518

1519
	atomic_andnot(mask, &adapter->status);
1520 1521 1522 1523 1524 1525 1526 1527 1528

	if (!common_mask)
		return;

	if (clear_counter)
		atomic_set(&adapter->erp_counter, 0);

	read_lock_irqsave(&adapter->port_list_lock, flags);
	list_for_each_entry(port, &adapter->port_list, list) {
1529
		atomic_andnot(common_mask, &port->status);
1530 1531
		if (clear_counter)
			atomic_set(&port->erp_counter, 0);
1532
	}
1533
	read_unlock_irqrestore(&adapter->port_list_lock, flags);
1534

1535 1536
	spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, adapter->scsi_host) {
1537
		atomic_andnot(common_mask, &sdev_to_zfcp(sdev)->status);
1538 1539
		if (clear_counter)
			atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
1540
	}
1541
	spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
L
Linus Torvalds 已提交
1542 1543
}

1544
/**
1545 1546
 * zfcp_erp_set_port_status - set port status bits
 * @port: port to change the status
1547 1548
 * @mask: status bits to change
 *
1549
 * Changes in common status bits are propagated to attached LUNs.
1550
 */
1551
void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
L
Linus Torvalds 已提交
1552
{
1553
	struct scsi_device *sdev;
1554
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1555
	unsigned long flags;
L
Linus Torvalds 已提交
1556

1557
	atomic_or(mask, &port->status);
L
Linus Torvalds 已提交
1558

1559 1560 1561
	if (!common_mask)
		return;

1562 1563
	spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, port->adapter->scsi_host)
1564
		if (sdev_to_zfcp(sdev)->port == port)
1565
			atomic_or(common_mask,
1566
					&sdev_to_zfcp(sdev)->status);
1567
	spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
L
Linus Torvalds 已提交
1568 1569
}

1570
/**
1571 1572
 * zfcp_erp_clear_port_status - clear port status bits
 * @port: adapter to change the status
1573
 * @mask: status bits to change
1574 1575
 *
 * Changes in common status bits are propagated to attached LUNs.
1576
 */
1577
void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
L
Linus Torvalds 已提交
1578
{
1579 1580 1581
	struct scsi_device *sdev;
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
	u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
1582
	unsigned long flags;
1583

1584
	atomic_andnot(mask, &port->status);
1585 1586 1587

	if (!common_mask)
		return;
1588

1589 1590 1591
	if (clear_counter)
		atomic_set(&port->erp_counter, 0);

1592 1593
	spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, port->adapter->scsi_host)
1594
		if (sdev_to_zfcp(sdev)->port == port) {
1595
			atomic_andnot(common_mask,
1596 1597 1598
					  &sdev_to_zfcp(sdev)->status);
			if (clear_counter)
				atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
1599
		}
1600
	spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
L
Linus Torvalds 已提交
1601 1602
}

1603
/**
1604 1605 1606
 * zfcp_erp_set_lun_status - set lun status bits
 * @sdev: SCSI device / lun to set the status bits
 * @mask: status bits to change
1607
 */
1608
void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask)
1609
{
1610 1611
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

1612
	atomic_or(mask, &zfcp_sdev->status);
1613 1614
}

1615
/**
1616 1617 1618
 * zfcp_erp_clear_lun_status - clear lun status bits
 * @sdev: SCSi device / lun to clear the status bits
 * @mask: status bits to change
1619
 */
1620
void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask)
1621
{
1622 1623
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

1624
	atomic_andnot(mask, &zfcp_sdev->status);
1625 1626 1627

	if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
		atomic_set(&zfcp_sdev->erp_counter, 0);
1628
}
1629