qla_os.c 101.0 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
A
Andrew Vasquez 已提交
2
 * QLogic Fibre Channel HBA Driver
3
 * Copyright (c)  2003-2008 QLogic Corporation
L
Linus Torvalds 已提交
4
 *
A
Andrew Vasquez 已提交
5
 * See LICENSE.qla2xxx for copyright and licensing details.
L
Linus Torvalds 已提交
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>
L
Linus Torvalds 已提交
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;

L
Linus Torvalds 已提交
29 30 31
/*
 * SRB allocation cache
 */
32
static struct kmem_cache *srb_cachep;
L
Linus Torvalds 已提交
33

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

L
Linus Torvalds 已提交
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;
L
Linus Torvalds 已提交
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 "
L
Linus Torvalds 已提交
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. "
L
Linus Torvalds 已提交
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.");

L
Linus Torvalds 已提交
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
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.");

101 102 103 104 105 106
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.");
107 108 109 110 111 112 113

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.");
114 115 116 117 118 119 120 121 122 123

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");

124 125 126 127 128 129
int ql2xetsenable;
module_param(ql2xetsenable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xetsenable,
		"Enables firmware ETS burst."
		"Default is 0 - skip ETS enablement.");

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
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");


145 146 147 148 149
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.");
L
Linus Torvalds 已提交
150
/*
A
Andrew Vasquez 已提交
151
 * SCSI host template entry points
L
Linus Torvalds 已提交
152 153
 */
static int qla2xxx_slave_configure(struct scsi_device * device);
已提交
154
static int qla2xxx_slave_alloc(struct scsi_device *);
155 156
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
static void qla2xxx_scan_start(struct Scsi_Host *);
已提交
157
static void qla2xxx_slave_destroy(struct scsi_device *);
158
static int qla2xxx_queuecommand(struct scsi_cmnd *cmd,
159
		void (*fn)(struct scsi_cmnd *));
L
Linus Torvalds 已提交
160 161
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
162
static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
L
Linus Torvalds 已提交
163 164 165
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);

166
static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
167 168
static int qla2x00_change_queue_type(struct scsi_device *, int);

169
struct scsi_host_template qla2xxx_driver_template = {
L
Linus Torvalds 已提交
170
	.module			= THIS_MODULE,
171
	.name			= QLA2XXX_DRIVER_NAME,
172
	.queuecommand		= qla2xxx_queuecommand,
173 174 175

	.eh_abort_handler	= qla2xxx_eh_abort,
	.eh_device_reset_handler = qla2xxx_eh_device_reset,
176
	.eh_target_reset_handler = qla2xxx_eh_target_reset,
177 178 179 180 181 182 183
	.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,
184 185
	.scan_finished		= qla2xxx_scan_finished,
	.scan_start		= qla2xxx_scan_start,
186 187
	.change_queue_depth	= qla2x00_change_queue_depth,
	.change_queue_type	= qla2x00_change_queue_type,
188 189 190 191 192 193
	.this_id		= -1,
	.cmd_per_lun		= 3,
	.use_clustering		= ENABLE_CLUSTERING,
	.sg_tablesize		= SG_ALL,

	.max_sectors		= 0xFFFF,
194
	.shost_attrs		= qla2x00_host_attrs,
195 196
};

L
Linus Torvalds 已提交
197
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
198
struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
L
Linus Torvalds 已提交
199 200 201 202 203 204

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

205
__inline__ void
206
qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval)
L
Linus Torvalds 已提交
207
{
208 209 210 211 212 213
	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;
L
Linus Torvalds 已提交
214 215 216
}

static inline void
217
qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
L
Linus Torvalds 已提交
218
{
219 220 221 222
	/* Currently used for 82XX only. */
	if (vha->device_flags & DFLG_DEV_FAILED)
		return;

223
	mod_timer(&vha->timer, jiffies + interval * HZ);
L
Linus Torvalds 已提交
224 225
}

A
Adrian Bunk 已提交
226
static __inline__ void
227
qla2x00_stop_timer(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
228
{
229 230
	del_timer_sync(&vha->timer);
	vha->timer_active = 0;
L
Linus Torvalds 已提交
231 232 233 234 235 236
}

static int qla2x00_do_dpc(void *data);

static void qla2x00_rst_aen(scsi_qla_host_t *);

237 238
static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
	struct req_que **, struct rsp_que **);
239 240
static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
L
Linus Torvalds 已提交
241 242

/* -------------------------------------------------------------------------- */
243 244
static int qla2x00_alloc_queues(struct qla_hw_data *ha)
{
245
	ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
246 247 248 249 250 251 252
				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;
	}

253
	ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
				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;
}

271
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
272 273 274 275 276 277 278 279 280 281
{
	if (req && req->ring)
		dma_free_coherent(&ha->pdev->dev,
		(req->length + 1) * sizeof(request_t),
		req->ring, req->dma);

	kfree(req);
	req = NULL;
}

282 283 284 285 286 287 288 289 290 291 292
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;
}

293 294 295 296 297 298
static void qla2x00_free_queues(struct qla_hw_data *ha)
{
	struct req_que *req;
	struct rsp_que *rsp;
	int cnt;

299
	for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
300
		req = ha->req_q_map[cnt];
301
		qla2x00_free_req_que(ha, req);
302 303 304
	}
	kfree(ha->req_q_map);
	ha->req_q_map = NULL;
305 306 307 308 309 310 311

	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;
312 313
}

314 315 316 317 318 319
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;

320 321 322 323 324
	if (!(ha->fw_attributes & BIT_6)) {
		qla_printk(KERN_INFO, ha,
			"Firmware is not multi-queue capable\n");
		goto fail;
	}
325 326 327 328 329 330 331 332 333 334
	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;
		}
335
		ha->wq = create_workqueue("qla2xxx_wq");
336 337 338 339 340 341 342 343 344 345
		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;
			}
		}
346 347
		ha->flags.cpu_affinity_enabled = 1;

348 349 350 351 352 353 354 355
		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);
356 357
	destroy_workqueue(ha->wq);
	ha->wq = NULL;
358 359
fail:
	ha->mqenable = 0;
360 361 362
	kfree(ha->req_q_map);
	kfree(ha->rsp_q_map);
	ha->max_req_queues = ha->max_rsp_queues = 1;
363 364 365
	return 1;
}

L
Linus Torvalds 已提交
366
static char *
367
qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str)
L
Linus Torvalds 已提交
368
{
369
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
	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);
}

390
static char *
391
qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
392 393
{
	static char *pci_bus_modes[] = { "33", "66", "100", "133", };
394
	struct qla_hw_data *ha = vha->hw;
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
	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)
411
			strcat(str, "2.5GT/s ");
412
		else if (lspeed == 2)
413
			strcat(str, "5.0GT/s ");
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
		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;
}

441
static char *
442
qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
L
Linus Torvalds 已提交
443 444
{
	char un_str[10];
445
	struct qla_hw_data *ha = vha->hw;
A
Andrew Vasquez 已提交
446

L
Linus Torvalds 已提交
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
	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);
}

480
static char *
481
qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
482
{
483
	struct qla_hw_data *ha = vha->hw;
484

485 486
	sprintf(str, "%d.%02d.%02d (%x)", ha->fw_major_version,
	    ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes);
487 488 489 490
	return str;
}

static inline srb_t *
491
qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
492 493 494
    struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
	srb_t *sp;
495
	struct qla_hw_data *ha = vha->hw;
496 497 498 499 500 501 502 503 504 505

	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;
506
	sp->ctx = NULL;
507 508 509 510

	return sp;
}

L
Linus Torvalds 已提交
511
static int
512
qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
513
{
514
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
515
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
516
	struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
517 518
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
519 520 521
	srb_t *sp;
	int rval;

522 523
	if (ha->flags.eeh_busy) {
		if (ha->flags.pci_channel_io_perm_failure)
524
			cmd->result = DID_NO_CONNECT << 16;
525 526
		else
			cmd->result = DID_REQUEUE << 16;
527 528 529
		goto qc24_fail_command;
	}

530 531 532
	rval = fc_remote_port_chkready(rport);
	if (rval) {
		cmd->result = rval;
533 534 535
		goto qc24_fail_command;
	}

536
	/* Close window on fcport/rport state-transitioning. */
537 538
	if (fcport->drport)
		goto qc24_target_busy;
539

540 541
	if (atomic_read(&fcport->state) != FCS_ONLINE) {
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
542
		    atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
543 544 545
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
		}
546
		goto qc24_target_busy;
547 548
	}

549
	spin_unlock_irq(vha->host->host_lock);
550

551
	sp = qla2x00_get_new_sp(base_vha, fcport, cmd, done);
552 553 554
	if (!sp)
		goto qc24_host_busy_lock;

555
	rval = ha->isp_ops->start_scsi(sp);
556 557 558
	if (rval != QLA_SUCCESS)
		goto qc24_host_busy_free_sp;

559
	spin_lock_irq(vha->host->host_lock);
560 561 562 563

	return 0;

qc24_host_busy_free_sp:
564 565
	qla2x00_sp_free_dma(sp);
	mempool_free(sp, ha->srb_mempool);
566 567

qc24_host_busy_lock:
568
	spin_lock_irq(vha->host->host_lock);
569 570
	return SCSI_MLQUEUE_HOST_BUSY;

571 572 573
qc24_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

574 575 576 577 578 579 580
qc24_fail_command:
	done(cmd);

	return 0;
}


L
Linus Torvalds 已提交
581 582 583 584 585 586 587 588 589 590 591 592 593
/*
 * 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
594
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
L
Linus Torvalds 已提交
595
{
596 597
#define ABORT_POLLING_PERIOD	1000
#define ABORT_WAIT_ITER		((10 * 1000) / (ABORT_POLLING_PERIOD))
已提交
598
	unsigned long wait_iter = ABORT_WAIT_ITER;
599 600
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
已提交
601
	int ret = QLA_SUCCESS;
L
Linus Torvalds 已提交
602

603 604 605 606 607
	if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
		DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n"));
		return ret;
	}

608
	while (CMD_SP(cmd) && wait_iter--) {
609
		msleep(ABORT_POLLING_PERIOD);
已提交
610 611 612
	}
	if (CMD_SP(cmd))
		ret = QLA_FUNCTION_FAILED;
L
Linus Torvalds 已提交
613

已提交
614
	return ret;
L
Linus Torvalds 已提交
615 616 617 618
}

/*
 * qla2x00_wait_for_hba_online
A
Andrew Vasquez 已提交
619
 *    Wait till the HBA is online after going through
L
Linus Torvalds 已提交
620 621 622 623 624
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline
 *
 * Input:
 *     ha - pointer to host adapter structure
A
Andrew Vasquez 已提交
625 626
 *
 * Note:
L
Linus Torvalds 已提交
627 628 629 630 631 632 633
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online) : 0
 *    Failed  (Adapter is offline/disabled) : 1
 */
634
int
635
qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
636
{
637 638
	int		return_status;
	unsigned long	wait_online;
639 640
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
641

A
Andrew Vasquez 已提交
642
	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
643 644 645 646
	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)) {
L
Linus Torvalds 已提交
647 648 649

		msleep(1000);
	}
650
	if (base_vha->flags.online)
A
Andrew Vasquez 已提交
651
		return_status = QLA_SUCCESS;
L
Linus Torvalds 已提交
652 653 654 655 656 657
	else
		return_status = QLA_FUNCTION_FAILED;

	return (return_status);
}

658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
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;
}

L
Linus Torvalds 已提交
686 687 688
/*
 * qla2x00_wait_for_loop_ready
 *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
A
Andrew Vasquez 已提交
689
 *    to be in LOOP_READY state.
L
Linus Torvalds 已提交
690 691
 * Input:
 *     ha - pointer to host adapter structure
A
Andrew Vasquez 已提交
692 693
 *
 * Note:
L
Linus Torvalds 已提交
694 695
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
A
Andrew Vasquez 已提交
696
 *
L
Linus Torvalds 已提交
697 698 699 700 701
 *
 * Return:
 *    Success (LOOP_READY) : 0
 *    Failed  (LOOP_NOT_READY) : 1
 */
A
Andrew Vasquez 已提交
702
static inline int
703
qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
704 705 706
{
	int 	 return_status = QLA_SUCCESS;
	unsigned long loop_timeout ;
707 708
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
709 710

	/* wait for 5 min at the max for loop to be ready */
A
Andrew Vasquez 已提交
711
	loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ);
L
Linus Torvalds 已提交
712

713 714 715 716
	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) {
717 718 719
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
L
Linus Torvalds 已提交
720 721 722 723 724 725
		msleep(1000);
		if (time_after_eq(jiffies, loop_timeout)) {
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
	}
A
Andrew Vasquez 已提交
726
	return (return_status);
L
Linus Torvalds 已提交
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
}

/**************************************************************************
* 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:
742
*    Only return FAILED if command not returned by firmware.
L
Linus Torvalds 已提交
743
**************************************************************************/
744
static int
L
Linus Torvalds 已提交
745 746
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
{
747
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
已提交
748
	srb_t *sp;
749
	int ret, i;
已提交
750 751
	unsigned int id, lun;
	unsigned long serial;
752
	unsigned long flags;
753
	int wait = 0;
754
	struct qla_hw_data *ha = vha->hw;
755
	struct req_que *req = vha->req;
756
	srb_t *spt;
L
Linus Torvalds 已提交
757

758
	fc_block_scsi_eh(cmd);
759

已提交
760
	if (!CMD_SP(cmd))
761
		return SUCCESS;
L
Linus Torvalds 已提交
762

763
	ret = SUCCESS;
L
Linus Torvalds 已提交
764

已提交
765 766 767
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
768 769 770
	spt = (srb_t *) CMD_SP(cmd);
	if (!spt)
		return SUCCESS;
L
Linus Torvalds 已提交
771

已提交
772
	/* Check active list for command command. */
773
	spin_lock_irqsave(&ha->hardware_lock, flags);
774 775
	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
		sp = req->outstanding_cmds[i];
L
Linus Torvalds 已提交
776

777 778
		if (sp == NULL)
			continue;
779
		if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID))
780
			continue;
781 782
		if (sp->cmd != cmd)
			continue;
L
Linus Torvalds 已提交
783

784 785 786 787
		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);
788
		if (ha->isp_ops->abort_command(sp)) {
789 790
			DEBUG2(printk("%s(%ld): abort_command "
			"mbx failed.\n", __func__, vha->host_no));
791
			ret = FAILED;
792 793 794 795
		} else {
			DEBUG3(printk("%s(%ld): abort_command "
			"mbx success.\n", __func__, vha->host_no));
			wait = 1;
796
		}
797 798
		spin_lock_irqsave(&ha->hardware_lock, flags);
		break;
已提交
799
	}
800
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
L
Linus Torvalds 已提交
801

已提交
802
	/* Wait for the command to be returned. */
803
	if (wait) {
804
		if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
A
Andrew Vasquez 已提交
805
			qla_printk(KERN_ERR, ha,
已提交
806
			    "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
807
			    "%x.\n", vha->host_no, id, lun, serial, ret);
808
			ret = FAILED;
已提交
809
		}
L
Linus Torvalds 已提交
810 811
	}

A
Andrew Vasquez 已提交
812
	qla_printk(KERN_INFO, ha,
813
	    "scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
814
	    vha->host_no, id, lun, wait, serial, ret);
L
Linus Torvalds 已提交
815

已提交
816 817
	return ret;
}
L
Linus Torvalds 已提交
818

819 820 821 822 823 824
enum nexus_wait_type {
	WAIT_HOST = 0,
	WAIT_TARGET,
	WAIT_LUN,
};

已提交
825
static int
826
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
827
	unsigned int l, srb_t *sp, enum nexus_wait_type type)
已提交
828
{
829
	int cnt, match, status;
830
	unsigned long flags;
831
	struct qla_hw_data *ha = vha->hw;
832
	struct req_que *req;
L
Linus Torvalds 已提交
833

834
	status = QLA_SUCCESS;
835 836 837
	if (!sp)
		return status;

838
	spin_lock_irqsave(&ha->hardware_lock, flags);
839
	req = vha->req;
840 841 842 843
	for (cnt = 1; status == QLA_SUCCESS &&
		cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (!sp)
844
			continue;
845 846
		if (sp->ctx)
			continue;
847 848 849 850 851 852 853 854 855 856 857 858 859 860
		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;
861
		}
862 863 864 865 866 867
		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);
L
Linus Torvalds 已提交
868
	}
869
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
870 871

	return status;
L
Linus Torvalds 已提交
872 873
}

874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
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"));
		}
	}
}

892 893 894 895 896 897
static char *reset_errors[] = {
	"HBA not online",
	"HBA not ready",
	"Task management failed",
	"Waiting for command completions",
};
L
Linus Torvalds 已提交
898

899
static int
900
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
901
    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
L
Linus Torvalds 已提交
902
{
903
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
904
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
905
	int err;
L
Linus Torvalds 已提交
906

907
	fc_block_scsi_eh(cmd);
908

909
	if (!fcport)
910
		return FAILED;
L
Linus Torvalds 已提交
911

912 913
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
L
Linus Torvalds 已提交
914

915
	err = 0;
916
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
917 918
		goto eh_reset_failed;
	err = 1;
919
	if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
920 921
		goto eh_reset_failed;
	err = 2;
922 923
	if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
		!= QLA_SUCCESS)
924 925
		goto eh_reset_failed;
	err = 3;
926
	if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
927
	    cmd->device->lun, (srb_t *) CMD_SP(cmd), type) != QLA_SUCCESS)
928 929
		goto eh_reset_failed;

930 931
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
932 933 934 935

	return SUCCESS;

 eh_reset_failed:
936 937
	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,
938 939 940
	    reset_errors[err]);
	return FAILED;
}
L
Linus Torvalds 已提交
941

942 943 944
static int
qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
{
945 946
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
947

948 949
	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
	    ha->isp_ops->lun_reset);
L
Linus Torvalds 已提交
950 951 952
}

static int
953
qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
L
Linus Torvalds 已提交
954
{
955 956
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
957

958 959
	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
	    ha->isp_ops->target_reset);
L
Linus Torvalds 已提交
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
}

/**************************************************************************
* 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).
*
**************************************************************************/
977
static int
L
Linus Torvalds 已提交
978 979
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
980
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
981
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
982
	int ret = FAILED;
已提交
983 984
	unsigned int id, lun;
	unsigned long serial;
985
	srb_t *sp = (srb_t *) CMD_SP(cmd);
已提交
986

987
	fc_block_scsi_eh(cmd);
988

已提交
989 990 991
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
L
Linus Torvalds 已提交
992

993
	if (!fcport)
已提交
994
		return ret;
L
Linus Torvalds 已提交
995

996
	qla_printk(KERN_INFO, vha->hw,
997
	    "scsi(%ld:%d:%d): BUS RESET ISSUED.\n", vha->host_no, id, lun);
L
Linus Torvalds 已提交
998

999
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
L
Linus Torvalds 已提交
1000
		DEBUG2(printk("%s failed:board disabled\n",__func__));
已提交
1001
		goto eh_bus_reset_done;
L
Linus Torvalds 已提交
1002 1003
	}

1004 1005
	if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
		if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
已提交
1006
			ret = SUCCESS;
L
Linus Torvalds 已提交
1007
	}
已提交
1008 1009
	if (ret == FAILED)
		goto eh_bus_reset_done;
L
Linus Torvalds 已提交
1010

1011
	/* Flush outstanding commands. */
1012
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) !=
1013
	    QLA_SUCCESS)
1014
		ret = FAILED;
L
Linus Torvalds 已提交
1015

已提交
1016
eh_bus_reset_done:
1017
	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
已提交
1018
	    (ret == FAILED) ? "failed" : "succeded");
L
Linus Torvalds 已提交
1019

已提交
1020
	return ret;
L
Linus Torvalds 已提交
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
}

/**************************************************************************
* 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:
**************************************************************************/
1038
static int
L
Linus Torvalds 已提交
1039 1040
qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
{
1041
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1042
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1043
	struct qla_hw_data *ha = vha->hw;
1044
	int ret = FAILED;
已提交
1045 1046
	unsigned int id, lun;
	unsigned long serial;
1047
	srb_t *sp = (srb_t *) CMD_SP(cmd);
1048
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
1049

1050
	fc_block_scsi_eh(cmd);
1051

已提交
1052 1053 1054 1055
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;

1056
	if (!fcport)
已提交
1057
		return ret;
L
Linus Torvalds 已提交
1058 1059

	qla_printk(KERN_INFO, ha,
1060
	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
L
Linus Torvalds 已提交
1061

1062
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
已提交
1063
		goto eh_host_reset_lock;
L
Linus Torvalds 已提交
1064 1065 1066

	/*
	 * Fixme-may be dpc thread is active and processing
A
Andrew Vasquez 已提交
1067
	 * loop_resync,so wait a while for it to
L
Linus Torvalds 已提交
1068 1069 1070 1071 1072
	 * be completed and then issue big hammer.Otherwise
	 * it may cause I/O failure as big hammer marks the
	 * devices as lost kicking of the port_down_timer
	 * while dpc is stuck for the mailbox to complete.
	 */
1073 1074 1075
	qla2x00_wait_for_loop_ready(vha);
	if (vha != base_vha) {
		if (qla2x00_vp_abort_isp(vha))
已提交
1076
			goto eh_host_reset_lock;
1077
	} else {
1078 1079 1080 1081 1082 1083 1084 1085
		if (IS_QLA82XX(vha->hw)) {
			if (!qla82xx_fcoe_ctx_reset(vha)) {
				/* Ctx reset success */
				ret = SUCCESS;
				goto eh_host_reset_lock;
			}
			/* fall thru if ctx reset failed */
		}
1086 1087 1088
		if (ha->wq)
			flush_workqueue(ha->wq);

1089
		set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
1090
		if (ha->isp_ops->abort_isp(base_vha)) {
1091 1092 1093 1094 1095 1096 1097 1098
			clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
			/* failed. schedule dpc to try */
			set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);

			if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
				goto eh_host_reset_lock;
		}
		clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
A
Andrew Vasquez 已提交
1099
	}
L
Linus Torvalds 已提交
1100

1101
	/* Waiting for command to be returned to OS.*/
1102
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) ==
1103
		QLA_SUCCESS)
已提交
1104
		ret = SUCCESS;
L
Linus Torvalds 已提交
1105

已提交
1106 1107 1108
eh_host_reset_lock:
	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
	    (ret == FAILED) ? "failed" : "succeded");
L
Linus Torvalds 已提交
1109

已提交
1110 1111
	return ret;
}
L
Linus Torvalds 已提交
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122

/*
* qla2x00_loop_reset
*      Issue loop reset.
*
* Input:
*      ha = adapter block pointer.
*
* Returns:
*      0 = success
*/
1123
int
1124
qla2x00_loop_reset(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
1125
{
1126
	int ret;
1127
	struct fc_port *fcport;
1128
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
1129

1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
	if (ha->flags.enable_target_reset) {
		list_for_each_entry(fcport, &vha->vp_fcports, list) {
			if (fcport->port_type != FCT_TARGET)
				continue;

			ret = ha->isp_ops->target_reset(fcport, 0, 0);
			if (ret != QLA_SUCCESS) {
				DEBUG2_3(printk("%s(%ld): bus_reset failed: "
				    "target_reset=%d d_id=%x.\n", __func__,
				    vha->host_no, ret, fcport->d_id.b24));
			}
		}
	}

1144
	if (ha->flags.enable_lip_full_login && !IS_QLA8XXX_TYPE(ha)) {
1145
		ret = qla2x00_full_login_lip(vha);
1146
		if (ret != QLA_SUCCESS) {
1147
			DEBUG2_3(printk("%s(%ld): failed: "
1148
			    "full_login_lip=%d.\n", __func__, vha->host_no,
1149
			    ret));
1150 1151 1152 1153 1154
		}
		atomic_set(&vha->loop_state, LOOP_DOWN);
		atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
		qla2x00_mark_all_devices_lost(vha, 0);
		qla2x00_wait_for_loop_ready(vha);
1155 1156
	}

1157
	if (ha->flags.enable_lip_reset) {
1158
		ret = qla2x00_lip_reset(vha);
1159
		if (ret != QLA_SUCCESS) {
1160
			DEBUG2_3(printk("%s(%ld): failed: "
1161 1162 1163
			    "lip_reset=%d.\n", __func__, vha->host_no, ret));
		} else
			qla2x00_wait_for_loop_ready(vha);
L
Linus Torvalds 已提交
1164 1165 1166
	}

	/* Issue marker command only when we are going to start the I/O */
1167
	vha->marker_needed = 1;
L
Linus Torvalds 已提交
1168

1169
	return QLA_SUCCESS;
L
Linus Torvalds 已提交
1170 1171
}

1172
void
1173
qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
1174
{
1175
	int que, cnt;
1176 1177
	unsigned long flags;
	srb_t *sp;
1178
	struct srb_ctx *ctx;
1179
	struct qla_hw_data *ha = vha->hw;
1180
	struct req_que *req;
1181 1182

	spin_lock_irqsave(&ha->hardware_lock, flags);
1183
	for (que = 0; que < ha->max_req_queues; que++) {
1184
		req = ha->req_q_map[que];
1185 1186 1187 1188
		if (!req)
			continue;
		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
			sp = req->outstanding_cmds[cnt];
1189
			if (sp) {
1190
				req->outstanding_cmds[cnt] = NULL;
1191 1192
				if (!sp->ctx ||
				(sp->flags & SRB_FCP_CMND_DMA_VALID)) {
1193 1194 1195 1196
					sp->cmd->result = res;
					qla2x00_sp_compl(ha, sp);
				} else {
					ctx = sp->ctx;
1197 1198
					if (ctx->type == SRB_LOGIN_CMD ||
					    ctx->type == SRB_LOGOUT_CMD) {
1199
						ctx->u.iocb_cmd->free(sp);
1200
					} else {
1201
						struct fc_bsg_job *bsg_job =
1202
						    ctx->u.bsg_job;
1203 1204
						if (bsg_job->request->msgcode
						    == FC_BSG_HST_CT)
1205
							kfree(sp->fcport);
1206 1207
						bsg_job->req->errors = 0;
						bsg_job->reply->result = res;
1208
						bsg_job->job_done(bsg_job);
1209
						kfree(sp->ctx);
1210
						mempool_free(sp,
1211
							ha->srb_mempool);
1212
					}
1213
				}
1214
			}
1215 1216 1217 1218 1219
		}
	}
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

已提交
1220 1221
static int
qla2xxx_slave_alloc(struct scsi_device *sdev)
L
Linus Torvalds 已提交
1222
{
1223
	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
L
Linus Torvalds 已提交
1224

1225
	if (!rport || fc_remote_port_chkready(rport))
已提交
1226
		return -ENXIO;
1227

1228
	sdev->hostdata = *(fc_port_t **)rport->dd_data;
L
Linus Torvalds 已提交
1229

已提交
1230 1231
	return 0;
}
L
Linus Torvalds 已提交
1232

已提交
1233 1234 1235
static int
qla2xxx_slave_configure(struct scsi_device *sdev)
{
1236 1237
	scsi_qla_host_t *vha = shost_priv(sdev->host);
	struct qla_hw_data *ha = vha->hw;
已提交
1238
	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
1239
	struct req_que *req = vha->req;
已提交
1240

已提交
1241
	if (sdev->tagged_supported)
1242
		scsi_activate_tcq(sdev, req->max_q_depth);
已提交
1243
	else
1244
		scsi_deactivate_tcq(sdev, req->max_q_depth);
L
Linus Torvalds 已提交
1245

1246
	rport->dev_loss_tmo = ha->port_down_retry_count;
已提交
1247

已提交
1248 1249
	return 0;
}
L
Linus Torvalds 已提交
1250

已提交
1251 1252 1253 1254
static void
qla2xxx_slave_destroy(struct scsi_device *sdev)
{
	sdev->hostdata = NULL;
L
Linus Torvalds 已提交
1255 1256
}

1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
{
	fc_port_t *fcport = (struct fc_port *) sdev->hostdata;

	if (!scsi_track_queue_full(sdev, qdepth))
		return;

	DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
		"scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
		fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
		sdev->queue_depth));
}

static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
{
	fc_port_t *fcport = sdev->hostdata;
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
	struct req_que *req = NULL;

	req = vha->req;
	if (!req)
		return;

	if (req->max_q_depth <= sdev->queue_depth || req->max_q_depth < qdepth)
		return;

	if (sdev->ordered_tags)
		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, qdepth);
	else
		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth);

	DEBUG2(qla_printk(KERN_INFO, ha,
	       "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
	       fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
	       sdev->queue_depth));
}

1295
static int
1296
qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
1297
{
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
	switch (reason) {
	case SCSI_QDEPTH_DEFAULT:
		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
		break;
	case SCSI_QDEPTH_QFULL:
		qla2x00_handle_queue_full(sdev, qdepth);
		break;
	case SCSI_QDEPTH_RAMP_UP:
		qla2x00_adjust_sdev_qdepth_up(sdev, qdepth);
		break;
	default:
1309
		return -EOPNOTSUPP;
1310
	}
1311

1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
	return sdev->queue_depth;
}

static int
qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type)
{
	if (sdev->tagged_supported) {
		scsi_set_tag_type(sdev, tag_type);
		if (tag_type)
			scsi_activate_tcq(sdev, sdev->queue_depth);
		else
			scsi_deactivate_tcq(sdev, sdev->queue_depth);
	} else
		tag_type = 0;

	return tag_type;
}

L
Linus Torvalds 已提交
1330 1331 1332 1333 1334 1335 1336 1337
/**
 * qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
 * @ha: HA context
 *
 * At exit, the @ha's flags.enable_64bit_addressing set to indicated
 * supported addressing method.
 */
static void
1338
qla2x00_config_dma_addressing(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
1339
{
1340
	/* Assume a 32bit DMA mask. */
L
Linus Torvalds 已提交
1341 1342
	ha->flags.enable_64bit_addressing = 0;

1343
	if (!dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
1344 1345
		/* Any upper-dword bits set? */
		if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
1346
		    !pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
1347
			/* Ok, a 64bit DMA mask is applicable. */
L
Linus Torvalds 已提交
1348
			ha->flags.enable_64bit_addressing = 1;
1349 1350
			ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
			ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64;
1351
			return;
L
Linus Torvalds 已提交
1352 1353
		}
	}
1354

1355 1356
	dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32));
	pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(32));
L
Linus Torvalds 已提交
1357 1358
}

1359
static void
1360
qla2x00_enable_intrs(struct qla_hw_data *ha)
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
{
	unsigned long flags = 0;
	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;

	spin_lock_irqsave(&ha->hardware_lock, flags);
	ha->interrupts_on = 1;
	/* enable risc and host interrupts */
	WRT_REG_WORD(&reg->ictrl, ICR_EN_INT | ICR_EN_RISC);
	RD_REG_WORD(&reg->ictrl);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

}

static void
1375
qla2x00_disable_intrs(struct qla_hw_data *ha)
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
{
	unsigned long flags = 0;
	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;

	spin_lock_irqsave(&ha->hardware_lock, flags);
	ha->interrupts_on = 0;
	/* disable risc and host interrupts */
	WRT_REG_WORD(&reg->ictrl, 0);
	RD_REG_WORD(&reg->ictrl);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

static void
1389
qla24xx_enable_intrs(struct qla_hw_data *ha)
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
{
	unsigned long flags = 0;
	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

	spin_lock_irqsave(&ha->hardware_lock, flags);
	ha->interrupts_on = 1;
	WRT_REG_DWORD(&reg->ictrl, ICRX_EN_RISC_INT);
	RD_REG_DWORD(&reg->ictrl);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

static void
1402
qla24xx_disable_intrs(struct qla_hw_data *ha)
1403 1404 1405 1406
{
	unsigned long flags = 0;
	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

1407 1408
	if (IS_NOPOLLING_TYPE(ha))
		return;
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
	spin_lock_irqsave(&ha->hardware_lock, flags);
	ha->interrupts_on = 0;
	WRT_REG_DWORD(&reg->ictrl, 0);
	RD_REG_DWORD(&reg->ictrl);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

static struct isp_operations qla2100_isp_ops = {
	.pci_config		= qla2100_pci_config,
	.reset_chip		= qla2x00_reset_chip,
	.chip_diag		= qla2x00_chip_diag,
	.config_rings		= qla2x00_config_rings,
	.reset_adapter		= qla2x00_reset_adapter,
	.nvram_config		= qla2x00_nvram_config,
	.update_fw_options	= qla2x00_update_fw_options,
	.load_risc		= qla2x00_load_risc,
	.pci_info_str		= qla2x00_pci_info_str,
	.fw_version_str		= qla2x00_fw_version_str,
	.intr_handler		= qla2100_intr_handler,
	.enable_intrs		= qla2x00_enable_intrs,
	.disable_intrs		= qla2x00_disable_intrs,
	.abort_command		= qla2x00_abort_command,
1431 1432
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447
	.fabric_login		= qla2x00_login_fabric,
	.fabric_logout		= qla2x00_fabric_logout,
	.calc_req_entries	= qla2x00_calc_iocbs_32,
	.build_iocbs		= qla2x00_build_scsi_iocbs_32,
	.prep_ms_iocb		= qla2x00_prep_ms_iocb,
	.prep_ms_fdmi_iocb	= qla2x00_prep_ms_fdmi_iocb,
	.read_nvram		= qla2x00_read_nvram_data,
	.write_nvram		= qla2x00_write_nvram_data,
	.fw_dump		= qla2100_fw_dump,
	.beacon_on		= NULL,
	.beacon_off		= NULL,
	.beacon_blink		= NULL,
	.read_optrom		= qla2x00_read_optrom_data,
	.write_optrom		= qla2x00_write_optrom_data,
	.get_flash_version	= qla2x00_get_flash_version,
1448
	.start_scsi		= qla2x00_start_scsi,
1449
	.abort_isp		= qla2x00_abort_isp,
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
};

static struct isp_operations qla2300_isp_ops = {
	.pci_config		= qla2300_pci_config,
	.reset_chip		= qla2x00_reset_chip,
	.chip_diag		= qla2x00_chip_diag,
	.config_rings		= qla2x00_config_rings,
	.reset_adapter		= qla2x00_reset_adapter,
	.nvram_config		= qla2x00_nvram_config,
	.update_fw_options	= qla2x00_update_fw_options,
	.load_risc		= qla2x00_load_risc,
	.pci_info_str		= qla2x00_pci_info_str,
	.fw_version_str		= qla2x00_fw_version_str,
	.intr_handler		= qla2300_intr_handler,
	.enable_intrs		= qla2x00_enable_intrs,
	.disable_intrs		= qla2x00_disable_intrs,
	.abort_command		= qla2x00_abort_command,
1467 1468
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
	.fabric_login		= qla2x00_login_fabric,
	.fabric_logout		= qla2x00_fabric_logout,
	.calc_req_entries	= qla2x00_calc_iocbs_32,
	.build_iocbs		= qla2x00_build_scsi_iocbs_32,
	.prep_ms_iocb		= qla2x00_prep_ms_iocb,
	.prep_ms_fdmi_iocb	= qla2x00_prep_ms_fdmi_iocb,
	.read_nvram		= qla2x00_read_nvram_data,
	.write_nvram		= qla2x00_write_nvram_data,
	.fw_dump		= qla2300_fw_dump,
	.beacon_on		= qla2x00_beacon_on,
	.beacon_off		= qla2x00_beacon_off,
	.beacon_blink		= qla2x00_beacon_blink,
	.read_optrom		= qla2x00_read_optrom_data,
	.write_optrom		= qla2x00_write_optrom_data,
	.get_flash_version	= qla2x00_get_flash_version,
1484
	.start_scsi		= qla2x00_start_scsi,
1485
	.abort_isp		= qla2x00_abort_isp,
1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502
};

static struct isp_operations qla24xx_isp_ops = {
	.pci_config		= qla24xx_pci_config,
	.reset_chip		= qla24xx_reset_chip,
	.chip_diag		= qla24xx_chip_diag,
	.config_rings		= qla24xx_config_rings,
	.reset_adapter		= qla24xx_reset_adapter,
	.nvram_config		= qla24xx_nvram_config,
	.update_fw_options	= qla24xx_update_fw_options,
	.load_risc		= qla24xx_load_risc,
	.pci_info_str		= qla24xx_pci_info_str,
	.fw_version_str		= qla24xx_fw_version_str,
	.intr_handler		= qla24xx_intr_handler,
	.enable_intrs		= qla24xx_enable_intrs,
	.disable_intrs		= qla24xx_disable_intrs,
	.abort_command		= qla24xx_abort_command,
1503 1504
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
	.fabric_login		= qla24xx_login_fabric,
	.fabric_logout		= qla24xx_fabric_logout,
	.calc_req_entries	= NULL,
	.build_iocbs		= NULL,
	.prep_ms_iocb		= qla24xx_prep_ms_iocb,
	.prep_ms_fdmi_iocb	= qla24xx_prep_ms_fdmi_iocb,
	.read_nvram		= qla24xx_read_nvram_data,
	.write_nvram		= qla24xx_write_nvram_data,
	.fw_dump		= qla24xx_fw_dump,
	.beacon_on		= qla24xx_beacon_on,
	.beacon_off		= qla24xx_beacon_off,
	.beacon_blink		= qla24xx_beacon_blink,
	.read_optrom		= qla24xx_read_optrom_data,
	.write_optrom		= qla24xx_write_optrom_data,
	.get_flash_version	= qla24xx_get_flash_version,
1520
	.start_scsi		= qla24xx_start_scsi,
1521
	.abort_isp		= qla2x00_abort_isp,
1522 1523
};

1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
static struct isp_operations qla25xx_isp_ops = {
	.pci_config		= qla25xx_pci_config,
	.reset_chip		= qla24xx_reset_chip,
	.chip_diag		= qla24xx_chip_diag,
	.config_rings		= qla24xx_config_rings,
	.reset_adapter		= qla24xx_reset_adapter,
	.nvram_config		= qla24xx_nvram_config,
	.update_fw_options	= qla24xx_update_fw_options,
	.load_risc		= qla24xx_load_risc,
	.pci_info_str		= qla24xx_pci_info_str,
	.fw_version_str		= qla24xx_fw_version_str,
	.intr_handler		= qla24xx_intr_handler,
	.enable_intrs		= qla24xx_enable_intrs,
	.disable_intrs		= qla24xx_disable_intrs,
	.abort_command		= qla24xx_abort_command,
1539 1540
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
	.fabric_login		= qla24xx_login_fabric,
	.fabric_logout		= qla24xx_fabric_logout,
	.calc_req_entries	= NULL,
	.build_iocbs		= NULL,
	.prep_ms_iocb		= qla24xx_prep_ms_iocb,
	.prep_ms_fdmi_iocb	= qla24xx_prep_ms_fdmi_iocb,
	.read_nvram		= qla25xx_read_nvram_data,
	.write_nvram		= qla25xx_write_nvram_data,
	.fw_dump		= qla25xx_fw_dump,
	.beacon_on		= qla24xx_beacon_on,
	.beacon_off		= qla24xx_beacon_off,
	.beacon_blink		= qla24xx_beacon_blink,
1553
	.read_optrom		= qla25xx_read_optrom_data,
1554 1555
	.write_optrom		= qla24xx_write_optrom_data,
	.get_flash_version	= qla24xx_get_flash_version,
1556
	.start_scsi		= qla24xx_start_scsi,
1557
	.abort_isp		= qla2x00_abort_isp,
1558 1559
};

1560 1561 1562 1563 1564 1565 1566 1567
static struct isp_operations qla81xx_isp_ops = {
	.pci_config		= qla25xx_pci_config,
	.reset_chip		= qla24xx_reset_chip,
	.chip_diag		= qla24xx_chip_diag,
	.config_rings		= qla24xx_config_rings,
	.reset_adapter		= qla24xx_reset_adapter,
	.nvram_config		= qla81xx_nvram_config,
	.update_fw_options	= qla81xx_update_fw_options,
1568
	.load_risc		= qla81xx_load_risc,
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582
	.pci_info_str		= qla24xx_pci_info_str,
	.fw_version_str		= qla24xx_fw_version_str,
	.intr_handler		= qla24xx_intr_handler,
	.enable_intrs		= qla24xx_enable_intrs,
	.disable_intrs		= qla24xx_disable_intrs,
	.abort_command		= qla24xx_abort_command,
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
	.fabric_login		= qla24xx_login_fabric,
	.fabric_logout		= qla24xx_fabric_logout,
	.calc_req_entries	= NULL,
	.build_iocbs		= NULL,
	.prep_ms_iocb		= qla24xx_prep_ms_iocb,
	.prep_ms_fdmi_iocb	= qla24xx_prep_ms_fdmi_iocb,
1583 1584
	.read_nvram		= NULL,
	.write_nvram		= NULL,
1585 1586 1587 1588 1589 1590 1591 1592
	.fw_dump		= qla81xx_fw_dump,
	.beacon_on		= qla24xx_beacon_on,
	.beacon_off		= qla24xx_beacon_off,
	.beacon_blink		= qla24xx_beacon_blink,
	.read_optrom		= qla25xx_read_optrom_data,
	.write_optrom		= qla24xx_write_optrom_data,
	.get_flash_version	= qla24xx_get_flash_version,
	.start_scsi		= qla24xx_start_scsi,
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
	.abort_isp		= qla2x00_abort_isp,
};

static struct isp_operations qla82xx_isp_ops = {
	.pci_config		= qla82xx_pci_config,
	.reset_chip		= qla82xx_reset_chip,
	.chip_diag		= qla24xx_chip_diag,
	.config_rings		= qla82xx_config_rings,
	.reset_adapter		= qla24xx_reset_adapter,
	.nvram_config		= qla81xx_nvram_config,
	.update_fw_options	= qla24xx_update_fw_options,
	.load_risc		= qla82xx_load_risc,
	.pci_info_str		= qla82xx_pci_info_str,
	.fw_version_str		= qla24xx_fw_version_str,
	.intr_handler		= qla82xx_intr_handler,
	.enable_intrs		= qla82xx_enable_intrs,
	.disable_intrs		= qla82xx_disable_intrs,
	.abort_command		= qla24xx_abort_command,
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
	.fabric_login		= qla24xx_login_fabric,
	.fabric_logout		= qla24xx_fabric_logout,
	.calc_req_entries	= NULL,
	.build_iocbs		= NULL,
	.prep_ms_iocb		= qla24xx_prep_ms_iocb,
	.prep_ms_fdmi_iocb	= qla24xx_prep_ms_fdmi_iocb,
	.read_nvram		= qla24xx_read_nvram_data,
	.write_nvram		= qla24xx_write_nvram_data,
	.fw_dump		= qla24xx_fw_dump,
	.beacon_on		= qla24xx_beacon_on,
	.beacon_off		= qla24xx_beacon_off,
	.beacon_blink		= qla24xx_beacon_blink,
	.read_optrom		= qla82xx_read_optrom_data,
	.write_optrom		= qla82xx_write_optrom_data,
	.get_flash_version	= qla24xx_get_flash_version,
	.start_scsi             = qla82xx_start_scsi,
	.abort_isp		= qla82xx_abort_isp,
1630 1631
};

1632
static inline void
1633
qla2x00_set_isp_flags(struct qla_hw_data *ha)
1634 1635 1636 1637 1638 1639
{
	ha->device_type = DT_EXTENDED_IDS;
	switch (ha->pdev->device) {
	case PCI_DEVICE_ID_QLOGIC_ISP2100:
		ha->device_type |= DT_ISP2100;
		ha->device_type &= ~DT_EXTENDED_IDS;
1640
		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
1641 1642 1643 1644
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2200:
		ha->device_type |= DT_ISP2200;
		ha->device_type &= ~DT_EXTENDED_IDS;
1645
		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
1646 1647 1648
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2300:
		ha->device_type |= DT_ISP2300;
1649
		ha->device_type |= DT_ZIO_SUPPORTED;
1650
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1651 1652 1653
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2312:
		ha->device_type |= DT_ISP2312;
1654
		ha->device_type |= DT_ZIO_SUPPORTED;
1655
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1656 1657 1658
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2322:
		ha->device_type |= DT_ISP2322;
1659
		ha->device_type |= DT_ZIO_SUPPORTED;
1660 1661 1662
		if (ha->pdev->subsystem_vendor == 0x1028 &&
		    ha->pdev->subsystem_device == 0x0170)
			ha->device_type |= DT_OEM_001;
1663
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1664 1665 1666
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP6312:
		ha->device_type |= DT_ISP6312;
1667
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1668 1669 1670
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP6322:
		ha->device_type |= DT_ISP6322;
1671
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1672 1673 1674
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2422:
		ha->device_type |= DT_ISP2422;
1675
		ha->device_type |= DT_ZIO_SUPPORTED;
1676
		ha->device_type |= DT_FWI2;
1677
		ha->device_type |= DT_IIDMA;
1678
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1679 1680 1681
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2432:
		ha->device_type |= DT_ISP2432;
1682
		ha->device_type |= DT_ZIO_SUPPORTED;
1683
		ha->device_type |= DT_FWI2;
1684
		ha->device_type |= DT_IIDMA;
1685
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1686
		break;
1687 1688 1689 1690 1691 1692 1693
	case PCI_DEVICE_ID_QLOGIC_ISP8432:
		ha->device_type |= DT_ISP8432;
		ha->device_type |= DT_ZIO_SUPPORTED;
		ha->device_type |= DT_FWI2;
		ha->device_type |= DT_IIDMA;
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
		break;
1694 1695
	case PCI_DEVICE_ID_QLOGIC_ISP5422:
		ha->device_type |= DT_ISP5422;
1696
		ha->device_type |= DT_FWI2;
1697
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1698
		break;
1699 1700
	case PCI_DEVICE_ID_QLOGIC_ISP5432:
		ha->device_type |= DT_ISP5432;
1701
		ha->device_type |= DT_FWI2;
1702
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1703
		break;
1704 1705 1706 1707 1708
	case PCI_DEVICE_ID_QLOGIC_ISP2532:
		ha->device_type |= DT_ISP2532;
		ha->device_type |= DT_ZIO_SUPPORTED;
		ha->device_type |= DT_FWI2;
		ha->device_type |= DT_IIDMA;
1709
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1710
		break;
1711 1712 1713 1714 1715 1716 1717
	case PCI_DEVICE_ID_QLOGIC_ISP8001:
		ha->device_type |= DT_ISP8001;
		ha->device_type |= DT_ZIO_SUPPORTED;
		ha->device_type |= DT_FWI2;
		ha->device_type |= DT_IIDMA;
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
		break;
1718 1719 1720 1721 1722 1723 1724 1725
	case PCI_DEVICE_ID_QLOGIC_ISP8021:
		ha->device_type |= DT_ISP8021;
		ha->device_type |= DT_ZIO_SUPPORTED;
		ha->device_type |= DT_FWI2;
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
		/* Initialize 82XX ISP flags */
		qla82xx_init_flags(ha);
		break;
1726
	}
1727

1728 1729 1730 1731 1732 1733
	if (IS_QLA82XX(ha))
		ha->port_no = !(ha->portnum & 1);
	else
		/* Get adapter physical port no from interrupt pin register. */
		pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no);

1734 1735 1736 1737
	if (ha->port_no & 1)
		ha->flags.port0 = 1;
	else
		ha->flags.port0 = 0;
1738 1739
}

L
Linus Torvalds 已提交
1740
static int
1741
qla2x00_iospace_config(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
1742
{
1743
	resource_size_t pio;
1744
	uint16_t msix;
1745
	int cpus;
L
Linus Torvalds 已提交
1746

1747 1748 1749
	if (IS_QLA82XX(ha))
		return qla82xx_iospace_config(ha);

1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760
	if (pci_request_selected_regions(ha->pdev, ha->bars,
	    QLA2XXX_DRIVER_NAME)) {
		qla_printk(KERN_WARNING, ha,
		    "Failed to reserve PIO/MMIO regions (%s)\n",
		    pci_name(ha->pdev));

		goto iospace_error_exit;
	}
	if (!(ha->bars & 1))
		goto skip_pio;

L
Linus Torvalds 已提交
1761 1762
	/* We only need PIO for Flash operations on ISP2312 v2 chips. */
	pio = pci_resource_start(ha->pdev, 0);
1763 1764
	if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
		if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) {
L
Linus Torvalds 已提交
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775
			qla_printk(KERN_WARNING, ha,
			    "Invalid PCI I/O region size (%s)...\n",
				pci_name(ha->pdev));
			pio = 0;
		}
	} else {
		qla_printk(KERN_WARNING, ha,
		    "region #0 not a PIO resource (%s)...\n",
		    pci_name(ha->pdev));
		pio = 0;
	}
1776
	ha->pio_address = pio;
L
Linus Torvalds 已提交
1777

1778
skip_pio:
L
Linus Torvalds 已提交
1779
	/* Use MMIO operations for all accesses. */
1780
	if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) {
L
Linus Torvalds 已提交
1781
		qla_printk(KERN_ERR, ha,
1782
		    "region #1 not an MMIO resource (%s), aborting\n",
L
Linus Torvalds 已提交
1783 1784 1785
		    pci_name(ha->pdev));
		goto iospace_error_exit;
	}
1786
	if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) {
L
Linus Torvalds 已提交
1787 1788 1789 1790 1791 1792
		qla_printk(KERN_ERR, ha,
		    "Invalid PCI mem region size (%s), aborting\n",
			pci_name(ha->pdev));
		goto iospace_error_exit;
	}

1793
	ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN);
L
Linus Torvalds 已提交
1794 1795 1796 1797 1798 1799 1800
	if (!ha->iobase) {
		qla_printk(KERN_ERR, ha,
		    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));

		goto iospace_error_exit;
	}

1801
	/* Determine queue resources */
1802
	ha->max_req_queues = ha->max_rsp_queues = 1;
1803 1804
	if ((ql2xmaxqueues <= 1 && !ql2xmultique_tag) ||
		(ql2xmaxqueues > 1 && ql2xmultique_tag) ||
1805
		(!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
1806
		goto mqiobase_exit;
1807

1808 1809 1810 1811 1812 1813
	ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3),
			pci_resource_len(ha->pdev, 3));
	if (ha->mqiobase) {
		/* Read MSIX vector size of the board */
		pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix);
		ha->msix_count = msix;
1814 1815 1816 1817
		/* Max queues are bounded by available msix vectors */
		/* queue 0 uses two msix vectors */
		if (ql2xmultique_tag) {
			cpus = num_online_cpus();
1818
			ha->max_rsp_queues = (ha->msix_count - 1 > cpus) ?
1819 1820 1821
				(cpus + 1) : (ha->msix_count - 1);
			ha->max_req_queues = 2;
		} else if (ql2xmaxqueues > 1) {
1822 1823 1824 1825 1826
			ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ?
						QLA_MQ_SIZE : ql2xmaxqueues;
			DEBUG2(qla_printk(KERN_INFO, ha, "QoS mode set, max no"
			" of request queues:%d\n", ha->max_req_queues));
		}
1827 1828
		qla_printk(KERN_INFO, ha,
			"MSI-X vector count: %d\n", msix);
1829 1830
	} else
		qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
1831 1832

mqiobase_exit:
1833
	ha->msix_count = ha->max_rsp_queues + 1;
L
Linus Torvalds 已提交
1834 1835 1836 1837 1838 1839
	return (0);

iospace_error_exit:
	return (-ENOMEM);
}

1840 1841 1842
static void
qla2xxx_scan_start(struct Scsi_Host *shost)
{
1843
	scsi_qla_host_t *vha = shost_priv(shost);
1844

1845 1846 1847
	if (vha->hw->flags.running_gold_fw)
		return;

1848 1849 1850 1851
	set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
	set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
	set_bit(RSCN_UPDATE, &vha->dpc_flags);
	set_bit(NPIV_CONFIG_NEEDED, &vha->dpc_flags);
1852 1853 1854 1855 1856
}

static int
qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
1857
	scsi_qla_host_t *vha = shost_priv(shost);
1858

1859
	if (!vha->host)
1860
		return 1;
1861
	if (time > vha->hw->loop_reset_delay * HZ)
1862 1863
		return 1;

1864
	return atomic_read(&vha->loop_state) == LOOP_READY;
1865 1866
}

L
Linus Torvalds 已提交
1867 1868 1869
/*
 * PCI driver interface
 */
1870 1871
static int __devinit
qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
L
Linus Torvalds 已提交
1872
{
1873
	int	ret = -ENODEV;
L
Linus Torvalds 已提交
1874
	struct Scsi_Host *host;
1875 1876
	scsi_qla_host_t *base_vha = NULL;
	struct qla_hw_data *ha;
1877
	char pci_info[30];
L
Linus Torvalds 已提交
1878
	char fw_str[30];
1879
	struct scsi_host_template *sht;
1880
	int bars, max_id, mem_only = 0;
1881
	uint16_t req_length = 0, rsp_length = 0;
1882 1883
	struct req_que *req = NULL;
	struct rsp_que *rsp = NULL;
L
Linus Torvalds 已提交
1884

1885
	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
1886
	sht = &qla2xxx_driver_template;
1887
	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
1888
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
1889
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
1890
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
1891
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
1892
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
1893 1894
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 ||
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021) {
1895
		bars = pci_select_bars(pdev, IORESOURCE_MEM);
1896
		mem_only = 1;
1897 1898
	}

1899 1900 1901 1902 1903 1904 1905
	if (mem_only) {
		if (pci_enable_device_mem(pdev))
			goto probe_out;
	} else {
		if (pci_enable_device(pdev))
			goto probe_out;
	}
1906

1907 1908
	/* This may fail but that's ok */
	pci_enable_pcie_error_reporting(pdev);
1909

1910 1911 1912 1913
	ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL);
	if (!ha) {
		DEBUG(printk("Unable to allocate memory for ha\n"));
		goto probe_out;
L
Linus Torvalds 已提交
1914
	}
1915
	ha->pdev = pdev;
L
Linus Torvalds 已提交
1916 1917

	/* Clear our data area */
1918
	ha->bars = bars;
1919
	ha->mem_only = mem_only;
1920
	spin_lock_init(&ha->hardware_lock);
L
Linus Torvalds 已提交
1921

1922 1923
	/* Set ISP-type information. */
	qla2x00_set_isp_flags(ha);
1924 1925 1926 1927 1928 1929

	/* Set EEH reset type to fundamental if required by hba */
	if ( IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha)) {
		pdev->needs_freset = 1;
	}

L
Linus Torvalds 已提交
1930 1931
	/* Configure PCI I/O space */
	ret = qla2x00_iospace_config(ha);
1932
	if (ret)
1933
		goto probe_hw_failed;
L
Linus Torvalds 已提交
1934 1935

	qla_printk(KERN_INFO, ha,
1936 1937
	    "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,
	    ha->iobase);
L
Linus Torvalds 已提交
1938 1939

	ha->prev_topology = 0;
1940
	ha->init_cb_size = sizeof(init_cb_t);
1941
	ha->link_data_rate = PORT_SPEED_UNKNOWN;
1942
	ha->optrom_size = OPTROM_SIZE_2300;
L
Linus Torvalds 已提交
1943

1944
	/* Assign ISP specific operations. */
1945
	max_id = MAX_TARGETS_2200;
L
Linus Torvalds 已提交
1946
	if (IS_QLA2100(ha)) {
1947
		max_id = MAX_TARGETS_2100;
L
Linus Torvalds 已提交
1948
		ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
1949 1950 1951
		req_length = REQUEST_ENTRY_CNT_2100;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1952
		ha->gid_list_info_size = 4;
1953 1954 1955 1956
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1957
		ha->isp_ops = &qla2100_isp_ops;
L
Linus Torvalds 已提交
1958 1959
	} else if (IS_QLA2200(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1960 1961 1962
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1963
		ha->gid_list_info_size = 4;
1964 1965 1966 1967
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1968
		ha->isp_ops = &qla2100_isp_ops;
1969
	} else if (IS_QLA23XX(ha)) {
L
Linus Torvalds 已提交
1970
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1971 1972 1973
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1974
		ha->gid_list_info_size = 6;
1975 1976
		if (IS_QLA2322(ha) || IS_QLA6322(ha))
			ha->optrom_size = OPTROM_SIZE_2322;
1977 1978 1979 1980
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1981
		ha->isp_ops = &qla2300_isp_ops;
1982
	} else if (IS_QLA24XX_TYPE(ha)) {
1983
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1984 1985 1986
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1987
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
1988
		ha->gid_list_info_size = 8;
1989
		ha->optrom_size = OPTROM_SIZE_24XX;
1990
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA24XX;
1991
		ha->isp_ops = &qla24xx_isp_ops;
1992 1993 1994 1995
		ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
		ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
		ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
		ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
1996 1997
	} else if (IS_QLA25XX(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1998 1999 2000
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
2001 2002 2003
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
		ha->gid_list_info_size = 8;
		ha->optrom_size = OPTROM_SIZE_25XX;
2004
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
2005
		ha->isp_ops = &qla25xx_isp_ops;
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017
		ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
		ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
		ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
		ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
	} else if (IS_QLA81XX(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
		ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
		ha->gid_list_info_size = 8;
		ha->optrom_size = OPTROM_SIZE_81XX;
2018
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
2019 2020 2021 2022 2023
		ha->isp_ops = &qla81xx_isp_ops;
		ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_81XX;
		ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
	} else if (IS_QLA82XX(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
		req_length = REQUEST_ENTRY_CNT_82XX;
		rsp_length = RESPONSE_ENTRY_CNT_82XX;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
		ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
		ha->gid_list_info_size = 8;
		ha->optrom_size = OPTROM_SIZE_82XX;
		ha->isp_ops = &qla82xx_isp_ops;
		ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
		ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
		ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
		ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
L
Linus Torvalds 已提交
2037 2038
	}

2039
	mutex_init(&ha->vport_lock);
2040 2041 2042
	init_completion(&ha->mbx_cmd_comp);
	complete(&ha->mbx_cmd_comp);
	init_completion(&ha->mbx_intr_comp);
L
Linus Torvalds 已提交
2043

2044
	set_bit(0, (unsigned long *) ha->vp_idx_map);
L
Linus Torvalds 已提交
2045

2046
	qla2x00_config_dma_addressing(ha);
2047
	ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp);
2048
	if (!ret) {
L
Linus Torvalds 已提交
2049 2050 2051
		qla_printk(KERN_WARNING, ha,
		    "[ERROR] Failed to allocate memory for adapter\n");

2052 2053 2054
		goto probe_hw_failed;
	}

2055
	req->max_q_depth = MAX_Q_DEPTH;
2056
	if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU)
2057 2058
		req->max_q_depth = ql2xmaxqdepth;

2059 2060 2061 2062 2063 2064

	base_vha = qla2x00_create_host(sht, ha);
	if (!base_vha) {
		qla_printk(KERN_WARNING, ha,
		    "[ERROR] Failed to allocate memory for scsi_host\n");

2065
		ret = -ENOMEM;
2066
		qla2x00_mem_free(ha);
2067 2068
		qla2x00_free_req_que(ha, req);
		qla2x00_free_rsp_que(ha, rsp);
2069
		goto probe_hw_failed;
L
Linus Torvalds 已提交
2070 2071
	}

2072 2073 2074
	pci_set_drvdata(pdev, base_vha);

	host = base_vha->host;
2075
	base_vha->req = req;
2076 2077
	host->can_queue = req->length + 128;
	if (IS_QLA2XXX_MIDTYPE(ha))
2078
		base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
2079
	else
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091
		base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
						base_vha->vp_idx;
	if (IS_QLA2100(ha))
		host->sg_tablesize = 32;
	host->max_id = max_id;
	host->this_id = 255;
	host->cmd_per_lun = 3;
	host->unique_id = host->host_no;
	host->max_cmd_len = MAX_CMDSZ;
	host->max_channel = MAX_BUSES - 1;
	host->max_lun = MAX_LUNS;
	host->transportt = qla2xxx_transport_template;
2092
	sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC);
2093

2094 2095 2096
	/* Set up the irqs */
	ret = qla2x00_request_irqs(ha, rsp);
	if (ret)
2097
		goto probe_init_failed;
2098 2099 2100

	pci_save_state(pdev);

2101
	/* Alloc arrays of request and response ring ptrs */
2102
que_init:
2103 2104 2105 2106
	if (!qla2x00_alloc_queues(ha)) {
		qla_printk(KERN_WARNING, ha,
		"[ERROR] Failed to allocate memory for queue"
		" pointers\n");
2107
		goto probe_init_failed;
2108
	}
2109

2110 2111
	ha->rsp_q_map[0] = rsp;
	ha->req_q_map[0] = req;
2112 2113 2114 2115
	rsp->req = req;
	req->rsp = rsp;
	set_bit(0, ha->req_qid_map);
	set_bit(0, ha->rsp_qid_map);
2116 2117 2118 2119 2120
	/* FWI2-capable only. */
	req->req_q_in = &ha->iobase->isp24.req_q_in;
	req->req_q_out = &ha->iobase->isp24.req_q_out;
	rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in;
	rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out;
2121
	if (ha->mqenable) {
2122 2123 2124 2125
		req->req_q_in = &ha->mqiobase->isp25mq.req_q_in;
		req->req_q_out = &ha->mqiobase->isp25mq.req_q_out;
		rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in;
		rsp->rsp_q_out =  &ha->mqiobase->isp25mq.rsp_q_out;
2126 2127
	}

2128 2129 2130 2131 2132 2133
	if (IS_QLA82XX(ha)) {
		req->req_q_out = &ha->iobase->isp82.req_q_out[0];
		rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0];
		rsp->rsp_q_out = &ha->iobase->isp82.rsp_q_out[0];
	}

2134
	if (qla2x00_initialize_adapter(base_vha)) {
L
Linus Torvalds 已提交
2135 2136 2137 2138 2139
		qla_printk(KERN_WARNING, ha,
		    "Failed to initialize adapter\n");

		DEBUG2(printk("scsi(%ld): Failed to initialize adapter - "
		    "Adapter flags %x.\n",
2140
		    base_vha->host_no, base_vha->device_flags));
L
Linus Torvalds 已提交
2141

2142 2143 2144 2145 2146 2147 2148 2149
		if (IS_QLA82XX(ha)) {
			qla82xx_idc_lock(ha);
			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
				QLA82XX_DEV_FAILED);
			qla82xx_idc_unlock(ha);
			qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
		}

2150
		ret = -ENODEV;
L
Linus Torvalds 已提交
2151 2152 2153
		goto probe_failed;
	}

2154 2155
	if (ha->mqenable) {
		if (qla25xx_setup_mode(base_vha)) {
2156 2157 2158
			qla_printk(KERN_WARNING, ha,
				"Can't create queues, falling back to single"
				" queue mode\n");
2159 2160 2161
			goto que_init;
		}
	}
2162

2163 2164 2165
	if (ha->flags.running_gold_fw)
		goto skip_dpc;

L
Linus Torvalds 已提交
2166 2167 2168
	/*
	 * Startup the kernel thread for this host adapter
	 */
2169
	ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
2170
			"%s_dpc", base_vha->host_str);
2171
	if (IS_ERR(ha->dpc_thread)) {
L
Linus Torvalds 已提交
2172 2173
		qla_printk(KERN_WARNING, ha,
		    "Unable to start DPC thread!\n");
2174
		ret = PTR_ERR(ha->dpc_thread);
L
Linus Torvalds 已提交
2175 2176 2177
		goto probe_failed;
	}

2178
skip_dpc:
2179 2180
	list_add_tail(&base_vha->list, &ha->vp_list);
	base_vha->host->irq = ha->pdev->irq;
L
Linus Torvalds 已提交
2181 2182

	/* Initialized the timer */
2183
	qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL);
L
Linus Torvalds 已提交
2184 2185

	DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
2186
	    base_vha->host_no, ha));
2187

2188 2189
	ha->isp_ops->enable_intrs(ha);

2190 2191 2192 2193
	ret = scsi_add_host(host, &pdev->dev);
	if (ret)
		goto probe_failed;

2194 2195 2196
	base_vha->flags.init_done = 1;
	base_vha->flags.online = 1;

2197 2198
	scsi_scan_host(host);

2199
	qla2x00_alloc_sysfs_attr(base_vha);
2200

2201
	qla2x00_init_host_attr(base_vha);
2202

2203
	qla2x00_dfs_setup(base_vha);
2204

L
Linus Torvalds 已提交
2205 2206 2207
	qla_printk(KERN_INFO, ha, "\n"
	    " QLogic Fibre Channel HBA Driver: %s\n"
	    "  QLogic %s - %s\n"
2208 2209
	    "  ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
	    qla2x00_version_str, ha->model_number,
2210 2211 2212 2213
	    ha->model_desc ? ha->model_desc : "", pdev->device,
	    ha->isp_ops->pci_info_str(base_vha, pci_info), pci_name(pdev),
	    ha->flags.enable_64bit_addressing ? '+' : '-', base_vha->host_no,
	    ha->isp_ops->fw_version_str(base_vha, fw_str));
L
Linus Torvalds 已提交
2214 2215 2216

	return 0;

2217
probe_init_failed:
2218 2219 2220
	qla2x00_free_req_que(ha, req);
	qla2x00_free_rsp_que(ha, rsp);
	ha->max_req_queues = ha->max_rsp_queues = 0;
2221

L
Linus Torvalds 已提交
2222
probe_failed:
2223 2224 2225 2226 2227 2228 2229 2230 2231 2232
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);
	base_vha->flags.online = 0;
	if (ha->dpc_thread) {
		struct task_struct *t = ha->dpc_thread;

		ha->dpc_thread = NULL;
		kthread_stop(t);
	}

2233
	qla2x00_free_device(base_vha);
L
Linus Torvalds 已提交
2234

2235
	scsi_host_put(base_vha->host);
L
Linus Torvalds 已提交
2236

2237
probe_hw_failed:
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248
	if (IS_QLA82XX(ha)) {
		qla82xx_idc_lock(ha);
		qla82xx_clear_drv_active(ha);
		qla82xx_idc_unlock(ha);
		iounmap((device_reg_t __iomem *)ha->nx_pcibase);
		if (!ql2xdbwr)
			iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr);
	} else {
		if (ha->iobase)
			iounmap(ha->iobase);
	}
2249 2250 2251
	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
L
Linus Torvalds 已提交
2252

2253
probe_out:
2254
	pci_disable_device(pdev);
2255
	return ret;
L
Linus Torvalds 已提交
2256 2257
}

A
Adrian Bunk 已提交
2258
static void
2259
qla2x00_remove_one(struct pci_dev *pdev)
L
Linus Torvalds 已提交
2260
{
2261 2262 2263 2264 2265 2266 2267 2268 2269 2270
	scsi_qla_host_t *base_vha, *vha, *temp;
	struct qla_hw_data  *ha;

	base_vha = pci_get_drvdata(pdev);
	ha = base_vha->hw;

	list_for_each_entry_safe(vha, temp, &ha->vp_list, list) {
		if (vha && vha->fc_vport)
			fc_vport_terminate(vha->fc_vport);
	}
L
Linus Torvalds 已提交
2271

2272
	set_bit(UNLOADING, &base_vha->dpc_flags);
L
Linus Torvalds 已提交
2273

2274 2275
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

2276
	qla2x00_dfs_remove(base_vha);
2277

2278
	qla84xx_put_chip(base_vha);
2279

2280 2281 2282 2283 2284 2285
	/* Disable timer */
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);

	base_vha->flags.online = 0;

2286 2287 2288 2289 2290 2291 2292
	/* Flush the work queue and remove it */
	if (ha->wq) {
		flush_workqueue(ha->wq);
		destroy_workqueue(ha->wq);
		ha->wq = NULL;
	}

2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304
	/* Kill the kernel thread for this host */
	if (ha->dpc_thread) {
		struct task_struct *t = ha->dpc_thread;

		/*
		 * qla2xxx_wake_dpc checks for ->dpc_thread
		 * so we need to zero it out.
		 */
		ha->dpc_thread = NULL;
		kthread_stop(t);
	}

2305
	qla2x00_free_sysfs_attr(base_vha);
2306

2307
	fc_remove_host(base_vha->host);
2308

2309
	scsi_remove_host(base_vha->host);
L
Linus Torvalds 已提交
2310

2311
	qla2x00_free_device(base_vha);
2312

2313
	scsi_host_put(base_vha->host);
L
Linus Torvalds 已提交
2314

2315 2316 2317 2318 2319 2320 2321
	if (IS_QLA82XX(ha)) {
		iounmap((device_reg_t __iomem *)ha->nx_pcibase);
		if (!ql2xdbwr)
			iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr);
	} else {
		if (ha->iobase)
			iounmap(ha->iobase);
L
Linus Torvalds 已提交
2322

2323 2324 2325
		if (ha->mqiobase)
			iounmap(ha->mqiobase);
	}
2326

2327 2328 2329
	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
L
Linus Torvalds 已提交
2330

2331 2332
	pci_disable_pcie_error_reporting(pdev);

2333
	pci_disable_device(pdev);
L
Linus Torvalds 已提交
2334 2335 2336 2337
	pci_set_drvdata(pdev, NULL);
}

static void
2338
qla2x00_free_device(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
2339
{
2340
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
2341

2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
	qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);

	/* Disable timer */
	if (vha->timer_active)
		qla2x00_stop_timer(vha);

	/* Kill the kernel thread for this host */
	if (ha->dpc_thread) {
		struct task_struct *t = ha->dpc_thread;

		/*
		 * qla2xxx_wake_dpc checks for ->dpc_thread
		 * so we need to zero it out.
		 */
		ha->dpc_thread = NULL;
		kthread_stop(t);
	}

2360 2361
	qla25xx_delete_queues(vha);

2362
	if (ha->flags.fce_enabled)
2363
		qla2x00_disable_fce_trace(vha, NULL, NULL);
2364

2365
	if (ha->eft)
2366
		qla2x00_disable_eft_trace(vha);
2367

2368
	/* Stop currently executing firmware. */
2369
	qla2x00_try_to_stop_firmware(vha);
L
Linus Torvalds 已提交
2370

2371 2372
	vha->flags.online = 0;

2373
	/* turn-off interrupts on the card */
2374 2375
	if (ha->interrupts_on) {
		vha->flags.init_done = 0;
2376
		ha->isp_ops->disable_intrs(ha);
2377
	}
2378

2379
	qla2x00_free_irqs(vha);
L
Linus Torvalds 已提交
2380

2381
	qla2x00_mem_free(ha);
2382 2383

	qla2x00_free_queues(ha);
L
Linus Torvalds 已提交
2384 2385
}

2386
static inline void
2387
qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
2388 2389 2390
    int defer)
{
	struct fc_rport *rport;
2391
	scsi_qla_host_t *base_vha;
2392 2393 2394 2395 2396 2397

	if (!fcport->rport)
		return;

	rport = fcport->rport;
	if (defer) {
2398
		base_vha = pci_get_drvdata(vha->hw->pdev);
2399
		spin_lock_irq(vha->host->host_lock);
2400
		fcport->drport = rport;
2401
		spin_unlock_irq(vha->host->host_lock);
2402 2403
		set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
		qla2xxx_wake_dpc(base_vha);
2404
	} else
2405 2406 2407
		fc_remote_port_delete(rport);
}

L
Linus Torvalds 已提交
2408 2409 2410 2411 2412 2413 2414 2415 2416
/*
 * qla2x00_mark_device_lost Updates fcport state when device goes offline.
 *
 * Input: ha = adapter block pointer.  fcport = port structure pointer.
 *
 * Return: None.
 *
 * Context:
 */
2417
void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
2418
    int do_login, int defer)
L
Linus Torvalds 已提交
2419
{
2420
	if (atomic_read(&fcport->state) == FCS_ONLINE &&
2421 2422 2423 2424
	    vha->vp_idx == fcport->vp_idx) {
		atomic_set(&fcport->state, FCS_DEVICE_LOST);
		qla2x00_schedule_rport_del(vha, fcport, defer);
	}
A
Andrew Vasquez 已提交
2425
	/*
L
Linus Torvalds 已提交
2426 2427 2428 2429 2430 2431 2432 2433 2434 2435
	 * We may need to retry the login, so don't change the state of the
	 * port but do the retries.
	 */
	if (atomic_read(&fcport->state) != FCS_DEVICE_DEAD)
		atomic_set(&fcport->state, FCS_DEVICE_LOST);

	if (!do_login)
		return;

	if (fcport->login_retry == 0) {
2436 2437
		fcport->login_retry = vha->hw->login_retry_count;
		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
2438 2439 2440 2441

		DEBUG(printk("scsi(%ld): Port login retry: "
		    "%02x%02x%02x%02x%02x%02x%02x%02x, "
		    "id = 0x%04x retry cnt=%d\n",
2442
		    vha->host_no,
L
Linus Torvalds 已提交
2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
		    fcport->port_name[0],
		    fcport->port_name[1],
		    fcport->port_name[2],
		    fcport->port_name[3],
		    fcport->port_name[4],
		    fcport->port_name[5],
		    fcport->port_name[6],
		    fcport->port_name[7],
		    fcport->loop_id,
		    fcport->login_retry));
	}
}

/*
 * qla2x00_mark_all_devices_lost
 *	Updates fcport state when device goes offline.
 *
 * Input:
 *	ha = adapter block pointer.
 *	fcport = port structure pointer.
 *
 * Return:
 *	None.
 *
 * Context:
 */
void
2470
qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
L
Linus Torvalds 已提交
2471 2472 2473
{
	fc_port_t *fcport;

2474
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
2475
		if (vha->vp_idx != 0 && vha->vp_idx != fcport->vp_idx)
L
Linus Torvalds 已提交
2476
			continue;
2477

L
Linus Torvalds 已提交
2478 2479 2480 2481 2482 2483
		/*
		 * No point in marking the device as lost, if the device is
		 * already DEAD.
		 */
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
			continue;
2484
		if (atomic_read(&fcport->state) == FCS_ONLINE) {
2485 2486 2487 2488 2489 2490
			if (defer)
				qla2x00_schedule_rport_del(vha, fcport, defer);
			else if (vha->vp_idx == fcport->vp_idx)
				qla2x00_schedule_rport_del(vha, fcport, defer);
		}
		atomic_set(&fcport->state, FCS_DEVICE_LOST);
L
Linus Torvalds 已提交
2491 2492 2493 2494 2495 2496 2497 2498 2499
	}
}

/*
* qla2x00_mem_alloc
*      Allocates adapter memory.
*
* Returns:
*      0  = success.
2500
*      !0  = failure.
L
Linus Torvalds 已提交
2501
*/
2502
static int
2503 2504
qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
	struct req_que **req, struct rsp_que **rsp)
L
Linus Torvalds 已提交
2505 2506 2507
{
	char	name[16];

2508
	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
2509
		&ha->init_cb_dma, GFP_KERNEL);
2510
	if (!ha->init_cb)
2511
		goto fail;
2512

2513 2514 2515
	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
		&ha->gid_list_dma, GFP_KERNEL);
	if (!ha->gid_list)
2516
		goto fail_free_init_cb;
L
Linus Torvalds 已提交
2517

2518 2519
	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
	if (!ha->srb_mempool)
2520
		goto fail_free_gid_list;
2521

2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536
	if (IS_QLA82XX(ha)) {
		/* Allocate cache for CT6 Ctx. */
		if (!ctx_cachep) {
			ctx_cachep = kmem_cache_create("qla2xxx_ctx",
				sizeof(struct ct6_dsd), 0,
				SLAB_HWCACHE_ALIGN, NULL);
			if (!ctx_cachep)
				goto fail_free_gid_list;
		}
		ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ,
			ctx_cachep);
		if (!ha->ctx_mempool)
			goto fail_free_srb_mempool;
	}

2537 2538 2539
	/* Get memory for cached NVRAM */
	ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL);
	if (!ha->nvram)
2540
		goto fail_free_ctx_mempool;
2541

2542 2543 2544 2545 2546 2547 2548
	snprintf(name, sizeof(name), "%s_%d", QLA2XXX_DRIVER_NAME,
		ha->pdev->device);
	ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
		DMA_POOL_SIZE, 8, 0);
	if (!ha->s_dma_pool)
		goto fail_free_nvram;

2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566
	if (IS_QLA82XX(ha)) {
		ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
			DSD_LIST_DMA_POOL_SIZE, 8, 0);
		if (!ha->dl_dma_pool) {
			qla_printk(KERN_WARNING, ha,
			    "Memory Allocation failed - dl_dma_pool\n");
			goto fail_s_dma_pool;
		}

		ha->fcp_cmnd_dma_pool = dma_pool_create(name, &ha->pdev->dev,
			FCP_CMND_DMA_POOL_SIZE, 8, 0);
		if (!ha->fcp_cmnd_dma_pool) {
			qla_printk(KERN_WARNING, ha,
			    "Memory Allocation failed - fcp_cmnd_dma_pool\n");
			goto fail_dl_dma_pool;
		}
	}

2567 2568
	/* Allocate memory for SNS commands */
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
2569
	/* Get consistent memory allocated for SNS commands */
2570
		ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,
2571
		sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL);
2572
		if (!ha->sns_cmd)
2573
			goto fail_dma_pool;
2574
	} else {
2575
	/* Get consistent memory allocated for MS IOCB */
2576
		ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
2577
			&ha->ms_iocb_dma);
2578
		if (!ha->ms_iocb)
2579 2580
			goto fail_dma_pool;
	/* Get consistent memory allocated for CT SNS commands */
2581
		ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,
2582
			sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
2583 2584
		if (!ha->ct_sns)
			goto fail_free_ms_iocb;
L
Linus Torvalds 已提交
2585 2586
	}

2587
	/* Allocate memory for request ring */
2588 2589
	*req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
	if (!*req) {
2590 2591 2592
		DEBUG(printk("Unable to allocate memory for req\n"));
		goto fail_req;
	}
2593 2594 2595 2596 2597
	(*req)->length = req_len;
	(*req)->ring = dma_alloc_coherent(&ha->pdev->dev,
		((*req)->length + 1) * sizeof(request_t),
		&(*req)->dma, GFP_KERNEL);
	if (!(*req)->ring) {
2598 2599 2600 2601
		DEBUG(printk("Unable to allocate memory for req_ring\n"));
		goto fail_req_ring;
	}
	/* Allocate memory for response ring */
2602 2603 2604 2605
	*rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
	if (!*rsp) {
		qla_printk(KERN_WARNING, ha,
			"Unable to allocate memory for rsp\n");
2606 2607
		goto fail_rsp;
	}
2608 2609 2610 2611 2612 2613 2614 2615
	(*rsp)->hw = ha;
	(*rsp)->length = rsp_len;
	(*rsp)->ring = dma_alloc_coherent(&ha->pdev->dev,
		((*rsp)->length + 1) * sizeof(response_t),
		&(*rsp)->dma, GFP_KERNEL);
	if (!(*rsp)->ring) {
		qla_printk(KERN_WARNING, ha,
			"Unable to allocate memory for rsp_ring\n");
2616 2617
		goto fail_rsp_ring;
	}
2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630
	(*req)->rsp = *rsp;
	(*rsp)->req = *req;
	/* Allocate memory for NVRAM data for vports */
	if (ha->nvram_npiv_size) {
		ha->npiv_info = kzalloc(sizeof(struct qla_npiv_entry) *
					ha->nvram_npiv_size, GFP_KERNEL);
		if (!ha->npiv_info) {
			qla_printk(KERN_WARNING, ha,
				"Unable to allocate memory for npiv info\n");
			goto fail_npiv_info;
		}
	} else
		ha->npiv_info = NULL;
2631

2632
	/* Get consistent memory allocated for EX-INIT-CB. */
2633
	if (IS_QLA8XXX_TYPE(ha)) {
2634 2635 2636 2637 2638 2639
		ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
		    &ha->ex_init_cb_dma);
		if (!ha->ex_init_cb)
			goto fail_ex_init_cb;
	}

2640 2641
	INIT_LIST_HEAD(&ha->gbl_dsd_list);

2642 2643 2644 2645 2646 2647 2648 2649
	/* Get consistent memory allocated for Async Port-Database. */
	if (!IS_FWI2_CAPABLE(ha)) {
		ha->async_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
			&ha->async_pd_dma);
		if (!ha->async_pd)
			goto fail_async_pd;
	}

2650 2651 2652
	INIT_LIST_HEAD(&ha->vp_list);
	return 1;

2653 2654
fail_async_pd:
	dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
2655 2656
fail_ex_init_cb:
	kfree(ha->npiv_info);
2657 2658 2659 2660 2661
fail_npiv_info:
	dma_free_coherent(&ha->pdev->dev, ((*rsp)->length + 1) *
		sizeof(response_t), (*rsp)->ring, (*rsp)->dma);
	(*rsp)->ring = NULL;
	(*rsp)->dma = 0;
2662
fail_rsp_ring:
2663
	kfree(*rsp);
2664
fail_rsp:
2665 2666 2667 2668
	dma_free_coherent(&ha->pdev->dev, ((*req)->length + 1) *
		sizeof(request_t), (*req)->ring, (*req)->dma);
	(*req)->ring = NULL;
	(*req)->dma = 0;
2669
fail_req_ring:
2670
	kfree(*req);
2671 2672 2673 2674 2675
fail_req:
	dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
		ha->ct_sns, ha->ct_sns_dma);
	ha->ct_sns = NULL;
	ha->ct_sns_dma = 0;
2676 2677 2678 2679
fail_free_ms_iocb:
	dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
	ha->ms_iocb = NULL;
	ha->ms_iocb_dma = 0;
2680
fail_dma_pool:
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690
	if (IS_QLA82XX(ha)) {
		dma_pool_destroy(ha->fcp_cmnd_dma_pool);
		ha->fcp_cmnd_dma_pool = NULL;
	}
fail_dl_dma_pool:
	if (IS_QLA82XX(ha)) {
		dma_pool_destroy(ha->dl_dma_pool);
		ha->dl_dma_pool = NULL;
	}
fail_s_dma_pool:
2691 2692
	dma_pool_destroy(ha->s_dma_pool);
	ha->s_dma_pool = NULL;
2693 2694 2695
fail_free_nvram:
	kfree(ha->nvram);
	ha->nvram = NULL;
2696 2697 2698
fail_free_ctx_mempool:
	mempool_destroy(ha->ctx_mempool);
	ha->ctx_mempool = NULL;
2699 2700 2701 2702 2703
fail_free_srb_mempool:
	mempool_destroy(ha->srb_mempool);
	ha->srb_mempool = NULL;
fail_free_gid_list:
	dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
2704
	ha->gid_list_dma);
2705 2706
	ha->gid_list = NULL;
	ha->gid_list_dma = 0;
2707 2708 2709 2710 2711
fail_free_init_cb:
	dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
	ha->init_cb_dma);
	ha->init_cb = NULL;
	ha->init_cb_dma = 0;
2712
fail:
2713
	DEBUG(printk("%s: Memory allocation failure\n", __func__));
2714
	return -ENOMEM;
L
Linus Torvalds 已提交
2715 2716 2717 2718 2719 2720 2721 2722 2723
}

/*
* qla2x00_mem_free
*      Frees all adapter allocated memory.
*
* Input:
*      ha = adapter block pointer.
*/
A
Adrian Bunk 已提交
2724
static void
2725
qla2x00_mem_free(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
2726
{
2727 2728
	if (ha->srb_mempool)
		mempool_destroy(ha->srb_mempool);
L
Linus Torvalds 已提交
2729

2730 2731
	if (ha->fce)
		dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
2732
		ha->fce_dma);
2733

2734 2735 2736
	if (ha->fw_dump) {
		if (ha->eft)
			dma_free_coherent(&ha->pdev->dev,
2737
			ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
2738 2739 2740
		vfree(ha->fw_dump);
	}

2741 2742 2743 2744
	if (ha->dcbx_tlv)
		dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
		    ha->dcbx_tlv, ha->dcbx_tlv_dma);

2745 2746 2747 2748
	if (ha->xgmac_data)
		dma_free_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
		    ha->xgmac_data, ha->xgmac_data_dma);

L
Linus Torvalds 已提交
2749 2750
	if (ha->sns_cmd)
		dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
2751
		ha->sns_cmd, ha->sns_cmd_dma);
L
Linus Torvalds 已提交
2752 2753 2754

	if (ha->ct_sns)
		dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
2755
		ha->ct_sns, ha->ct_sns_dma);
L
Linus Torvalds 已提交
2756

2757 2758 2759
	if (ha->sfp_data)
		dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);

2760 2761 2762
	if (ha->edc_data)
		dma_pool_free(ha->s_dma_pool, ha->edc_data, ha->edc_data_dma);

L
Linus Torvalds 已提交
2763 2764 2765
	if (ha->ms_iocb)
		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);

2766
	if (ha->ex_init_cb)
2767 2768
		dma_pool_free(ha->s_dma_pool,
			ha->ex_init_cb, ha->ex_init_cb_dma);
2769

2770 2771 2772
	if (ha->async_pd)
		dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);

L
Linus Torvalds 已提交
2773 2774 2775 2776 2777
	if (ha->s_dma_pool)
		dma_pool_destroy(ha->s_dma_pool);

	if (ha->gid_list)
		dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
2778
		ha->gid_list_dma);
L
Linus Torvalds 已提交
2779

2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803
	if (IS_QLA82XX(ha)) {
		if (!list_empty(&ha->gbl_dsd_list)) {
			struct dsd_dma *dsd_ptr, *tdsd_ptr;

			/* clean up allocated prev pool */
			list_for_each_entry_safe(dsd_ptr,
				tdsd_ptr, &ha->gbl_dsd_list, list) {
				dma_pool_free(ha->dl_dma_pool,
				dsd_ptr->dsd_addr, dsd_ptr->dsd_list_dma);
				list_del(&dsd_ptr->list);
				kfree(dsd_ptr);
			}
		}
	}

	if (ha->dl_dma_pool)
		dma_pool_destroy(ha->dl_dma_pool);

	if (ha->fcp_cmnd_dma_pool)
		dma_pool_destroy(ha->fcp_cmnd_dma_pool);

	if (ha->ctx_mempool)
		mempool_destroy(ha->ctx_mempool);

2804 2805
	if (ha->init_cb)
		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
2806
			ha->init_cb, ha->init_cb_dma);
2807 2808
	vfree(ha->optrom_buffer);
	kfree(ha->nvram);
2809
	kfree(ha->npiv_info);
L
Linus Torvalds 已提交
2810

2811
	ha->srb_mempool = NULL;
2812
	ha->ctx_mempool = NULL;
2813 2814
	ha->eft = NULL;
	ha->eft_dma = 0;
L
Linus Torvalds 已提交
2815 2816 2817 2818 2819 2820 2821 2822
	ha->sns_cmd = NULL;
	ha->sns_cmd_dma = 0;
	ha->ct_sns = NULL;
	ha->ct_sns_dma = 0;
	ha->ms_iocb = NULL;
	ha->ms_iocb_dma = 0;
	ha->init_cb = NULL;
	ha->init_cb_dma = 0;
2823 2824
	ha->ex_init_cb = NULL;
	ha->ex_init_cb_dma = 0;
2825 2826
	ha->async_pd = NULL;
	ha->async_pd_dma = 0;
L
Linus Torvalds 已提交
2827 2828

	ha->s_dma_pool = NULL;
2829 2830
	ha->dl_dma_pool = NULL;
	ha->fcp_cmnd_dma_pool = NULL;
L
Linus Torvalds 已提交
2831 2832 2833 2834

	ha->gid_list = NULL;
	ha->gid_list_dma = 0;

2835 2836 2837 2838
	ha->fw_dump = NULL;
	ha->fw_dumped = 0;
	ha->fw_dump_reading = 0;
}
L
Linus Torvalds 已提交
2839

2840 2841 2842 2843 2844
struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
						struct qla_hw_data *ha)
{
	struct Scsi_Host *host;
	struct scsi_qla_host *vha = NULL;
2845

2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864
	host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
	if (host == NULL) {
		printk(KERN_WARNING
		"qla2xxx: Couldn't allocate host from scsi layer!\n");
		goto fail;
	}

	/* Clear our data area */
	vha = shost_priv(host);
	memset(vha, 0, sizeof(scsi_qla_host_t));

	vha->host = host;
	vha->host_no = host->host_no;
	vha->hw = ha;

	INIT_LIST_HEAD(&vha->vp_fcports);
	INIT_LIST_HEAD(&vha->work_list);
	INIT_LIST_HEAD(&vha->list);

2865 2866
	spin_lock_init(&vha->work_lock);

2867 2868 2869 2870 2871
	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
	return vha;

fail:
	return vha;
L
Linus Torvalds 已提交
2872 2873
}

2874
static struct qla_work_evt *
2875
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
2876 2877 2878
{
	struct qla_work_evt *e;

2879
	e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC);
2880 2881 2882 2883 2884 2885 2886 2887 2888
	if (!e)
		return NULL;

	INIT_LIST_HEAD(&e->list);
	e->type = type;
	e->flags = QLA_EVT_FLAG_FREE;
	return e;
}

2889
static int
2890
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
2891
{
2892
	unsigned long flags;
2893

2894
	spin_lock_irqsave(&vha->work_lock, flags);
2895
	list_add_tail(&e->list, &vha->work_list);
2896
	spin_unlock_irqrestore(&vha->work_lock, flags);
2897
	qla2xxx_wake_dpc(vha);
2898

2899 2900 2901 2902
	return QLA_SUCCESS;
}

int
2903
qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
2904 2905 2906 2907
    u32 data)
{
	struct qla_work_evt *e;

2908
	e = qla2x00_alloc_work(vha, QLA_EVT_AEN);
2909 2910 2911 2912 2913
	if (!e)
		return QLA_FUNCTION_FAILED;

	e->u.aen.code = code;
	e->u.aen.data = data;
2914
	return qla2x00_post_work(vha, e);
2915 2916
}

2917 2918 2919 2920 2921
int
qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
{
	struct qla_work_evt *e;

2922
	e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK);
2923 2924 2925 2926
	if (!e)
		return QLA_FUNCTION_FAILED;

	memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
2927
	return qla2x00_post_work(vha, e);
2928 2929
}

2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952
#define qla2x00_post_async_work(name, type)	\
int qla2x00_post_async_##name##_work(		\
    struct scsi_qla_host *vha,			\
    fc_port_t *fcport, uint16_t *data)		\
{						\
	struct qla_work_evt *e;			\
						\
	e = qla2x00_alloc_work(vha, type);	\
	if (!e)					\
		return QLA_FUNCTION_FAILED;	\
						\
	e->u.logio.fcport = fcport;		\
	if (data) {				\
		e->u.logio.data[0] = data[0];	\
		e->u.logio.data[1] = data[1];	\
	}					\
	return qla2x00_post_work(vha, e);	\
}

qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE);
qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
2953 2954
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE);
2955

2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
int
qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code)
{
	struct qla_work_evt *e;

	e = qla2x00_alloc_work(vha, QLA_EVT_UEVENT);
	if (!e)
		return QLA_FUNCTION_FAILED;

	e->u.uevent.code = code;
	return qla2x00_post_work(vha, e);
}

static void
qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code)
{
	char event_string[40];
	char *envp[] = { event_string, NULL };

	switch (code) {
	case QLA_UEVENT_CODE_FW_DUMP:
		snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld",
		    vha->host_no);
		break;
	default:
		/* do nothing */
		break;
	}
	kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp);
}

2987
void
2988
qla2x00_do_work(struct scsi_qla_host *vha)
2989
{
2990 2991 2992
	struct qla_work_evt *e, *tmp;
	unsigned long flags;
	LIST_HEAD(work);
2993

2994 2995 2996 2997 2998
	spin_lock_irqsave(&vha->work_lock, flags);
	list_splice_init(&vha->work_list, &work);
	spin_unlock_irqrestore(&vha->work_lock, flags);

	list_for_each_entry_safe(e, tmp, &work, list) {
2999 3000 3001 3002
		list_del_init(&e->list);

		switch (e->type) {
		case QLA_EVT_AEN:
3003
			fc_host_post_event(vha->host, fc_get_event_number(),
3004 3005
			    e->u.aen.code, e->u.aen.data);
			break;
3006 3007 3008
		case QLA_EVT_IDC_ACK:
			qla81xx_idc_ack(vha, e->u.idc_ack.mb);
			break;
3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023
		case QLA_EVT_ASYNC_LOGIN:
			qla2x00_async_login(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
		case QLA_EVT_ASYNC_LOGIN_DONE:
			qla2x00_async_login_done(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
		case QLA_EVT_ASYNC_LOGOUT:
			qla2x00_async_logout(vha, e->u.logio.fcport);
			break;
		case QLA_EVT_ASYNC_LOGOUT_DONE:
			qla2x00_async_logout_done(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
3024 3025 3026 3027 3028 3029 3030 3031
		case QLA_EVT_ASYNC_ADISC:
			qla2x00_async_adisc(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
		case QLA_EVT_ASYNC_ADISC_DONE:
			qla2x00_async_adisc_done(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
3032 3033 3034
		case QLA_EVT_UEVENT:
			qla2x00_uevent_emit(vha, e->u.uevent.code);
			break;
3035 3036 3037
		}
		if (e->flags & QLA_EVT_FLAG_FREE)
			kfree(e);
3038 3039
	}
}
3040

3041 3042 3043 3044 3045 3046
/* Relogins all the fcports of a vport
 * Context: dpc thread
 */
void qla2x00_relogin(struct scsi_qla_host *vha)
{
	fc_port_t       *fcport;
3047
	int status;
3048 3049
	uint16_t        next_loopid = 0;
	struct qla_hw_data *ha = vha->hw;
3050
	uint16_t data[2];
3051 3052 3053 3054 3055 3056

	list_for_each_entry(fcport, &vha->vp_fcports, list) {
	/*
	 * If the port is not ONLINE then try to login
	 * to it if we haven't run out of retries.
	 */
3057 3058
		if (atomic_read(&fcport->state) != FCS_ONLINE &&
		    fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
3059
			fcport->login_retry--;
3060
			if (fcport->flags & FCF_FABRIC_DEVICE) {
3061
				if (fcport->flags & FCF_FCP2_DEVICE)
3062 3063 3064 3065 3066 3067
					ha->isp_ops->fabric_logout(vha,
							fcport->loop_id,
							fcport->d_id.b.domain,
							fcport->d_id.b.area,
							fcport->d_id.b.al_pa);

3068
				if (IS_ALOGIO_CAPABLE(ha)) {
3069
					fcport->flags |= FCF_ASYNC_SENT;
3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080
					data[0] = 0;
					data[1] = QLA_LOGIO_LOGIN_RETRIED;
					status = qla2x00_post_async_login_work(
					    vha, fcport, data);
					if (status == QLA_SUCCESS)
						continue;
					/* Attempt a retry. */
					status = 1;
				} else
					status = qla2x00_fabric_login(vha,
					    fcport, &next_loopid);
3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108
			} else
				status = qla2x00_local_device_login(vha,
								fcport);

			if (status == QLA_SUCCESS) {
				fcport->old_loop_id = fcport->loop_id;

				DEBUG(printk("scsi(%ld): port login OK: logged "
				"in ID 0x%x\n", vha->host_no, fcport->loop_id));

				qla2x00_update_fcport(vha, fcport);

			} else if (status == 1) {
				set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
				/* retry the login again */
				DEBUG(printk("scsi(%ld): Retrying"
				" %d login again loop_id 0x%x\n",
				vha->host_no, fcport->login_retry,
						fcport->loop_id));
			} else {
				fcport->login_retry = 0;
			}

			if (fcport->login_retry == 0 && status != QLA_SUCCESS)
				fcport->loop_id = FC_NO_LOOP_ID;
		}
		if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
			break;
3109 3110 3111
	}
}

L
Linus Torvalds 已提交
3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127
/**************************************************************************
* qla2x00_do_dpc
*   This kernel thread is a task that is schedule by the interrupt handler
*   to perform the background processing for interrupts.
*
* Notes:
* This task always run in the context of a kernel thread.  It
* is kick-off by the driver's detect code and starts up
* up one per adapter. It immediately goes to sleep and waits for
* some fibre event.  When either the interrupt handler or
* the timer routine detects a event it will one of the task
* bits then wake us up.
**************************************************************************/
static int
qla2x00_do_dpc(void *data)
{
3128
	int		rval;
3129 3130
	scsi_qla_host_t *base_vha;
	struct qla_hw_data *ha;
L
Linus Torvalds 已提交
3131

3132 3133
	ha = (struct qla_hw_data *)data;
	base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
3134 3135 3136

	set_user_nice(current, -20);

3137
	while (!kthread_should_stop()) {
L
Linus Torvalds 已提交
3138 3139
		DEBUG3(printk("qla2x00: DPC handler sleeping\n"));

3140 3141 3142
		set_current_state(TASK_INTERRUPTIBLE);
		schedule();
		__set_current_state(TASK_RUNNING);
L
Linus Torvalds 已提交
3143 3144 3145 3146

		DEBUG3(printk("qla2x00: DPC handler waking up\n"));

		/* Initialization not yet finished. Don't do anything yet. */
3147
		if (!base_vha->flags.init_done)
L
Linus Torvalds 已提交
3148 3149
			continue;

3150 3151 3152 3153 3154 3155 3156
		if (ha->flags.eeh_busy) {
			DEBUG17(qla_printk(KERN_WARNING, ha,
			    "qla2x00_do_dpc: dpc_flags: %lx\n",
			    base_vha->dpc_flags));
			continue;
		}

3157
		DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
L
Linus Torvalds 已提交
3158 3159 3160 3161 3162 3163 3164 3165

		ha->dpc_active = 1;

		if (ha->flags.mbox_busy) {
			ha->dpc_active = 0;
			continue;
		}

3166
		qla2x00_do_work(base_vha);
3167

3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206
		if (IS_QLA82XX(ha)) {
			if (test_and_clear_bit(ISP_UNRECOVERABLE,
				&base_vha->dpc_flags)) {
				qla82xx_idc_lock(ha);
				qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
					QLA82XX_DEV_FAILED);
				qla82xx_idc_unlock(ha);
				qla_printk(KERN_INFO, ha,
					"HW State: FAILED\n");
				qla82xx_device_state_handler(base_vha);
				continue;
			}

			if (test_and_clear_bit(FCOE_CTX_RESET_NEEDED,
				&base_vha->dpc_flags)) {

				DEBUG(printk(KERN_INFO
					"scsi(%ld): dpc: sched "
					"qla82xx_fcoe_ctx_reset ha = %p\n",
					base_vha->host_no, ha));
				if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
					&base_vha->dpc_flags))) {
					if (qla82xx_fcoe_ctx_reset(base_vha)) {
						/* FCoE-ctx reset failed.
						 * Escalate to chip-reset
						 */
						set_bit(ISP_ABORT_NEEDED,
							&base_vha->dpc_flags);
					}
					clear_bit(ABORT_ISP_ACTIVE,
						&base_vha->dpc_flags);
				}

				DEBUG(printk("scsi(%ld): dpc:"
					" qla82xx_fcoe_ctx_reset end\n",
					base_vha->host_no));
			}
		}

3207 3208
		if (test_and_clear_bit(ISP_ABORT_NEEDED,
						&base_vha->dpc_flags)) {
L
Linus Torvalds 已提交
3209 3210 3211

			DEBUG(printk("scsi(%ld): dpc: sched "
			    "qla2x00_abort_isp ha = %p\n",
3212
			    base_vha->host_no, ha));
L
Linus Torvalds 已提交
3213
			if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
3214
			    &base_vha->dpc_flags))) {
L
Linus Torvalds 已提交
3215

3216
				if (ha->isp_ops->abort_isp(base_vha)) {
L
Linus Torvalds 已提交
3217 3218
					/* failed. retry later */
					set_bit(ISP_ABORT_NEEDED,
3219
					    &base_vha->dpc_flags);
3220
				}
3221 3222
				clear_bit(ABORT_ISP_ACTIVE,
						&base_vha->dpc_flags);
3223 3224
			}

L
Linus Torvalds 已提交
3225
			DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",
3226
			    base_vha->host_no));
L
Linus Torvalds 已提交
3227 3228
		}

3229 3230 3231
		if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) {
			qla2x00_update_fcports(base_vha);
			clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
3232
		}
3233

3234 3235 3236
		if (test_and_clear_bit(RESET_MARKER_NEEDED,
							&base_vha->dpc_flags) &&
		    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
L
Linus Torvalds 已提交
3237 3238

			DEBUG(printk("scsi(%ld): qla2x00_reset_marker()\n",
3239
			    base_vha->host_no));
L
Linus Torvalds 已提交
3240

3241 3242
			qla2x00_rst_aen(base_vha);
			clear_bit(RESET_ACTIVE, &base_vha->dpc_flags);
L
Linus Torvalds 已提交
3243 3244 3245
		}

		/* Retry each device up to login retry count */
3246 3247 3248 3249
		if ((test_and_clear_bit(RELOGIN_NEEDED,
						&base_vha->dpc_flags)) &&
		    !test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags) &&
		    atomic_read(&base_vha->loop_state) != LOOP_DOWN) {
L
Linus Torvalds 已提交
3250 3251

			DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
3252 3253 3254
					base_vha->host_no));
			qla2x00_relogin(base_vha);

L
Linus Torvalds 已提交
3255
			DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
3256
			    base_vha->host_no));
L
Linus Torvalds 已提交
3257 3258
		}

3259 3260
		if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
							&base_vha->dpc_flags)) {
L
Linus Torvalds 已提交
3261 3262

			DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
3263
				base_vha->host_no));
L
Linus Torvalds 已提交
3264 3265

			if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE,
3266
			    &base_vha->dpc_flags))) {
L
Linus Torvalds 已提交
3267

3268
				rval = qla2x00_loop_resync(base_vha);
L
Linus Torvalds 已提交
3269

3270 3271
				clear_bit(LOOP_RESYNC_ACTIVE,
						&base_vha->dpc_flags);
L
Linus Torvalds 已提交
3272 3273 3274
			}

			DEBUG(printk("scsi(%ld): qla2x00_loop_resync - end\n",
3275
			    base_vha->host_no));
L
Linus Torvalds 已提交
3276 3277
		}

3278 3279 3280 3281
		if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) &&
		    atomic_read(&base_vha->loop_state) == LOOP_READY) {
			clear_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags);
			qla2xxx_flash_npiv_conf(base_vha);
3282 3283
		}

L
Linus Torvalds 已提交
3284
		if (!ha->interrupts_on)
3285
			ha->isp_ops->enable_intrs(ha);
L
Linus Torvalds 已提交
3286

3287 3288 3289
		if (test_and_clear_bit(BEACON_BLINK_NEEDED,
					&base_vha->dpc_flags))
			ha->isp_ops->beacon_blink(base_vha);
3290

3291
		qla2x00_do_dpc_all_vps(base_vha);
3292

L
Linus Torvalds 已提交
3293 3294 3295
		ha->dpc_active = 0;
	} /* End of while(1) */

3296
	DEBUG(printk("scsi(%ld): DPC handler exiting\n", base_vha->host_no));
L
Linus Torvalds 已提交
3297 3298 3299 3300 3301 3302

	/*
	 * Make sure that nobody tries to wake us up again.
	 */
	ha->dpc_active = 0;

3303 3304 3305
	/* Cleanup any residual CTX SRBs. */
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

3306 3307 3308 3309
	return 0;
}

void
3310
qla2xxx_wake_dpc(struct scsi_qla_host *vha)
3311
{
3312
	struct qla_hw_data *ha = vha->hw;
3313 3314
	struct task_struct *t = ha->dpc_thread;

3315
	if (!test_bit(UNLOADING, &vha->dpc_flags) && t)
3316
		wake_up_process(t);
L
Linus Torvalds 已提交
3317 3318 3319 3320 3321 3322 3323 3324 3325 3326
}

/*
*  qla2x00_rst_aen
*      Processes asynchronous reset.
*
* Input:
*      ha  = adapter block pointer.
*/
static void
3327
qla2x00_rst_aen(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
3328
{
3329 3330 3331
	if (vha->flags.online && !vha->flags.reset_active &&
	    !atomic_read(&vha->loop_down_timer) &&
	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))) {
L
Linus Torvalds 已提交
3332
		do {
3333
			clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
3334 3335 3336 3337 3338

			/*
			 * Issue marker command only when we are going to start
			 * the I/O.
			 */
3339 3340 3341
			vha->marker_needed = 1;
		} while (!atomic_read(&vha->loop_down_timer) &&
		    (test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags)));
L
Linus Torvalds 已提交
3342 3343 3344
	}
}

已提交
3345
static void
3346
qla2x00_sp_free_dma(srb_t *sp)
已提交
3347 3348 3349 3350
{
	struct scsi_cmnd *cmd = sp->cmd;

	if (sp->flags & SRB_DMA_VALID) {
3351
		scsi_dma_unmap(cmd);
已提交
3352 3353
		sp->flags &= ~SRB_DMA_VALID;
	}
3354
	CMD_SP(cmd) = NULL;
已提交
3355 3356 3357
}

void
3358
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
已提交
3359 3360 3361
{
	struct scsi_cmnd *cmd = sp->cmd;

3362
	qla2x00_sp_free_dma(sp);
已提交
3363

3364 3365 3366 3367 3368 3369 3370 3371 3372 3373
	if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
		struct ct6_dsd *ctx = sp->ctx;
		dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd,
			ctx->fcp_cmnd_dma);
		list_splice(&ctx->dsd_list, &ha->gbl_dsd_list);
		ha->gbl_dsd_inuse -= ctx->dsd_use_cnt;
		ha->gbl_dsd_avail += ctx->dsd_use_cnt;
		mempool_free(sp->ctx, ha->ctx_mempool);
		sp->ctx = NULL;
	}
已提交
3374

3375
	mempool_free(sp, ha->srb_mempool);
已提交
3376 3377
	cmd->scsi_done(cmd);
}
3378

L
Linus Torvalds 已提交
3379 3380 3381 3382 3383 3384 3385 3386
/**************************************************************************
*   qla2x00_timer
*
* Description:
*   One second timer
*
* Context: Interrupt
***************************************************************************/
3387
void
3388
qla2x00_timer(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
3389 3390 3391 3392 3393 3394
{
	unsigned long	cpu_flags = 0;
	fc_port_t	*fcport;
	int		start_dpc = 0;
	int		index;
	srb_t		*sp;
已提交
3395
	int		t;
3396
	uint16_t        w;
3397
	struct qla_hw_data *ha = vha->hw;
3398
	struct req_que *req;
3399

3400 3401 3402
	if (IS_QLA82XX(ha))
		qla82xx_watchdog(vha);

3403 3404 3405
	/* Hardware read to raise pending EEH errors during mailbox waits. */
	if (!pci_channel_offline(ha->pdev))
		pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
L
Linus Torvalds 已提交
3406 3407 3408 3409 3410
	/*
	 * Ports - Port down timer.
	 *
	 * Whenever, a port is in the LOST state we start decrementing its port
	 * down timer every second until it reaches zero. Once  it reaches zero
A
Andrew Vasquez 已提交
3411
	 * the port it marked DEAD.
L
Linus Torvalds 已提交
3412 3413
	 */
	t = 0;
3414
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
L
Linus Torvalds 已提交
3415 3416 3417 3418 3419 3420 3421 3422
		if (fcport->port_type != FCT_TARGET)
			continue;

		if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {

			if (atomic_read(&fcport->port_down_timer) == 0)
				continue;

A
Andrew Vasquez 已提交
3423
			if (atomic_dec_and_test(&fcport->port_down_timer) != 0)
L
Linus Torvalds 已提交
3424
				atomic_set(&fcport->state, FCS_DEVICE_DEAD);
A
Andrew Vasquez 已提交
3425

L
Linus Torvalds 已提交
3426
			DEBUG(printk("scsi(%ld): fcport-%d - port retry count: "
3427
			    "%d remaining\n",
3428
			    vha->host_no,
L
Linus Torvalds 已提交
3429 3430 3431 3432 3433 3434 3435
			    t, atomic_read(&fcport->port_down_timer)));
		}
		t++;
	} /* End of for fcport  */


	/* Loop down handler. */
3436 3437 3438
	if (atomic_read(&vha->loop_down_timer) > 0 &&
	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
		&& vha->flags.online) {
L
Linus Torvalds 已提交
3439

3440 3441
		if (atomic_read(&vha->loop_down_timer) ==
		    vha->loop_down_abort_time) {
L
Linus Torvalds 已提交
3442 3443 3444

			DEBUG(printk("scsi(%ld): Loop Down - aborting the "
			    "queues before time expire\n",
3445
			    vha->host_no));
L
Linus Torvalds 已提交
3446

3447 3448
			if (!IS_QLA2100(ha) && vha->link_down_timeout)
				atomic_set(&vha->loop_state, LOOP_DEAD);
L
Linus Torvalds 已提交
3449

3450 3451 3452 3453
			/*
			 * Schedule an ISP abort to return any FCP2-device
			 * commands.
			 */
3454
			/* NPIV - scan physical port only */
3455
			if (!vha->vp_idx) {
3456 3457
				spin_lock_irqsave(&ha->hardware_lock,
				    cpu_flags);
3458
				req = ha->req_q_map[0];
3459 3460 3461 3462 3463
				for (index = 1;
				    index < MAX_OUTSTANDING_COMMANDS;
				    index++) {
					fc_port_t *sfcp;

3464
					sp = req->outstanding_cmds[index];
3465 3466
					if (!sp)
						continue;
3467 3468
					if (sp->ctx)
						continue;
3469
					sfcp = sp->fcport;
3470
					if (!(sfcp->flags & FCF_FCP2_DEVICE))
3471
						continue;
3472

3473
					set_bit(ISP_ABORT_NEEDED,
3474
							&vha->dpc_flags);
3475 3476 3477
					break;
				}
				spin_unlock_irqrestore(&ha->hardware_lock,
3478
								cpu_flags);
L
Linus Torvalds 已提交
3479 3480 3481 3482 3483
			}
			start_dpc++;
		}

		/* if the loop has been down for 4 minutes, reinit adapter */
3484
		if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
3485
			if (!(vha->device_flags & DFLG_NO_CABLE)) {
L
Linus Torvalds 已提交
3486 3487
				DEBUG(printk("scsi(%ld): Loop down - "
				    "aborting ISP.\n",
3488
				    vha->host_no));
L
Linus Torvalds 已提交
3489 3490 3491
				qla_printk(KERN_WARNING, ha,
				    "Loop down - aborting ISP.\n");

3492
				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
3493 3494
			}
		}
3495
		DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
3496 3497
		    vha->host_no,
		    atomic_read(&vha->loop_down_timer)));
L
Linus Torvalds 已提交
3498 3499
	}

3500 3501
	/* Check if beacon LED needs to be blinked */
	if (ha->beacon_blink_led == 1) {
3502
		set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
3503 3504 3505
		start_dpc++;
	}

3506
	/* Process any deferred work. */
3507
	if (!list_empty(&vha->work_list))
3508 3509
		start_dpc++;

L
Linus Torvalds 已提交
3510
	/* Schedule the DPC routine if needed */
3511 3512 3513
	if ((test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
	    test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
	    test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags) ||
L
Linus Torvalds 已提交
3514
	    start_dpc ||
3515 3516
	    test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) ||
	    test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags) ||
3517 3518
	    test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) ||
	    test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) ||
3519 3520 3521
	    test_bit(VP_DPC_NEEDED, &vha->dpc_flags) ||
	    test_bit(RELOGIN_NEEDED, &vha->dpc_flags)))
		qla2xxx_wake_dpc(vha);
L
Linus Torvalds 已提交
3522

3523
	qla2x00_restart_timer(vha, WATCH_INTERVAL);
L
Linus Torvalds 已提交
3524 3525
}

3526 3527
/* Firmware interface routines. */

3528
#define FW_BLOBS	8
3529 3530 3531 3532
#define FW_ISP21XX	0
#define FW_ISP22XX	1
#define FW_ISP2300	2
#define FW_ISP2322	3
3533
#define FW_ISP24XX	4
3534
#define FW_ISP25XX	5
3535
#define FW_ISP81XX	6
3536
#define FW_ISP82XX	7
3537

3538 3539 3540 3541 3542
#define FW_FILE_ISP21XX	"ql2100_fw.bin"
#define FW_FILE_ISP22XX	"ql2200_fw.bin"
#define FW_FILE_ISP2300	"ql2300_fw.bin"
#define FW_FILE_ISP2322	"ql2322_fw.bin"
#define FW_FILE_ISP24XX	"ql2400_fw.bin"
3543
#define FW_FILE_ISP25XX	"ql2500_fw.bin"
3544
#define FW_FILE_ISP81XX	"ql8100_fw.bin"
3545
#define FW_FILE_ISP82XX	"ql8200_fw.bin"
3546

3547
static DEFINE_MUTEX(qla_fw_lock);
3548 3549

static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
3550 3551 3552 3553 3554
	{ .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, },
	{ .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, },
	{ .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, },
	{ .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
	{ .name = FW_FILE_ISP24XX, },
3555
	{ .name = FW_FILE_ISP25XX, },
3556
	{ .name = FW_FILE_ISP81XX, },
3557
	{ .name = FW_FILE_ISP82XX, },
3558 3559 3560
};

struct fw_blob *
3561
qla2x00_request_firmware(scsi_qla_host_t *vha)
3562
{
3563
	struct qla_hw_data *ha = vha->hw;
3564 3565 3566 3567 3568 3569 3570
	struct fw_blob *blob;

	blob = NULL;
	if (IS_QLA2100(ha)) {
		blob = &qla_fw_blobs[FW_ISP21XX];
	} else if (IS_QLA2200(ha)) {
		blob = &qla_fw_blobs[FW_ISP22XX];
3571
	} else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3572
		blob = &qla_fw_blobs[FW_ISP2300];
3573
	} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
3574
		blob = &qla_fw_blobs[FW_ISP2322];
3575
	} else if (IS_QLA24XX_TYPE(ha)) {
3576
		blob = &qla_fw_blobs[FW_ISP24XX];
3577 3578
	} else if (IS_QLA25XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP25XX];
3579 3580
	} else if (IS_QLA81XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP81XX];
3581 3582
	} else if (IS_QLA82XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP82XX];
3583 3584
	}

3585
	mutex_lock(&qla_fw_lock);
3586 3587 3588 3589 3590
	if (blob->fw)
		goto out;

	if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
		DEBUG2(printk("scsi(%ld): Failed to load firmware image "
3591
		    "(%s).\n", vha->host_no, blob->name));
3592 3593 3594 3595 3596 3597
		blob->fw = NULL;
		blob = NULL;
		goto out;
	}

out:
3598
	mutex_unlock(&qla_fw_lock);
3599 3600 3601 3602 3603 3604 3605 3606
	return blob;
}

static void
qla2x00_release_firmware(void)
{
	int idx;

3607
	mutex_lock(&qla_fw_lock);
3608 3609 3610
	for (idx = 0; idx < FW_BLOBS; idx++)
		if (qla_fw_blobs[idx].fw)
			release_firmware(qla_fw_blobs[idx].fw);
3611
	mutex_unlock(&qla_fw_lock);
3612 3613
}

3614 3615 3616
static pci_ers_result_t
qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
3617 3618 3619 3620 3621
	scsi_qla_host_t *vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = vha->hw;

	DEBUG2(qla_printk(KERN_WARNING, ha, "error_detected:state %x\n",
	    state));
3622

3623 3624
	switch (state) {
	case pci_channel_io_normal:
3625
		ha->flags.eeh_busy = 0;
3626 3627
		return PCI_ERS_RESULT_CAN_RECOVER;
	case pci_channel_io_frozen:
3628
		ha->flags.eeh_busy = 1;
3629
		qla2x00_free_irqs(vha);
3630 3631 3632
		pci_disable_device(pdev);
		return PCI_ERS_RESULT_NEED_RESET;
	case pci_channel_io_perm_failure:
3633 3634
		ha->flags.pci_channel_io_perm_failure = 1;
		qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645
		return PCI_ERS_RESULT_DISCONNECT;
	}
	return PCI_ERS_RESULT_NEED_RESET;
}

static pci_ers_result_t
qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
{
	int risc_paused = 0;
	uint32_t stat;
	unsigned long flags;
3646 3647
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669
	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
	struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;

	spin_lock_irqsave(&ha->hardware_lock, flags);
	if (IS_QLA2100(ha) || IS_QLA2200(ha)){
		stat = RD_REG_DWORD(&reg->hccr);
		if (stat & HCCR_RISC_PAUSE)
			risc_paused = 1;
	} else if (IS_QLA23XX(ha)) {
		stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
		if (stat & HSR_RISC_PAUSED)
			risc_paused = 1;
	} else if (IS_FWI2_CAPABLE(ha)) {
		stat = RD_REG_DWORD(&reg24->host_status);
		if (stat & HSRX_RISC_PAUSED)
			risc_paused = 1;
	}
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

	if (risc_paused) {
		qla_printk(KERN_INFO, ha, "RISC paused -- mmio_enabled, "
		    "Dumping firmware!\n");
3670
		ha->isp_ops->fw_dump(base_vha, 0);
3671 3672 3673 3674 3675 3676 3677 3678 3679 3680

		return PCI_ERS_RESULT_NEED_RESET;
	} else
		return PCI_ERS_RESULT_RECOVERED;
}

static pci_ers_result_t
qla2xxx_pci_slot_reset(struct pci_dev *pdev)
{
	pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
3681 3682
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3683 3684
	struct rsp_que *rsp;
	int rc, retries = 10;
3685

3686 3687
	DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n"));

3688 3689 3690 3691 3692 3693 3694 3695
	/* Workaround: qla2xxx driver which access hardware earlier
	 * needs error state to be pci_channel_io_online.
	 * Otherwise mailbox command timesout.
	 */
	pdev->error_state = pci_channel_io_normal;

	pci_restore_state(pdev);

3696 3697 3698 3699 3700
	/* pci_restore_state() clears the saved_state flag of the device
	 * save restored state which resets saved_state flag
	 */
	pci_save_state(pdev);

3701 3702 3703 3704
	if (ha->mem_only)
		rc = pci_enable_device_mem(pdev);
	else
		rc = pci_enable_device(pdev);
3705

3706
	if (rc) {
3707 3708 3709 3710 3711
		qla_printk(KERN_WARNING, ha,
		    "Can't re-enable PCI device after reset.\n");
		return ret;
	}

3712 3713 3714 3715
	rsp = ha->rsp_q_map[0];
	if (qla2x00_request_irqs(ha, rsp))
		return ret;

3716
	if (ha->isp_ops->pci_config(base_vha))
3717 3718
		return ret;

3719 3720
	while (ha->flags.mbox_busy && retries--)
		msleep(1000);
3721

3722
	set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3723
	if (ha->isp_ops->abort_isp(base_vha) == QLA_SUCCESS)
3724
		ret =  PCI_ERS_RESULT_RECOVERED;
3725
	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3726

3727

3728 3729 3730
	DEBUG17(qla_printk(KERN_WARNING, ha,
	    "slot_reset-return:ret=%x\n", ret));

3731 3732 3733 3734 3735 3736
	return ret;
}

static void
qla2xxx_pci_resume(struct pci_dev *pdev)
{
3737 3738
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3739 3740
	int ret;

3741 3742
	DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n"));

3743
	ret = qla2x00_wait_for_hba_online(base_vha);
3744 3745 3746 3747 3748
	if (ret != QLA_SUCCESS) {
		qla_printk(KERN_ERR, ha,
		    "the device failed to resume I/O "
		    "from slot/link_reset");
	}
3749

3750 3751
	pci_cleanup_aer_uncorrect_error_status(pdev);

3752
	ha->flags.eeh_busy = 0;
3753 3754 3755 3756 3757 3758 3759 3760 3761
}

static struct pci_error_handlers qla2xxx_err_handler = {
	.error_detected = qla2xxx_pci_error_detected,
	.mmio_enabled = qla2xxx_pci_mmio_enabled,
	.slot_reset = qla2xxx_pci_slot_reset,
	.resume = qla2xxx_pci_resume,
};

3762
static struct pci_device_id qla2xxx_pci_tbl[] = {
3763 3764 3765 3766 3767 3768 3769 3770 3771
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) },
3772
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
3773 3774
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
3775
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
3776
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
3777
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) },
3778 3779 3780 3781
	{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);

3782
static struct pci_driver qla2xxx_pci_driver = {
3783
	.name		= QLA2XXX_DRIVER_NAME,
3784 3785 3786
	.driver		= {
		.owner		= THIS_MODULE,
	},
3787
	.id_table	= qla2xxx_pci_tbl,
3788
	.probe		= qla2x00_probe_one,
A
Adrian Bunk 已提交
3789
	.remove		= qla2x00_remove_one,
3790
	.err_handler	= &qla2xxx_err_handler,
3791 3792
};

3793 3794 3795 3796
static struct file_operations apidev_fops = {
	.owner = THIS_MODULE,
};

L
Linus Torvalds 已提交
3797 3798 3799 3800 3801 3802
/**
 * qla2x00_module_init - Module initialization.
 **/
static int __init
qla2x00_module_init(void)
{
3803 3804
	int ret = 0;

L
Linus Torvalds 已提交
3805
	/* Allocate cache for SRBs. */
3806
	srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
3807
	    SLAB_HWCACHE_ALIGN, NULL);
L
Linus Torvalds 已提交
3808 3809 3810 3811 3812 3813 3814 3815
	if (srb_cachep == NULL) {
		printk(KERN_ERR
		    "qla2xxx: Unable to allocate SRB cache...Failing load!\n");
		return -ENOMEM;
	}

	/* Derive version string. */
	strcpy(qla2x00_version_str, QLA2XXX_VERSION);
3816
	if (ql2xextended_error_logging)
3817 3818
		strcat(qla2x00_version_str, "-debug");

3819 3820
	qla2xxx_transport_template =
	    fc_attach_transport(&qla2xxx_transport_functions);
3821 3822
	if (!qla2xxx_transport_template) {
		kmem_cache_destroy(srb_cachep);
L
Linus Torvalds 已提交
3823
		return -ENODEV;
3824
	}
3825 3826 3827 3828 3829 3830 3831

	apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops);
	if (apidev_major < 0) {
		printk(KERN_WARNING "qla2xxx: Unable to register char device "
		    "%s\n", QLA2XXX_APIDEV);
	}

3832 3833 3834 3835 3836
	qla2xxx_transport_vport_template =
	    fc_attach_transport(&qla2xxx_transport_vport_functions);
	if (!qla2xxx_transport_vport_template) {
		kmem_cache_destroy(srb_cachep);
		fc_release_transport(qla2xxx_transport_template);
L
Linus Torvalds 已提交
3837
		return -ENODEV;
3838
	}
L
Linus Torvalds 已提交
3839

3840 3841
	printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
	    qla2x00_version_str);
3842
	ret = pci_register_driver(&qla2xxx_pci_driver);
3843 3844 3845
	if (ret) {
		kmem_cache_destroy(srb_cachep);
		fc_release_transport(qla2xxx_transport_template);
3846
		fc_release_transport(qla2xxx_transport_vport_template);
3847 3848
	}
	return ret;
L
Linus Torvalds 已提交
3849 3850 3851 3852 3853 3854 3855 3856
}

/**
 * qla2x00_module_exit - Module cleanup.
 **/
static void __exit
qla2x00_module_exit(void)
{
3857
	unregister_chrdev(apidev_major, QLA2XXX_APIDEV);
3858
	pci_unregister_driver(&qla2xxx_pci_driver);
3859
	qla2x00_release_firmware();
3860
	kmem_cache_destroy(srb_cachep);
3861 3862
	if (ctx_cachep)
		kmem_cache_destroy(ctx_cachep);
L
Linus Torvalds 已提交
3863
	fc_release_transport(qla2xxx_transport_template);
3864
	fc_release_transport(qla2xxx_transport_vport_template);
L
Linus Torvalds 已提交
3865 3866 3867 3868 3869 3870 3871 3872 3873
}

module_init(qla2x00_module_init);
module_exit(qla2x00_module_exit);

MODULE_AUTHOR("QLogic Corporation");
MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(QLA2XXX_VERSION);
3874 3875 3876 3877 3878
MODULE_FIRMWARE(FW_FILE_ISP21XX);
MODULE_FIRMWARE(FW_FILE_ISP22XX);
MODULE_FIRMWARE(FW_FILE_ISP2300);
MODULE_FIRMWARE(FW_FILE_ISP2322);
MODULE_FIRMWARE(FW_FILE_ISP24XX);
3879
MODULE_FIRMWARE(FW_FILE_ISP25XX);