zfcp_erp.c 43.2 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, 2010
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 194 195
		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
				&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 209 210
		zfcp_erp_action_dismiss_port(port);
		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
		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 220 221
		zfcp_erp_action_dismiss_adapter(adapter);
		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
		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_set_mask(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_set_mask(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_set_mask(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_set_mask(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 645 646 647
	if (list_empty(&adapter->erp_ready_head) &&
	    list_empty(&adapter->erp_running_head)) {
			atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
					  &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 669 670 671 672 673 674 675 676 677 678 679
	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);

	for (retries = 7; retries; retries--) {
		atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
				  &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)) {
			atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
					  &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 696
	atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
			  &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_clear_mask(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 777 778 779 780
		atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
				  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
				  &adapter->status);
		return ZFCP_ERP_FAILED;
	}
781

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

	atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &adapter->status);

	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_clear_mask(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_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1191
				  &zfcp_sdev->status);
1192
		break;
L
Linus Torvalds 已提交
1193

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

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

1207
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
L
Linus Torvalds 已提交
1208
{
1209 1210
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
1211
	struct scsi_device *sdev = act->sdev;
L
Linus Torvalds 已提交
1212

1213
	switch (act->action) {
1214
	case ZFCP_ERP_ACTION_REOPEN_LUN:
1215
		if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
1216
			scsi_device_put(sdev);
1217
		break;
L
Linus Torvalds 已提交
1218

1219
	case ZFCP_ERP_ACTION_REOPEN_PORT:
1220 1221
		if (result == ZFCP_ERP_SUCCEEDED)
			zfcp_scsi_schedule_rport_register(port);
1222 1223
		/* fall through */
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1224
		put_device(&port->dev);
1225 1226 1227
		break;

	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1228
		if (result == ZFCP_ERP_SUCCEEDED) {
1229
			register_service_level(&adapter->service_level);
1230
			zfcp_fc_conditional_port_scan(adapter);
1231
			queue_work(adapter->work_queue, &adapter->ns_up_work);
1232 1233
		} else
			unregister_service_level(&adapter->service_level);
1234

1235
		kref_put(&adapter->ref, zfcp_adapter_release);
1236 1237
		break;
	}
L
Linus Torvalds 已提交
1238 1239
}

1240
static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1241
{
1242 1243 1244 1245 1246 1247 1248
	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);
1249 1250
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		return zfcp_erp_lun_strategy(erp_action);
1251 1252
	}
	return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
1253 1254
}

1255
static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1256 1257
{
	int retval;
1258
	unsigned long flags;
1259
	struct zfcp_adapter *adapter = erp_action->adapter;
L
Linus Torvalds 已提交
1260

1261
	kref_get(&adapter->ref);
L
Linus Torvalds 已提交
1262

1263
	write_lock_irqsave(&adapter->erp_lock, flags);
1264
	zfcp_erp_strategy_check_fsfreq(erp_action);
L
Linus Torvalds 已提交
1265

1266 1267 1268 1269
	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
		zfcp_erp_action_dequeue(erp_action);
		retval = ZFCP_ERP_DISMISSED;
		goto unlock;
1270
	}
L
Linus Torvalds 已提交
1271

1272 1273 1274 1275 1276
	if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
		retval = ZFCP_ERP_FAILED;
		goto check_target;
	}

1277
	zfcp_erp_action_to_running(erp_action);
L
Linus Torvalds 已提交
1278

1279
	/* no lock to allow for blocking operations */
1280
	write_unlock_irqrestore(&adapter->erp_lock, flags);
1281
	retval = zfcp_erp_strategy_do_action(erp_action);
1282
	write_lock_irqsave(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1283

1284 1285
	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
		retval = ZFCP_ERP_CONTINUES;
1286

1287 1288 1289 1290 1291
	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 已提交
1292
		}
1293
		if (adapter->erp_total_count == adapter->erp_low_mem_count)
1294
			_zfcp_erp_adapter_reopen(adapter, 0, "erstgy1");
1295 1296 1297
		else {
			zfcp_erp_strategy_memwait(erp_action);
			retval = ZFCP_ERP_CONTINUES;
L
Linus Torvalds 已提交
1298
		}
1299
		goto unlock;
L
Linus Torvalds 已提交
1300

1301 1302 1303 1304
	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 已提交
1305
		}
1306
		goto unlock;
L
Linus Torvalds 已提交
1307 1308
	}

1309
check_target:
1310 1311 1312 1313 1314
	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;
1315 1316 1317 1318
	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 已提交
1319

1320
 unlock:
1321
	write_unlock_irqrestore(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1322

1323 1324
	if (retval != ZFCP_ERP_CONTINUES)
		zfcp_erp_action_cleanup(erp_action, retval);
L
Linus Torvalds 已提交
1325

1326
	kref_put(&adapter->ref, zfcp_adapter_release);
L
Linus Torvalds 已提交
1327 1328 1329
	return retval;
}

1330
static int zfcp_erp_thread(void *data)
L
Linus Torvalds 已提交
1331
{
1332 1333 1334 1335
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
	struct list_head *next;
	struct zfcp_erp_action *act;
	unsigned long flags;
1336

1337 1338 1339 1340
	for (;;) {
		wait_event_interruptible(adapter->erp_ready_wq,
			   !list_empty(&adapter->erp_ready_head) ||
			   kthread_should_stop());
1341

1342 1343 1344
		if (kthread_should_stop())
			break;

1345 1346 1347
		write_lock_irqsave(&adapter->erp_lock, flags);
		next = adapter->erp_ready_head.next;
		write_unlock_irqrestore(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1348

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

1352 1353 1354
			/* there is more to come after dismission, no notify */
			if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
				zfcp_erp_wakeup(adapter);
L
Linus Torvalds 已提交
1355 1356 1357
		}
	}

1358 1359
	return 0;
}
L
Linus Torvalds 已提交
1360

1361 1362 1363 1364 1365 1366 1367 1368
/**
 * 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)
{
1369
	struct task_struct *thread;
L
Linus Torvalds 已提交
1370

1371 1372 1373
	thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
			     dev_name(&adapter->ccw_device->dev));
	if (IS_ERR(thread)) {
1374
		dev_err(&adapter->ccw_device->dev,
1375
			"Creating an ERP thread for the FCP device failed.\n");
1376
		return PTR_ERR(thread);
L
Linus Torvalds 已提交
1377
	}
1378 1379

	adapter->erp_thread = thread;
1380 1381
	return 0;
}
L
Linus Torvalds 已提交
1382

1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
/**
 * 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)
{
1394 1395
	kthread_stop(adapter->erp_thread);
	adapter->erp_thread = NULL;
1396 1397
	WARN_ON(!list_empty(&adapter->erp_ready_head));
	WARN_ON(!list_empty(&adapter->erp_running_head));
L
Linus Torvalds 已提交
1398 1399
}

1400
/**
1401 1402
 * zfcp_erp_wait - wait for completion of error recovery on an adapter
 * @adapter: adapter for which to wait for completion of its error recovery
1403
 */
1404
void zfcp_erp_wait(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
1405
{
1406 1407 1408
	wait_event(adapter->erp_done_wqh,
		   !(atomic_read(&adapter->status) &
			ZFCP_STATUS_ADAPTER_ERP_PENDING));
1409
}
L
Linus Torvalds 已提交
1410

1411
/**
1412 1413 1414 1415 1416
 * 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.
1417
 */
1418
void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
1419
{
1420 1421 1422 1423
	struct zfcp_port *port;
	struct scsi_device *sdev;
	unsigned long flags;
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
L
Linus Torvalds 已提交
1424

1425
	atomic_set_mask(mask, &adapter->status);
L
Linus Torvalds 已提交
1426

1427 1428 1429 1430 1431 1432 1433 1434
	if (!common_mask)
		return;

	read_lock_irqsave(&adapter->port_list_lock, flags);
	list_for_each_entry(port, &adapter->port_list, list)
		atomic_set_mask(common_mask, &port->status);
	read_unlock_irqrestore(&adapter->port_list_lock, flags);

1435 1436
	spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, adapter->scsi_host)
1437
		atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
1438
	spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
1439
}
L
Linus Torvalds 已提交
1440

1441
/**
1442
 * zfcp_erp_clear_adapter_status - clear adapter status bits
1443 1444 1445
 * @adapter: adapter to change the status
 * @mask: status bits to change
 *
1446
 * Changes in common status bits are propagated to attached ports and LUNs.
1447
 */
1448
void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
L
Linus Torvalds 已提交
1449 1450
{
	struct zfcp_port *port;
1451
	struct scsi_device *sdev;
1452
	unsigned long flags;
1453
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1454
	u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
L
Linus Torvalds 已提交
1455

1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
	atomic_clear_mask(mask, &adapter->status);

	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) {
		atomic_clear_mask(common_mask, &port->status);
		if (clear_counter)
			atomic_set(&port->erp_counter, 0);
1469
	}
1470
	read_unlock_irqrestore(&adapter->port_list_lock, flags);
1471

1472 1473
	spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, adapter->scsi_host) {
1474 1475 1476
		atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
		if (clear_counter)
			atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
1477
	}
1478
	spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
L
Linus Torvalds 已提交
1479 1480
}

1481
/**
1482 1483
 * zfcp_erp_set_port_status - set port status bits
 * @port: port to change the status
1484 1485
 * @mask: status bits to change
 *
1486
 * Changes in common status bits are propagated to attached LUNs.
1487
 */
1488
void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
L
Linus Torvalds 已提交
1489
{
1490
	struct scsi_device *sdev;
1491
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1492
	unsigned long flags;
L
Linus Torvalds 已提交
1493

1494
	atomic_set_mask(mask, &port->status);
L
Linus Torvalds 已提交
1495

1496 1497 1498
	if (!common_mask)
		return;

1499 1500
	spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, port->adapter->scsi_host)
1501 1502 1503
		if (sdev_to_zfcp(sdev)->port == port)
			atomic_set_mask(common_mask,
					&sdev_to_zfcp(sdev)->status);
1504
	spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
L
Linus Torvalds 已提交
1505 1506
}

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

	atomic_clear_mask(mask, &port->status);

	if (!common_mask)
		return;
1525

1526 1527 1528
	if (clear_counter)
		atomic_set(&port->erp_counter, 0);

1529 1530
	spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
	__shost_for_each_device(sdev, port->adapter->scsi_host)
1531 1532 1533 1534 1535
		if (sdev_to_zfcp(sdev)->port == port) {
			atomic_clear_mask(common_mask,
					  &sdev_to_zfcp(sdev)->status);
			if (clear_counter)
				atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
1536
		}
1537
	spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
L
Linus Torvalds 已提交
1538 1539
}

1540
/**
1541 1542 1543
 * zfcp_erp_set_lun_status - set lun status bits
 * @sdev: SCSI device / lun to set the status bits
 * @mask: status bits to change
1544
 */
1545
void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask)
1546
{
1547 1548 1549
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

	atomic_set_mask(mask, &zfcp_sdev->status);
1550 1551
}

1552
/**
1553 1554 1555
 * zfcp_erp_clear_lun_status - clear lun status bits
 * @sdev: SCSi device / lun to clear the status bits
 * @mask: status bits to change
1556
 */
1557
void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask)
1558
{
1559 1560 1561 1562 1563 1564
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

	atomic_clear_mask(mask, &zfcp_sdev->status);

	if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
		atomic_set(&zfcp_sdev->erp_counter, 0);
1565
}
1566