zfcp_erp.c 44.7 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 Corporation 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
	zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL,
61 62
				       ZFCP_STATUS_COMMON_UNBLOCKED | mask,
				       ZFCP_CLEAR);
63
}
L
Linus Torvalds 已提交
64

65
static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
66
{
67 68 69 70 71 72
	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 已提交
73 74
}

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

	list_move(&act->list, &act->adapter->erp_ready_head);
S
Swen Schillig 已提交
80
	zfcp_dbf_rec_action("erardy1", act);
81
	wake_up(&adapter->erp_ready_wq);
S
Swen Schillig 已提交
82
	zfcp_dbf_rec_thread("erardy2", adapter->dbf);
83 84
}

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

92
static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev)
93
{
94 95 96 97
	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);
98
}
L
Linus Torvalds 已提交
99

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

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

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

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

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

134
	switch (want) {
135 136 137 138
	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)
139 140 141 142 143 144 145 146 147
			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:
148 149 150 151 152
		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:
153 154 155 156 157 158 159 160 161 162 163 164 165 166
		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;
		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;
167 168 169
		if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) &&
		    !(a_status & ZFCP_STATUS_COMMON_OPEN))
			return 0; /* shutdown requested for closed adapter */
170
	}
L
Linus Torvalds 已提交
171

172
	return need;
L
Linus Torvalds 已提交
173 174
}

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

183
	switch (need) {
184 185
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		zfcp_sdev = sdev_to_zfcp(sdev);
186
		if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
187
			if (scsi_device_get(sdev))
188
				return NULL;
189 190 191 192 193
		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
				&zfcp_sdev->status);
		erp_action = &zfcp_sdev->erp_action;
		if (!(atomic_read(&zfcp_sdev->status) &
		      ZFCP_STATUS_COMMON_RUNNING))
194
			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
195
		break;
L
Linus Torvalds 已提交
196

197 198
	case ZFCP_ERP_ACTION_REOPEN_PORT:
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
199
		if (!get_device(&port->dev))
200
			return NULL;
201 202 203 204
		zfcp_erp_action_dismiss_port(port);
		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
		erp_action = &port->erp_action;
		if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
205
			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
206
		break;
L
Linus Torvalds 已提交
207

208
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
209
		kref_get(&adapter->ref);
210 211 212 213 214
		zfcp_erp_action_dismiss_adapter(adapter);
		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
		erp_action = &adapter->erp_action;
		if (!(atomic_read(&adapter->status) &
		      ZFCP_STATUS_COMMON_RUNNING))
215
			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
216 217 218 219 220
		break;

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

222 223 224
	memset(erp_action, 0, sizeof(struct zfcp_erp_action));
	erp_action->adapter = adapter;
	erp_action->port = port;
225
	erp_action->sdev = sdev;
226
	erp_action->action = need;
227
	erp_action->status = act_status;
L
Linus Torvalds 已提交
228

229
	return erp_action;
L
Linus Torvalds 已提交
230 231
}

232 233
static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
				   struct zfcp_port *port,
234 235
				   struct scsi_device *sdev,
				   char *id, void *ref, u32 act_status)
L
Linus Torvalds 已提交
236
{
237 238
	int retval = 1, need;
	struct zfcp_erp_action *act = NULL;
L
Linus Torvalds 已提交
239

240
	if (!adapter->erp_thread)
241
		return -EIO;
L
Linus Torvalds 已提交
242

243
	need = zfcp_erp_required_act(want, adapter, port, sdev);
244
	if (!need)
L
Linus Torvalds 已提交
245 246
		goto out;

247
	act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
248 249
	if (!act)
		goto out;
250
	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
251 252
	++adapter->erp_total_count;
	list_add_tail(&act->list, &adapter->erp_ready_head);
253
	wake_up(&adapter->erp_ready_wq);
S
Swen Schillig 已提交
254
	zfcp_dbf_rec_thread("eracte1", adapter->dbf);
255
	retval = 0;
L
Linus Torvalds 已提交
256
 out:
257
	zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, sdev);
L
Linus Torvalds 已提交
258 259 260
	return retval;
}

261
static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
262
				    int clear_mask, char *id, void *ref)
263 264
{
	zfcp_erp_adapter_block(adapter, clear_mask);
265
	zfcp_scsi_schedule_rports_block(adapter);
266 267 268

	/* ensure propagation of failed status to new devices */
	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
269
		zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
270 271 272
		return -EIO;
	}
	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
273
				       adapter, NULL, NULL, id, ref, 0);
274 275 276 277 278 279 280 281
}

/**
 * zfcp_erp_adapter_reopen - Reopen adapter.
 * @adapter: Adapter to reopen.
 * @clear: Status flags to clear.
 * @id: Id for debug trace event.
 * @ref: Reference for debug trace event.
L
Linus Torvalds 已提交
282
 */
283
void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
284
			     char *id, void *ref)
L
Linus Torvalds 已提交
285 286 287
{
	unsigned long flags;

288 289 290 291 292 293 294 295
	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)
		zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
	else
		zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
296
					NULL, NULL, id, ref, 0);
297
	write_unlock_irqrestore(&adapter->erp_lock, flags);
298
}
L
Linus Torvalds 已提交
299

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

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

static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
{
330
	zfcp_erp_modify_port_status(port, "erpblk1", NULL,
331 332 333 334 335
				    ZFCP_STATUS_COMMON_UNBLOCKED | clear,
				    ZFCP_CLEAR);
}

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

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

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

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

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

365
static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
366 367 368
				 void *ref)
{
	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_port_failed(port, "erpreo1", NULL);
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, ref, 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
L
Linus Torvalds 已提交
385
 *
386
 * Returns 0 if recovery has been triggered, < 0 if not.
L
Linus Torvalds 已提交
387
 */
388
int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref)
L
Linus Torvalds 已提交
389
{
390
	int retval;
391
	unsigned long flags;
L
Linus Torvalds 已提交
392 393
	struct zfcp_adapter *adapter = port->adapter;

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

	return retval;
}

401
static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask)
402
{
403 404 405
	zfcp_erp_modify_lun_status(sdev, "erlblk1", NULL,
				   ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
				   ZFCP_CLEAR);
406 407
}

408 409
static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
				 void *ref, 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 420
	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
				zfcp_sdev->port, sdev, id, ref, 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
L
Linus Torvalds 已提交
427 428
 * Return: 0 on success, < 0 on error
 */
429 430
void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
			 void *ref)
L
Linus Torvalds 已提交
431 432
{
	unsigned long flags;
433 434
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
	struct zfcp_port *port = zfcp_sdev->port;
435
	struct zfcp_adapter *adapter = port->adapter;
L
Linus Torvalds 已提交
436

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

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

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

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

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

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

486
static int status_change_clear(unsigned long mask, atomic_t *status)
487
{
488
	return atomic_read(status) & mask;
489 490
}

491
static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
492
{
493
	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
S
Swen Schillig 已提交
494
		zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf);
495
	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
496 497
}

498
static void zfcp_erp_port_unblock(struct zfcp_port *port)
L
Linus Torvalds 已提交
499
{
500
	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
S
Swen Schillig 已提交
501
		zfcp_dbf_rec_port("erpubl1", NULL, port);
502
	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
L
Linus Torvalds 已提交
503 504
}

505
static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
L
Linus Torvalds 已提交
506
{
507 508 509 510 511
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
		zfcp_dbf_rec_lun("erlubl1", NULL, sdev);
	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
L
Linus Torvalds 已提交
512 513
}

514
static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
515
{
516
	list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
S
Swen Schillig 已提交
517
	zfcp_dbf_rec_action("erator1", erp_action);
L
Linus Torvalds 已提交
518 519
}

520
static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
521
{
522
	struct zfcp_adapter *adapter = act->adapter;
523
	struct zfcp_fsf_req *req;
L
Linus Torvalds 已提交
524

525
	if (!act->fsf_req_id)
526
		return;
L
Linus Torvalds 已提交
527

528 529
	spin_lock(&adapter->req_list->lock);
	req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id);
530
	if (req && req->erp_action == act) {
531 532
		if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
				   ZFCP_STATUS_ERP_TIMEDOUT)) {
533
			req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
S
Swen Schillig 已提交
534
			zfcp_dbf_rec_action("erscf_1", act);
535
			req->erp_action = NULL;
L
Linus Torvalds 已提交
536
		}
537
		if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
S
Swen Schillig 已提交
538
			zfcp_dbf_rec_action("erscf_2", act);
539 540
		if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
			act->fsf_req_id = 0;
541
	} else
542
		act->fsf_req_id = 0;
543
	spin_unlock(&adapter->req_list->lock);
L
Linus Torvalds 已提交
544 545
}

546 547 548 549
/**
 * zfcp_erp_notify - Trigger ERP action.
 * @erp_action: ERP action to continue.
 * @set_mask: ERP action status flags to set.
L
Linus Torvalds 已提交
550
 */
551
void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask)
L
Linus Torvalds 已提交
552 553
{
	struct zfcp_adapter *adapter = erp_action->adapter;
554
	unsigned long flags;
L
Linus Torvalds 已提交
555

556
	write_lock_irqsave(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
557 558 559 560 561 562 563
	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);
}

564 565 566
/**
 * zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request
 * @data: ERP action (from timer data)
L
Linus Torvalds 已提交
567
 */
568
void zfcp_erp_timeout_handler(unsigned long data)
L
Linus Torvalds 已提交
569
{
570 571
	struct zfcp_erp_action *act = (struct zfcp_erp_action *) data;
	zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT);
L
Linus Torvalds 已提交
572 573
}

574
static void zfcp_erp_memwait_handler(unsigned long data)
L
Linus Torvalds 已提交
575
{
576
	zfcp_erp_notify((struct zfcp_erp_action *)data, 0);
L
Linus Torvalds 已提交
577 578
}

579
static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
580
{
581 582 583 584 585
	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 已提交
586 587
}

588
static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
589
				      int clear, char *id, void *ref)
L
Linus Torvalds 已提交
590
{
591
	struct zfcp_port *port;
L
Linus Torvalds 已提交
592

593 594
	read_lock(&adapter->port_list_lock);
	list_for_each_entry(port, &adapter->port_list, list)
595
		_zfcp_erp_port_reopen(port, clear, id, ref);
596
	read_unlock(&adapter->port_list_lock);
L
Linus Torvalds 已提交
597 598
}

599 600
static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
				     char *id, void *ref)
L
Linus Torvalds 已提交
601
{
602
	struct scsi_device *sdev;
L
Linus Torvalds 已提交
603

604 605 606
	shost_for_each_device(sdev, port->adapter->scsi_host)
		if (sdev_to_zfcp(sdev)->port == port)
			_zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
L
Linus Torvalds 已提交
607 608
}

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

static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act)
{
	switch (act->action) {
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		_zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL);
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
		_zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT:
637
		_zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3", NULL);
638
		break;
L
Linus Torvalds 已提交
639 640 641
	}
}

642
static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
643 644 645
{
	unsigned long flags;

646
	read_lock_irqsave(&adapter->erp_lock, flags);
647 648 649 650 651
	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 已提交
652
	}
653
	read_unlock_irqrestore(&adapter->erp_lock, flags);
654
}
L
Linus Torvalds 已提交
655

656 657
static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
{
658 659 660
	struct zfcp_qdio *qdio = act->adapter->qdio;

	if (zfcp_qdio_open(qdio))
661
		return ZFCP_ERP_FAILED;
662
	init_waitqueue_head(&qdio->req_q_wq);
663 664 665
	atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status);
	return ZFCP_ERP_SUCCEEDED;
}
L
Linus Torvalds 已提交
666

667 668 669 670 671 672 673
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;
674
	_zfcp_erp_port_reopen(port, 0, "ereptp1", NULL);
675
}
L
Linus Torvalds 已提交
676

677 678 679 680 681
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 已提交
682

683 684 685 686 687 688 689 690 691 692 693 694
	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 已提交
695 696
		}

S
Swen Schillig 已提交
697
		zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf);
698 699
		wait_event(adapter->erp_ready_wq,
			   !list_empty(&adapter->erp_ready_head));
S
Swen Schillig 已提交
700
		zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf);
701 702
		if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
			break;
L
Linus Torvalds 已提交
703

704 705 706
		if (!(atomic_read(&adapter->status) &
		      ZFCP_STATUS_ADAPTER_HOST_CON_INIT))
			break;
L
Linus Torvalds 已提交
707

708 709
		ssleep(sleep);
		sleep *= 2;
L
Linus Torvalds 已提交
710 711
	}

712 713
	atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
			  &adapter->status);
L
Linus Torvalds 已提交
714

715 716
	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK))
		return ZFCP_ERP_FAILED;
S
Swen Schillig 已提交
717

718 719
	if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
		zfcp_erp_enqueue_ptp_port(adapter);
L
Linus Torvalds 已提交
720

721
	return ZFCP_ERP_SUCCEEDED;
L
Linus Torvalds 已提交
722 723
}

724
static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
725
{
726 727
	int ret;
	struct zfcp_adapter *adapter = act->adapter;
L
Linus Torvalds 已提交
728

729 730 731 732 733 734 735 736 737 738
	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;

S
Swen Schillig 已提交
739
	zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf);
740 741
	wait_event(adapter->erp_ready_wq,
		   !list_empty(&adapter->erp_ready_head));
S
Swen Schillig 已提交
742
	zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf);
743 744 745 746
	if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
		return ZFCP_ERP_FAILED;

	return ZFCP_ERP_SUCCEEDED;
L
Linus Torvalds 已提交
747 748
}

749
static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
750
{
751 752
	if (zfcp_erp_adapter_strat_fsf_xconf(act) == ZFCP_ERP_FAILED)
		return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
753

754 755
	if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
		return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
756

757 758 759 760 761 762 763 764
	if (mempool_resize(act->adapter->pool.status_read_data,
			   act->adapter->stat_read_buf_num, GFP_KERNEL))
		return ZFCP_ERP_FAILED;

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

765
	atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
766 767
	if (zfcp_status_read_refill(act->adapter))
		return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
768

769 770
	return ZFCP_ERP_SUCCEEDED;
}
L
Linus Torvalds 已提交
771

772
static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
773 774
{
	struct zfcp_adapter *adapter = act->adapter;
L
Linus Torvalds 已提交
775

776
	/* close queues to ensure that buffers are not accessed by adapter */
777
	zfcp_qdio_close(adapter->qdio);
778 779
	zfcp_fsf_req_dismiss_all(adapter);
	adapter->fsf_req_seq_no = 0;
780
	zfcp_fc_wka_ports_force_offline(adapter->gs);
781
	/* all ports and LUNs are closed */
782
	zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
783
				       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
784

785
	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
786
			  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
L
Linus Torvalds 已提交
787 788
}

789
static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
790
{
791
	struct zfcp_adapter *adapter = act->adapter;
L
Linus Torvalds 已提交
792

793 794 795 796 797 798
	if (zfcp_erp_adapter_strategy_open_qdio(act)) {
		atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
				  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
				  &adapter->status);
		return ZFCP_ERP_FAILED;
	}
799

800 801 802 803 804 805 806 807 808
	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;
}
809

810 811 812 813 814 815 816 817 818 819 820
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)) {
821
		ssleep(8);
822 823
		return ZFCP_ERP_FAILED;
	}
L
Linus Torvalds 已提交
824

825
	return ZFCP_ERP_SUCCEEDED;
L
Linus Torvalds 已提交
826 827
}

828
static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
829
{
830 831 832 833 834 835 836 837 838 839
	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 已提交
840 841
}

842
static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
L
Linus Torvalds 已提交
843
{
844
	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status);
845
}
L
Linus Torvalds 已提交
846

847 848 849 850 851 852 853 854 855 856 857 858 859 860 861
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:
		zfcp_erp_port_strategy_clearstati(port);
		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:
862
		if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN))
863 864 865
			return ZFCP_ERP_SUCCEEDED;
	}
	return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
866 867
}

868
static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
869
{
870
	int retval;
L
Linus Torvalds 已提交
871

872 873 874 875 876 877 878
	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 已提交
879 880
}

881
static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
882
{
883
	int retval;
L
Linus Torvalds 已提交
884

885 886 887 888 889 890 891 892
	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 已提交
893

894
static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
L
Linus Torvalds 已提交
895
{
896 897
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
L
Linus Torvalds 已提交
898

899
	if (port->wwpn != adapter->peer_wwpn) {
900
		zfcp_erp_port_failed(port, "eroptp1", NULL);
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
		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);
919
		if (!port->d_id) {
920
			zfcp_fc_trigger_did_lookup(port);
921
			return ZFCP_ERP_EXIT;
922 923 924 925 926
		}
		return zfcp_erp_port_strategy_open_port(act);

	case ZFCP_ERP_STEP_PORT_OPENING:
		/* D_ID might have changed during open */
927
		if (p_status & ZFCP_STATUS_COMMON_OPEN) {
928 929 930
			if (!port->d_id) {
				zfcp_fc_trigger_did_lookup(port);
				return ZFCP_ERP_EXIT;
931
			}
932
			return ZFCP_ERP_SUCCEEDED;
933
		}
934 935
		if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) {
			port->d_id = 0;
936
			return ZFCP_ERP_FAILED;
937 938
		}
		/* fall through otherwise */
939 940 941 942 943 944 945
	}
	return ZFCP_ERP_FAILED;
}

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

948 949
	if ((p_status & ZFCP_STATUS_COMMON_NOESC) &&
	    !(p_status & ZFCP_STATUS_COMMON_OPEN))
950 951
		goto close_init_done;

952 953 954
	switch (erp_action->step) {
	case ZFCP_ERP_STEP_UNINITIALIZED:
		zfcp_erp_port_strategy_clearstati(port);
955
		if (p_status & ZFCP_STATUS_COMMON_OPEN)
956
			return zfcp_erp_port_strategy_close(erp_action);
L
Linus Torvalds 已提交
957 958
		break;

959
	case ZFCP_ERP_STEP_PORT_CLOSING:
960
		if (p_status & ZFCP_STATUS_COMMON_OPEN)
961
			return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
962 963
		break;
	}
964 965

close_init_done:
966 967
	if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
		return ZFCP_ERP_EXIT;
L
Linus Torvalds 已提交
968

969
	return zfcp_erp_port_strategy_open_common(erp_action);
970 971
}

972
static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev)
973
{
974 975
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

976
	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
977 978
			  ZFCP_STATUS_LUN_SHARED | ZFCP_STATUS_LUN_READONLY,
			  &zfcp_sdev->status);
979 980
}

981
static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action)
982
{
983
	int retval = zfcp_fsf_close_lun(erp_action);
984 985
	if (retval == -ENOMEM)
		return ZFCP_ERP_NOMEM;
986
	erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING;
987 988 989 990 991
	if (retval)
		return ZFCP_ERP_FAILED;
	return ZFCP_ERP_CONTINUES;
}

992
static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action)
993
{
994
	int retval = zfcp_fsf_open_lun(erp_action);
995 996
	if (retval == -ENOMEM)
		return ZFCP_ERP_NOMEM;
997
	erp_action->step = ZFCP_ERP_STEP_LUN_OPENING;
998 999 1000
	if (retval)
		return  ZFCP_ERP_FAILED;
	return ZFCP_ERP_CONTINUES;
L
Linus Torvalds 已提交
1001 1002
}

1003
static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1004
{
1005 1006
	struct scsi_device *sdev = erp_action->sdev;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
1007 1008 1009

	switch (erp_action->step) {
	case ZFCP_ERP_STEP_UNINITIALIZED:
1010 1011 1012
		zfcp_erp_lun_strategy_clearstati(sdev);
		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
			return zfcp_erp_lun_strategy_close(erp_action);
1013
		/* already closed, fall through */
1014 1015
	case ZFCP_ERP_STEP_LUN_CLOSING:
		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
1016 1017 1018
			return ZFCP_ERP_FAILED;
		if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
			return ZFCP_ERP_EXIT;
1019
		return zfcp_erp_lun_strategy_open(erp_action);
1020

1021 1022
	case ZFCP_ERP_STEP_LUN_OPENING:
		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
1023 1024 1025
			return ZFCP_ERP_SUCCEEDED;
	}
	return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
1026 1027
}

1028
static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result)
L
Linus Torvalds 已提交
1029
{
1030 1031
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

L
Linus Torvalds 已提交
1032 1033
	switch (result) {
	case ZFCP_ERP_SUCCEEDED :
1034 1035
		atomic_set(&zfcp_sdev->erp_counter, 0);
		zfcp_erp_lun_unblock(sdev);
L
Linus Torvalds 已提交
1036 1037
		break;
	case ZFCP_ERP_FAILED :
1038 1039 1040 1041
		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 "
1042
				"port 0x%016Lx\n",
1043 1044 1045
				(unsigned long long)zfcp_scsi_dev_lun(sdev),
				(unsigned long long)zfcp_sdev->port->wwpn);
			zfcp_erp_lun_failed(sdev, "ersckl1", NULL);
1046
		}
L
Linus Torvalds 已提交
1047 1048 1049
		break;
	}

1050 1051
	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
		zfcp_erp_lun_block(sdev, 0);
L
Linus Torvalds 已提交
1052 1053 1054 1055 1056
		result = ZFCP_ERP_EXIT;
	}
	return result;
}

1057
static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
L
Linus Torvalds 已提交
1058 1059 1060 1061 1062 1063
{
	switch (result) {
	case ZFCP_ERP_SUCCEEDED :
		atomic_set(&port->erp_counter, 0);
		zfcp_erp_port_unblock(port);
		break;
1064

L
Linus Torvalds 已提交
1065
	case ZFCP_ERP_FAILED :
1066
		if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) {
1067 1068 1069
			zfcp_erp_port_block(port, 0);
			result = ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1070
		atomic_inc(&port->erp_counter);
1071 1072 1073
		if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
			dev_err(&port->adapter->ccw_device->dev,
				"ERP failed for remote port 0x%016Lx\n",
1074
				(unsigned long long)port->wwpn);
1075
			zfcp_erp_port_failed(port, "erpsck1", NULL);
1076
		}
L
Linus Torvalds 已提交
1077 1078 1079
		break;
	}

1080 1081
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
		zfcp_erp_port_block(port, 0);
L
Linus Torvalds 已提交
1082 1083 1084 1085 1086
		result = ZFCP_ERP_EXIT;
	}
	return result;
}

1087 1088
static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
					   int result)
L
Linus Torvalds 已提交
1089 1090 1091 1092 1093 1094
{
	switch (result) {
	case ZFCP_ERP_SUCCEEDED :
		atomic_set(&adapter->erp_counter, 0);
		zfcp_erp_adapter_unblock(adapter);
		break;
1095

L
Linus Torvalds 已提交
1096 1097
	case ZFCP_ERP_FAILED :
		atomic_inc(&adapter->erp_counter);
1098 1099 1100 1101
		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");
1102
			zfcp_erp_adapter_failed(adapter, "erasck1", NULL);
1103
		}
L
Linus Torvalds 已提交
1104 1105 1106
		break;
	}

1107 1108
	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
		zfcp_erp_adapter_block(adapter, 0);
L
Linus Torvalds 已提交
1109 1110 1111 1112 1113
		result = ZFCP_ERP_EXIT;
	}
	return result;
}

1114 1115
static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action,
					  int result)
1116
{
1117 1118
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_port *port = erp_action->port;
1119
	struct scsi_device *sdev = erp_action->sdev;
1120 1121 1122

	switch (erp_action->action) {

1123 1124
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		result = zfcp_erp_strategy_check_lun(sdev, result);
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
		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;
1137 1138
}

1139
static int zfcp_erp_strat_change_det(atomic_t *target_status, u32 erp_status)
1140
{
1141
	int status = atomic_read(target_status);
1142

1143 1144 1145
	if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
	    (erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
		return 1; /* take it online */
1146

1147 1148 1149 1150 1151
	if (!(status & ZFCP_STATUS_COMMON_RUNNING) &&
	    !(erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY))
		return 1; /* take it offline */

	return 0;
1152 1153
}

1154
static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
L
Linus Torvalds 已提交
1155
{
1156 1157 1158
	int action = act->action;
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
1159 1160
	struct scsi_device *sdev = act->sdev;
	struct zfcp_scsi_dev *zfcp_sdev;
1161
	u32 erp_status = act->status;
L
Linus Torvalds 已提交
1162

1163
	switch (action) {
L
Linus Torvalds 已提交
1164
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1165 1166 1167
		if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) {
			_zfcp_erp_adapter_reopen(adapter,
						 ZFCP_STATUS_COMMON_ERP_FAILED,
1168
						 "ersscg1", NULL);
1169 1170
			return ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1171 1172 1173 1174
		break;

	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
	case ZFCP_ERP_ACTION_REOPEN_PORT:
1175 1176 1177
		if (zfcp_erp_strat_change_det(&port->status, erp_status)) {
			_zfcp_erp_port_reopen(port,
					      ZFCP_STATUS_COMMON_ERP_FAILED,
1178
					      "ersscg2", NULL);
1179 1180
			return ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1181 1182
		break;

1183 1184 1185 1186 1187 1188
	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,
					     "ersscg3", NULL, 0);
1189 1190
			return ZFCP_ERP_EXIT;
		}
L
Linus Torvalds 已提交
1191 1192
		break;
	}
1193
	return ret;
L
Linus Torvalds 已提交
1194 1195
}

1196
static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1197
{
1198
	struct zfcp_adapter *adapter = erp_action->adapter;
1199
	struct zfcp_scsi_dev *zfcp_sdev;
L
Linus Torvalds 已提交
1200

1201 1202 1203 1204
	adapter->erp_total_count--;
	if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
		adapter->erp_low_mem_count--;
		erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
1205
	}
L
Linus Torvalds 已提交
1206

1207
	list_del(&erp_action->list);
S
Swen Schillig 已提交
1208
	zfcp_dbf_rec_action("eractd1", erp_action);
L
Linus Torvalds 已提交
1209

1210
	switch (erp_action->action) {
1211 1212
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
1213
		atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1214
				  &zfcp_sdev->status);
1215
		break;
L
Linus Torvalds 已提交
1216

1217 1218 1219 1220 1221
	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 已提交
1222

1223 1224 1225 1226 1227
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
				  &erp_action->adapter->status);
		break;
	}
L
Linus Torvalds 已提交
1228 1229
}

1230
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
L
Linus Torvalds 已提交
1231
{
1232 1233
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
1234
	struct scsi_device *sdev = act->sdev;
L
Linus Torvalds 已提交
1235

1236
	switch (act->action) {
1237
	case ZFCP_ERP_ACTION_REOPEN_LUN:
1238
		if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
1239
			scsi_device_put(sdev);
1240
		break;
L
Linus Torvalds 已提交
1241

1242
	case ZFCP_ERP_ACTION_REOPEN_PORT:
1243 1244
		if (result == ZFCP_ERP_SUCCEEDED)
			zfcp_scsi_schedule_rport_register(port);
1245 1246
		/* fall through */
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
1247
		put_device(&port->dev);
1248 1249 1250
		break;

	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1251
		if (result == ZFCP_ERP_SUCCEEDED) {
1252
			register_service_level(&adapter->service_level);
1253
			queue_work(adapter->work_queue, &adapter->scan_work);
1254 1255
		} else
			unregister_service_level(&adapter->service_level);
1256
		kref_put(&adapter->ref, zfcp_adapter_release);
1257 1258
		break;
	}
L
Linus Torvalds 已提交
1259 1260
}

1261
static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1262
{
1263 1264 1265 1266 1267 1268 1269
	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);
1270 1271
	case ZFCP_ERP_ACTION_REOPEN_LUN:
		return zfcp_erp_lun_strategy(erp_action);
1272 1273
	}
	return ZFCP_ERP_FAILED;
L
Linus Torvalds 已提交
1274 1275
}

1276
static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1277 1278
{
	int retval;
1279
	unsigned long flags;
1280
	struct zfcp_adapter *adapter = erp_action->adapter;
L
Linus Torvalds 已提交
1281

1282
	kref_get(&adapter->ref);
L
Linus Torvalds 已提交
1283

1284
	write_lock_irqsave(&adapter->erp_lock, flags);
1285
	zfcp_erp_strategy_check_fsfreq(erp_action);
L
Linus Torvalds 已提交
1286

1287 1288 1289 1290
	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
		zfcp_erp_action_dequeue(erp_action);
		retval = ZFCP_ERP_DISMISSED;
		goto unlock;
1291
	}
L
Linus Torvalds 已提交
1292

1293 1294 1295 1296 1297
	if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
		retval = ZFCP_ERP_FAILED;
		goto check_target;
	}

1298
	zfcp_erp_action_to_running(erp_action);
L
Linus Torvalds 已提交
1299

1300
	/* no lock to allow for blocking operations */
1301
	write_unlock_irqrestore(&adapter->erp_lock, flags);
1302
	retval = zfcp_erp_strategy_do_action(erp_action);
1303
	write_lock_irqsave(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1304

1305 1306
	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
		retval = ZFCP_ERP_CONTINUES;
1307

1308 1309 1310 1311 1312
	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 已提交
1313
		}
1314
		if (adapter->erp_total_count == adapter->erp_low_mem_count)
1315
			_zfcp_erp_adapter_reopen(adapter, 0, "erstgy1", NULL);
1316 1317 1318
		else {
			zfcp_erp_strategy_memwait(erp_action);
			retval = ZFCP_ERP_CONTINUES;
L
Linus Torvalds 已提交
1319
		}
1320
		goto unlock;
L
Linus Torvalds 已提交
1321

1322 1323 1324 1325
	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 已提交
1326
		}
1327
		goto unlock;
L
Linus Torvalds 已提交
1328 1329
	}

1330
check_target:
1331 1332 1333 1334 1335
	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;
1336 1337 1338 1339
	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 已提交
1340

1341
 unlock:
1342
	write_unlock_irqrestore(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1343

1344 1345
	if (retval != ZFCP_ERP_CONTINUES)
		zfcp_erp_action_cleanup(erp_action, retval);
L
Linus Torvalds 已提交
1346

1347
	kref_put(&adapter->ref, zfcp_adapter_release);
L
Linus Torvalds 已提交
1348 1349 1350
	return retval;
}

1351
static int zfcp_erp_thread(void *data)
L
Linus Torvalds 已提交
1352
{
1353 1354 1355 1356
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
	struct list_head *next;
	struct zfcp_erp_action *act;
	unsigned long flags;
1357

1358
	for (;;) {
S
Swen Schillig 已提交
1359
		zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf);
1360 1361 1362
		wait_event_interruptible(adapter->erp_ready_wq,
			   !list_empty(&adapter->erp_ready_head) ||
			   kthread_should_stop());
S
Swen Schillig 已提交
1363
		zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf);
1364

1365 1366 1367
		if (kthread_should_stop())
			break;

1368 1369 1370
		write_lock_irqsave(&adapter->erp_lock, flags);
		next = adapter->erp_ready_head.next;
		write_unlock_irqrestore(&adapter->erp_lock, flags);
L
Linus Torvalds 已提交
1371

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

1375 1376 1377
			/* there is more to come after dismission, no notify */
			if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
				zfcp_erp_wakeup(adapter);
L
Linus Torvalds 已提交
1378 1379 1380
		}
	}

1381 1382
	return 0;
}
L
Linus Torvalds 已提交
1383

1384 1385 1386 1387 1388 1389 1390 1391
/**
 * 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)
{
1392
	struct task_struct *thread;
L
Linus Torvalds 已提交
1393

1394 1395 1396
	thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
			     dev_name(&adapter->ccw_device->dev));
	if (IS_ERR(thread)) {
1397
		dev_err(&adapter->ccw_device->dev,
1398
			"Creating an ERP thread for the FCP device failed.\n");
1399
		return PTR_ERR(thread);
L
Linus Torvalds 已提交
1400
	}
1401 1402

	adapter->erp_thread = thread;
1403 1404
	return 0;
}
L
Linus Torvalds 已提交
1405

1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
/**
 * 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)
{
1417 1418
	kthread_stop(adapter->erp_thread);
	adapter->erp_thread = NULL;
1419 1420
	WARN_ON(!list_empty(&adapter->erp_ready_head));
	WARN_ON(!list_empty(&adapter->erp_running_head));
L
Linus Torvalds 已提交
1421 1422
}

1423 1424 1425 1426 1427 1428
/**
 * zfcp_erp_adapter_failed - Set adapter status to failed.
 * @adapter: Failed adapter.
 * @id: Event id for debug trace.
 * @ref: Reference for debug trace.
 */
1429
void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref)
L
Linus Torvalds 已提交
1430
{
1431 1432 1433
	zfcp_erp_modify_adapter_status(adapter, id, ref,
				       ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
}
L
Linus Torvalds 已提交
1434

1435 1436 1437 1438 1439 1440
/**
 * zfcp_erp_port_failed - Set port status to failed.
 * @port: Failed port.
 * @id: Event id for debug trace.
 * @ref: Reference for debug trace.
 */
1441
void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref)
1442 1443 1444
{
	zfcp_erp_modify_port_status(port, id, ref,
				    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
L
Linus Torvalds 已提交
1445 1446 1447
}

/**
1448 1449
 * zfcp_erp_lun_failed - Set LUN status to failed.
 * @sdev: Failed SCSI device / LUN
1450 1451
 * @id: Event id for debug trace.
 * @ref: Reference for debug trace.
L
Linus Torvalds 已提交
1452
 */
1453
void zfcp_erp_lun_failed(struct scsi_device *sdev, char *id, void *ref)
L
Linus Torvalds 已提交
1454
{
1455 1456
	zfcp_erp_modify_lun_status(sdev, id, ref,
				   ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
L
Linus Torvalds 已提交
1457 1458
}

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

1470 1471 1472 1473 1474 1475 1476 1477
/**
 * zfcp_erp_modify_adapter_status - change adapter status bits
 * @adapter: adapter to change the status
 * @id: id for the debug trace
 * @ref: reference for the debug trace
 * @mask: status bits to change
 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
 *
1478
 * Changes in common status bits are propagated to attached ports and LUNs.
1479
 */
1480
void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
1481
				    void *ref, u32 mask, int set_or_clear)
L
Linus Torvalds 已提交
1482 1483
{
	struct zfcp_port *port;
1484
	unsigned long flags;
1485
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
L
Linus Torvalds 已提交
1486

1487 1488
	if (set_or_clear == ZFCP_SET) {
		if (status_change_set(mask, &adapter->status))
S
Swen Schillig 已提交
1489
			zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
1490 1491 1492
		atomic_set_mask(mask, &adapter->status);
	} else {
		if (status_change_clear(mask, &adapter->status))
S
Swen Schillig 已提交
1493
			zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
1494 1495 1496 1497 1498
		atomic_clear_mask(mask, &adapter->status);
		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
			atomic_set(&adapter->erp_counter, 0);
	}

1499 1500 1501
	if (common_mask) {
		read_lock_irqsave(&adapter->port_list_lock, flags);
		list_for_each_entry(port, &adapter->port_list, list)
1502 1503
			zfcp_erp_modify_port_status(port, id, ref, common_mask,
						    set_or_clear);
1504 1505
		read_unlock_irqrestore(&adapter->port_list_lock, flags);
	}
L
Linus Torvalds 已提交
1506 1507
}

1508 1509 1510 1511 1512 1513 1514 1515
/**
 * zfcp_erp_modify_port_status - change port status bits
 * @port: port to change the status bits
 * @id: id for the debug trace
 * @ref: reference for the debug trace
 * @mask: status bits to change
 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
 *
1516
 * Changes in common status bits are propagated to attached LUNs.
1517
 */
1518
void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
1519
				 u32 mask, int set_or_clear)
L
Linus Torvalds 已提交
1520
{
1521
	struct scsi_device *sdev;
1522
	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
L
Linus Torvalds 已提交
1523

1524 1525
	if (set_or_clear == ZFCP_SET) {
		if (status_change_set(mask, &port->status))
S
Swen Schillig 已提交
1526
			zfcp_dbf_rec_port(id, ref, port);
1527 1528 1529
		atomic_set_mask(mask, &port->status);
	} else {
		if (status_change_clear(mask, &port->status))
S
Swen Schillig 已提交
1530
			zfcp_dbf_rec_port(id, ref, port);
1531 1532 1533 1534
		atomic_clear_mask(mask, &port->status);
		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
			atomic_set(&port->erp_counter, 0);
	}
L
Linus Torvalds 已提交
1535

1536 1537 1538 1539 1540 1541
	if (common_mask)
		shost_for_each_device(sdev, port->adapter->scsi_host)
			if (sdev_to_zfcp(sdev)->port == port)
				zfcp_erp_modify_lun_status(sdev, id, ref,
							   common_mask,
							   set_or_clear);
L
Linus Torvalds 已提交
1542 1543
}

1544
/**
1545 1546
 * zfcp_erp_modify_lun_status - change LUN status bits
 * @sdev: SCSI device / LUN where to change the status bits
1547 1548 1549 1550 1551
 * @id: id for the debug trace
 * @ref: reference for the debug trace
 * @mask: status bits to change
 * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
 */
1552 1553
void zfcp_erp_modify_lun_status(struct scsi_device *sdev, char *id, void *ref,
				u32 mask, int set_or_clear)
L
Linus Torvalds 已提交
1554
{
1555 1556
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

1557
	if (set_or_clear == ZFCP_SET) {
1558 1559 1560
		if (status_change_set(mask, &zfcp_sdev->status))
			zfcp_dbf_rec_lun(id, ref, sdev);
		atomic_set_mask(mask, &zfcp_sdev->status);
1561
	} else {
1562 1563 1564
		if (status_change_clear(mask, &zfcp_sdev->status))
			zfcp_dbf_rec_lun(id, ref, sdev);
		atomic_clear_mask(mask, &zfcp_sdev->status);
1565
		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
1566
			atomic_set(&zfcp_sdev->erp_counter, 0);
1567 1568
		}
	}
L
Linus Torvalds 已提交
1569 1570
}

1571 1572 1573 1574 1575 1576
/**
 * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP
 * @port: The "boxed" port.
 * @id: The debug trace id.
 * @id: Reference for the debug trace.
 */
1577
void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref)
1578
{
1579 1580
	zfcp_erp_modify_port_status(port, id, ref,
				    ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
1581
	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
1582 1583
}

1584
/**
1585 1586
 * zfcp_erp_lun_boxed - Mark LUN as "boxed" and start ERP
 * @sdev: The "boxed" SCSI device / LUN.
1587
 * @id: The debug trace id.
1588
 * @ref: Reference for the debug trace.
1589
 */
1590
void zfcp_erp_lun_boxed(struct scsi_device *sdev, char *id, void *ref)
1591
{
1592 1593 1594
	zfcp_erp_modify_lun_status(sdev, id, ref,
				   ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
	zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
1595
}