qla_os.c 104 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
144
145
146
147
148
149
150
151
152
153
154
155
156
int ql2xdbwr;
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
520
521
522
523
524

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

	sp->fcport = fcport;
	sp->cmd = cmd;
	sp->flags = 0;
	CMD_SP(cmd) = (void *)sp;
	cmd->scsi_done = done;
525
	sp->ctx = NULL;
526
527
528
529

	return sp;
}

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

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

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

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

559
560
561
562
563
564
565
566
	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;
	}
567
568
	if (atomic_read(&fcport->state) != FCS_ONLINE) {
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
569
		    atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
570
571
572
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
		}
573
		goto qc24_target_busy;
574
575
	}

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

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

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

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

	return 0;

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

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

598
599
600
qc24_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

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

	return 0;
}


Linus Torvalds's avatar
Linus Torvalds committed
608
609
610
611
612
613
614
615
616
617
618
619
620
/*
 * 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
621
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
Linus Torvalds's avatar
Linus Torvalds committed
622
{
623
624
#define ABORT_POLLING_PERIOD	1000
#define ABORT_WAIT_ITER		((10 * 1000) / (ABORT_POLLING_PERIOD))
625
	unsigned long wait_iter = ABORT_WAIT_ITER;
626
627
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
628
	int ret = QLA_SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
629

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

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

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

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

669
	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
670
671
672
673
	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
674
675
676

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

	return (return_status);
}

685
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
/*
 * 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;
}

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

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

784
785
786
787
	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) {
788
789
790
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
Linus Torvalds's avatar
Linus Torvalds committed
791
792
793
794
795
796
		msleep(1000);
		if (time_after_eq(jiffies, loop_timeout)) {
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
	}
797
	return (return_status);
Linus Torvalds's avatar
Linus Torvalds committed
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
}

/**************************************************************************
* 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:
813
*    Only return FAILED if command not returned by firmware.
Linus Torvalds's avatar
Linus Torvalds committed
814
**************************************************************************/
815
static int
Linus Torvalds's avatar
Linus Torvalds committed
816
817
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
{
818
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
819
	srb_t *sp;
820
	int ret, i;
821
822
	unsigned int id, lun;
	unsigned long serial;
823
	unsigned long flags;
824
	int wait = 0;
825
	struct qla_hw_data *ha = vha->hw;
826
	struct req_que *req = vha->req;
827
	srb_t *spt;
Linus Torvalds's avatar
Linus Torvalds committed
828

829
	fc_block_scsi_eh(cmd);
830

831
	if (!CMD_SP(cmd))
832
		return SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
833

834
	ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
835

836
837
838
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
839
840
841
	spt = (srb_t *) CMD_SP(cmd);
	if (!spt)
		return SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
842

843
	/* Check active list for command command. */
844
	spin_lock_irqsave(&ha->hardware_lock, flags);
845
846
	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
		sp = req->outstanding_cmds[i];
Linus Torvalds's avatar
Linus Torvalds committed
847

848
849
		if (sp == NULL)
			continue;
850
851
		if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID) &&
		    !IS_PROT_IO(sp))
852
			continue;
853
854
		if (sp->cmd != cmd)
			continue;
Linus Torvalds's avatar
Linus Torvalds committed
855

856
857
858
859
		DEBUG2(printk("%s(%ld): aborting sp %p from RISC."
		" pid=%ld.\n", __func__, vha->host_no, sp, serial));

		spin_unlock_irqrestore(&ha->hardware_lock, flags);
860
		if (ha->isp_ops->abort_command(sp)) {
861
862
			DEBUG2(printk("%s(%ld): abort_command "
			"mbx failed.\n", __func__, vha->host_no));
863
			ret = FAILED;
864
865
866
867
		} else {
			DEBUG3(printk("%s(%ld): abort_command "
			"mbx success.\n", __func__, vha->host_no));
			wait = 1;
868
		}
869
870
		spin_lock_irqsave(&ha->hardware_lock, flags);
		break;
871
	}
872
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
873

874
	/* Wait for the command to be returned. */
875
	if (wait) {
876
		if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
877
			qla_printk(KERN_ERR, ha,
878
			    "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
879
			    "%x.\n", vha->host_no, id, lun, serial, ret);
880
			ret = FAILED;
881
		}
Linus Torvalds's avatar
Linus Torvalds committed
882
883
	}

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

888
889
	return ret;
}
Linus Torvalds's avatar
Linus Torvalds committed
890

891
892
893
894
895
896
enum nexus_wait_type {
	WAIT_HOST = 0,
	WAIT_TARGET,
	WAIT_LUN,
};

897
static int
898
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
899
	unsigned int l, srb_t *sp, enum nexus_wait_type type)
900
{
901
	int cnt, match, status;
902
	unsigned long flags;
903
	struct qla_hw_data *ha = vha->hw;
904
	struct req_que *req;
Linus Torvalds's avatar
Linus Torvalds committed
905

906
	status = QLA_SUCCESS;
907
908
909
	if (!sp)
		return status;

910
	spin_lock_irqsave(&ha->hardware_lock, flags);
911
	req = vha->req;
912
913
914
915
	for (cnt = 1; status == QLA_SUCCESS &&
		cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (!sp)
916
			continue;
917
		if ((sp->ctx) && !IS_PROT_IO(sp))
918
			continue;
919
920
921
922
923
924
925
926
927
928
929
930
931
932
		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;
933
		}
934
935
936
937
938
939
		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
940
	}
941
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
942
943

	return status;
Linus Torvalds's avatar
Linus Torvalds committed
944
945
}

946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
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"));
		}
	}
}

964
965
966
967
968
969
static char *reset_errors[] = {
	"HBA not online",
	"HBA not ready",
	"Task management failed",
	"Waiting for command completions",
};
Linus Torvalds's avatar
Linus Torvalds committed
970

971
static int
972
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
973
    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
Linus Torvalds's avatar
Linus Torvalds committed
974
{
975
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
976
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
977
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
978

979
	fc_block_scsi_eh(cmd);
980

981
	if (!fcport)
982
		return FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
983

984
985
	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
986

987
	err = 0;
988
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
989
990
		goto eh_reset_failed;
	err = 1;
991
	if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
992
993
		goto eh_reset_failed;
	err = 2;
994
995
	if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
		!= QLA_SUCCESS)
996
997
		goto eh_reset_failed;
	err = 3;
998
	if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
999
	    cmd->device->lun, (srb_t *) CMD_SP(cmd), type) != QLA_SUCCESS)
1000
1001
		goto eh_reset_failed;

1002
1003
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
1004
1005
1006
1007

	return SUCCESS;

 eh_reset_failed:
1008
1009
	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,
1010
1011
1012
	    reset_errors[err]);
	return FAILED;
}
Linus Torvalds's avatar
Linus Torvalds committed
1013

1014
1015
1016
static int
qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
{
1017
1018
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
1019

1020
1021
	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
	    ha->isp_ops->lun_reset);
Linus Torvalds's avatar
Linus Torvalds committed
1022
1023
1024
}

static int
1025
qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
Linus Torvalds's avatar
Linus Torvalds committed
1026
{
1027
1028
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
1029

1030
1031
	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
	    ha->isp_ops->target_reset);
Linus Torvalds's avatar
Linus Torvalds committed
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
}

/**************************************************************************
* 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).
*
**************************************************************************/
1049
static int
Linus Torvalds's avatar
Linus Torvalds committed
1050
1051
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
1052
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1053
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1054
	int ret = FAILED;
1055
1056
	unsigned int id, lun;
	unsigned long serial;
1057
	srb_t *sp = (srb_t *) CMD_SP(cmd);
1058

1059
	fc_block_scsi_eh(cmd);
1060

1061
1062
1063
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
Linus Torvalds's avatar
Linus Torvalds committed
1064

1065
	if (!fcport)
1066
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1067

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

1071
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
Linus Torvalds's avatar
Linus Torvalds committed
1072
		DEBUG2(printk("%s failed:board disabled\n",__func__));
1073
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
1074
1075
	}

1076
1077
	if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
		if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
1078
			ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
1079
	}
1080
1081
	if (ret == FAILED)
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
1082

1083
	/* Flush outstanding commands. */
1084
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) !=
1085
	    QLA_SUCCESS)
1086
		ret = FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
1087

1088
eh_bus_reset_done:
1089
	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
1090
	    (ret == FAILED) ? "failed" : "succeded");
Linus Torvalds's avatar
Linus Torvalds committed
1091

1092
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
}

/**************************************************************************
* qla2xxx_eh_host_reset
*
* Description:
*    The reset function will reset the Adapter.
*
* Input:
*      cmd = Linux SCSI command packet of the command that cause the
*            adapter reset.
*
* Returns:
*      Either SUCCESS or FAILED.
*
* Note:
**************************************************************************/
1110
static int
Linus Torvalds's avatar
Linus Torvalds committed
1111
1112
qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
{
1113
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1114
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1115
	struct qla_hw_data *ha = vha->hw;
1116
	int ret = FAILED;
1117
1118
	unsigned int id, lun