qla_os.c 88.9 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>
L
Linus Torvalds 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28

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

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

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

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

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

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

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

L
Linus Torvalds 已提交
67 68
static void qla2x00_free_device(scsi_qla_host_t *);

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

75 76 77 78 79 80
#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.");

81 82 83 84 85 86 87 88
int ql2xqfulltracking = 1;
module_param(ql2xqfulltracking, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xqfulltracking,
		"Controls whether the driver tracks queue full status "
		"returns and dynamically adjusts a scsi device's queue "
		"depth.  Default is 1, perform tracking.  Set to 0 to "
		"disable dynamic tracking and adjustment of queue depth.");

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

96 97 98 99 100 101
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.");

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

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

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

L
Linus Torvalds 已提交
125
/*
A
Andrew Vasquez 已提交
126
 * SCSI host template entry points
L
Linus Torvalds 已提交
127 128
 */
static int qla2xxx_slave_configure(struct scsi_device * device);
已提交
129
static int qla2xxx_slave_alloc(struct scsi_device *);
130 131
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
static void qla2xxx_scan_start(struct Scsi_Host *);
已提交
132
static void qla2xxx_slave_destroy(struct scsi_device *);
133
static int qla2xxx_queuecommand(struct scsi_cmnd *cmd,
134
		void (*fn)(struct scsi_cmnd *));
L
Linus Torvalds 已提交
135 136
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
137
static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
L
Linus Torvalds 已提交
138 139 140
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);

141
static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
142 143
static int qla2x00_change_queue_type(struct scsi_device *, int);

144
struct scsi_host_template qla2xxx_driver_template = {
L
Linus Torvalds 已提交
145
	.module			= THIS_MODULE,
146
	.name			= QLA2XXX_DRIVER_NAME,
147
	.queuecommand		= qla2xxx_queuecommand,
148 149 150

	.eh_abort_handler	= qla2xxx_eh_abort,
	.eh_device_reset_handler = qla2xxx_eh_device_reset,
151
	.eh_target_reset_handler = qla2xxx_eh_target_reset,
152 153 154 155 156 157 158
	.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,
159 160
	.scan_finished		= qla2xxx_scan_finished,
	.scan_start		= qla2xxx_scan_start,
161 162
	.change_queue_depth	= qla2x00_change_queue_depth,
	.change_queue_type	= qla2x00_change_queue_type,
163 164 165 166 167 168
	.this_id		= -1,
	.cmd_per_lun		= 3,
	.use_clustering		= ENABLE_CLUSTERING,
	.sg_tablesize		= SG_ALL,

	.max_sectors		= 0xFFFF,
169
	.shost_attrs		= qla2x00_host_attrs,
170 171
};

L
Linus Torvalds 已提交
172
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
173
struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
L
Linus Torvalds 已提交
174 175 176 177 178 179

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

180
__inline__ void
181
qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval)
L
Linus Torvalds 已提交
182
{
183 184 185 186 187 188
	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 已提交
189 190 191
}

static inline void
192
qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
L
Linus Torvalds 已提交
193
{
194
	mod_timer(&vha->timer, jiffies + interval * HZ);
L
Linus Torvalds 已提交
195 196
}

A
Adrian Bunk 已提交
197
static __inline__ void
198
qla2x00_stop_timer(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
199
{
200 201
	del_timer_sync(&vha->timer);
	vha->timer_active = 0;
L
Linus Torvalds 已提交
202 203 204 205 206 207
}

static int qla2x00_do_dpc(void *data);

static void qla2x00_rst_aen(scsi_qla_host_t *);

208 209
static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
	struct req_que **, struct rsp_que **);
210 211
static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
L
Linus Torvalds 已提交
212 213

/* -------------------------------------------------------------------------- */
214 215
static int qla2x00_alloc_queues(struct qla_hw_data *ha)
{
216
	ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
217 218 219 220 221 222 223
				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;
	}

224
	ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
				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;
}

242
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
243 244 245 246 247 248 249 250 251 252
{
	if (req && req->ring)
		dma_free_coherent(&ha->pdev->dev,
		(req->length + 1) * sizeof(request_t),
		req->ring, req->dma);

	kfree(req);
	req = NULL;
}

253 254 255 256 257 258 259 260 261 262 263
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;
}

264 265 266 267 268 269
static void qla2x00_free_queues(struct qla_hw_data *ha)
{
	struct req_que *req;
	struct rsp_que *rsp;
	int cnt;

270
	for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
271
		req = ha->req_q_map[cnt];
272
		qla2x00_free_req_que(ha, req);
273 274 275
	}
	kfree(ha->req_q_map);
	ha->req_q_map = NULL;
276 277 278 279 280 281 282

	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;
283 284
}

285 286 287 288 289 290
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;

291 292 293 294 295
	if (!(ha->fw_attributes & BIT_6)) {
		qla_printk(KERN_INFO, ha,
			"Firmware is not multi-queue capable\n");
		goto fail;
	}
296 297 298 299 300 301 302 303 304 305
	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;
		}
306
		ha->wq = create_workqueue("qla2xxx_wq");
307 308 309 310 311 312 313 314 315 316
		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;
			}
		}
317 318
		ha->flags.cpu_affinity_enabled = 1;

319 320 321 322 323 324 325 326
		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);
327 328
	destroy_workqueue(ha->wq);
	ha->wq = NULL;
329 330
fail:
	ha->mqenable = 0;
331 332 333
	kfree(ha->req_q_map);
	kfree(ha->rsp_q_map);
	ha->max_req_queues = ha->max_rsp_queues = 1;
334 335 336
	return 1;
}

L
Linus Torvalds 已提交
337
static char *
338
qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str)
L
Linus Torvalds 已提交
339
{
340
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
	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);
}

361
static char *
362
qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
363 364
{
	static char *pci_bus_modes[] = { "33", "66", "100", "133", };
365
	struct qla_hw_data *ha = vha->hw;
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
	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)
382
			strcat(str, "2.5GT/s ");
383
		else if (lspeed == 2)
384
			strcat(str, "5.0GT/s ");
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
		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;
}

412
static char *
413
qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
L
Linus Torvalds 已提交
414 415
{
	char un_str[10];
416
	struct qla_hw_data *ha = vha->hw;
A
Andrew Vasquez 已提交
417

L
Linus Torvalds 已提交
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
	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);
}

451
static char *
452
qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
453
{
454
	struct qla_hw_data *ha = vha->hw;
455

456 457
	sprintf(str, "%d.%02d.%02d (%x)", ha->fw_major_version,
	    ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes);
458 459 460 461
	return str;
}

static inline srb_t *
462
qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
463 464 465
    struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
	srb_t *sp;
466
	struct qla_hw_data *ha = vha->hw;
467 468 469 470 471 472 473 474 475 476

	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;
477
	sp->ctx = NULL;
478 479 480 481

	return sp;
}

L
Linus Torvalds 已提交
482
static int
483
qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
484
{
485
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
486
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
487
	struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
488 489
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
490 491 492
	srb_t *sp;
	int rval;

493
	if (unlikely(pci_channel_offline(ha->pdev))) {
494 495 496 497
		if (ha->pdev->error_state == pci_channel_io_frozen)
			cmd->result = DID_REQUEUE << 16;
		else
			cmd->result = DID_NO_CONNECT << 16;
498 499 500
		goto qc24_fail_command;
	}

501 502 503
	rval = fc_remote_port_chkready(rport);
	if (rval) {
		cmd->result = rval;
504 505 506
		goto qc24_fail_command;
	}

507
	/* Close window on fcport/rport state-transitioning. */
508 509
	if (fcport->drport)
		goto qc24_target_busy;
510

511 512
	if (atomic_read(&fcport->state) != FCS_ONLINE) {
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
513
		    atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
514 515 516
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
		}
517
		goto qc24_target_busy;
518 519
	}

520
	spin_unlock_irq(vha->host->host_lock);
521

522
	sp = qla2x00_get_new_sp(base_vha, fcport, cmd, done);
523 524 525
	if (!sp)
		goto qc24_host_busy_lock;

526
	rval = ha->isp_ops->start_scsi(sp);
527 528 529
	if (rval != QLA_SUCCESS)
		goto qc24_host_busy_free_sp;

530
	spin_lock_irq(vha->host->host_lock);
531 532 533 534

	return 0;

qc24_host_busy_free_sp:
535 536
	qla2x00_sp_free_dma(sp);
	mempool_free(sp, ha->srb_mempool);
537 538

qc24_host_busy_lock:
539
	spin_lock_irq(vha->host->host_lock);
540 541
	return SCSI_MLQUEUE_HOST_BUSY;

542 543 544
qc24_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

545 546 547 548 549 550 551
qc24_fail_command:
	done(cmd);

	return 0;
}


L
Linus Torvalds 已提交
552 553 554 555 556 557 558 559 560 561 562 563 564
/*
 * 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
565
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
L
Linus Torvalds 已提交
566
{
567 568
#define ABORT_POLLING_PERIOD	1000
#define ABORT_WAIT_ITER		((10 * 1000) / (ABORT_POLLING_PERIOD))
已提交
569 570
	unsigned long wait_iter = ABORT_WAIT_ITER;
	int ret = QLA_SUCCESS;
L
Linus Torvalds 已提交
571

572
	while (CMD_SP(cmd) && wait_iter--) {
573
		msleep(ABORT_POLLING_PERIOD);
已提交
574 575 576
	}
	if (CMD_SP(cmd))
		ret = QLA_FUNCTION_FAILED;
L
Linus Torvalds 已提交
577

已提交
578
	return ret;
L
Linus Torvalds 已提交
579 580 581 582
}

/*
 * qla2x00_wait_for_hba_online
A
Andrew Vasquez 已提交
583
 *    Wait till the HBA is online after going through
L
Linus Torvalds 已提交
584 585 586 587 588
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline
 *
 * Input:
 *     ha - pointer to host adapter structure
A
Andrew Vasquez 已提交
589 590
 *
 * Note:
L
Linus Torvalds 已提交
591 592 593 594 595 596 597
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online) : 0
 *    Failed  (Adapter is offline/disabled) : 1
 */
598
int
599
qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
600
{
601 602
	int		return_status;
	unsigned long	wait_online;
603 604
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
605

A
Andrew Vasquez 已提交
606
	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
607 608 609 610
	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 已提交
611 612 613

		msleep(1000);
	}
614
	if (base_vha->flags.online)
A
Andrew Vasquez 已提交
615
		return_status = QLA_SUCCESS;
L
Linus Torvalds 已提交
616 617 618 619 620 621
	else
		return_status = QLA_FUNCTION_FAILED;

	return (return_status);
}

622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
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 已提交
650 651 652
/*
 * qla2x00_wait_for_loop_ready
 *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
A
Andrew Vasquez 已提交
653
 *    to be in LOOP_READY state.
L
Linus Torvalds 已提交
654 655
 * Input:
 *     ha - pointer to host adapter structure
A
Andrew Vasquez 已提交
656 657
 *
 * Note:
L
Linus Torvalds 已提交
658 659
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
A
Andrew Vasquez 已提交
660
 *
L
Linus Torvalds 已提交
661 662 663 664 665
 *
 * Return:
 *    Success (LOOP_READY) : 0
 *    Failed  (LOOP_NOT_READY) : 1
 */
A
Andrew Vasquez 已提交
666
static inline int
667
qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
668 669 670
{
	int 	 return_status = QLA_SUCCESS;
	unsigned long loop_timeout ;
671 672
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
673 674

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

677 678 679 680
	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) {
681 682 683
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
L
Linus Torvalds 已提交
684 685 686 687 688 689
		msleep(1000);
		if (time_after_eq(jiffies, loop_timeout)) {
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
	}
A
Andrew Vasquez 已提交
690
	return (return_status);
L
Linus Torvalds 已提交
691 692
}

693 694 695
void
qla2x00_abort_fcport_cmds(fc_port_t *fcport)
{
696
	int cnt;
697 698
	unsigned long flags;
	srb_t *sp;
699 700
	scsi_qla_host_t *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
701
	struct req_que *req;
702

703
	spin_lock_irqsave(&ha->hardware_lock, flags);
704 705 706 707 708 709
	req = vha->req;
	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (!sp)
			continue;
		if (sp->fcport != fcport)
710
			continue;
711 712
		if (sp->ctx)
			continue;
713

714 715 716 717 718 719 720 721
		spin_unlock_irqrestore(&ha->hardware_lock, flags);
		if (ha->isp_ops->abort_command(sp)) {
			DEBUG2(qla_printk(KERN_WARNING, ha,
			"Abort failed --  %lx\n",
			sp->cmd->serial_number));
		} else {
			if (qla2x00_eh_wait_on_command(sp->cmd) !=
				QLA_SUCCESS)
722
				DEBUG2(qla_printk(KERN_WARNING, ha,
723
				"Abort failed while waiting --  %lx\n",
724
				sp->cmd->serial_number));
725
		}
726
		spin_lock_irqsave(&ha->hardware_lock, flags);
727
	}
728
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
729 730
}

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

760
	fc_block_scsi_eh(cmd);
761

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

765
	ret = SUCCESS;
L
Linus Torvalds 已提交
766

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

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

779 780
		if (sp == NULL)
			continue;
781 782
		if (sp->ctx)
			continue;
783 784
		if (sp->cmd != cmd)
			continue;
L
Linus Torvalds 已提交
785

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

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

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

已提交
818 819
	return ret;
}
L
Linus Torvalds 已提交
820

821 822 823 824 825 826
enum nexus_wait_type {
	WAIT_HOST = 0,
	WAIT_TARGET,
	WAIT_LUN,
};

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

836
	status = QLA_SUCCESS;
837 838 839
	if (!sp)
		return status;

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

	return status;
L
Linus Torvalds 已提交
874 875
}

876 877 878 879 880 881
static char *reset_errors[] = {
	"HBA not online",
	"HBA not ready",
	"Task management failed",
	"Waiting for command completions",
};
L
Linus Torvalds 已提交
882

883
static int
884
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
885
    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
L
Linus Torvalds 已提交
886
{
887
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
888
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
889
	int err;
L
Linus Torvalds 已提交
890

891
	fc_block_scsi_eh(cmd);
892

893
	if (!fcport)
894
		return FAILED;
L
Linus Torvalds 已提交
895

896 897
	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 已提交
898

899
	err = 0;
900
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
901 902
		goto eh_reset_failed;
	err = 1;
903
	if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
904 905
		goto eh_reset_failed;
	err = 2;
906 907
	if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
		!= QLA_SUCCESS)
908 909
		goto eh_reset_failed;
	err = 3;
910
	if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
911
	    cmd->device->lun, (srb_t *) CMD_SP(cmd), type) != QLA_SUCCESS)
912 913
		goto eh_reset_failed;

914 915
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
916 917 918 919

	return SUCCESS;

 eh_reset_failed:
920 921
	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,
922 923 924
	    reset_errors[err]);
	return FAILED;
}
L
Linus Torvalds 已提交
925

926 927 928
static int
qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
{
929 930
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
931

932 933
	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
	    ha->isp_ops->lun_reset);
L
Linus Torvalds 已提交
934 935 936
}

static int
937
qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
L
Linus Torvalds 已提交
938
{
939 940
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
941

942 943
	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
	    ha->isp_ops->target_reset);
L
Linus Torvalds 已提交
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
}

/**************************************************************************
* 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).
*
**************************************************************************/
961
static int
L
Linus Torvalds 已提交
962 963
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
964
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
965
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
966
	int ret = FAILED;
已提交
967 968
	unsigned int id, lun;
	unsigned long serial;
969
	srb_t *sp = (srb_t *) CMD_SP(cmd);
已提交
970

971
	fc_block_scsi_eh(cmd);
972

已提交
973 974 975
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
L
Linus Torvalds 已提交
976

977
	if (!fcport)
已提交
978
		return ret;
L
Linus Torvalds 已提交
979

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

983
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
L
Linus Torvalds 已提交
984
		DEBUG2(printk("%s failed:board disabled\n",__func__));
已提交
985
		goto eh_bus_reset_done;
L
Linus Torvalds 已提交
986 987
	}

988 989
	if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
		if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
已提交
990
			ret = SUCCESS;
L
Linus Torvalds 已提交
991
	}
已提交
992 993
	if (ret == FAILED)
		goto eh_bus_reset_done;
L
Linus Torvalds 已提交
994

995
	/* Flush outstanding commands. */
996
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) !=
997
	    QLA_SUCCESS)
998
		ret = FAILED;
L
Linus Torvalds 已提交
999

已提交
1000
eh_bus_reset_done:
1001
	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
已提交
1002
	    (ret == FAILED) ? "failed" : "succeded");
L
Linus Torvalds 已提交
1003

已提交
1004
	return ret;
L
Linus Torvalds 已提交
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
}

/**************************************************************************
* 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:
**************************************************************************/
1022
static int
L
Linus Torvalds 已提交
1023 1024
qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
{
1025
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1026
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1027
	struct qla_hw_data *ha = vha->hw;
1028
	int ret = FAILED;
已提交
1029 1030
	unsigned int id, lun;
	unsigned long serial;
1031
	srb_t *sp = (srb_t *) CMD_SP(cmd);
1032
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
1033

1034
	fc_block_scsi_eh(cmd);
1035

已提交
1036 1037 1038 1039
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;

1040
	if (!fcport)
已提交
1041
		return ret;
L
Linus Torvalds 已提交
1042 1043

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

1046
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
已提交
1047
		goto eh_host_reset_lock;
L
Linus Torvalds 已提交
1048 1049 1050

	/*
	 * Fixme-may be dpc thread is active and processing
A
Andrew Vasquez 已提交
1051
	 * loop_resync,so wait a while for it to
L
Linus Torvalds 已提交
1052 1053 1054 1055 1056
	 * 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.
	 */
1057 1058 1059
	qla2x00_wait_for_loop_ready(vha);
	if (vha != base_vha) {
		if (qla2x00_vp_abort_isp(vha))
已提交
1060
			goto eh_host_reset_lock;
1061
	} else {
1062 1063 1064
		if (ha->wq)
			flush_workqueue(ha->wq);

1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
		set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
		if (qla2x00_abort_isp(base_vha)) {
			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 已提交
1075
	}
L
Linus Torvalds 已提交
1076

1077
	/* Waiting for command to be returned to OS.*/
1078
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) ==
1079
		QLA_SUCCESS)
已提交
1080
		ret = SUCCESS;
L
Linus Torvalds 已提交
1081

已提交
1082 1083 1084
eh_host_reset_lock:
	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
	    (ret == FAILED) ? "failed" : "succeded");
L
Linus Torvalds 已提交
1085

已提交
1086 1087
	return ret;
}
L
Linus Torvalds 已提交
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098

/*
* qla2x00_loop_reset
*      Issue loop reset.
*
* Input:
*      ha = adapter block pointer.
*
* Returns:
*      0 = success
*/
1099
int
1100
qla2x00_loop_reset(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
1101
{
1102
	int ret;
1103
	struct fc_port *fcport;
1104
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
1105

1106
	if (ha->flags.enable_lip_full_login && !IS_QLA81XX(ha)) {
1107
		ret = qla2x00_full_login_lip(vha);
1108
		if (ret != QLA_SUCCESS) {
1109
			DEBUG2_3(printk("%s(%ld): failed: "
1110
			    "full_login_lip=%d.\n", __func__, vha->host_no,
1111
			    ret));
1112 1113 1114 1115 1116
		}
		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);
1117 1118
	}

1119
	if (ha->flags.enable_lip_reset) {
1120
		ret = qla2x00_lip_reset(vha);
1121
		if (ret != QLA_SUCCESS) {
1122
			DEBUG2_3(printk("%s(%ld): failed: "
1123 1124 1125
			    "lip_reset=%d.\n", __func__, vha->host_no, ret));
		} else
			qla2x00_wait_for_loop_ready(vha);
L
Linus Torvalds 已提交
1126 1127
	}

1128
	if (ha->flags.enable_target_reset) {
1129
		list_for_each_entry(fcport, &vha->vp_fcports, list) {
1130
			if (fcport->port_type != FCT_TARGET)
L
Linus Torvalds 已提交
1131 1132
				continue;

1133
			ret = ha->isp_ops->target_reset(fcport, 0, 0);
1134 1135 1136
			if (ret != QLA_SUCCESS) {
				DEBUG2_3(printk("%s(%ld): bus_reset failed: "
				    "target_reset=%d d_id=%x.\n", __func__,
1137
				    vha->host_no, ret, fcport->d_id.b24));
1138
			}
L
Linus Torvalds 已提交
1139 1140 1141
		}
	}
	/* Issue marker command only when we are going to start the I/O */
1142
	vha->marker_needed = 1;
L
Linus Torvalds 已提交
1143

1144
	return QLA_SUCCESS;
L
Linus Torvalds 已提交
1145 1146
}

1147
void
1148
qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
1149
{
1150
	int que, cnt;
1151 1152
	unsigned long flags;
	srb_t *sp;
1153
	struct srb_ctx *ctx;
1154
	struct qla_hw_data *ha = vha->hw;
1155
	struct req_que *req;
1156 1157

	spin_lock_irqsave(&ha->hardware_lock, flags);
1158
	for (que = 0; que < ha->max_req_queues; que++) {
1159
		req = ha->req_q_map[que];
1160 1161 1162 1163
		if (!req)
			continue;
		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
			sp = req->outstanding_cmds[cnt];
1164
			if (sp) {
1165
				req->outstanding_cmds[cnt] = NULL;
1166 1167 1168 1169 1170 1171 1172 1173
				if (!sp->ctx) {
					sp->cmd->result = res;
					qla2x00_sp_compl(ha, sp);
				} else {
					ctx = sp->ctx;
					del_timer_sync(&ctx->timer);
					ctx->free(sp);
				}
1174
			}
1175 1176 1177 1178 1179
		}
	}
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

已提交
1180 1181
static int
qla2xxx_slave_alloc(struct scsi_device *sdev)
L
Linus Torvalds 已提交
1182
{
1183
	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
L
Linus Torvalds 已提交
1184

1185
	if (!rport || fc_remote_port_chkready(rport))
已提交
1186
		return -ENXIO;
1187

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

已提交
1190 1191
	return 0;
}
L
Linus Torvalds 已提交
1192

已提交
1193 1194 1195
static int
qla2xxx_slave_configure(struct scsi_device *sdev)
{
1196 1197
	scsi_qla_host_t *vha = shost_priv(sdev->host);
	struct qla_hw_data *ha = vha->hw;
已提交
1198
	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
1199
	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1200
	struct req_que *req = vha->req;
已提交
1201

已提交
1202
	if (sdev->tagged_supported)
1203
		scsi_activate_tcq(sdev, req->max_q_depth);
已提交
1204
	else
1205
		scsi_deactivate_tcq(sdev, req->max_q_depth);
L
Linus Torvalds 已提交
1206

1207
	rport->dev_loss_tmo = ha->port_down_retry_count;
1208 1209
	if (sdev->type == TYPE_TAPE)
		fcport->flags |= FCF_TAPE_PRESENT;
已提交
1210

已提交
1211 1212
	return 0;
}
L
Linus Torvalds 已提交
1213

已提交
1214 1215 1216 1217
static void
qla2xxx_slave_destroy(struct scsi_device *sdev)
{
	sdev->hostdata = NULL;
L
Linus Torvalds 已提交
1218 1219
}

1220
static int
1221
qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
1222
{
1223 1224 1225
	if (reason != SCSI_QDEPTH_DEFAULT)
		return -EOPNOTSUPP;

1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
	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 已提交
1245 1246 1247 1248 1249 1250 1251 1252
/**
 * 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
1253
qla2x00_config_dma_addressing(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
1254
{
1255
	/* Assume a 32bit DMA mask. */
L
Linus Torvalds 已提交
1256 1257
	ha->flags.enable_64bit_addressing = 0;

1258
	if (!dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
1259 1260
		/* Any upper-dword bits set? */
		if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
1261
		    !pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
1262
			/* Ok, a 64bit DMA mask is applicable. */
L
Linus Torvalds 已提交
1263
			ha->flags.enable_64bit_addressing = 1;
1264 1265
			ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
			ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64;
1266
			return;
L
Linus Torvalds 已提交
1267 1268
		}
	}
1269

1270 1271
	dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32));
	pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(32));
L
Linus Torvalds 已提交
1272 1273
}

1274
static void
1275
qla2x00_enable_intrs(struct qla_hw_data *ha)
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
{
	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
1290
qla2x00_disable_intrs(struct qla_hw_data *ha)
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
{
	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
1304
qla24xx_enable_intrs(struct qla_hw_data *ha)
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
{
	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
1317
qla24xx_disable_intrs(struct qla_hw_data *ha)
1318 1319 1320 1321
{
	unsigned long flags = 0;
	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

1322 1323
	if (IS_NOPOLLING_TYPE(ha))
		return;
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
	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,
1346 1347
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
	.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,
1363
	.start_scsi		= qla2x00_start_scsi,
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
};

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,
1381 1382
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
	.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,
1398
	.start_scsi		= qla2x00_start_scsi,
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
};

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,
1416 1417
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
	.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,
1433
	.start_scsi		= qla24xx_start_scsi,
1434 1435
};

1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
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,
1451 1452
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464
	.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,
1465
	.read_optrom		= qla25xx_read_optrom_data,
1466 1467
	.write_optrom		= qla24xx_write_optrom_data,
	.get_flash_version	= qla24xx_get_flash_version,
1468
	.start_scsi		= qla24xx_start_scsi,
1469 1470
};

1471 1472 1473 1474 1475 1476 1477 1478
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,
1479
	.load_risc		= qla81xx_load_risc,
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
	.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,
1494 1495
	.read_nvram		= NULL,
	.write_nvram		= NULL,
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505
	.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,
};

1506
static inline void
1507
qla2x00_set_isp_flags(struct qla_hw_data *ha)
1508 1509 1510 1511 1512 1513
{
	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;
1514
		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
1515 1516 1517 1518
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2200:
		ha->device_type |= DT_ISP2200;
		ha->device_type &= ~DT_EXTENDED_IDS;
1519
		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
1520 1521 1522
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2300:
		ha->device_type |= DT_ISP2300;
1523
		ha->device_type |= DT_ZIO_SUPPORTED;
1524
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1525 1526 1527
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2312:
		ha->device_type |= DT_ISP2312;
1528
		ha->device_type |= DT_ZIO_SUPPORTED;
1529
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1530 1531 1532
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2322:
		ha->device_type |= DT_ISP2322;
1533
		ha->device_type |= DT_ZIO_SUPPORTED;
1534 1535 1536
		if (ha->pdev->subsystem_vendor == 0x1028 &&
		    ha->pdev->subsystem_device == 0x0170)
			ha->device_type |= DT_OEM_001;
1537
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1538 1539 1540
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP6312:
		ha->device_type |= DT_ISP6312;
1541
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1542 1543 1544
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP6322:
		ha->device_type |= DT_ISP6322;
1545
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1546 1547 1548
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2422:
		ha->device_type |= DT_ISP2422;
1549
		ha->device_type |= DT_ZIO_SUPPORTED;
1550
		ha->device_type |= DT_FWI2;
1551
		ha->device_type |= DT_IIDMA;
1552
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1553 1554 1555
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2432:
		ha->device_type |= DT_ISP2432;
1556
		ha->device_type |= DT_ZIO_SUPPORTED;
1557
		ha->device_type |= DT_FWI2;
1558
		ha->device_type |= DT_IIDMA;
1559
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1560
		break;
1561 1562 1563 1564 1565 1566 1567
	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;
1568 1569
	case PCI_DEVICE_ID_QLOGIC_ISP5422:
		ha->device_type |= DT_ISP5422;
1570
		ha->device_type |= DT_FWI2;
1571
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1572
		break;
1573 1574
	case PCI_DEVICE_ID_QLOGIC_ISP5432:
		ha->device_type |= DT_ISP5432;
1575
		ha->device_type |= DT_FWI2;
1576
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1577
		break;
1578 1579 1580 1581 1582
	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;
1583
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1584
		break;
1585 1586 1587 1588 1589 1590 1591
	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;
1592
	}
1593 1594 1595 1596 1597 1598 1599

	/* Get adapter physical port no from interrupt pin register. */
	pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no);
	if (ha->port_no & 1)
		ha->flags.port0 = 1;
	else
		ha->flags.port0 = 0;
1600 1601
}

L
Linus Torvalds 已提交
1602
static int
1603
qla2x00_iospace_config(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
1604
{
1605
	resource_size_t pio;
1606
	uint16_t msix;
1607
	int cpus;
L
Linus Torvalds 已提交
1608

1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
	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 已提交
1620 1621
	/* We only need PIO for Flash operations on ISP2312 v2 chips. */
	pio = pci_resource_start(ha->pdev, 0);
1622 1623
	if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
		if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) {
L
Linus Torvalds 已提交
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
			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;
	}
1635
	ha->pio_address = pio;
L
Linus Torvalds 已提交
1636

1637
skip_pio:
L
Linus Torvalds 已提交
1638
	/* Use MMIO operations for all accesses. */
1639
	if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) {
L
Linus Torvalds 已提交
1640
		qla_printk(KERN_ERR, ha,
1641
		    "region #1 not an MMIO resource (%s), aborting\n",
L
Linus Torvalds 已提交
1642 1643 1644
		    pci_name(ha->pdev));
		goto iospace_error_exit;
	}
1645
	if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) {
L
Linus Torvalds 已提交
1646 1647 1648 1649 1650 1651
		qla_printk(KERN_ERR, ha,
		    "Invalid PCI mem region size (%s), aborting\n",
			pci_name(ha->pdev));
		goto iospace_error_exit;
	}

1652
	ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN);
L
Linus Torvalds 已提交
1653 1654 1655 1656 1657 1658 1659
	if (!ha->iobase) {
		qla_printk(KERN_ERR, ha,
		    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));

		goto iospace_error_exit;
	}

1660
	/* Determine queue resources */
1661
	ha->max_req_queues = ha->max_rsp_queues = 1;
1662
	if ((ql2xmaxqueues <= 1 || ql2xmultique_tag < 1) &&
1663
		(!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
1664 1665 1666 1667 1668 1669 1670
		goto mqiobase_exit;
	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;
1671 1672 1673 1674
		/* Max queues are bounded by available msix vectors */
		/* queue 0 uses two msix vectors */
		if (ql2xmultique_tag) {
			cpus = num_online_cpus();
1675
			ha->max_rsp_queues = (ha->msix_count - 1 > cpus) ?
1676 1677 1678
				(cpus + 1) : (ha->msix_count - 1);
			ha->max_req_queues = 2;
		} else if (ql2xmaxqueues > 1) {
1679 1680 1681 1682 1683
			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));
		}
1684 1685
		qla_printk(KERN_INFO, ha,
			"MSI-X vector count: %d\n", msix);
1686 1687
	} else
		qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
1688 1689

mqiobase_exit:
1690
	ha->msix_count = ha->max_rsp_queues + 1;
L
Linus Torvalds 已提交
1691 1692 1693 1694 1695 1696
	return (0);

iospace_error_exit:
	return (-ENOMEM);
}

1697 1698 1699
static void
qla2xxx_scan_start(struct Scsi_Host *shost)
{
1700
	scsi_qla_host_t *vha = shost_priv(shost);
1701

1702 1703 1704
	if (vha->hw->flags.running_gold_fw)
		return;

1705 1706 1707 1708
	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);
1709 1710 1711 1712 1713
}

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

1716
	if (!vha->host)
1717
		return 1;
1718
	if (time > vha->hw->loop_reset_delay * HZ)
1719 1720
		return 1;

1721
	return atomic_read(&vha->loop_state) == LOOP_READY;
1722 1723
}

L
Linus Torvalds 已提交
1724 1725 1726
/*
 * PCI driver interface
 */
1727 1728
static int __devinit
qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
L
Linus Torvalds 已提交
1729
{
1730
	int	ret = -ENODEV;
L
Linus Torvalds 已提交
1731
	struct Scsi_Host *host;
1732 1733
	scsi_qla_host_t *base_vha = NULL;
	struct qla_hw_data *ha;
1734
	char pci_info[30];
L
Linus Torvalds 已提交
1735
	char fw_str[30];
1736
	struct scsi_host_template *sht;
1737
	int bars, max_id, mem_only = 0;
1738
	uint16_t req_length = 0, rsp_length = 0;
1739 1740
	struct req_que *req = NULL;
	struct rsp_que *rsp = NULL;
L
Linus Torvalds 已提交
1741

1742
	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
1743
	sht = &qla2xxx_driver_template;
1744
	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
1745
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
1746
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
1747
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
1748
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
1749 1750
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001) {
1751
		bars = pci_select_bars(pdev, IORESOURCE_MEM);
1752
		mem_only = 1;
1753 1754
	}

1755 1756 1757 1758 1759 1760 1761
	if (mem_only) {
		if (pci_enable_device_mem(pdev))
			goto probe_out;
	} else {
		if (pci_enable_device(pdev))
			goto probe_out;
	}
1762

1763 1764
	/* This may fail but that's ok */
	pci_enable_pcie_error_reporting(pdev);
1765

1766 1767 1768 1769
	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 已提交
1770
	}
1771
	ha->pdev = pdev;
L
Linus Torvalds 已提交
1772 1773

	/* Clear our data area */
1774
	ha->bars = bars;
1775
	ha->mem_only = mem_only;
1776
	spin_lock_init(&ha->hardware_lock);
L
Linus Torvalds 已提交
1777

1778 1779
	/* Set ISP-type information. */
	qla2x00_set_isp_flags(ha);
L
Linus Torvalds 已提交
1780 1781
	/* Configure PCI I/O space */
	ret = qla2x00_iospace_config(ha);
1782
	if (ret)
1783
		goto probe_hw_failed;
L
Linus Torvalds 已提交
1784 1785

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

	ha->prev_topology = 0;
1790
	ha->init_cb_size = sizeof(init_cb_t);
1791
	ha->link_data_rate = PORT_SPEED_UNKNOWN;
1792
	ha->optrom_size = OPTROM_SIZE_2300;
L
Linus Torvalds 已提交
1793

1794
	/* Assign ISP specific operations. */
1795
	max_id = MAX_TARGETS_2200;
L
Linus Torvalds 已提交
1796
	if (IS_QLA2100(ha)) {
1797
		max_id = MAX_TARGETS_2100;
L
Linus Torvalds 已提交
1798
		ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
1799 1800 1801
		req_length = REQUEST_ENTRY_CNT_2100;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1802
		ha->gid_list_info_size = 4;
1803 1804 1805 1806
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1807
		ha->isp_ops = &qla2100_isp_ops;
L
Linus Torvalds 已提交
1808 1809
	} else if (IS_QLA2200(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1810 1811 1812
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1813
		ha->gid_list_info_size = 4;
1814 1815 1816 1817
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1818
		ha->isp_ops = &qla2100_isp_ops;
1819
	} else if (IS_QLA23XX(ha)) {
L
Linus Torvalds 已提交
1820
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1821 1822 1823
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1824
		ha->gid_list_info_size = 6;
1825 1826
		if (IS_QLA2322(ha) || IS_QLA6322(ha))
			ha->optrom_size = OPTROM_SIZE_2322;
1827 1828 1829 1830
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1831
		ha->isp_ops = &qla2300_isp_ops;
1832
	} else if (IS_QLA24XX_TYPE(ha)) {
1833
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1834 1835 1836
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1837
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
1838
		ha->gid_list_info_size = 8;
1839
		ha->optrom_size = OPTROM_SIZE_24XX;
1840
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA24XX;
1841
		ha->isp_ops = &qla24xx_isp_ops;
1842 1843 1844 1845
		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;
1846 1847
	} else if (IS_QLA25XX(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1848 1849 1850
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1851 1852 1853
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
		ha->gid_list_info_size = 8;
		ha->optrom_size = OPTROM_SIZE_25XX;
1854
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
1855
		ha->isp_ops = &qla25xx_isp_ops;
1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867
		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;
1868
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
1869 1870 1871 1872 1873
		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;
L
Linus Torvalds 已提交
1874 1875
	}

1876
	mutex_init(&ha->vport_lock);
1877 1878 1879
	init_completion(&ha->mbx_cmd_comp);
	complete(&ha->mbx_cmd_comp);
	init_completion(&ha->mbx_intr_comp);
L
Linus Torvalds 已提交
1880

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

1883
	qla2x00_config_dma_addressing(ha);
1884
	ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp);
1885
	if (!ret) {
L
Linus Torvalds 已提交
1886 1887 1888
		qla_printk(KERN_WARNING, ha,
		    "[ERROR] Failed to allocate memory for adapter\n");

1889 1890 1891
		goto probe_hw_failed;
	}

1892
	req->max_q_depth = MAX_Q_DEPTH;
1893
	if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU)
1894 1895
		req->max_q_depth = ql2xmaxqdepth;

1896 1897 1898 1899 1900 1901

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

1902
		ret = -ENOMEM;
1903
		qla2x00_mem_free(ha);
1904 1905
		qla2x00_free_req_que(ha, req);
		qla2x00_free_rsp_que(ha, rsp);
1906
		goto probe_hw_failed;
L
Linus Torvalds 已提交
1907 1908
	}

1909 1910 1911
	pci_set_drvdata(pdev, base_vha);

	host = base_vha->host;
1912
	base_vha->req = req;
1913 1914
	host->can_queue = req->length + 128;
	if (IS_QLA2XXX_MIDTYPE(ha))
1915
		base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
1916
	else
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929
		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;

1930 1931 1932
	/* Set up the irqs */
	ret = qla2x00_request_irqs(ha, rsp);
	if (ret)
1933
		goto probe_init_failed;
1934
	/* Alloc arrays of request and response ring ptrs */
1935
que_init:
1936 1937 1938 1939
	if (!qla2x00_alloc_queues(ha)) {
		qla_printk(KERN_WARNING, ha,
		"[ERROR] Failed to allocate memory for queue"
		" pointers\n");
1940
		goto probe_init_failed;
1941 1942 1943
	}
	ha->rsp_q_map[0] = rsp;
	ha->req_q_map[0] = req;
1944 1945 1946 1947
	rsp->req = req;
	req->rsp = rsp;
	set_bit(0, ha->req_qid_map);
	set_bit(0, ha->rsp_qid_map);
1948 1949 1950 1951 1952
	/* 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;
1953
	if (ha->mqenable) {
1954 1955 1956 1957
		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;
1958 1959
	}

1960
	if (qla2x00_initialize_adapter(base_vha)) {
L
Linus Torvalds 已提交
1961 1962 1963 1964 1965
		qla_printk(KERN_WARNING, ha,
		    "Failed to initialize adapter\n");

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

1968
		ret = -ENODEV;
L
Linus Torvalds 已提交
1969 1970 1971
		goto probe_failed;
	}

1972 1973
	if (ha->mqenable) {
		if (qla25xx_setup_mode(base_vha)) {
1974 1975 1976
			qla_printk(KERN_WARNING, ha,
				"Can't create queues, falling back to single"
				" queue mode\n");
1977 1978 1979
			goto que_init;
		}
	}
1980

1981 1982 1983
	if (ha->flags.running_gold_fw)
		goto skip_dpc;

L
Linus Torvalds 已提交
1984 1985 1986
	/*
	 * Startup the kernel thread for this host adapter
	 */
1987
	ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
1988
			"%s_dpc", base_vha->host_str);
1989
	if (IS_ERR(ha->dpc_thread)) {
L
Linus Torvalds 已提交
1990 1991
		qla_printk(KERN_WARNING, ha,
		    "Unable to start DPC thread!\n");
1992
		ret = PTR_ERR(ha->dpc_thread);
L
Linus Torvalds 已提交
1993 1994 1995
		goto probe_failed;
	}

1996
skip_dpc:
1997 1998
	list_add_tail(&base_vha->list, &ha->vp_list);
	base_vha->host->irq = ha->pdev->irq;
L
Linus Torvalds 已提交
1999 2000

	/* Initialized the timer */
2001
	qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL);
L
Linus Torvalds 已提交
2002 2003

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

2006 2007
	base_vha->flags.init_done = 1;
	base_vha->flags.online = 1;
2008

2009 2010 2011 2012
	ret = scsi_add_host(host, &pdev->dev);
	if (ret)
		goto probe_failed;

2013 2014
	ha->isp_ops->enable_intrs(ha);

2015 2016
	scsi_scan_host(host);

2017
	qla2x00_alloc_sysfs_attr(base_vha);
2018

2019
	qla2x00_init_host_attr(base_vha);
2020

2021
	qla2x00_dfs_setup(base_vha);
2022

L
Linus Torvalds 已提交
2023 2024 2025
	qla_printk(KERN_INFO, ha, "\n"
	    " QLogic Fibre Channel HBA Driver: %s\n"
	    "  QLogic %s - %s\n"
2026 2027
	    "  ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
	    qla2x00_version_str, ha->model_number,
2028 2029 2030 2031
	    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 已提交
2032 2033 2034

	return 0;

2035
probe_init_failed:
2036 2037 2038
	qla2x00_free_req_que(ha, req);
	qla2x00_free_rsp_que(ha, rsp);
	ha->max_req_queues = ha->max_rsp_queues = 0;
2039

L
Linus Torvalds 已提交
2040
probe_failed:
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
	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);
	}

2051
	qla2x00_free_device(base_vha);
L
Linus Torvalds 已提交
2052

2053
	scsi_host_put(base_vha->host);
L
Linus Torvalds 已提交
2054

2055 2056 2057 2058 2059 2060 2061
probe_hw_failed:
	if (ha->iobase)
		iounmap(ha->iobase);

	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
L
Linus Torvalds 已提交
2062

2063
probe_out:
2064
	pci_disable_device(pdev);
2065
	return ret;
L
Linus Torvalds 已提交
2066 2067
}

A
Adrian Bunk 已提交
2068
static void
2069
qla2x00_remove_one(struct pci_dev *pdev)
L
Linus Torvalds 已提交
2070
{
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
	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 已提交
2081

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

2084 2085
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

2086
	qla2x00_dfs_remove(base_vha);
2087

2088
	qla84xx_put_chip(base_vha);
2089

2090 2091 2092 2093 2094 2095
	/* Disable timer */
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);

	base_vha->flags.online = 0;

2096 2097 2098 2099 2100 2101 2102
	/* Flush the work queue and remove it */
	if (ha->wq) {
		flush_workqueue(ha->wq);
		destroy_workqueue(ha->wq);
		ha->wq = NULL;
	}

2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114
	/* 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);
	}

2115
	qla2x00_free_sysfs_attr(base_vha);
2116

2117
	fc_remove_host(base_vha->host);
2118

2119
	scsi_remove_host(base_vha->host);
L
Linus Torvalds 已提交
2120

2121
	qla2x00_free_device(base_vha);
2122

2123
	scsi_host_put(base_vha->host);
L
Linus Torvalds 已提交
2124

2125 2126
	if (ha->iobase)
		iounmap(ha->iobase);
L
Linus Torvalds 已提交
2127

2128 2129 2130
	if (ha->mqiobase)
		iounmap(ha->mqiobase);

2131 2132 2133
	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
L
Linus Torvalds 已提交
2134

2135
	pci_disable_device(pdev);
L
Linus Torvalds 已提交
2136 2137 2138 2139
	pci_set_drvdata(pdev, NULL);
}

static void
2140
qla2x00_free_device(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
2141
{
2142
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
2143

2144 2145
	qla25xx_delete_queues(vha);

2146
	if (ha->flags.fce_enabled)
2147
		qla2x00_disable_fce_trace(vha, NULL, NULL);
2148

2149
	if (ha->eft)
2150
		qla2x00_disable_eft_trace(vha);
2151

2152
	/* Stop currently executing firmware. */
2153
	qla2x00_try_to_stop_firmware(vha);
L
Linus Torvalds 已提交
2154

2155 2156
	/* turn-off interrupts on the card */
	if (ha->interrupts_on)
2157
		ha->isp_ops->disable_intrs(ha);
2158

2159
	qla2x00_free_irqs(vha);
L
Linus Torvalds 已提交
2160

2161
	qla2x00_mem_free(ha);
2162 2163

	qla2x00_free_queues(ha);
L
Linus Torvalds 已提交
2164 2165
}

2166
static inline void
2167
qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
2168 2169 2170
    int defer)
{
	struct fc_rport *rport;
2171
	scsi_qla_host_t *base_vha;
2172 2173 2174 2175 2176 2177

	if (!fcport->rport)
		return;

	rport = fcport->rport;
	if (defer) {
2178
		base_vha = pci_get_drvdata(vha->hw->pdev);
2179
		spin_lock_irq(vha->host->host_lock);
2180
		fcport->drport = rport;
2181
		spin_unlock_irq(vha->host->host_lock);
2182 2183
		set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
		qla2xxx_wake_dpc(base_vha);
2184
	} else
2185 2186 2187
		fc_remote_port_delete(rport);
}

L
Linus Torvalds 已提交
2188 2189 2190 2191 2192 2193 2194 2195 2196
/*
 * qla2x00_mark_device_lost Updates fcport state when device goes offline.
 *
 * Input: ha = adapter block pointer.  fcport = port structure pointer.
 *
 * Return: None.
 *
 * Context:
 */
2197
void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
2198
    int do_login, int defer)
L
Linus Torvalds 已提交
2199
{
2200
	if (atomic_read(&fcport->state) == FCS_ONLINE &&
2201 2202 2203 2204
	    vha->vp_idx == fcport->vp_idx) {
		atomic_set(&fcport->state, FCS_DEVICE_LOST);
		qla2x00_schedule_rport_del(vha, fcport, defer);
	}
A
Andrew Vasquez 已提交
2205
	/*
L
Linus Torvalds 已提交
2206 2207 2208 2209 2210 2211 2212 2213 2214 2215
	 * 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) {
2216 2217
		fcport->login_retry = vha->hw->login_retry_count;
		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
2218 2219 2220 2221

		DEBUG(printk("scsi(%ld): Port login retry: "
		    "%02x%02x%02x%02x%02x%02x%02x%02x, "
		    "id = 0x%04x retry cnt=%d\n",
2222
		    vha->host_no,
L
Linus Torvalds 已提交
2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249
		    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
2250
qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
L
Linus Torvalds 已提交
2251 2252 2253
{
	fc_port_t *fcport;

2254
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
2255
		if (vha->vp_idx != 0 && vha->vp_idx != fcport->vp_idx)
L
Linus Torvalds 已提交
2256
			continue;
2257

L
Linus Torvalds 已提交
2258 2259 2260 2261 2262 2263
		/*
		 * No point in marking the device as lost, if the device is
		 * already DEAD.
		 */
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
			continue;
2264
		if (atomic_read(&fcport->state) == FCS_ONLINE) {
2265 2266 2267 2268 2269 2270
			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 已提交
2271 2272 2273 2274 2275 2276 2277 2278 2279
	}
}

/*
* qla2x00_mem_alloc
*      Allocates adapter memory.
*
* Returns:
*      0  = success.
2280
*      !0  = failure.
L
Linus Torvalds 已提交
2281
*/
2282
static int
2283 2284
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 已提交
2285 2286 2287
{
	char	name[16];

2288
	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
2289
		&ha->init_cb_dma, GFP_KERNEL);
2290
	if (!ha->init_cb)
2291
		goto fail;
2292

2293 2294 2295
	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
		&ha->gid_list_dma, GFP_KERNEL);
	if (!ha->gid_list)
2296
		goto fail_free_init_cb;
L
Linus Torvalds 已提交
2297

2298 2299
	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
	if (!ha->srb_mempool)
2300
		goto fail_free_gid_list;
2301 2302 2303 2304 2305 2306

	/* Get memory for cached NVRAM */
	ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL);
	if (!ha->nvram)
		goto fail_free_srb_mempool;

2307 2308 2309 2310 2311 2312 2313
	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;

2314 2315
	/* Allocate memory for SNS commands */
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
2316
	/* Get consistent memory allocated for SNS commands */
2317
		ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,
2318
		sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL);
2319
		if (!ha->sns_cmd)
2320
			goto fail_dma_pool;
2321
	} else {
2322
	/* Get consistent memory allocated for MS IOCB */
2323
		ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
2324
			&ha->ms_iocb_dma);
2325
		if (!ha->ms_iocb)
2326 2327
			goto fail_dma_pool;
	/* Get consistent memory allocated for CT SNS commands */
2328
		ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,
2329
			sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
2330 2331
		if (!ha->ct_sns)
			goto fail_free_ms_iocb;
L
Linus Torvalds 已提交
2332 2333
	}

2334
	/* Allocate memory for request ring */
2335 2336
	*req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
	if (!*req) {
2337 2338 2339
		DEBUG(printk("Unable to allocate memory for req\n"));
		goto fail_req;
	}
2340 2341 2342 2343 2344
	(*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) {
2345 2346 2347 2348
		DEBUG(printk("Unable to allocate memory for req_ring\n"));
		goto fail_req_ring;
	}
	/* Allocate memory for response ring */
2349 2350 2351 2352
	*rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
	if (!*rsp) {
		qla_printk(KERN_WARNING, ha,
			"Unable to allocate memory for rsp\n");
2353 2354
		goto fail_rsp;
	}
2355 2356 2357 2358 2359 2360 2361 2362
	(*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");
2363 2364
		goto fail_rsp_ring;
	}
2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377
	(*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;
2378

2379 2380 2381 2382 2383 2384 2385 2386
	/* Get consistent memory allocated for EX-INIT-CB. */
	if (IS_QLA81XX(ha)) {
		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;
	}

2387 2388 2389
	INIT_LIST_HEAD(&ha->vp_list);
	return 1;

2390 2391
fail_ex_init_cb:
	kfree(ha->npiv_info);
2392 2393 2394 2395 2396
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;
2397
fail_rsp_ring:
2398
	kfree(*rsp);
2399
fail_rsp:
2400 2401 2402 2403
	dma_free_coherent(&ha->pdev->dev, ((*req)->length + 1) *
		sizeof(request_t), (*req)->ring, (*req)->dma);
	(*req)->ring = NULL;
	(*req)->dma = 0;
2404
fail_req_ring:
2405
	kfree(*req);
2406 2407 2408 2409 2410
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;
2411 2412 2413 2414
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;
2415 2416 2417
fail_dma_pool:
	dma_pool_destroy(ha->s_dma_pool);
	ha->s_dma_pool = NULL;
2418 2419 2420 2421 2422 2423 2424 2425
fail_free_nvram:
	kfree(ha->nvram);
	ha->nvram = NULL;
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,
2426
	ha->gid_list_dma);
2427 2428
	ha->gid_list = NULL;
	ha->gid_list_dma = 0;
2429 2430 2431 2432 2433
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;
2434
fail:
2435
	DEBUG(printk("%s: Memory allocation failure\n", __func__));
2436
	return -ENOMEM;
L
Linus Torvalds 已提交
2437 2438 2439 2440 2441 2442 2443 2444 2445
}

/*
* qla2x00_mem_free
*      Frees all adapter allocated memory.
*
* Input:
*      ha = adapter block pointer.
*/
A
Adrian Bunk 已提交
2446
static void
2447
qla2x00_mem_free(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
2448
{
2449 2450
	if (ha->srb_mempool)
		mempool_destroy(ha->srb_mempool);
L
Linus Torvalds 已提交
2451

2452 2453
	if (ha->fce)
		dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
2454
		ha->fce_dma);
2455

2456 2457 2458
	if (ha->fw_dump) {
		if (ha->eft)
			dma_free_coherent(&ha->pdev->dev,
2459
			ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
2460 2461 2462
		vfree(ha->fw_dump);
	}

2463 2464 2465 2466
	if (ha->dcbx_tlv)
		dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
		    ha->dcbx_tlv, ha->dcbx_tlv_dma);

2467 2468 2469 2470
	if (ha->xgmac_data)
		dma_free_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
		    ha->xgmac_data, ha->xgmac_data_dma);

L
Linus Torvalds 已提交
2471 2472
	if (ha->sns_cmd)
		dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
2473
		ha->sns_cmd, ha->sns_cmd_dma);
L
Linus Torvalds 已提交
2474 2475 2476

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

2479 2480 2481
	if (ha->sfp_data)
		dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);

2482 2483 2484
	if (ha->edc_data)
		dma_pool_free(ha->s_dma_pool, ha->edc_data, ha->edc_data_dma);

L
Linus Torvalds 已提交
2485 2486 2487
	if (ha->ms_iocb)
		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);

2488 2489 2490
	if (ha->ex_init_cb)
		dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);

L
Linus Torvalds 已提交
2491 2492 2493 2494 2495
	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,
2496
		ha->gid_list_dma);
L
Linus Torvalds 已提交
2497

2498 2499 2500 2501 2502
	if (ha->init_cb)
		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
		ha->init_cb, ha->init_cb_dma);
	vfree(ha->optrom_buffer);
	kfree(ha->nvram);
2503
	kfree(ha->npiv_info);
L
Linus Torvalds 已提交
2504

2505
	ha->srb_mempool = NULL;
2506 2507
	ha->eft = NULL;
	ha->eft_dma = 0;
L
Linus Torvalds 已提交
2508 2509 2510 2511 2512 2513 2514 2515
	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;
2516 2517
	ha->ex_init_cb = NULL;
	ha->ex_init_cb_dma = 0;
L
Linus Torvalds 已提交
2518 2519 2520 2521 2522 2523

	ha->s_dma_pool = NULL;

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

2524 2525 2526 2527
	ha->fw_dump = NULL;
	ha->fw_dumped = 0;
	ha->fw_dump_reading = 0;
}
L
Linus Torvalds 已提交
2528

2529 2530 2531 2532 2533
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;
2534

2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553
	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);

2554 2555
	spin_lock_init(&vha->work_lock);

2556 2557 2558 2559 2560
	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
	return vha;

fail:
	return vha;
L
Linus Torvalds 已提交
2561 2562
}

2563
static struct qla_work_evt *
2564
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
2565 2566 2567
{
	struct qla_work_evt *e;

2568
	e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC);
2569 2570 2571 2572 2573 2574 2575 2576 2577
	if (!e)
		return NULL;

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

2578
static int
2579
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
2580
{
2581
	unsigned long flags;
2582

2583
	spin_lock_irqsave(&vha->work_lock, flags);
2584
	list_add_tail(&e->list, &vha->work_list);
2585
	spin_unlock_irqrestore(&vha->work_lock, flags);
2586
	qla2xxx_wake_dpc(vha);
2587

2588 2589 2590 2591
	return QLA_SUCCESS;
}

int
2592
qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
2593 2594 2595 2596
    u32 data)
{
	struct qla_work_evt *e;

2597
	e = qla2x00_alloc_work(vha, QLA_EVT_AEN);
2598 2599 2600 2601 2602
	if (!e)
		return QLA_FUNCTION_FAILED;

	e->u.aen.code = code;
	e->u.aen.data = data;
2603
	return qla2x00_post_work(vha, e);
2604 2605
}

2606 2607 2608 2609 2610
int
qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
{
	struct qla_work_evt *e;

2611
	e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK);
2612 2613 2614 2615
	if (!e)
		return QLA_FUNCTION_FAILED;

	memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
2616
	return qla2x00_post_work(vha, e);
2617 2618
}

2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642
#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);

2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673
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);
}

2674
void
2675
qla2x00_do_work(struct scsi_qla_host *vha)
2676
{
2677 2678 2679
	struct qla_work_evt *e, *tmp;
	unsigned long flags;
	LIST_HEAD(work);
2680

2681 2682 2683 2684 2685
	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) {
2686 2687 2688 2689
		list_del_init(&e->list);

		switch (e->type) {
		case QLA_EVT_AEN:
2690
			fc_host_post_event(vha->host, fc_get_event_number(),
2691 2692
			    e->u.aen.code, e->u.aen.data);
			break;
2693 2694 2695
		case QLA_EVT_IDC_ACK:
			qla81xx_idc_ack(vha, e->u.idc_ack.mb);
			break;
2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710
		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;
2711 2712 2713
		case QLA_EVT_UEVENT:
			qla2x00_uevent_emit(vha, e->u.uevent.code);
			break;
2714 2715 2716
		}
		if (e->flags & QLA_EVT_FLAG_FREE)
			kfree(e);
2717 2718
	}
}
2719

2720 2721 2722 2723 2724 2725
/* Relogins all the fcports of a vport
 * Context: dpc thread
 */
void qla2x00_relogin(struct scsi_qla_host *vha)
{
	fc_port_t       *fcport;
2726
	int status;
2727 2728
	uint16_t        next_loopid = 0;
	struct qla_hw_data *ha = vha->hw;
2729
	uint16_t data[2];
2730 2731 2732 2733 2734 2735 2736 2737 2738

	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.
	 */
		if (atomic_read(&fcport->state) !=
			FCS_ONLINE && fcport->login_retry) {

2739
			fcport->login_retry--;
2740 2741 2742 2743 2744 2745 2746 2747
			if (fcport->flags & FCF_FABRIC_DEVICE) {
				if (fcport->flags & FCF_TAPE_PRESENT)
					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);

2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759
				if (IS_ALOGIO_CAPABLE(ha)) {
					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);
2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787
			} 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;
2788 2789 2790
	}
}

L
Linus Torvalds 已提交
2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806
/**************************************************************************
* 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)
{
2807
	int		rval;
2808 2809
	scsi_qla_host_t *base_vha;
	struct qla_hw_data *ha;
L
Linus Torvalds 已提交
2810

2811 2812
	ha = (struct qla_hw_data *)data;
	base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
2813 2814 2815

	set_user_nice(current, -20);

2816
	while (!kthread_should_stop()) {
L
Linus Torvalds 已提交
2817 2818
		DEBUG3(printk("qla2x00: DPC handler sleeping\n"));

2819 2820 2821
		set_current_state(TASK_INTERRUPTIBLE);
		schedule();
		__set_current_state(TASK_RUNNING);
L
Linus Torvalds 已提交
2822 2823 2824 2825

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

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

2829
		DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
L
Linus Torvalds 已提交
2830 2831 2832 2833 2834 2835 2836 2837

		ha->dpc_active = 1;

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

2838
		qla2x00_do_work(base_vha);
2839

2840 2841
		if (test_and_clear_bit(ISP_ABORT_NEEDED,
						&base_vha->dpc_flags)) {
L
Linus Torvalds 已提交
2842 2843 2844

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

2849
				if (qla2x00_abort_isp(base_vha)) {
L
Linus Torvalds 已提交
2850 2851
					/* failed. retry later */
					set_bit(ISP_ABORT_NEEDED,
2852
					    &base_vha->dpc_flags);
2853
				}
2854 2855
				clear_bit(ABORT_ISP_ACTIVE,
						&base_vha->dpc_flags);
2856 2857
			}

L
Linus Torvalds 已提交
2858
			DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",
2859
			    base_vha->host_no));
L
Linus Torvalds 已提交
2860 2861
		}

2862 2863 2864
		if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) {
			qla2x00_update_fcports(base_vha);
			clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
2865
		}
2866

2867 2868 2869
		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 已提交
2870 2871

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

2874 2875
			qla2x00_rst_aen(base_vha);
			clear_bit(RESET_ACTIVE, &base_vha->dpc_flags);
L
Linus Torvalds 已提交
2876 2877 2878
		}

		/* Retry each device up to login retry count */
2879 2880 2881 2882
		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 已提交
2883 2884

			DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
2885 2886 2887
					base_vha->host_no));
			qla2x00_relogin(base_vha);

L
Linus Torvalds 已提交
2888
			DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
2889
			    base_vha->host_no));
L
Linus Torvalds 已提交
2890 2891
		}

2892 2893
		if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
							&base_vha->dpc_flags)) {
L
Linus Torvalds 已提交
2894 2895

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

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

2901
				rval = qla2x00_loop_resync(base_vha);
L
Linus Torvalds 已提交
2902

2903 2904
				clear_bit(LOOP_RESYNC_ACTIVE,
						&base_vha->dpc_flags);
L
Linus Torvalds 已提交
2905 2906 2907
			}

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

2911 2912 2913 2914
		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);
2915 2916
		}

L
Linus Torvalds 已提交
2917
		if (!ha->interrupts_on)
2918
			ha->isp_ops->enable_intrs(ha);
L
Linus Torvalds 已提交
2919

2920 2921 2922
		if (test_and_clear_bit(BEACON_BLINK_NEEDED,
					&base_vha->dpc_flags))
			ha->isp_ops->beacon_blink(base_vha);
2923

2924
		qla2x00_do_dpc_all_vps(base_vha);
2925

L
Linus Torvalds 已提交
2926 2927 2928
		ha->dpc_active = 0;
	} /* End of while(1) */

2929
	DEBUG(printk("scsi(%ld): DPC handler exiting\n", base_vha->host_no));
L
Linus Torvalds 已提交
2930 2931 2932 2933 2934 2935

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

2936 2937 2938
	/* Cleanup any residual CTX SRBs. */
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

2939 2940 2941 2942
	return 0;
}

void
2943
qla2xxx_wake_dpc(struct scsi_qla_host *vha)
2944
{
2945
	struct qla_hw_data *ha = vha->hw;
2946 2947
	struct task_struct *t = ha->dpc_thread;

2948
	if (!test_bit(UNLOADING, &vha->dpc_flags) && t)
2949
		wake_up_process(t);
L
Linus Torvalds 已提交
2950 2951 2952 2953 2954 2955 2956 2957 2958 2959
}

/*
*  qla2x00_rst_aen
*      Processes asynchronous reset.
*
* Input:
*      ha  = adapter block pointer.
*/
static void
2960
qla2x00_rst_aen(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
2961
{
2962 2963 2964
	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 已提交
2965
		do {
2966
			clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
2967 2968 2969 2970 2971

			/*
			 * Issue marker command only when we are going to start
			 * the I/O.
			 */
2972 2973 2974
			vha->marker_needed = 1;
		} while (!atomic_read(&vha->loop_down_timer) &&
		    (test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags)));
L
Linus Torvalds 已提交
2975 2976 2977
	}
}

已提交
2978
static void
2979
qla2x00_sp_free_dma(srb_t *sp)
已提交
2980 2981 2982 2983
{
	struct scsi_cmnd *cmd = sp->cmd;

	if (sp->flags & SRB_DMA_VALID) {
2984
		scsi_dma_unmap(cmd);
已提交
2985 2986
		sp->flags &= ~SRB_DMA_VALID;
	}
2987
	CMD_SP(cmd) = NULL;
已提交
2988 2989 2990
}

void
2991
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
已提交
2992 2993 2994
{
	struct scsi_cmnd *cmd = sp->cmd;

2995
	qla2x00_sp_free_dma(sp);
已提交
2996 2997 2998 2999 3000

	mempool_free(sp, ha->srb_mempool);

	cmd->scsi_done(cmd);
}
3001

L
Linus Torvalds 已提交
3002 3003 3004 3005 3006 3007 3008 3009
/**************************************************************************
*   qla2x00_timer
*
* Description:
*   One second timer
*
* Context: Interrupt
***************************************************************************/
3010
void
3011
qla2x00_timer(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
3012 3013 3014 3015 3016 3017
{
	unsigned long	cpu_flags = 0;
	fc_port_t	*fcport;
	int		start_dpc = 0;
	int		index;
	srb_t		*sp;
已提交
3018
	int		t;
3019
	struct qla_hw_data *ha = vha->hw;
3020
	struct req_que *req;
L
Linus Torvalds 已提交
3021 3022 3023 3024 3025
	/*
	 * 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 已提交
3026
	 * the port it marked DEAD.
L
Linus Torvalds 已提交
3027 3028
	 */
	t = 0;
3029
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
L
Linus Torvalds 已提交
3030 3031 3032 3033 3034 3035 3036 3037
		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 已提交
3038
			if (atomic_dec_and_test(&fcport->port_down_timer) != 0)
L
Linus Torvalds 已提交
3039
				atomic_set(&fcport->state, FCS_DEVICE_DEAD);
A
Andrew Vasquez 已提交
3040

L
Linus Torvalds 已提交
3041
			DEBUG(printk("scsi(%ld): fcport-%d - port retry count: "
3042
			    "%d remaining\n",
3043
			    vha->host_no,
L
Linus Torvalds 已提交
3044 3045 3046 3047 3048 3049 3050
			    t, atomic_read(&fcport->port_down_timer)));
		}
		t++;
	} /* End of for fcport  */


	/* Loop down handler. */
3051 3052 3053
	if (atomic_read(&vha->loop_down_timer) > 0 &&
	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
		&& vha->flags.online) {
L
Linus Torvalds 已提交
3054

3055 3056
		if (atomic_read(&vha->loop_down_timer) ==
		    vha->loop_down_abort_time) {
L
Linus Torvalds 已提交
3057 3058 3059

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

3062 3063
			if (!IS_QLA2100(ha) && vha->link_down_timeout)
				atomic_set(&vha->loop_state, LOOP_DEAD);
L
Linus Torvalds 已提交
3064 3065

			/* Schedule an ISP abort to return any tape commands. */
3066
			/* NPIV - scan physical port only */
3067
			if (!vha->vp_idx) {
3068 3069
				spin_lock_irqsave(&ha->hardware_lock,
				    cpu_flags);
3070
				req = ha->req_q_map[0];
3071 3072 3073 3074 3075
				for (index = 1;
				    index < MAX_OUTSTANDING_COMMANDS;
				    index++) {
					fc_port_t *sfcp;

3076
					sp = req->outstanding_cmds[index];
3077 3078
					if (!sp)
						continue;
3079 3080
					if (sp->ctx)
						continue;
3081 3082 3083
					sfcp = sp->fcport;
					if (!(sfcp->flags & FCF_TAPE_PRESENT))
						continue;
3084

3085
					set_bit(ISP_ABORT_NEEDED,
3086
							&vha->dpc_flags);
3087 3088 3089
					break;
				}
				spin_unlock_irqrestore(&ha->hardware_lock,
3090
								cpu_flags);
L
Linus Torvalds 已提交
3091 3092 3093 3094 3095
			}
			start_dpc++;
		}

		/* if the loop has been down for 4 minutes, reinit adapter */
3096
		if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
3097
			if (!(vha->device_flags & DFLG_NO_CABLE)) {
L
Linus Torvalds 已提交
3098 3099
				DEBUG(printk("scsi(%ld): Loop down - "
				    "aborting ISP.\n",
3100
				    vha->host_no));
L
Linus Torvalds 已提交
3101 3102 3103
				qla_printk(KERN_WARNING, ha,
				    "Loop down - aborting ISP.\n");

3104
				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
3105 3106
			}
		}
3107
		DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
3108 3109
		    vha->host_no,
		    atomic_read(&vha->loop_down_timer)));
L
Linus Torvalds 已提交
3110 3111
	}

3112 3113
	/* Check if beacon LED needs to be blinked */
	if (ha->beacon_blink_led == 1) {
3114
		set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
3115 3116 3117
		start_dpc++;
	}

3118
	/* Process any deferred work. */
3119
	if (!list_empty(&vha->work_list))
3120 3121
		start_dpc++;

L
Linus Torvalds 已提交
3122
	/* Schedule the DPC routine if needed */
3123 3124 3125
	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 已提交
3126
	    start_dpc ||
3127 3128 3129 3130 3131
	    test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) ||
	    test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags) ||
	    test_bit(VP_DPC_NEEDED, &vha->dpc_flags) ||
	    test_bit(RELOGIN_NEEDED, &vha->dpc_flags)))
		qla2xxx_wake_dpc(vha);
L
Linus Torvalds 已提交
3132

3133
	qla2x00_restart_timer(vha, WATCH_INTERVAL);
L
Linus Torvalds 已提交
3134 3135
}

3136 3137
/* Firmware interface routines. */

3138
#define FW_BLOBS	7
3139 3140 3141 3142
#define FW_ISP21XX	0
#define FW_ISP22XX	1
#define FW_ISP2300	2
#define FW_ISP2322	3
3143
#define FW_ISP24XX	4
3144
#define FW_ISP25XX	5
3145
#define FW_ISP81XX	6
3146

3147 3148 3149 3150 3151
#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"
3152
#define FW_FILE_ISP25XX	"ql2500_fw.bin"
3153
#define FW_FILE_ISP81XX	"ql8100_fw.bin"
3154

3155
static DEFINE_MUTEX(qla_fw_lock);
3156 3157

static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
3158 3159 3160 3161 3162
	{ .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, },
3163
	{ .name = FW_FILE_ISP25XX, },
3164
	{ .name = FW_FILE_ISP81XX, },
3165 3166 3167
};

struct fw_blob *
3168
qla2x00_request_firmware(scsi_qla_host_t *vha)
3169
{
3170
	struct qla_hw_data *ha = vha->hw;
3171 3172 3173 3174 3175 3176 3177
	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];
3178
	} else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3179
		blob = &qla_fw_blobs[FW_ISP2300];
3180
	} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
3181
		blob = &qla_fw_blobs[FW_ISP2322];
3182
	} else if (IS_QLA24XX_TYPE(ha)) {
3183
		blob = &qla_fw_blobs[FW_ISP24XX];
3184 3185
	} else if (IS_QLA25XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP25XX];
3186 3187
	} else if (IS_QLA81XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP81XX];
3188 3189
	}

3190
	mutex_lock(&qla_fw_lock);
3191 3192 3193 3194 3195
	if (blob->fw)
		goto out;

	if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
		DEBUG2(printk("scsi(%ld): Failed to load firmware image "
3196
		    "(%s).\n", vha->host_no, blob->name));
3197 3198 3199 3200 3201 3202
		blob->fw = NULL;
		blob = NULL;
		goto out;
	}

out:
3203
	mutex_unlock(&qla_fw_lock);
3204 3205 3206 3207 3208 3209 3210 3211
	return blob;
}

static void
qla2x00_release_firmware(void)
{
	int idx;

3212
	mutex_lock(&qla_fw_lock);
3213 3214 3215
	for (idx = 0; idx < FW_BLOBS; idx++)
		if (qla_fw_blobs[idx].fw)
			release_firmware(qla_fw_blobs[idx].fw);
3216
	mutex_unlock(&qla_fw_lock);
3217 3218
}

3219 3220 3221
static pci_ers_result_t
qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
3222 3223
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);

3224 3225 3226 3227 3228 3229 3230
	switch (state) {
	case pci_channel_io_normal:
		return PCI_ERS_RESULT_CAN_RECOVER;
	case pci_channel_io_frozen:
		pci_disable_device(pdev);
		return PCI_ERS_RESULT_NEED_RESET;
	case pci_channel_io_perm_failure:
3231
		qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242
		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;
3243 3244
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266
	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");
3267
		ha->isp_ops->fw_dump(base_vha, 0);
3268 3269 3270 3271 3272 3273 3274 3275 3276 3277

		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;
3278 3279
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3280 3281 3282 3283 3284 3285
	int rc;

	if (ha->mem_only)
		rc = pci_enable_device_mem(pdev);
	else
		rc = pci_enable_device(pdev);
3286

3287
	if (rc) {
3288 3289 3290 3291 3292 3293 3294
		qla_printk(KERN_WARNING, ha,
		    "Can't re-enable PCI device after reset.\n");

		return ret;
	}
	pci_set_master(pdev);

3295
	if (ha->isp_ops->pci_config(base_vha))
3296 3297
		return ret;

3298 3299
	set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
	if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS)
3300
		ret =  PCI_ERS_RESULT_RECOVERED;
3301
	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3302 3303 3304 3305 3306 3307 3308

	return ret;
}

static void
qla2xxx_pci_resume(struct pci_dev *pdev)
{
3309 3310
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3311 3312
	int ret;

3313
	ret = qla2x00_wait_for_hba_online(base_vha);
3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328
	if (ret != QLA_SUCCESS) {
		qla_printk(KERN_ERR, ha,
		    "the device failed to resume I/O "
		    "from slot/link_reset");
	}
	pci_cleanup_aer_uncorrect_error_status(pdev);
}

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,
};

3329
static struct pci_device_id qla2xxx_pci_tbl[] = {
3330 3331 3332 3333 3334 3335 3336 3337 3338
	{ 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) },
3339
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
3340 3341
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
3342
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
3343
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
3344 3345 3346 3347
	{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);

3348
static struct pci_driver qla2xxx_pci_driver = {
3349
	.name		= QLA2XXX_DRIVER_NAME,
3350 3351 3352
	.driver		= {
		.owner		= THIS_MODULE,
	},
3353
	.id_table	= qla2xxx_pci_tbl,
3354
	.probe		= qla2x00_probe_one,
A
Adrian Bunk 已提交
3355
	.remove		= qla2x00_remove_one,
3356
	.err_handler	= &qla2xxx_err_handler,
3357 3358
};

L
Linus Torvalds 已提交
3359 3360 3361 3362 3363 3364
/**
 * qla2x00_module_init - Module initialization.
 **/
static int __init
qla2x00_module_init(void)
{
3365 3366
	int ret = 0;

L
Linus Torvalds 已提交
3367
	/* Allocate cache for SRBs. */
3368
	srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
3369
	    SLAB_HWCACHE_ALIGN, NULL);
L
Linus Torvalds 已提交
3370 3371 3372 3373 3374 3375 3376 3377
	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);
3378
	if (ql2xextended_error_logging)
3379 3380
		strcat(qla2x00_version_str, "-debug");

3381 3382
	qla2xxx_transport_template =
	    fc_attach_transport(&qla2xxx_transport_functions);
3383 3384
	if (!qla2xxx_transport_template) {
		kmem_cache_destroy(srb_cachep);
L
Linus Torvalds 已提交
3385
		return -ENODEV;
3386 3387 3388 3389 3390 3391
	}
	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 已提交
3392
		return -ENODEV;
3393
	}
L
Linus Torvalds 已提交
3394

3395 3396
	printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
	    qla2x00_version_str);
3397
	ret = pci_register_driver(&qla2xxx_pci_driver);
3398 3399 3400
	if (ret) {
		kmem_cache_destroy(srb_cachep);
		fc_release_transport(qla2xxx_transport_template);
3401
		fc_release_transport(qla2xxx_transport_vport_template);
3402 3403
	}
	return ret;
L
Linus Torvalds 已提交
3404 3405 3406 3407 3408 3409 3410 3411
}

/**
 * qla2x00_module_exit - Module cleanup.
 **/
static void __exit
qla2x00_module_exit(void)
{
3412
	pci_unregister_driver(&qla2xxx_pci_driver);
3413
	qla2x00_release_firmware();
3414
	kmem_cache_destroy(srb_cachep);
L
Linus Torvalds 已提交
3415
	fc_release_transport(qla2xxx_transport_template);
3416
	fc_release_transport(qla2xxx_transport_vport_template);
L
Linus Torvalds 已提交
3417 3418 3419 3420 3421 3422 3423 3424 3425
}

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);
3426 3427 3428 3429 3430
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);
3431
MODULE_FIRMWARE(FW_FILE_ISP25XX);
3432
MODULE_FIRMWARE(FW_FILE_ISP81XX);