qla_os.c 84.5 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>
Linus Torvalds's avatar
Linus Torvalds committed
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#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];

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

int ql2xlogintimeout = 20;
module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xlogintimeout,
		"Login timeout value in seconds.");

35
int qlport_down_retry;
Linus Torvalds's avatar
Linus Torvalds committed
36
37
module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(qlport_down_retry,
38
		"Maximum number of command retries to a port that returns "
Linus Torvalds's avatar
Linus Torvalds committed
39
40
41
42
43
44
		"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 "
45
		"a Fabric scan.  This is needed for several broken switches. "
Linus Torvalds's avatar
Linus Torvalds committed
46
47
48
49
50
51
52
		"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.");

53
54
55
56
57
58
59
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.");

60
int ql2xextended_error_logging;
61
module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
62
MODULE_PARM_DESC(ql2xextended_error_logging,
63
64
65
		"Option to enable extended error logging, "
		"Default is 0 - no logging. 1 - log errors.");

Linus Torvalds's avatar
Linus Torvalds committed
66
67
static void qla2x00_free_device(scsi_qla_host_t *);

68
int ql2xfdmienable=1;
69
70
71
72
73
module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfdmienable,
		"Enables FDMI registratons "
		"Default is 0 - no FDMI. 1 - perfom FDMI.");

74
75
76
77
78
79
80
81
82
83
84
85
86
#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.");

int ql2xqfullrampup = 120;
module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xqfullrampup,
		"Number of seconds to wait to begin to ramp-up the queue "
		"depth for a device after a queue-full condition has been "
		"detected.  Default is 120 seconds.");

87
88
89
90
91
92
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.");

93
94
95
96
97
98
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.");
Linus Torvalds's avatar
Linus Torvalds committed
99
/*
100
 * SCSI host template entry points
Linus Torvalds's avatar
Linus Torvalds committed
101
102
 */
static int qla2xxx_slave_configure(struct scsi_device * device);
103
static int qla2xxx_slave_alloc(struct scsi_device *);
104
105
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
static void qla2xxx_scan_start(struct Scsi_Host *);
106
static void qla2xxx_slave_destroy(struct scsi_device *);
Linus Torvalds's avatar
Linus Torvalds committed
107
108
static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
		void (*fn)(struct scsi_cmnd *));
109
110
static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
		void (*fn)(struct scsi_cmnd *));
Linus Torvalds's avatar
Linus Torvalds committed
111
112
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
113
static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
Linus Torvalds's avatar
Linus Torvalds committed
114
115
116
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);

117
118
119
static int qla2x00_change_queue_depth(struct scsi_device *, int);
static int qla2x00_change_queue_type(struct scsi_device *, int);

Adrian Bunk's avatar
Adrian Bunk committed
120
static struct scsi_host_template qla2x00_driver_template = {
Linus Torvalds's avatar
Linus Torvalds committed
121
	.module			= THIS_MODULE,
122
	.name			= QLA2XXX_DRIVER_NAME,
Linus Torvalds's avatar
Linus Torvalds committed
123
124
125
126
	.queuecommand		= qla2x00_queuecommand,

	.eh_abort_handler	= qla2xxx_eh_abort,
	.eh_device_reset_handler = qla2xxx_eh_device_reset,
127
	.eh_target_reset_handler = qla2xxx_eh_target_reset,
Linus Torvalds's avatar
Linus Torvalds committed
128
129
130
131
132
	.eh_bus_reset_handler	= qla2xxx_eh_bus_reset,
	.eh_host_reset_handler	= qla2xxx_eh_host_reset,

	.slave_configure	= qla2xxx_slave_configure,

133
134
	.slave_alloc		= qla2xxx_slave_alloc,
	.slave_destroy		= qla2xxx_slave_destroy,
135
136
	.scan_finished		= qla2xxx_scan_finished,
	.scan_start		= qla2xxx_scan_start,
137
138
	.change_queue_depth	= qla2x00_change_queue_depth,
	.change_queue_type	= qla2x00_change_queue_type,
Linus Torvalds's avatar
Linus Torvalds committed
139
140
141
142
143
144
145
146
147
148
	.this_id		= -1,
	.cmd_per_lun		= 3,
	.use_clustering		= ENABLE_CLUSTERING,
	.sg_tablesize		= SG_ALL,

	/*
	 * The RISC allows for each command to transfer (2^32-1) bytes of data,
	 * which equates to 0x800000 sectors.
	 */
	.max_sectors		= 0xFFFF,
149
	.shost_attrs		= qla2x00_host_attrs,
Linus Torvalds's avatar
Linus Torvalds committed
150
151
};

152
struct scsi_host_template qla24xx_driver_template = {
153
	.module			= THIS_MODULE,
154
	.name			= QLA2XXX_DRIVER_NAME,
155
156
157
158
	.queuecommand		= qla24xx_queuecommand,

	.eh_abort_handler	= qla2xxx_eh_abort,
	.eh_device_reset_handler = qla2xxx_eh_device_reset,
159
	.eh_target_reset_handler = qla2xxx_eh_target_reset,
160
161
162
163
164
165
166
	.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,
167
168
	.scan_finished		= qla2xxx_scan_finished,
	.scan_start		= qla2xxx_scan_start,
169
170
	.change_queue_depth	= qla2x00_change_queue_depth,
	.change_queue_type	= qla2x00_change_queue_type,
171
172
173
174
175
176
	.this_id		= -1,
	.cmd_per_lun		= 3,
	.use_clustering		= ENABLE_CLUSTERING,
	.sg_tablesize		= SG_ALL,

	.max_sectors		= 0xFFFF,
177
	.shost_attrs		= qla2x00_host_attrs,
178
179
};

Linus Torvalds's avatar
Linus Torvalds committed
180
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
181
struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
182
183
184
185
186
187

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

188
__inline__ void
189
qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval)
Linus Torvalds's avatar
Linus Torvalds committed
190
{
191
192
193
194
195
196
	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
197
198
199
}

static inline void
200
qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
Linus Torvalds's avatar
Linus Torvalds committed
201
{
202
	mod_timer(&vha->timer, jiffies + interval * HZ);
Linus Torvalds's avatar
Linus Torvalds committed
203
204
}

Adrian Bunk's avatar
Adrian Bunk committed
205
static __inline__ void
206
qla2x00_stop_timer(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
207
{
208
209
	del_timer_sync(&vha->timer);
	vha->timer_active = 0;
Linus Torvalds's avatar
Linus Torvalds committed
210
211
212
213
214
215
}

static int qla2x00_do_dpc(void *data);

static void qla2x00_rst_aen(scsi_qla_host_t *);

216
217
static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
	struct req_que **, struct rsp_que **);
218
219
static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
Linus Torvalds's avatar
Linus Torvalds committed
220
221

/* -------------------------------------------------------------------------- */
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
static int qla2x00_alloc_queues(struct qla_hw_data *ha)
{
	ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_queues,
				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;
	}

	ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_queues,
				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;
}

static void qla2x00_free_que(struct qla_hw_data *ha, struct req_que *req,
	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;
	if (req && req->ring)
		dma_free_coherent(&ha->pdev->dev,
		(req->length + 1) * sizeof(request_t),
		req->ring, req->dma);

	kfree(req);
	req = NULL;
}

static void qla2x00_free_queues(struct qla_hw_data *ha)
{
	struct req_que *req;
	struct rsp_que *rsp;
	int cnt;

	for (cnt = 0; cnt < ha->max_queues; cnt++) {
		rsp = ha->rsp_q_map[cnt];
		req = ha->req_q_map[cnt];
		qla2x00_free_que(ha, req, rsp);
	}
	kfree(ha->rsp_q_map);
	ha->rsp_q_map = NULL;

	kfree(ha->req_q_map);
	ha->req_q_map = NULL;
}

Linus Torvalds's avatar
Linus Torvalds committed
287
static char *
288
qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str)
Linus Torvalds's avatar
Linus Torvalds committed
289
{
290
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
	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);
}

311
static char *
312
qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
313
314
{
	static char *pci_bus_modes[] = { "33", "66", "100", "133", };
315
	struct qla_hw_data *ha = vha->hw;
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
	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)
332
			strcat(str, "2.5GT/s ");
333
		else if (lspeed == 2)
334
			strcat(str, "5.0GT/s ");
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
		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;
}

362
static char *
363
qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
Linus Torvalds's avatar
Linus Torvalds committed
364
365
{
	char un_str[10];
366
	struct qla_hw_data *ha = vha->hw;
367

Linus Torvalds's avatar
Linus Torvalds committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
	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);
}

401
static char *
402
qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
403
{
404
	struct qla_hw_data *ha = vha->hw;
405

406
407
	sprintf(str, "%d.%02d.%02d (%x)", ha->fw_major_version,
	    ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes);
408
409
410
411
	return str;
}

static inline srb_t *
412
qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
413
414
415
    struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
	srb_t *sp;
416
	struct qla_hw_data *ha = vha->hw;
417
418
419
420
421
422
423

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

	sp->fcport = fcport;
	sp->cmd = cmd;
424
	sp->que = ha->req_q_map[0];
425
426
427
428
429
430
431
	sp->flags = 0;
	CMD_SP(cmd) = (void *)sp;
	cmd->scsi_done = done;

	return sp;
}

Linus Torvalds's avatar
Linus Torvalds committed
432
static int
433
qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
Linus Torvalds's avatar
Linus Torvalds committed
434
{
435
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
436
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
437
	struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
438
	struct qla_hw_data *ha = vha->hw;
439
440
	srb_t *sp;
	int rval;
Linus Torvalds's avatar
Linus Torvalds committed
441

442
443
444
445
446
	if (unlikely(pci_channel_offline(ha->pdev))) {
		cmd->result = DID_REQUEUE << 16;
		goto qc_fail_command;
	}

447
448
449
	rval = fc_remote_port_chkready(rport);
	if (rval) {
		cmd->result = rval;
450
451
		goto qc_fail_command;
	}
Linus Torvalds's avatar
Linus Torvalds committed
452

453
	/* Close window on fcport/rport state-transitioning. */
454
455
	if (fcport->drport)
		goto qc_target_busy;
456

457
458
	if (atomic_read(&fcport->state) != FCS_ONLINE) {
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
459
		    atomic_read(&vha->loop_state) == LOOP_DEAD) {
460
461
462
			cmd->result = DID_NO_CONNECT << 16;
			goto qc_fail_command;
		}
463
		goto qc_target_busy;
464
	}
Linus Torvalds's avatar
Linus Torvalds committed
465

466
	spin_unlock_irq(vha->host->host_lock);
Linus Torvalds's avatar
Linus Torvalds committed
467

468
	sp = qla2x00_get_new_sp(vha, fcport, cmd, done);
469
	if (!sp)
470
		goto qc_host_busy_lock;
Linus Torvalds's avatar
Linus Torvalds committed
471

472
	rval = ha->isp_ops->start_scsi(sp);
473
474
	if (rval != QLA_SUCCESS)
		goto qc_host_busy_free_sp;
Linus Torvalds's avatar
Linus Torvalds committed
475

476
	spin_lock_irq(vha->host->host_lock);
Linus Torvalds's avatar
Linus Torvalds committed
477

478
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
479

480
qc_host_busy_free_sp:
481
	qla2x00_sp_free_dma(sp);
482
	mempool_free(sp, ha->srb_mempool);
Linus Torvalds's avatar
Linus Torvalds committed
483

484
qc_host_busy_lock:
485
	spin_lock_irq(vha->host->host_lock);
486
	return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds's avatar
Linus Torvalds committed
487

488
489
490
qc_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

491
492
qc_fail_command:
	done(cmd);
Linus Torvalds's avatar
Linus Torvalds committed
493

494
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
495
496
}

497
498
499
500

static int
qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
501
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
502
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
503
	struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
504
505
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
506
507
508
	srb_t *sp;
	int rval;

509
	if (unlikely(pci_channel_offline(ha->pdev))) {
510
511
512
513
		cmd->result = DID_REQUEUE << 16;
		goto qc24_fail_command;
	}

514
515
516
	rval = fc_remote_port_chkready(rport);
	if (rval) {
		cmd->result = rval;
517
518
519
		goto qc24_fail_command;
	}

520
	/* Close window on fcport/rport state-transitioning. */
521
522
	if (fcport->drport)
		goto qc24_target_busy;
523

524
525
	if (atomic_read(&fcport->state) != FCS_ONLINE) {
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
526
		    atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
527
528
529
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
		}
530
		goto qc24_target_busy;
531
532
	}

533
	spin_unlock_irq(vha->host->host_lock);
534

535
	sp = qla2x00_get_new_sp(base_vha, fcport, cmd, done);
536
537
538
	if (!sp)
		goto qc24_host_busy_lock;

539
	rval = ha->isp_ops->start_scsi(sp);
540
541
542
	if (rval != QLA_SUCCESS)
		goto qc24_host_busy_free_sp;

543
	spin_lock_irq(vha->host->host_lock);
544
545
546
547

	return 0;

qc24_host_busy_free_sp:
548
549
	qla2x00_sp_free_dma(sp);
	mempool_free(sp, ha->srb_mempool);
550
551

qc24_host_busy_lock:
552
	spin_lock_irq(vha->host->host_lock);
553
554
	return SCSI_MLQUEUE_HOST_BUSY;

555
556
557
qc24_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

558
559
560
561
562
563
564
qc24_fail_command:
	done(cmd);

	return 0;
}


Linus Torvalds's avatar
Linus Torvalds committed
565
566
567
568
569
570
571
572
573
574
575
576
577
/*
 * 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
578
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
Linus Torvalds's avatar
Linus Torvalds committed
579
{
580
581
#define ABORT_POLLING_PERIOD	1000
#define ABORT_WAIT_ITER		((10 * 1000) / (ABORT_POLLING_PERIOD))
582
583
	unsigned long wait_iter = ABORT_WAIT_ITER;
	int ret = QLA_SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
584

585
	while (CMD_SP(cmd)) {
586
		msleep(ABORT_POLLING_PERIOD);
Linus Torvalds's avatar
Linus Torvalds committed
587

588
589
590
591
592
		if (--wait_iter)
			break;
	}
	if (CMD_SP(cmd))
		ret = QLA_FUNCTION_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
593

594
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
595
596
597
598
}

/*
 * qla2x00_wait_for_hba_online
599
 *    Wait till the HBA is online after going through
Linus Torvalds's avatar
Linus Torvalds committed
600
601
602
603
604
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline
 *
 * Input:
 *     ha - pointer to host adapter structure
605
606
 *
 * Note:
Linus Torvalds's avatar
Linus Torvalds committed
607
608
609
610
611
612
613
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online) : 0
 *    Failed  (Adapter is offline/disabled) : 1
 */
614
int
615
qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
616
{
617
618
	int		return_status;
	unsigned long	wait_online;
619
620
	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
621

622
	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
623
624
625
626
	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
627
628
629

		msleep(1000);
	}
630
	if (base_vha->flags.online)
631
		return_status = QLA_SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
632
633
634
635
636
637
638
639
640
	else
		return_status = QLA_FUNCTION_FAILED;

	return (return_status);
}

/*
 * qla2x00_wait_for_loop_ready
 *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
641
 *    to be in LOOP_READY state.
Linus Torvalds's avatar
Linus Torvalds committed
642
643
 * Input:
 *     ha - pointer to host adapter structure
644
645
 *
 * Note:
Linus Torvalds's avatar
Linus Torvalds committed
646
647
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
648
 *
Linus Torvalds's avatar
Linus Torvalds committed
649
650
651
652
653
 *
 * Return:
 *    Success (LOOP_READY) : 0
 *    Failed  (LOOP_NOT_READY) : 1
 */
654
static inline int
655
qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
656
657
658
{
	int 	 return_status = QLA_SUCCESS;
	unsigned long loop_timeout ;
659
660
	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
661
662

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

665
666
667
668
	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) {
669
670
671
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
Linus Torvalds's avatar
Linus Torvalds committed
672
673
674
675
676
677
		msleep(1000);
		if (time_after_eq(jiffies, loop_timeout)) {
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
	}
678
	return (return_status);
Linus Torvalds's avatar
Linus Torvalds committed
679
680
}

681
682
683
void
qla2x00_abort_fcport_cmds(fc_port_t *fcport)
{
684
	int cnt, que, id;
685
686
	unsigned long flags;
	srb_t *sp;
687
688
	scsi_qla_host_t *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
689
	struct req_que *req;
690

691
	spin_lock_irqsave(&ha->hardware_lock, flags);
692
693
694
695
	for (que = 0; que < QLA_MAX_HOST_QUES; que++) {
		id = vha->req_ques[que];
		req = ha->req_q_map[id];
		if (!req)
696
			continue;
697
698
699
700
701
702
		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
			sp = req->outstanding_cmds[cnt];
			if (!sp)
				continue;
			if (sp->fcport != fcport)
				continue;
703

704
705
			spin_unlock_irqrestore(&ha->hardware_lock, flags);
			if (ha->isp_ops->abort_command(vha, sp, req)) {
706
				DEBUG2(qla_printk(KERN_WARNING, ha,
707
708
709
710
711
712
713
714
715
716
				"Abort failed --  %lx\n",
				sp->cmd->serial_number));
			} else {
				if (qla2x00_eh_wait_on_command(sp->cmd) !=
					QLA_SUCCESS)
					DEBUG2(qla_printk(KERN_WARNING, ha,
					"Abort failed while waiting --  %lx\n",
					sp->cmd->serial_number));
			}
			spin_lock_irqsave(&ha->hardware_lock, flags);
717
718
		}
	}
719
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
720
721
}

722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
static void
qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
{
	struct Scsi_Host *shost = cmnd->device->host;
	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
	unsigned long flags;

	spin_lock_irqsave(shost->host_lock, flags);
	while (rport->port_state == FC_PORTSTATE_BLOCKED) {
		spin_unlock_irqrestore(shost->host_lock, flags);
		msleep(1000);
		spin_lock_irqsave(shost->host_lock, flags);
	}
	spin_unlock_irqrestore(shost->host_lock, flags);
	return;
}

Linus Torvalds's avatar
Linus Torvalds committed
739
740
741
742
743
744
745
746
747
748
749
750
751
/**************************************************************************
* 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:
752
*    Only return FAILED if command not returned by firmware.
Linus Torvalds's avatar
Linus Torvalds committed
753
**************************************************************************/
754
static int
Linus Torvalds's avatar
Linus Torvalds committed
755
756
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
{
757
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
758
	srb_t *sp;
759
	int ret, i;
760
761
	unsigned int id, lun;
	unsigned long serial;
762
	unsigned long flags;
763
	int wait = 0;
764
	struct qla_hw_data *ha = vha->hw;
765
	struct req_que *req;
766
	srb_t *spt;
Linus Torvalds's avatar
Linus Torvalds committed
767

768
769
	qla2x00_block_error_handler(cmd);

770
	if (!CMD_SP(cmd))
771
		return SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
772

773
	ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
774

775
776
777
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
778
779
780
781
	spt = (srb_t *) CMD_SP(cmd);
	if (!spt)
		return SUCCESS;
	req = spt->que;
Linus Torvalds's avatar
Linus Torvalds committed
782

783
	/* Check active list for command command. */
784
	spin_lock_irqsave(&ha->hardware_lock, flags);
785
786
	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
		sp = req->outstanding_cmds[i];
Linus Torvalds's avatar
Linus Torvalds committed
787

788
789
		if (sp == NULL)
			continue;
Linus Torvalds's avatar
Linus Torvalds committed
790

791
792
		if (sp->cmd != cmd)
			continue;
Linus Torvalds's avatar
Linus Torvalds committed
793

794
795
796
797
798
799
800
		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);
		if (ha->isp_ops->abort_command(vha, sp, req)) {
			DEBUG2(printk("%s(%ld): abort_command "
			"mbx failed.\n", __func__, vha->host_no));
801
			ret = FAILED;
802
803
804
805
		} else {
			DEBUG3(printk("%s(%ld): abort_command "
			"mbx success.\n", __func__, vha->host_no));
			wait = 1;
806
		}
807
808
		spin_lock_irqsave(&ha->hardware_lock, flags);
		break;
809
	}
810
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
811

812
	/* Wait for the command to be returned. */
813
	if (wait) {
814
		if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
815
			qla_printk(KERN_ERR, ha,
816
			    "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
817
			    "%x.\n", vha->host_no, id, lun, serial, ret);
818
			ret = FAILED;
819
		}
Linus Torvalds's avatar
Linus Torvalds committed
820
821
	}

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

826
827
	return ret;
}
Linus Torvalds's avatar
Linus Torvalds committed
828

829
830
831
832
833
834
enum nexus_wait_type {
	WAIT_HOST = 0,
	WAIT_TARGET,
	WAIT_LUN,
};

835
static int
836
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
837
	unsigned int l, srb_t *sp, enum nexus_wait_type type)
838
{
839
	int cnt, match, status;
840
	unsigned long flags;
841
	struct qla_hw_data *ha = vha->hw;
842
	struct req_que *req;
Linus Torvalds's avatar
Linus Torvalds committed
843

844
	status = QLA_SUCCESS;
845
846
847
	if (!sp)
		return status;

848
	spin_lock_irqsave(&ha->hardware_lock, flags);
849
850
851
852
853
	req = sp->que;
	for (cnt = 1; status == QLA_SUCCESS &&
		cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (!sp)
854
			continue;
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
		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;
870
		}
871
872
873
874
875
876
		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
877
	}
878
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
879
880

	return status;
Linus Torvalds's avatar
Linus Torvalds committed
881
882
}

883
884
885
886
887
888
static char *reset_errors[] = {
	"HBA not online",
	"HBA not ready",
	"Task management failed",
	"Waiting for command completions",
};
Linus Torvalds's avatar
Linus Torvalds committed
889

890
static int
891
892
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int))
Linus Torvalds's avatar
Linus Torvalds committed
893
{
894
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
895
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
896
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
897

898
899
	qla2x00_block_error_handler(cmd);

900
	if (!fcport)
901
		return FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
902

903
904
	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
905

906
	err = 0;
907
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
908
909
		goto eh_reset_failed;
	err = 1;
910
	if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
911
912
913
914
915
		goto eh_reset_failed;
	err = 2;
	if (do_reset(fcport, cmd->device->lun) != QLA_SUCCESS)
		goto eh_reset_failed;
	err = 3;
916
	if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
917
	    cmd->device->lun, (srb_t *) CMD_SP(cmd), type) != QLA_SUCCESS)
918
919
		goto eh_reset_failed;

920
921
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
922
923
924
925

	return SUCCESS;

 eh_reset_failed:
926
927
	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,
928
929
930
	    reset_errors[err]);
	return FAILED;
}
Linus Torvalds's avatar
Linus Torvalds committed
931

932
933
934
static int
qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
{
935
936
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
937

938
939
	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
	    ha->isp_ops->lun_reset);
Linus Torvalds's avatar
Linus Torvalds committed
940
941
942
}

static int
943
qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
Linus Torvalds's avatar
Linus Torvalds committed
944
{
945
946
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
947

948
949
	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
	    ha->isp_ops->target_reset);
Linus Torvalds's avatar
Linus Torvalds committed
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
}

/**************************************************************************
* 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).
*
**************************************************************************/
967
static int
Linus Torvalds's avatar
Linus Torvalds committed
968
969
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
970
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
971
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
972
	int ret = FAILED;
973
974
	unsigned int id, lun;
	unsigned long serial;
975
	srb_t *sp = (srb_t *) CMD_SP(cmd);
976

977
978
	qla2x00_block_error_handler(cmd);

979
980
981
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
Linus Torvalds's avatar
Linus Torvalds committed
982

983
	if (!fcport)
984
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
985

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

989
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
Linus Torvalds's avatar
Linus Torvalds committed
990
		DEBUG2(printk("%s failed:board disabled\n",__func__));
991
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
992
993
	}

994
995
	if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
		if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
996
			ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
997
	}
998
999
	if (ret == FAILED)
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
1000

1001
	/* Flush outstanding commands. */
1002
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) !=
1003
	    QLA_SUCCESS)
1004
		ret = FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
1005

1006
eh_bus_reset_done:
1007
	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
1008
	    (ret == FAILED) ? "failed" : "succeded");
Linus Torvalds's avatar
Linus Torvalds committed
1009

1010
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
}

/**************************************************************************
* 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:
**************************************************************************/
1028
static int
Linus Torvalds's avatar
Linus Torvalds committed
1029
1030
qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
{
1031
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1032
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1033
	struct qla_hw_data *ha = vha->hw;
1034
	int ret = FAILED;
1035
1036
	unsigned int id, lun;
	unsigned long serial;
1037
	srb_t *sp = (srb_t *) CMD_SP(cmd);
1038
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds's avatar
Linus Torvalds committed
1039

1040
1041
	qla2x00_block_error_handler(cmd);

1042
1043
1044
1045
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;

1046
	if (!fcport)
1047
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1048
1049

	qla_printk(KERN_INFO, ha,
1050
	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->