qla_os.c 105 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2
 * QLogic Fibre Channel HBA Driver
3
 * Copyright (c)  2003-2008 QLogic Corporation
Linus Torvalds's avatar
Linus Torvalds committed
4
 *
5
 * See LICENSE.qla2xxx for copyright and licensing details.
Linus Torvalds's avatar
Linus Torvalds committed
6
7
8
9
10
11
 */
#include "qla_def.h"

#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
12
#include <linux/kthread.h>
13
#include <linux/mutex.h>
14
#include <linux/kobject.h>
15
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
16
17
18
19
20
21
22
23
24
25
26

#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>

/*
 * Driver version
 */
char qla2x00_version_str[40];

27
28
static int apidev_major;

Linus Torvalds's avatar
Linus Torvalds committed
29
30
31
/*
 * SRB allocation cache
 */
32
static struct kmem_cache *srb_cachep;
Linus Torvalds's avatar
Linus Torvalds committed
33

34
35
36
37
38
/*
 * CT6 CTX allocation cache
 */
static struct kmem_cache *ctx_cachep;

Linus Torvalds's avatar
Linus Torvalds committed
39
40
41
42
43
int ql2xlogintimeout = 20;
module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xlogintimeout,
		"Login timeout value in seconds.");

44
int qlport_down_retry;
Linus Torvalds's avatar
Linus Torvalds committed
45
46
module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(qlport_down_retry,
47
		"Maximum number of command retries to a port that returns "
Linus Torvalds's avatar
Linus Torvalds committed
48
49
50
51
52
53
		"a PORT-DOWN status.");

int ql2xplogiabsentdevice;
module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xplogiabsentdevice,
		"Option to enable PLOGI to devices that are not present after "
54
		"a Fabric scan.  This is needed for several broken switches. "
Linus Torvalds's avatar
Linus Torvalds committed
55
56
57
58
59
60
61
		"Default is 0 - no PLOGI. 1 - perfom PLOGI.");

int ql2xloginretrycount = 0;
module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xloginretrycount,
		"Specify an alternate value for the NVRAM login retry count.");

62
63
64
65
66
67
68
int ql2xallocfwdump = 1;
module_param(ql2xallocfwdump, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xallocfwdump,
		"Option to enable allocation of memory for a firmware dump "
		"during HBA initialization.  Memory allocation requirements "
		"vary by ISP type.  Default is 1 - allocate memory.");

69
int ql2xextended_error_logging;
70
module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
71
MODULE_PARM_DESC(ql2xextended_error_logging,
72
73
74
		"Option to enable extended error logging, "
		"Default is 0 - no logging. 1 - log errors.");

75
76
77
78
79
80
int ql2xshiftctondsd = 6;
module_param(ql2xshiftctondsd, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xshiftctondsd,
		"Set to control shifting of command type processing "
		"based on total number of SG elements.");

Linus Torvalds's avatar
Linus Torvalds committed
81
82
static void qla2x00_free_device(scsi_qla_host_t *);

83
int ql2xfdmienable=1;
84
85
module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfdmienable,
86
87
		"Enables FDMI registrations. "
		"0 - no FDMI. Default is 1 - perform FDMI.");
88

89
90
91
92
93
94
#define MAX_Q_DEPTH    32
static int ql2xmaxqdepth = MAX_Q_DEPTH;
module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xmaxqdepth,
		"Maximum queue depth to report for target devices.");

95
96
97
98
99
100
101
102
103
104
105
106
107
/* Do not change the value of this after module load */
int ql2xenabledif = 1;
module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenabledif,
		" Enable T10-CRC-DIF "
		" Default is 0 - No DIF Support. 1 - Enable it");

int ql2xenablehba_err_chk;
module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenablehba_err_chk,
		" Enable T10-CRC-DIF Error isolation by HBA"
		" Default is 0 - Error isolation disabled, 1 - Enable it");

108
109
110
111
112
113
int ql2xiidmaenable=1;
module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xiidmaenable,
		"Enables iIDMA settings "
		"Default is 1 - perform iIDMA. 0 - no iIDMA.");

114
115
116
117
118
119
int ql2xmaxqueues = 1;
module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xmaxqueues,
		"Enables MQ settings "
		"Default is 1 for single queue. Set it to number \
			of queues in MQ mode.");
120
121
122
123
124
125
126

int ql2xmultique_tag;
module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xmultique_tag,
		"Enables CPU affinity settings for the driver "
		"Default is 0 for no affinity of request and response IO. "
		"Set it to 1 to turn on the cpu affinity.");
127
128
129
130
131
132
133
134
135
136

int ql2xfwloadbin;
module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfwloadbin,
		"Option to specify location from which to load ISP firmware:\n"
		" 2 -- load firmware via the request_firmware() (hotplug)\n"
		"      interface.\n"
		" 1 -- load firmware from flash.\n"
		" 0 -- use default semantics.\n");

137
138
139
140
141
142
int ql2xetsenable;
module_param(ql2xetsenable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xetsenable,
		"Enables firmware ETS burst."
		"Default is 0 - skip ETS enablement.");

143
int ql2xdbwr = 1;
144
145
146
147
148
149
150
151
152
153
154
155
156
module_param(ql2xdbwr, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xdbwr,
	"Option to specify scheme for request queue posting\n"
	" 0 -- Regular doorbell.\n"
	" 1 -- CAMRAM doorbell (faster).\n");

int ql2xdontresethba;
module_param(ql2xdontresethba, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xdontresethba,
	"Option to specify reset behaviour\n"
	" 0 (Default) -- Reset on failure.\n"
	" 1 -- Do not reset on failure.\n");

157
158
159
160
161
162
int ql2xtargetreset = 1;
module_param(ql2xtargetreset, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xtargetreset,
		 "Enable target reset."
		 "Default is 1 - use hw defaults.");

163

164
165
166
167
168
int ql2xasynctmfenable;
module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xasynctmfenable,
		"Enables issue of TM IOCBs asynchronously via IOCB mechanism"
		"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
Linus Torvalds's avatar
Linus Torvalds committed
169
/*
170
 * SCSI host template entry points
Linus Torvalds's avatar
Linus Torvalds committed
171
172
 */
static int qla2xxx_slave_configure(struct scsi_device * device);
173
static int qla2xxx_slave_alloc(struct scsi_device *);
174
175
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
static void qla2xxx_scan_start(struct Scsi_Host *);
176
static void qla2xxx_slave_destroy(struct scsi_device *);
177
static int qla2xxx_queuecommand(struct scsi_cmnd *cmd,
178
		void (*fn)(struct scsi_cmnd *));
Linus Torvalds's avatar
Linus Torvalds committed
179
180
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
181
static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
Linus Torvalds's avatar
Linus Torvalds committed
182
183
184
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);

185
static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
186
187
static int qla2x00_change_queue_type(struct scsi_device *, int);

188
struct scsi_host_template qla2xxx_driver_template = {
Linus Torvalds's avatar
Linus Torvalds committed
189
	.module			= THIS_MODULE,
190
	.name			= QLA2XXX_DRIVER_NAME,
191
	.queuecommand		= qla2xxx_queuecommand,
192
193
194

	.eh_abort_handler	= qla2xxx_eh_abort,
	.eh_device_reset_handler = qla2xxx_eh_device_reset,
195
	.eh_target_reset_handler = qla2xxx_eh_target_reset,
196
197
198
199
200
201
202
	.eh_bus_reset_handler	= qla2xxx_eh_bus_reset,
	.eh_host_reset_handler	= qla2xxx_eh_host_reset,

	.slave_configure	= qla2xxx_slave_configure,

	.slave_alloc		= qla2xxx_slave_alloc,
	.slave_destroy		= qla2xxx_slave_destroy,
203
204
	.scan_finished		= qla2xxx_scan_finished,
	.scan_start		= qla2xxx_scan_start,
205
206
	.change_queue_depth	= qla2x00_change_queue_depth,
	.change_queue_type	= qla2x00_change_queue_type,
207
208
209
210
211
212
	.this_id		= -1,
	.cmd_per_lun		= 3,
	.use_clustering		= ENABLE_CLUSTERING,
	.sg_tablesize		= SG_ALL,

	.max_sectors		= 0xFFFF,
213
	.shost_attrs		= qla2x00_host_attrs,
214
215
};

Linus Torvalds's avatar
Linus Torvalds committed
216
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
217
struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
218
219
220
221
222
223

/* TODO Convert to inlines
 *
 * Timer routines
 */

224
__inline__ void
225
qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval)
Linus Torvalds's avatar
Linus Torvalds committed
226
{
227
228
229
230
231
232
	init_timer(&vha->timer);
	vha->timer.expires = jiffies + interval * HZ;
	vha->timer.data = (unsigned long)vha;
	vha->timer.function = (void (*)(unsigned long))func;
	add_timer(&vha->timer);
	vha->timer_active = 1;
Linus Torvalds's avatar
Linus Torvalds committed
233
234
235
}

static inline void
236
qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
Linus Torvalds's avatar
Linus Torvalds committed
237
{
238
239
240
241
	/* Currently used for 82XX only. */
	if (vha->device_flags & DFLG_DEV_FAILED)
		return;

242
	mod_timer(&vha->timer, jiffies + interval * HZ);
Linus Torvalds's avatar
Linus Torvalds committed
243
244
}

Adrian Bunk's avatar
Adrian Bunk committed
245
static __inline__ void
246
qla2x00_stop_timer(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
247
{
248
249
	del_timer_sync(&vha->timer);
	vha->timer_active = 0;
Linus Torvalds's avatar
Linus Torvalds committed
250
251
252
253
254
255
}

static int qla2x00_do_dpc(void *data);

static void qla2x00_rst_aen(scsi_qla_host_t *);

256
257
static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
	struct req_que **, struct rsp_que **);
258
259
static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
Linus Torvalds's avatar
Linus Torvalds committed
260
261

/* -------------------------------------------------------------------------- */
262
263
static int qla2x00_alloc_queues(struct qla_hw_data *ha)
{
264
	ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
265
266
267
268
269
270
271
				GFP_KERNEL);
	if (!ha->req_q_map) {
		qla_printk(KERN_WARNING, ha,
			"Unable to allocate memory for request queue ptrs\n");
		goto fail_req_map;
	}

272
	ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
				GFP_KERNEL);
	if (!ha->rsp_q_map) {
		qla_printk(KERN_WARNING, ha,
			"Unable to allocate memory for response queue ptrs\n");
		goto fail_rsp_map;
	}
	set_bit(0, ha->rsp_qid_map);
	set_bit(0, ha->req_qid_map);
	return 1;

fail_rsp_map:
	kfree(ha->req_q_map);
	ha->req_q_map = NULL;
fail_req_map:
	return -ENOMEM;
}

290
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
291
292
293
294
295
296
297
298
299
300
{
	if (req && req->ring)
		dma_free_coherent(&ha->pdev->dev,
		(req->length + 1) * sizeof(request_t),
		req->ring, req->dma);

	kfree(req);
	req = NULL;
}

301
302
303
304
305
306
307
308
309
310
311
static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
{
	if (rsp && rsp->ring)
		dma_free_coherent(&ha->pdev->dev,
		(rsp->length + 1) * sizeof(response_t),
		rsp->ring, rsp->dma);

	kfree(rsp);
	rsp = NULL;
}

312
313
314
315
316
317
static void qla2x00_free_queues(struct qla_hw_data *ha)
{
	struct req_que *req;
	struct rsp_que *rsp;
	int cnt;

318
	for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
319
		req = ha->req_q_map[cnt];
320
		qla2x00_free_req_que(ha, req);
321
322
323
	}
	kfree(ha->req_q_map);
	ha->req_q_map = NULL;
324
325
326
327
328
329
330

	for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
		rsp = ha->rsp_q_map[cnt];
		qla2x00_free_rsp_que(ha, rsp);
	}
	kfree(ha->rsp_q_map);
	ha->rsp_q_map = NULL;
331
332
}

333
334
335
336
337
338
static int qla25xx_setup_mode(struct scsi_qla_host *vha)
{
	uint16_t options = 0;
	int ques, req, ret;
	struct qla_hw_data *ha = vha->hw;

339
340
341
342
343
	if (!(ha->fw_attributes & BIT_6)) {
		qla_printk(KERN_INFO, ha,
			"Firmware is not multi-queue capable\n");
		goto fail;
	}
344
345
346
347
348
349
350
351
352
353
	if (ql2xmultique_tag) {
		/* create a request queue for IO */
		options |= BIT_7;
		req = qla25xx_create_req_que(ha, options, 0, 0, -1,
			QLA_DEFAULT_QUE_QOS);
		if (!req) {
			qla_printk(KERN_WARNING, ha,
				"Can't create request queue\n");
			goto fail;
		}
354
		ha->wq = create_workqueue("qla2xxx_wq");
355
356
357
358
359
360
361
362
363
364
		vha->req = ha->req_q_map[req];
		options |= BIT_1;
		for (ques = 1; ques < ha->max_rsp_queues; ques++) {
			ret = qla25xx_create_rsp_que(ha, options, 0, 0, req);
			if (!ret) {
				qla_printk(KERN_WARNING, ha,
					"Response Queue create failed\n");
				goto fail2;
			}
		}
365
366
		ha->flags.cpu_affinity_enabled = 1;

367
368
369
370
371
372
373
374
		DEBUG2(qla_printk(KERN_INFO, ha,
			"CPU affinity mode enabled, no. of response"
			" queues:%d, no. of request queues:%d\n",
			ha->max_rsp_queues, ha->max_req_queues));
	}
	return 0;
fail2:
	qla25xx_delete_queues(vha);
375
376
	destroy_workqueue(ha->wq);
	ha->wq = NULL;
377
378
fail:
	ha->mqenable = 0;
379
380
381
	kfree(ha->req_q_map);
	kfree(ha->rsp_q_map);
	ha->max_req_queues = ha->max_rsp_queues = 1;
382
383
384
	return 1;
}

Linus Torvalds's avatar
Linus Torvalds committed
385
static char *
386
qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str)
Linus Torvalds's avatar
Linus Torvalds committed
387
{
388
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
	static char *pci_bus_modes[] = {
		"33", "66", "100", "133",
	};
	uint16_t pci_bus;

	strcpy(str, "PCI");
	pci_bus = (ha->pci_attr & (BIT_9 | BIT_10)) >> 9;
	if (pci_bus) {
		strcat(str, "-X (");
		strcat(str, pci_bus_modes[pci_bus]);
	} else {
		pci_bus = (ha->pci_attr & BIT_8) >> 8;
		strcat(str, " (");
		strcat(str, pci_bus_modes[pci_bus]);
	}
	strcat(str, " MHz)");

	return (str);
}

409
static char *
410
qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
411
412
{
	static char *pci_bus_modes[] = { "33", "66", "100", "133", };
413
	struct qla_hw_data *ha = vha->hw;
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
	uint32_t pci_bus;
	int pcie_reg;

	pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP);
	if (pcie_reg) {
		char lwstr[6];
		uint16_t pcie_lstat, lspeed, lwidth;

		pcie_reg += 0x12;
		pci_read_config_word(ha->pdev, pcie_reg, &pcie_lstat);
		lspeed = pcie_lstat & (BIT_0 | BIT_1 | BIT_2 | BIT_3);
		lwidth = (pcie_lstat &
		    (BIT_4 | BIT_5 | BIT_6 | BIT_7 | BIT_8 | BIT_9)) >> 4;

		strcpy(str, "PCIe (");
		if (lspeed == 1)
430
			strcat(str, "2.5GT/s ");
431
		else if (lspeed == 2)
432
			strcat(str, "5.0GT/s ");
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
		else
			strcat(str, "<unknown> ");
		snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
		strcat(str, lwstr);

		return str;
	}

	strcpy(str, "PCI");
	pci_bus = (ha->pci_attr & CSRX_PCIX_BUS_MODE_MASK) >> 8;
	if (pci_bus == 0 || pci_bus == 8) {
		strcat(str, " (");
		strcat(str, pci_bus_modes[pci_bus >> 3]);
	} else {
		strcat(str, "-X ");
		if (pci_bus & BIT_2)
			strcat(str, "Mode 2");
		else
			strcat(str, "Mode 1");
		strcat(str, " (");
		strcat(str, pci_bus_modes[pci_bus & ~BIT_2]);
	}
	strcat(str, " MHz)");

	return str;
}

460
static char *
461
qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
Linus Torvalds's avatar
Linus Torvalds committed
462
463
{
	char un_str[10];
464
	struct qla_hw_data *ha = vha->hw;
465

Linus Torvalds's avatar
Linus Torvalds committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
	sprintf(str, "%d.%02d.%02d ", ha->fw_major_version,
	    ha->fw_minor_version,
	    ha->fw_subminor_version);

	if (ha->fw_attributes & BIT_9) {
		strcat(str, "FLX");
		return (str);
	}

	switch (ha->fw_attributes & 0xFF) {
	case 0x7:
		strcat(str, "EF");
		break;
	case 0x17:
		strcat(str, "TP");
		break;
	case 0x37:
		strcat(str, "IP");
		break;
	case 0x77:
		strcat(str, "VI");
		break;
	default:
		sprintf(un_str, "(%x)", ha->fw_attributes);
		strcat(str, un_str);
		break;
	}
	if (ha->fw_attributes & 0x100)
		strcat(str, "X");

	return (str);
}

499
static char *
500
qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
501
{
502
	struct qla_hw_data *ha = vha->hw;
503

504
505
	sprintf(str, "%d.%02d.%02d (%x)", ha->fw_major_version,
	    ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes);
506
507
508
509
	return str;
}

static inline srb_t *
510
qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
511
512
513
    struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
	srb_t *sp;
514
	struct qla_hw_data *ha = vha->hw;
515
516
517
518
519

	sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
	if (!sp)
		return sp;

520
	atomic_set(&sp->ref_count, 1);
521
522
523
524
525
	sp->fcport = fcport;
	sp->cmd = cmd;
	sp->flags = 0;
	CMD_SP(cmd) = (void *)sp;
	cmd->scsi_done = done;
526
	sp->ctx = NULL;
527
528
529
530

	return sp;
}

Linus Torvalds's avatar
Linus Torvalds committed
531
static int
532
qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
533
{
534
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
535
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
536
	struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
537
538
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
539
540
541
	srb_t *sp;
	int rval;

542
543
	if (ha->flags.eeh_busy) {
		if (ha->flags.pci_channel_io_perm_failure)
544
			cmd->result = DID_NO_CONNECT << 16;
545
546
		else
			cmd->result = DID_REQUEUE << 16;
547
548
549
		goto qc24_fail_command;
	}

550
551
552
	rval = fc_remote_port_chkready(rport);
	if (rval) {
		cmd->result = rval;
553
554
555
		goto qc24_fail_command;
	}

556
	/* Close window on fcport/rport state-transitioning. */
557
558
	if (fcport->drport)
		goto qc24_target_busy;
559

560
561
562
563
564
565
566
567
	if (!vha->flags.difdix_supported &&
		scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
			DEBUG2(qla_printk(KERN_ERR, ha,
			    "DIF Cap Not Reg, fail DIF capable cmd's:%x\n",
			    cmd->cmnd[0]));
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
	}
568
569
	if (atomic_read(&fcport->state) != FCS_ONLINE) {
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
570
		    atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
571
572
573
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
		}
574
		goto qc24_target_busy;
575
576
	}

577
	spin_unlock_irq(vha->host->host_lock);
578

579
	sp = qla2x00_get_new_sp(base_vha, fcport, cmd, done);
580
581
582
	if (!sp)
		goto qc24_host_busy_lock;

583
	rval = ha->isp_ops->start_scsi(sp);
584
585
586
	if (rval != QLA_SUCCESS)
		goto qc24_host_busy_free_sp;

587
	spin_lock_irq(vha->host->host_lock);
588
589
590
591

	return 0;

qc24_host_busy_free_sp:
592
593
	qla2x00_sp_free_dma(sp);
	mempool_free(sp, ha->srb_mempool);
594
595

qc24_host_busy_lock:
596
	spin_lock_irq(vha->host->host_lock);
597
598
	return SCSI_MLQUEUE_HOST_BUSY;

599
600
601
qc24_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

602
603
604
605
606
607
608
qc24_fail_command:
	done(cmd);

	return 0;
}


Linus Torvalds's avatar
Linus Torvalds committed
609
610
611
612
613
614
615
616
617
618
619
620
621
/*
 * qla2x00_eh_wait_on_command
 *    Waits for the command to be returned by the Firmware for some
 *    max time.
 *
 * Input:
 *    cmd = Scsi Command to wait on.
 *
 * Return:
 *    Not Found : 0
 *    Found : 1
 */
static int
622
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
Linus Torvalds's avatar
Linus Torvalds committed
623
{
624
625
#define ABORT_POLLING_PERIOD	1000
#define ABORT_WAIT_ITER		((10 * 1000) / (ABORT_POLLING_PERIOD))
626
	unsigned long wait_iter = ABORT_WAIT_ITER;
627
628
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
629
	int ret = QLA_SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
630

631
632
633
634
635
	if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
		DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n"));
		return ret;
	}

636
	while (CMD_SP(cmd) && wait_iter--) {
637
		msleep(ABORT_POLLING_PERIOD);
638
639
640
	}
	if (CMD_SP(cmd))
		ret = QLA_FUNCTION_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
641

642
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
643
644
645
646
}

/*
 * qla2x00_wait_for_hba_online
647
 *    Wait till the HBA is online after going through
Linus Torvalds's avatar
Linus Torvalds committed
648
649
650
651
652
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline
 *
 * Input:
 *     ha - pointer to host adapter structure
653
654
 *
 * Note:
Linus Torvalds's avatar
Linus Torvalds committed
655
656
657
658
659
660
661
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online) : 0
 *    Failed  (Adapter is offline/disabled) : 1
 */
662
int
663
qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
664
{
665
666
	int		return_status;
	unsigned long	wait_online;
667
668
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds's avatar
Linus Torvalds committed
669

670
	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
671
672
673
674
	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
	    ha->dpc_active) && time_before(jiffies, wait_online)) {
Linus Torvalds's avatar
Linus Torvalds committed
675
676
677

		msleep(1000);
	}
678
	if (base_vha->flags.online)
679
		return_status = QLA_SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
680
681
682
683
684
685
	else
		return_status = QLA_FUNCTION_FAILED;

	return (return_status);
}

686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
/*
 * qla2x00_wait_for_reset_ready
 *    Wait till the HBA is online after going through
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline or flash
 *    operations are in progress.
 *
 * Input:
 *     ha - pointer to host adapter structure
 *
 * Note:
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online/no flash ops) : 0
 *    Failed  (Adapter is offline/disabled/flash ops in progress) : 1
 */
int
qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha)
{
	int		return_status;
	unsigned long	wait_online;
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);

	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
	    ha->optrom_state != QLA_SWAITING ||
	    ha->dpc_active) && time_before(jiffies, wait_online))
		msleep(1000);

	if (base_vha->flags.online &&  ha->optrom_state == QLA_SWAITING)
		return_status = QLA_SUCCESS;
	else
		return_status = QLA_FUNCTION_FAILED;

	DEBUG2(printk("%s return_status=%d\n", __func__, return_status));

	return return_status;
}

730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
int
qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
{
	int		return_status;
	unsigned long	wait_reset;
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);

	wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ);
	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
	    ha->dpc_active) && time_before(jiffies, wait_reset)) {

		msleep(1000);

		if (!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
		    ha->flags.chip_reset_done)
			break;
	}
	if (ha->flags.chip_reset_done)
		return_status = QLA_SUCCESS;
	else
		return_status = QLA_FUNCTION_FAILED;

	return return_status;
}

Linus Torvalds's avatar
Linus Torvalds committed
758
759
760
/*
 * qla2x00_wait_for_loop_ready
 *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
761
 *    to be in LOOP_READY state.
Linus Torvalds's avatar
Linus Torvalds committed
762
763
 * Input:
 *     ha - pointer to host adapter structure
764
765
 *
 * Note:
Linus Torvalds's avatar
Linus Torvalds committed
766
767
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
768
 *
Linus Torvalds's avatar
Linus Torvalds committed
769
770
771
772
773
 *
 * Return:
 *    Success (LOOP_READY) : 0
 *    Failed  (LOOP_NOT_READY) : 1
 */
774
static inline int
775
qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
776
777
778
{
	int 	 return_status = QLA_SUCCESS;
	unsigned long loop_timeout ;
779
780
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds's avatar
Linus Torvalds committed
781
782

	/* wait for 5 min at the max for loop to be ready */
783
	loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ);
Linus Torvalds's avatar
Linus Torvalds committed
784

785
786
787
788
	while ((!atomic_read(&base_vha->loop_down_timer) &&
	    atomic_read(&base_vha->loop_state) == LOOP_DOWN) ||
	    atomic_read(&base_vha->loop_state) != LOOP_READY) {
		if (atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
789
790
791
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
Linus Torvalds's avatar
Linus Torvalds committed
792
793
794
795
796
797
		msleep(1000);
		if (time_after_eq(jiffies, loop_timeout)) {
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
	}
798
	return (return_status);
Linus Torvalds's avatar
Linus Torvalds committed
799
800
}

801
802
803
804
805
806
static void
sp_get(struct srb *sp)
{
	atomic_inc(&sp->ref_count);
}

Linus Torvalds's avatar
Linus Torvalds committed
807
808
809
810
811
812
813
814
815
816
817
818
819
/**************************************************************************
* qla2xxx_eh_abort
*
* Description:
*    The abort function will abort the specified command.
*
* Input:
*    cmd = Linux SCSI command packet to be aborted.
*
* Returns:
*    Either SUCCESS or FAILED.
*
* Note:
820
*    Only return FAILED if command not returned by firmware.
Linus Torvalds's avatar
Linus Torvalds committed
821
**************************************************************************/
822
static int
Linus Torvalds's avatar
Linus Torvalds committed
823
824
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
{
825
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
826
	srb_t *sp;
827
	int ret, i;
828
829
	unsigned int id, lun;
	unsigned long serial;
830
	unsigned long flags;
831
	int wait = 0;
832
	struct qla_hw_data *ha = vha->hw;
833
	struct req_que *req = vha->req;
834
	srb_t *spt;
835
	int got_ref = 0;
Linus Torvalds's avatar
Linus Torvalds committed
836

837
	fc_block_scsi_eh(cmd);
838

839
	if (!CMD_SP(cmd))
840
		return SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
841

842
	ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
843

844
845
846
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
847
848
849
	spt = (srb_t *) CMD_SP(cmd);
	if (!spt)
		return SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
850

851
	/* Check active list for command command. */
852
	spin_lock_irqsave(&ha->hardware_lock, flags);
853
854
	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
		sp = req->outstanding_cmds[i];
Linus Torvalds's avatar
Linus Torvalds committed
855

856
857
		if (sp == NULL)
			continue;
858
859
		if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID) &&
		    !IS_PROT_IO(sp))
860
			continue;
861
862
		if (sp->cmd != cmd)
			continue;
Linus Torvalds's avatar
Linus Torvalds committed
863

864
865
866
		DEBUG2(printk("%s(%ld): aborting sp %p from RISC."
		" pid=%ld.\n", __func__, vha->host_no, sp, serial));

867
868
869
870
		/* Get a reference to the sp and drop the lock.*/
		sp_get(sp);
		got_ref++;

871
		spin_unlock_irqrestore(&ha->hardware_lock, flags);
872
		if (ha->isp_ops->abort_command(sp)) {
873
874
			DEBUG2(printk("%s(%ld): abort_command "
			"mbx failed.\n", __func__, vha->host_no));
875
			ret = FAILED;
876
877
878
879
		} else {
			DEBUG3(printk("%s(%ld): abort_command "
			"mbx success.\n", __func__, vha->host_no));
			wait = 1;
880
		}
881
882
		spin_lock_irqsave(&ha->hardware_lock, flags);
		break;
883
	}
884
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
885

886
	/* Wait for the command to be returned. */
887
	if (wait) {
888
		if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
889
			qla_printk(KERN_ERR, ha,
890
			    "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
891
			    "%x.\n", vha->host_no, id, lun, serial, ret);
892
			ret = FAILED;
893
		}
Linus Torvalds's avatar
Linus Torvalds committed
894
895
	}

896
897
898
	if (got_ref)
		qla2x00_sp_compl(ha, sp);

899
	qla_printk(KERN_INFO, ha,
900
	    "scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
901
	    vha->host_no, id, lun, wait, serial, ret);
Linus Torvalds's avatar
Linus Torvalds committed
902

903
904
	return ret;
}
Linus Torvalds's avatar
Linus Torvalds committed
905

906
907
908
909
910
911
enum nexus_wait_type {
	WAIT_HOST = 0,
	WAIT_TARGET,
	WAIT_LUN,
};

912
static int
913
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
914
	unsigned int l, srb_t *sp, enum nexus_wait_type type)
915
{
916
	int cnt, match, status;
917
	unsigned long flags;
918
	struct qla_hw_data *ha = vha->hw;
919
	struct req_que *req;
Linus Torvalds's avatar
Linus Torvalds committed
920

921
	status = QLA_SUCCESS;
922
923
924
	if (!sp)
		return status;

925
	spin_lock_irqsave(&ha->hardware_lock, flags);
926
	req = vha->req;
927
928
929
930
	for (cnt = 1; status == QLA_SUCCESS &&
		cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (!sp)
931
			continue;
932
		if ((sp->ctx) && !IS_PROT_IO(sp))
933
			continue;
934
935
936
937
938
939
940
941
942
943
944
945
946
947
		if (vha->vp_idx != sp->fcport->vha->vp_idx)
			continue;
		match = 0;
		switch (type) {
		case WAIT_HOST:
			match = 1;
			break;
		case WAIT_TARGET:
			match = sp->cmd->device->id == t;
			break;
		case WAIT_LUN:
			match = (sp->cmd->device->id == t &&
				sp->cmd->device->lun == l);
			break;
948
		}
949
950
951
952
953
954
		if (!match)
			continue;

		spin_unlock_irqrestore(&ha->hardware_lock, flags);
		status = qla2x00_eh_wait_on_command(sp->cmd);
		spin_lock_irqsave(&ha->hardware_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
955
	}
956
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
957
958

	return status;
Linus Torvalds's avatar
Linus Torvalds committed
959
960
}

961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
void qla82xx_wait_for_pending_commands(scsi_qla_host_t *vha)
{
	int cnt;
	srb_t *sp;
	struct req_que *req = vha->req;

	DEBUG2(qla_printk(KERN_INFO, vha->hw,
		"Waiting for pending commands\n"));
	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
			sp, WAIT_HOST) == QLA_SUCCESS) {
			DEBUG2(qla_printk(KERN_INFO, vha->hw,
				"Done wait for pending commands\n"));
		}
	}
}

979
980
981
982
983
984
static char *reset_errors[] = {
	"HBA not online",
	"HBA not ready",
	"Task management failed",
	"Waiting for command completions",
};
Linus Torvalds's avatar
Linus Torvalds committed
985

986
static int
987
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
988
    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
Linus Torvalds's avatar
Linus Torvalds committed
989
{
990
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
991
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
992
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
993

994
	fc_block_scsi_eh(cmd);
995

996
	if (!fcport)
997
		return FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
998

999
1000
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
Linus Torvalds's avatar
Linus Torvalds committed
1001

1002
	err = 0;
1003
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
1004
1005
		goto eh_reset_failed;
	err = 1;
1006
	if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
1007
1008
		goto eh_reset_failed;
	err = 2;
1009
1010
	if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
		!= QLA_SUCCESS)
1011
1012
		goto eh_reset_failed;
	err = 3;
1013
	if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
1014
	    cmd->device->lun, (srb_t *) CMD_SP(cmd), type) != QLA_SUCCESS)
1015
1016
		goto eh_reset_failed;

1017
1018
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
1019
1020
1021
1022

	return SUCCESS;

 eh_reset_failed:
1023
1024
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n"
	    , vha->host_no, cmd->device->id, cmd->device->lun, name,
1025
1026
1027
	    reset_errors[err]);
	return FAILED;
}
Linus Torvalds's avatar
Linus Torvalds committed
1028

1029
1030
1031
static int
qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
{
1032
1033
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
1034

1035
1036
	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
	    ha->isp_ops->lun_reset);
Linus Torvalds's avatar
Linus Torvalds committed
1037
1038
1039
}

static int
1040
qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
Linus Torvalds's avatar
Linus Torvalds committed
1041
{
1042
1043
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
1044

1045
1046
	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
	    ha->isp_ops->target_reset);
Linus Torvalds's avatar
Linus Torvalds committed
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
}

/**************************************************************************
* qla2xxx_eh_bus_reset
*
* Description:
*    The bus reset function will reset the bus and abort any executing
*    commands.
*
* Input:
*    cmd = Linux SCSI command packet of the command that cause the
*          bus reset.
*
* Returns:
*    SUCCESS/FAILURE (defined as macro in scsi.h).
*
**************************************************************************/
1064
static int
Linus Torvalds's avatar
Linus Torvalds committed
1065
1066
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
1067
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1068
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1069
	int ret = FAILED;
1070
1071
	unsigned int id, lun;
	unsigned long serial;
1072
	srb_t *sp = (srb_t *) CMD_SP(cmd);
1073

1074
	fc_block_scsi_eh(cmd);
1075

1076
1077
1078
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
Linus Torvalds's avatar
Linus Torvalds committed
1079

1080
	if (!fcport)
1081
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1082

1083
	qla_printk(KERN_INFO, vha->hw,
1084
	    "scsi(%ld:%d:%d): BUS RESET ISSUED.\n", vha->host_no, id, lun);
Linus Torvalds's avatar
Linus Torvalds committed
1085

1086
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
Linus Torvalds's avatar
Linus Torvalds committed
1087
		DEBUG2(printk("%s failed:board disabled\n",__func__));
1088
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
1089
1090
	}

1091
1092
	if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
		if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
1093
			ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
1094
	}
1095
1096
	if (ret == FAILED)
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
1097

1098
	/* Flush outstanding commands. */
1099
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) !=
1100
	    QLA_SUCCESS)
1101
		ret = FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
1102

1103
eh_bus_reset_done:
1104
	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
1105
	    (ret == FAILED) ? "failed" : "succeded");
Linus Torvalds's avatar
Linus Torvalds committed
1106

1107
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1108
1109
1110
1111
1112
1113