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

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

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

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

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

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

35
int qlport_down_retry;
Linus Torvalds's avatar
Linus Torvalds committed
36 37
module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(qlport_down_retry,
38
		"Maximum number of command retries to a port that returns "
Linus Torvalds's avatar
Linus Torvalds committed
39 40 41 42 43 44
		"a PORT-DOWN status.");

int ql2xplogiabsentdevice;
module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xplogiabsentdevice,
		"Option to enable PLOGI to devices that are not present after "
45
		"a Fabric scan.  This is needed for several broken switches. "
Linus Torvalds's avatar
Linus Torvalds committed
46 47 48 49 50 51 52
		"Default is 0 - no PLOGI. 1 - perfom PLOGI.");

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

53 54 55 56 57 58 59
int ql2xallocfwdump = 1;
module_param(ql2xallocfwdump, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xallocfwdump,
		"Option to enable allocation of memory for a firmware dump "
		"during HBA initialization.  Memory allocation requirements "
		"vary by ISP type.  Default is 1 - allocate memory.");

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

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

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

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

80 81 82 83 84 85 86 87
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.");

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

95 96 97 98 99 100
int ql2xiidmaenable=1;
module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xiidmaenable,
		"Enables iIDMA settings "
		"Default is 1 - perform iIDMA. 0 - no iIDMA.");

101 102 103 104 105 106
int ql2xmaxqueues = 1;
module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xmaxqueues,
		"Enables MQ settings "
		"Default is 1 for single queue. Set it to number \
			of queues in MQ mode.");
107 108 109 110 111 112 113

int ql2xmultique_tag;
module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xmultique_tag,
		"Enables CPU affinity settings for the driver "
		"Default is 0 for no affinity of request and response IO. "
		"Set it to 1 to turn on the cpu affinity.");
114 115 116 117 118 119 120 121 122 123

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

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

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

143
struct scsi_host_template qla2xxx_driver_template = {
Linus Torvalds's avatar
Linus Torvalds committed
144
	.module			= THIS_MODULE,
145
	.name			= QLA2XXX_DRIVER_NAME,
146
	.queuecommand		= qla2xxx_queuecommand,
147 148 149

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

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

Linus Torvalds's avatar
Linus Torvalds committed
171
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
172
struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
173 174 175 176 177 178

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

179
__inline__ void
180
qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval)
Linus Torvalds's avatar
Linus Torvalds committed
181
{
182 183 184 185 186 187
	init_timer(&vha->timer);
	vha->timer.expires = jiffies + interval * HZ;
	vha->timer.data = (unsigned long)vha;
	vha->timer.function = (void (*)(unsigned long))func;
	add_timer(&vha->timer);
	vha->timer_active = 1;
Linus Torvalds's avatar
Linus Torvalds committed
188 189 190
}

static inline void
191
qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
Linus Torvalds's avatar
Linus Torvalds committed
192
{
193
	mod_timer(&vha->timer, jiffies + interval * HZ);
Linus Torvalds's avatar
Linus Torvalds committed
194 195
}

Adrian Bunk's avatar
Adrian Bunk committed
196
static __inline__ void
197
qla2x00_stop_timer(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
198
{
199 200
	del_timer_sync(&vha->timer);
	vha->timer_active = 0;
Linus Torvalds's avatar
Linus Torvalds committed
201 202 203 204 205 206
}

static int qla2x00_do_dpc(void *data);

static void qla2x00_rst_aen(scsi_qla_host_t *);

207 208
static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
	struct req_que **, struct rsp_que **);
209 210
static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
Linus Torvalds's avatar
Linus Torvalds committed
211 212

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

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

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

	kfree(req);
	req = NULL;
}

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

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

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

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

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

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

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

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

360
static char *
361
qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
362 363
{
	static char *pci_bus_modes[] = { "33", "66", "100", "133", };
364
	struct qla_hw_data *ha = vha->hw;
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
	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)
381
			strcat(str, "2.5GT/s ");
382
		else if (lspeed == 2)
383
			strcat(str, "5.0GT/s ");
384 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
		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;
}

411
static char *
412
qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
Linus Torvalds's avatar
Linus Torvalds committed
413 414
{
	char un_str[10];
415
	struct qla_hw_data *ha = vha->hw;
416

Linus Torvalds's avatar
Linus Torvalds committed
417 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
	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);
}

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

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

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

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

	return sp;
}

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

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

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

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

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

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

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

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

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

	return 0;

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

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

541 542 543
qc24_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

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

	return 0;
}


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

571
	while (CMD_SP(cmd)) {
572
		msleep(ABORT_POLLING_PERIOD);
Linus Torvalds's avatar
Linus Torvalds committed
573

574 575 576 577 578
		if (--wait_iter)
			break;
	}
	if (CMD_SP(cmd))
		ret = QLA_FUNCTION_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
579

580
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
581 582 583 584
}

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

608
	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
609 610 611 612
	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
	    ha->dpc_active) && time_before(jiffies, wait_online)) {
Linus Torvalds's avatar
Linus Torvalds committed
613 614 615

		msleep(1000);
	}
616
	if (base_vha->flags.online)
617
		return_status = QLA_SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
618 619 620 621 622 623
	else
		return_status = QLA_FUNCTION_FAILED;

	return (return_status);
}

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 650 651
int
qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
{
	int		return_status;
	unsigned long	wait_reset;
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);

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

		msleep(1000);

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

	return return_status;
}

Linus Torvalds's avatar
Linus Torvalds committed
652 653 654
/*
 * qla2x00_wait_for_loop_ready
 *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
655
 *    to be in LOOP_READY state.
Linus Torvalds's avatar
Linus Torvalds committed
656 657
 * Input:
 *     ha - pointer to host adapter structure
658 659
 *
 * Note:
Linus Torvalds's avatar
Linus Torvalds committed
660 661
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
662
 *
Linus Torvalds's avatar
Linus Torvalds committed
663 664 665 666 667
 *
 * Return:
 *    Success (LOOP_READY) : 0
 *    Failed  (LOOP_NOT_READY) : 1
 */
668
static inline int
669
qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
670 671 672
{
	int 	 return_status = QLA_SUCCESS;
	unsigned long loop_timeout ;
673 674
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds's avatar
Linus Torvalds committed
675 676

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

679 680 681 682
	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) {
683 684 685
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
Linus Torvalds's avatar
Linus Torvalds committed
686 687 688 689 690 691
		msleep(1000);
		if (time_after_eq(jiffies, loop_timeout)) {
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
	}
692
	return (return_status);
Linus Torvalds's avatar
Linus Torvalds committed
693 694
}

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

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

716 717 718 719 720 721 722 723
		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)
724
				DEBUG2(qla_printk(KERN_WARNING, ha,
725
				"Abort failed while waiting --  %lx\n",
726
				sp->cmd->serial_number));
727
		}
728
		spin_lock_irqsave(&ha->hardware_lock, flags);
729
	}
730
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
731 732
}

733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
static void
qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
{
	struct Scsi_Host *shost = cmnd->device->host;
	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
	unsigned long flags;

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

Linus Torvalds's avatar
Linus Torvalds committed
750 751 752 753 754 755 756 757 758 759 760 761 762
/**************************************************************************
* 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:
763
*    Only return FAILED if command not returned by firmware.
Linus Torvalds's avatar
Linus Torvalds committed
764
**************************************************************************/
765
static int
Linus Torvalds's avatar
Linus Torvalds committed
766 767
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
{
768
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
769
	srb_t *sp;
770
	int ret, i;
771 772
	unsigned int id, lun;
	unsigned long serial;
773
	unsigned long flags;
774
	int wait = 0;
775
	struct qla_hw_data *ha = vha->hw;
776
	struct req_que *req = vha->req;
777
	srb_t *spt;
Linus Torvalds's avatar
Linus Torvalds committed
778

779 780
	qla2x00_block_error_handler(cmd);

781
	if (!CMD_SP(cmd))
782
		return SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
783

784
	ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
785

786 787 788
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
789 790 791
	spt = (srb_t *) CMD_SP(cmd);
	if (!spt)
		return SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
792

793
	/* Check active list for command command. */
794
	spin_lock_irqsave(&ha->hardware_lock, flags);
795 796
	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
		sp = req->outstanding_cmds[i];
Linus Torvalds's avatar
Linus Torvalds committed
797

798 799
		if (sp == NULL)
			continue;
800 801
		if (sp->ctx)
			continue;
802 803
		if (sp->cmd != cmd)
			continue;
Linus Torvalds's avatar
Linus Torvalds committed
804

805 806 807 808
		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);
809
		if (ha->isp_ops->abort_command(sp)) {
810 811
			DEBUG2(printk("%s(%ld): abort_command "
			"mbx failed.\n", __func__, vha->host_no));
812
			ret = FAILED;
813 814 815 816
		} else {
			DEBUG3(printk("%s(%ld): abort_command "
			"mbx success.\n", __func__, vha->host_no));
			wait = 1;
817
		}
818 819
		spin_lock_irqsave(&ha->hardware_lock, flags);
		break;
820
	}
821
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
822

823
	/* Wait for the command to be returned. */
824
	if (wait) {
825
		if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
826
			qla_printk(KERN_ERR, ha,
827
			    "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
828
			    "%x.\n", vha->host_no, id, lun, serial, ret);
829
			ret = FAILED;
830
		}
Linus Torvalds's avatar
Linus Torvalds committed
831 832
	}

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

837 838
	return ret;
}
Linus Torvalds's avatar
Linus Torvalds committed
839

840 841 842 843 844 845
enum nexus_wait_type {
	WAIT_HOST = 0,
	WAIT_TARGET,
	WAIT_LUN,
};

846
static int
847
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
848
	unsigned int l, srb_t *sp, enum nexus_wait_type type)
849
{
850
	int cnt, match, status;
851
	unsigned long flags;
852
	struct qla_hw_data *ha = vha->hw;
853
	struct req_que *req;
Linus Torvalds's avatar
Linus Torvalds committed
854

855
	status = QLA_SUCCESS;
856 857 858
	if (!sp)
		return status;

859
	spin_lock_irqsave(&ha->hardware_lock, flags);
860
	req = vha->req;
861 862 863 864
	for (cnt = 1; status == QLA_SUCCESS &&
		cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (!sp)
865
			continue;
866 867
		if (sp->ctx)
			continue;
868 869 870 871 872 873 874 875 876 877 878 879 880 881
		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;
882
		}
883 884 885 886 887 888
		if (!match)
			continue;

		spin_unlock_irqrestore(&ha->hardware_lock, flags);
		status = qla2x00_eh_wait_on_command(sp->cmd);
		spin_lock_irqsave(&ha->hardware_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
889
	}
890
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
891 892

	return status;
Linus Torvalds's avatar
Linus Torvalds committed
893 894
}

895 896 897 898 899 900
static char *reset_errors[] = {
	"HBA not online",
	"HBA not ready",
	"Task management failed",
	"Waiting for command completions",
};
Linus Torvalds's avatar
Linus Torvalds committed
901

902
static int
903
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
904
    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
Linus Torvalds's avatar
Linus Torvalds committed
905
{
906
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
907
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
908
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
909

910 911
	qla2x00_block_error_handler(cmd);

912
	if (!fcport)
913
		return FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
914

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

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

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

	return SUCCESS;

 eh_reset_failed:
939 940
	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,
941 942 943
	    reset_errors[err]);
	return FAILED;
}
Linus Torvalds's avatar
Linus Torvalds committed
944

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

951 952
	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
	    ha->isp_ops->lun_reset);
Linus Torvalds's avatar
Linus Torvalds committed
953 954 955
}

static int
956
qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
Linus Torvalds's avatar
Linus Torvalds committed
957
{
958 959
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
960

961 962
	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
	    ha->isp_ops->target_reset);
Linus Torvalds's avatar
Linus Torvalds committed
963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
}

/**************************************************************************
* 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).
*
**************************************************************************/
980
static int
Linus Torvalds's avatar
Linus Torvalds committed
981 982
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
983
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
984
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
985
	int ret = FAILED;
986 987
	unsigned int id, lun;
	unsigned long serial;
988
	srb_t *sp = (srb_t *) CMD_SP(cmd);
989

990 991
	qla2x00_block_error_handler(cmd);

992 993 994
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;
Linus Torvalds's avatar
Linus Torvalds committed
995

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

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

1002
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
Linus Torvalds's avatar
Linus Torvalds committed
1003
		DEBUG2(printk("%s failed:board disabled\n",__func__));
1004
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
1005 1006
	}

1007 1008
	if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
		if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
1009
			ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
1010
	}
1011 1012
	if (ret == FAILED)
		goto eh_bus_reset_done;
Linus Torvalds's avatar
Linus Torvalds committed
1013

1014
	/* Flush outstanding commands. */
1015
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) !=
1016
	    QLA_SUCCESS)
1017
		ret = FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
1018

1019
eh_bus_reset_done:
1020
	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
1021
	    (ret == FAILED) ? "failed" : "succeded");
Linus Torvalds's avatar
Linus Torvalds committed
1022

1023
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
}

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

1053 1054
	qla2x00_block_error_handler(cmd);

1055 1056 1057 1058
	id = cmd->device->id;
	lun = cmd->device->lun;
	serial = cmd->serial_number;

1059
	if (!fcport)
1060
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1061 1062

	qla_printk(KERN_INFO, ha,
1063
	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
Linus Torvalds's avatar
Linus Torvalds committed
1064

1065
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
1066
		goto eh_host_reset_lock;
Linus Torvalds's avatar
Linus Torvalds committed
1067 1068 1069

	/*
	 * Fixme-may be dpc thread is active and processing
1070
	 * loop_resync,so wait a while for it to
Linus Torvalds's avatar
Linus Torvalds committed
1071 1072 1073 1074 1075
	 * 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.
	 */
1076 1077 1078
	qla2x00_wait_for_loop_ready(vha);
	if (vha != base_vha) {
		if (qla2x00_vp_abort_isp(vha))
1079
			goto eh_host_reset_lock;
1080
	} else {
1081 1082 1083
		if (ha->wq)
			flush_workqueue(ha->wq);

1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
		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);
1094
	}
Linus Torvalds's avatar
Linus Torvalds committed
1095

1096
	/* Waiting for command to be returned to OS.*/
1097
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) ==
1098
		QLA_SUCCESS)
1099
		ret = SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
1100

1101 1102 1103
eh_host_reset_lock:
	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
	    (ret == FAILED) ? "failed" : "succeded");
Linus Torvalds's avatar
Linus Torvalds committed
1104

1105 1106
	return ret;
}
Linus Torvalds's avatar
Linus Torvalds committed
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117

/*
* qla2x00_loop_reset
*      Issue loop reset.
*
* Input:
*      ha = adapter block pointer.
*
* Returns:
*      0 = success
*/
1118
int
1119
qla2x00_loop_reset(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
1120
{
1121
	int ret;
1122
	struct fc_port *fcport;
1123
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
1124

1125 1126
	if (ha->flags.enable_lip_full_login && !vha->vp_idx &&
	    !IS_QLA81XX(ha)) {
1127
		ret = qla2x00_full_login_lip(vha);
1128
		if (ret != QLA_SUCCESS) {
1129
			DEBUG2_3(printk("%s(%ld): failed: "
1130
			    "full_login_lip=%d.\n", __func__, vha->host_no,
1131
			    ret));
1132 1133 1134 1135 1136
		}
		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);
1137 1138
	}

1139
	if (ha->flags.enable_lip_reset && !vha->vp_idx) {
1140
		ret = qla2x00_lip_reset(vha);
1141
		if (ret != QLA_SUCCESS) {
1142
			DEBUG2_3(printk("%s(%ld): failed: "
1143 1144 1145
			    "lip_reset=%d.\n", __func__, vha->host_no, ret));
		} else
			qla2x00_wait_for_loop_ready(vha);
Linus Torvalds's avatar
Linus Torvalds committed
1146 1147
	}

1148
	if (ha->flags.enable_target_reset) {
1149
		list_for_each_entry(fcport, &vha->vp_fcports, list) {
1150
			if (fcport->port_type != FCT_TARGET)
Linus Torvalds's avatar
Linus Torvalds committed
1151 1152
				continue;

1153
			ret = ha->isp_ops->target_reset(fcport, 0, 0);
1154 1155 1156
			if (ret != QLA_SUCCESS) {
				DEBUG2_3(printk("%s(%ld): bus_reset failed: "
				    "target_reset=%d d_id=%x.\n", __func__,
1157
				    vha->host_no, ret, fcport->d_id.b24));
1158
			}
Linus Torvalds's avatar
Linus Torvalds committed
1159 1160 1161
		}
	}
	/* Issue marker command only when we are going to start the I/O */
1162
	vha->marker_needed = 1;
Linus Torvalds's avatar
Linus Torvalds committed
1163

1164
	return QLA_SUCCESS;
Linus Torvalds's avatar
Linus Torvalds committed
1165 1166
}

1167
void
1168
qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
1169
{
1170
	int que, cnt;
1171 1172
	unsigned long flags;
	srb_t *sp;
1173
	struct srb_ctx *ctx;
1174
	struct qla_hw_data *ha = vha->hw;
1175
	struct req_que *req;
1176 1177

	spin_lock_irqsave(&ha->hardware_lock, flags);
1178
	for (que = 0; que < ha->max_req_queues; que++) {
1179
		req = ha->req_q_map[que];
1180 1181 1182 1183
		if (!req)
			continue;
		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
			sp = req->outstanding_cmds[cnt];
1184
			if (sp) {
1185
				req->outstanding_cmds[cnt] = NULL;
1186 1187 1188 1189 1190 1191 1192 1193
				if (!sp->ctx) {
					sp->cmd->result = res;
					qla2x00_sp_compl(ha, sp);
				} else {
					ctx = sp->ctx;
					del_timer_sync(&ctx->timer);
					ctx->free(sp);
				}
1194
			}
1195 1196 1197 1198 1199
		}
	}
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

1200 1201
static int
qla2xxx_slave_alloc(struct scsi_device *sdev)
Linus Torvalds's avatar
Linus Torvalds committed
1202
{
1203
	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
Linus Torvalds's avatar
Linus Torvalds committed
1204

1205
	if (!rport || fc_remote_port_chkready(rport))
1206
		return -ENXIO;
1207

1208
	sdev->hostdata = *(fc_port_t **)rport->dd_data;
Linus Torvalds's avatar
Linus Torvalds committed
1209

1210 1211
	return 0;
}
Linus Torvalds's avatar
Linus Torvalds committed
1212

1213 1214 1215
static int
qla2xxx_slave_configure(struct scsi_device *sdev)
{
1216 1217
	scsi_qla_host_t *vha = shost_priv(sdev->host);
	struct qla_hw_data *ha = vha->hw;
1218
	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
1219
	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1220
	struct req_que *req = vha->req;
1221

1222
	if (sdev->tagged_supported)
1223
		scsi_activate_tcq(sdev, req->max_q_depth);
1224
	else
1225
		scsi_deactivate_tcq(sdev, req->max_q_depth);
Linus Torvalds's avatar
Linus Torvalds committed
1226

1227
	rport->dev_loss_tmo = ha->port_down_retry_count;
1228 1229
	if (sdev->type == TYPE_TAPE)
		fcport->flags |= FCF_TAPE_PRESENT;
1230

1231 1232
	return 0;
}
Linus Torvalds's avatar
Linus Torvalds committed
1233

1234 1235 1236 1237
static void
qla2xxx_slave_destroy(struct scsi_device *sdev)
{
	sdev->hostdata = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
1238 1239
}

1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
static int
qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
	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;
}

Linus Torvalds's avatar
Linus Torvalds committed
1262 1263 1264 1265 1266 1267 1268 1269
/**
 * 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
1270
qla2x00_config_dma_addressing(struct qla_hw_data *ha)
Linus Torvalds's avatar
Linus Torvalds committed
1271
{
1272
	/* Assume a 32bit DMA mask. */
Linus Torvalds's avatar
Linus Torvalds committed
1273 1274
	ha->flags.enable_64bit_addressing = 0;

1275
	if (!dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
1276 1277
		/* Any upper-dword bits set? */
		if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
1278
		    !pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
1279
			/* Ok, a 64bit DMA mask is applicable. */
Linus Torvalds's avatar
Linus Torvalds committed
1280
			ha->flags.enable_64bit_addressing = 1;
1281 1282
			ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
			ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64;
1283
			return;
Linus Torvalds's avatar
Linus Torvalds committed
1284 1285
		}
	}
1286

1287 1288
	dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32));
	pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(32));
Linus Torvalds's avatar
Linus Torvalds committed
1289 1290
}

1291
static void
1292
qla2x00_enable_intrs(struct qla_hw_data *ha)
1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
{
	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
1307
qla2x00_disable_intrs(struct qla_hw_data *ha)
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
{
	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
1321
qla24xx_enable_intrs(struct qla_hw_data *ha)
1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
{
	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
1334
qla24xx_disable_intrs(struct qla_hw_data *ha)
1335 1336 1337 1338
{
	unsigned long flags = 0;
	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

1339 1340
	if (IS_NOPOLLING_TYPE(ha))
		return;
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
	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,
1363 1364
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
	.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,
1380
	.start_scsi		= qla2x00_start_scsi,
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
};

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,
1398 1399
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
	.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,
1415
	.start_scsi		= qla2x00_start_scsi,
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
};

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,
1433 1434
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
	.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,
1450
	.start_scsi		= qla24xx_start_scsi,
1451 1452
};

1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467
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,
1468 1469
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
	.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,
1482
	.read_optrom		= qla25xx_read_optrom_data,
1483 1484
	.write_optrom		= qla24xx_write_optrom_data,
	.get_flash_version	= qla24xx_get_flash_version,
1485
	.start_scsi		= qla24xx_start_scsi,
1486 1487
};

1488 1489 1490 1491 1492 1493 1494 1495
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,
1496
	.load_risc		= qla81xx_load_risc,
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
	.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,
1511 1512
	.read_nvram		= NULL,
	.write_nvram		= NULL,
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
	.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,
};

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

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

Linus Torvalds's avatar
Linus Torvalds committed
1619
static int
1620
qla2x00_iospace_config(struct qla_hw_data *ha)
Linus Torvalds's avatar
Linus Torvalds committed
1621
{
1622
	resource_size_t pio;
1623
	uint16_t msix;
1624
	int cpus;
Linus Torvalds's avatar
Linus Torvalds committed
1625

1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
	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;

Linus Torvalds's avatar
Linus Torvalds committed
1637 1638
	/* We only need PIO for Flash operations on ISP2312 v2 chips. */
	pio = pci_resource_start(ha->pdev, 0);
1639 1640
	if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
		if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) {
Linus Torvalds's avatar
Linus Torvalds committed
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651
			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;
	}
1652
	ha->pio_address = pio;
Linus Torvalds's avatar
Linus Torvalds committed
1653

1654
skip_pio:
Linus Torvalds's avatar
Linus Torvalds committed
1655
	/* Use MMIO operations for all accesses. */
1656
	if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) {
Linus Torvalds's avatar
Linus Torvalds committed
1657
		qla_printk(KERN_ERR, ha,
1658
		    "region #1 not an MMIO resource (%s), aborting\n",
Linus Torvalds's avatar
Linus Torvalds committed
1659 1660 1661
		    pci_name(ha->pdev));
		goto iospace_error_exit;
	}
1662
	if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) {
Linus Torvalds's avatar
Linus Torvalds committed
1663 1664 1665 1666 1667 1668
		qla_printk(KERN_ERR, ha,
		    "Invalid PCI mem region size (%s), aborting\n",
			pci_name(ha->pdev));
		goto iospace_error_exit;
	}

1669
	ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN);
Linus Torvalds's avatar
Linus Torvalds committed
1670 1671 1672 1673 1674 1675 1676
	if (!ha->iobase) {
		qla_printk(KERN_ERR, ha,
		    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));

		goto iospace_error_exit;
	}

1677
	/* Determine queue resources */
1678
	ha->max_req_queues = ha->max_rsp_queues = 1;
1679
	if ((ql2xmaxqueues <= 1 || ql2xmultique_tag < 1) &&
1680
		(!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
1681 1682 1683 1684 1685 1686 1687
		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;
1688 1689 1690 1691
		/* Max queues are bounded by available msix vectors */
		/* queue 0 uses two msix vectors */
		if (ql2xmultique_tag) {
			cpus = num_online_cpus();
1692
			ha->max_rsp_queues = (ha->msix_count - 1 > cpus) ?
1693 1694 1695
				(cpus + 1) : (ha->msix_count - 1);
			ha->max_req_queues = 2;
		} else if (ql2xmaxqueues > 1) {
1696 1697 1698 1699 1700
			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));
		}
1701 1702
		qla_printk(KERN_INFO, ha,
			"MSI-X vector count: %d\n", msix);
1703 1704
	} else
		qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
1705 1706

mqiobase_exit:
1707
	ha->msix_count = ha->max_rsp_queues + 1;
Linus Torvalds's avatar
Linus Torvalds committed
1708 1709 1710 1711 1712 1713
	return (0);

iospace_error_exit:
	return (-ENOMEM);
}

1714 1715 1716
static void
qla2xxx_scan_start(struct Scsi_Host *shost)
{
1717
	scsi_qla_host_t *vha = shost_priv(shost);
1718

1719 1720 1721
	if (vha->hw->flags.running_gold_fw)
		return;

1722 1723 1724 1725
	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);
1726 1727 1728 1729 1730
}

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

1733
	if (!vha->host)
1734
		return 1;
1735
	if (time > vha->hw->loop_reset_delay * HZ)
1736 1737
		return 1;

1738
	return atomic_read(&vha->loop_state) == LOOP_READY;
1739 1740
}

Linus Torvalds's avatar
Linus Torvalds committed
1741 1742 1743
/*
 * PCI driver interface
 */
1744 1745
static int __devinit
qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
Linus Torvalds's avatar
Linus Torvalds committed
1746
{
1747
	int	ret = -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
1748
	struct Scsi_Host *host;
1749 1750
	scsi_qla_host_t *base_vha = NULL;
	struct qla_hw_data *ha;
1751
	char pci_info[30];
Linus Torvalds's avatar
Linus Torvalds committed
1752
	char fw_str[30];
1753
	struct scsi_host_template *sht;
1754
	int bars, max_id, mem_only = 0;
1755
	uint16_t req_length = 0, rsp_length = 0;
1756 1757
	struct req_que *req = NULL;
	struct rsp_que *rsp = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
1758

1759
	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
1760
	sht = &qla2xxx_driver_template;
1761
	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
1762
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
1763
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
1764
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
1765
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
1766 1767
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001) {
1768
		bars = pci_select_bars(pdev, IORESOURCE_MEM);
1769
		mem_only = 1;
1770 1771
	}

1772 1773 1774 1775 1776 1777 1778
	if (mem_only) {
		if (pci_enable_device_mem(pdev))
			goto probe_out;
	} else {
		if (pci_enable_device(pdev))
			goto probe_out;
	}
1779

1780 1781
	/* This may fail but that's ok */
	pci_enable_pcie_error_reporting(pdev);
1782

1783 1784 1785 1786
	ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL);
	if (!ha) {
		DEBUG(printk("Unable to allocate memory for ha\n"));
		goto probe_out;
Linus Torvalds's avatar
Linus Torvalds committed
1787
	}
1788
	ha->pdev = pdev;
Linus Torvalds's avatar
Linus Torvalds committed
1789 1790

	/* Clear our data area */
1791
	ha->bars = bars;
1792
	ha->mem_only = mem_only;
1793
	spin_lock_init(&ha->hardware_lock);
Linus Torvalds's avatar
Linus Torvalds committed
1794

1795 1796
	/* Set ISP-type information. */
	qla2x00_set_isp_flags(ha);
Linus Torvalds's avatar
Linus Torvalds committed
1797 1798
	/* Configure PCI I/O space */
	ret = qla2x00_iospace_config(ha);
1799
	if (ret)
1800
		goto probe_hw_failed;
Linus Torvalds's avatar
Linus Torvalds committed
1801 1802

	qla_printk(KERN_INFO, ha,
1803 1804
	    "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,
	    ha->iobase);
Linus Torvalds's avatar
Linus Torvalds committed
1805 1806

	ha->prev_topology = 0;
1807
	ha->init_cb_size = sizeof(init_cb_t);
1808
	ha->link_data_rate = PORT_SPEED_UNKNOWN;
1809
	ha->optrom_size = OPTROM_SIZE_2300;
Linus Torvalds's avatar
Linus Torvalds committed
1810

1811
	/* Assign ISP specific operations. */
1812
	max_id = MAX_TARGETS_2200;
Linus Torvalds's avatar
Linus Torvalds committed
1813
	if (IS_QLA2100(ha)) {
1814
		max_id = MAX_TARGETS_2100;
Linus Torvalds's avatar
Linus Torvalds committed
1815
		ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
1816 1817 1818
		req_length = REQUEST_ENTRY_CNT_2100;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1819
		ha->gid_list_info_size = 4;
1820 1821 1822 1823
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1824
		ha->isp_ops = &qla2100_isp_ops;
Linus Torvalds's avatar
Linus Torvalds committed
1825 1826
	} else if (IS_QLA2200(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1827 1828 1829
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1830
		ha->gid_list_info_size = 4;
1831 1832 1833 1834
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1835
		ha->isp_ops = &qla2100_isp_ops;
1836
	} else if (IS_QLA23XX(ha)) {
Linus Torvalds's avatar
Linus Torvalds committed
1837
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1838 1839 1840
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1841
		ha->gid_list_info_size = 6;
1842 1843
		if (IS_QLA2322(ha) || IS_QLA6322(ha))
			ha->optrom_size = OPTROM_SIZE_2322;
1844 1845 1846 1847
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1848
		ha->isp_ops = &qla2300_isp_ops;
1849
	} else if (IS_QLA24XX_TYPE(ha)) {
1850
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1851 1852 1853
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1854
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
1855
		ha->gid_list_info_size = 8;
1856
		ha->optrom_size = OPTROM_SIZE_24XX;
1857
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA24XX;
1858
		ha->isp_ops = &qla24xx_isp_ops;
1859 1860 1861 1862
		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;
1863 1864
	} else if (IS_QLA25XX(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1865 1866 1867
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
1868 1869 1870
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
		ha->gid_list_info_size = 8;
		ha->optrom_size = OPTROM_SIZE_25XX;
1871
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
1872
		ha->isp_ops = &qla25xx_isp_ops;
1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884
		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;
1885
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
1886 1887 1888 1889 1890
		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;
Linus Torvalds's avatar
Linus Torvalds committed
1891 1892
	}

1893
	mutex_init(&ha->vport_lock);
1894 1895 1896
	init_completion(&ha->mbx_cmd_comp);
	complete(&ha->mbx_cmd_comp);
	init_completion(&ha->mbx_intr_comp);
Linus Torvalds's avatar
Linus Torvalds committed
1897

1898
	set_bit(0, (unsigned long *) ha->vp_idx_map);
Linus Torvalds's avatar
Linus Torvalds committed
1899

1900
	qla2x00_config_dma_addressing(ha);
1901
	ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp);
1902
	if (!ret) {
Linus Torvalds's avatar
Linus Torvalds committed
1903 1904 1905
		qla_printk(KERN_WARNING, ha,
		    "[ERROR] Failed to allocate memory for adapter\n");

1906 1907 1908
		goto probe_hw_failed;
	}

1909
	req->max_q_depth = MAX_Q_DEPTH;
1910
	if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU)
1911 1912
		req->max_q_depth = ql2xmaxqdepth;

1913 1914 1915 1916 1917 1918

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

1919
		ret = -ENOMEM;
1920
		qla2x00_mem_free(ha);
1921 1922
		qla2x00_free_req_que(ha, req);
		qla2x00_free_rsp_que(ha, rsp);
1923
		goto probe_hw_failed;
Linus Torvalds's avatar
Linus Torvalds committed
1924 1925
	}

1926 1927 1928
	pci_set_drvdata(pdev, base_vha);

	host = base_vha->host;
1929
	base_vha->req = req;
1930 1931
	host->can_queue = req->length + 128;
	if (IS_QLA2XXX_MIDTYPE(ha))
1932
		base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
1933
	else
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946
		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;

1947 1948 1949
	/* Set up the irqs */
	ret = qla2x00_request_irqs(ha, rsp);
	if (ret)
1950
		goto probe_init_failed;
1951
	/* Alloc arrays of request and response ring ptrs */
1952
que_init:
1953 1954 1955 1956
	if (!qla2x00_alloc_queues(ha)) {
		qla_printk(KERN_WARNING, ha,
		"[ERROR] Failed to allocate memory for queue"
		" pointers\n");
1957
		goto probe_init_failed;
1958 1959 1960
	}
	ha->rsp_q_map[0] = rsp;
	ha->req_q_map[0] = req;
1961 1962 1963 1964
	rsp->req = req;
	req->rsp = rsp;
	set_bit(0, ha->req_qid_map);
	set_bit(0, ha->rsp_qid_map);
1965 1966 1967 1968 1969
	/* 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;
1970
	if (ha->mqenable) {
1971 1972 1973 1974
		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;
1975 1976
	}

1977
	if (qla2x00_initialize_adapter(base_vha)) {
Linus Torvalds's avatar
Linus Torvalds committed
1978 1979 1980 1981 1982
		qla_printk(KERN_WARNING, ha,
		    "Failed to initialize adapter\n");

		DEBUG2(printk("scsi(%ld): Failed to initialize adapter - "
		    "Adapter flags %x.\n",
1983
		    base_vha->host_no, base_vha->device_flags));
Linus Torvalds's avatar
Linus Torvalds committed
1984

1985
		ret = -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
1986 1987 1988
		goto probe_failed;
	}

1989 1990
	if (ha->mqenable) {
		if (qla25xx_setup_mode(base_vha)) {
1991 1992 1993
			qla_printk(KERN_WARNING, ha,
				"Can't create queues, falling back to single"
				" queue mode\n");
1994 1995 1996
			goto que_init;
		}
	}
1997

1998 1999 2000
	if (ha->flags.running_gold_fw)
		goto skip_dpc;

Linus Torvalds's avatar
Linus Torvalds committed
2001 2002 2003
	/*
	 * Startup the kernel thread for this host adapter
	 */
2004
	ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
2005
			"%s_dpc", base_vha->host_str);
2006
	if (IS_ERR(ha->dpc_thread)) {
Linus Torvalds's avatar
Linus Torvalds committed
2007 2008
		qla_printk(KERN_WARNING, ha,
		    "Unable to start DPC thread!\n");
2009
		ret = PTR_ERR(ha->dpc_thread);
Linus Torvalds's avatar
Linus Torvalds committed
2010 2011 2012
		goto probe_failed;
	}

2013
skip_dpc:
2014 2015
	list_add_tail(&base_vha->list, &ha->vp_list);
	base_vha->host->irq = ha->pdev->irq;
Linus Torvalds's avatar
Linus Torvalds committed
2016 2017

	/* Initialized the timer */
2018
	qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL);
Linus Torvalds's avatar
Linus Torvalds committed
2019 2020

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

2023 2024
	base_vha->flags.init_done = 1;
	base_vha->flags.online = 1;
2025

2026 2027 2028 2029
	ret = scsi_add_host(host, &pdev->dev);
	if (ret)
		goto probe_failed;

2030 2031
	ha->isp_ops->enable_intrs(ha);

2032 2033
	scsi_scan_host(host);

2034
	qla2x00_alloc_sysfs_attr(base_vha);
2035

2036
	qla2x00_init_host_attr(base_vha);
2037

2038
	qla2x00_dfs_setup(base_vha);
2039

Linus Torvalds's avatar
Linus Torvalds committed
2040 2041 2042
	qla_printk(KERN_INFO, ha, "\n"
	    " QLogic Fibre Channel HBA Driver: %s\n"
	    "  QLogic %s - %s\n"
2043 2044
	    "  ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
	    qla2x00_version_str, ha->model_number,
2045 2046 2047 2048
	    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));
Linus Torvalds's avatar
Linus Torvalds committed
2049 2050 2051

	return 0;

2052
probe_init_failed:
2053 2054 2055
	qla2x00_free_req_que(ha, req);
	qla2x00_free_rsp_que(ha, rsp);
	ha->max_req_queues = ha->max_rsp_queues = 0;
2056

Linus Torvalds's avatar
Linus Torvalds committed
2057
probe_failed:
2058 2059 2060 2061 2062 2063 2064 2065 2066 2067
	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);
	}

2068
	qla2x00_free_device(base_vha);
Linus Torvalds's avatar
Linus Torvalds committed
2069

2070
	scsi_host_put(base_vha->host);
Linus Torvalds's avatar
Linus Torvalds committed
2071

2072 2073 2074 2075 2076 2077 2078
probe_hw_failed:
	if (ha->iobase)
		iounmap(ha->iobase);

	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
2079

2080
probe_out:
2081
	pci_disable_device(pdev);
2082
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
2083 2084
}

2085
static void
2086
qla2x00_remove_one(struct pci_dev *pdev)
Linus Torvalds's avatar
Linus Torvalds committed
2087
{
2088 2089 2090 2091 2092 2093 2094 2095 2096 2097
	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);
	}
Linus Torvalds's avatar
Linus Torvalds committed
2098

2099
	set_bit(UNLOADING, &base_vha->dpc_flags);
Linus Torvalds's avatar
Linus Torvalds committed
2100

2101 2102
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

2103
	qla2x00_dfs_remove(base_vha);
2104

2105
	qla84xx_put_chip(base_vha);
2106

2107 2108 2109 2110 2111 2112
	/* Disable timer */
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);

	base_vha->flags.online = 0;

2113 2114 2115 2116 2117 2118 2119
	/* Flush the work queue and remove it */
	if (ha->wq) {
		flush_workqueue(ha->wq);
		destroy_workqueue(ha->wq);
		ha->wq = NULL;
	}

2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131
	/* 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);
	}

2132
	qla2x00_free_sysfs_attr(base_vha);
2133

2134
	fc_remove_host(base_vha->host);
2135

2136
	scsi_remove_host(base_vha->host);
Linus Torvalds's avatar
Linus Torvalds committed
2137

2138
	qla2x00_free_device(base_vha);
2139

2140
	scsi_host_put(base_vha->host);
Linus Torvalds's avatar
Linus Torvalds committed
2141

2142 2143
	if (ha->iobase)
		iounmap(ha->iobase);
Linus Torvalds's avatar
Linus Torvalds committed
2144

2145 2146 2147
	if (ha->mqiobase)
		iounmap(ha->mqiobase);

2148 2149 2150
	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
2151

2152
	pci_disable_device(pdev);
Linus Torvalds's avatar
Linus Torvalds committed
2153 2154 2155 2156
	pci_set_drvdata(pdev, NULL);
}

static void
2157
qla2x00_free_device(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
2158
{
2159
	struct qla_hw_data *ha = vha->hw;
Linus Torvalds's avatar
Linus Torvalds committed
2160

2161 2162
	qla25xx_delete_queues(vha);

2163
	if (ha->flags.fce_enabled)
2164
		qla2x00_disable_fce_trace(vha, NULL, NULL);
2165

2166
	if (ha->eft)
2167
		qla2x00_disable_eft_trace(vha);
2168

2169
	/* Stop currently executing firmware. */
2170
	qla2x00_try_to_stop_firmware(vha);
Linus Torvalds's avatar
Linus Torvalds committed
2171

2172 2173
	/* turn-off interrupts on the card */
	if (ha->interrupts_on)
2174
		ha->isp_ops->disable_intrs(ha);
2175

2176
	qla2x00_free_irqs(vha);
Linus Torvalds's avatar
Linus Torvalds committed
2177

2178
	qla2x00_mem_free(ha);
2179 2180

	qla2x00_free_queues(ha);
Linus Torvalds's avatar
Linus Torvalds committed
2181 2182
}

2183
static inline void
2184
qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
2185 2186 2187 2188 2189 2190 2191 2192 2193
    int defer)
{
	struct fc_rport *rport;

	if (!fcport->rport)
		return;

	rport = fcport->rport;
	if (defer) {
2194
		spin_lock_irq(vha->host->host_lock);
2195
		fcport->drport = rport;
2196 2197 2198
		spin_unlock_irq(vha->host->host_lock);
		set_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags);
		qla2xxx_wake_dpc(vha);
2199
	} else
2200 2201 2202
		fc_remote_port_delete(rport);
}

Linus Torvalds's avatar
Linus Torvalds committed
2203 2204 2205 2206 2207 2208 2209 2210 2211
/*
 * qla2x00_mark_device_lost Updates fcport state when device goes offline.
 *
 * Input: ha = adapter block pointer.  fcport = port structure pointer.
 *
 * Return: None.
 *
 * Context:
 */
2212
void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
2213
    int do_login, int defer)
Linus Torvalds's avatar
Linus Torvalds committed
2214
{
2215
	if (atomic_read(&fcport->state) == FCS_ONLINE &&
2216 2217 2218 2219
	    vha->vp_idx == fcport->vp_idx) {
		atomic_set(&fcport->state, FCS_DEVICE_LOST);
		qla2x00_schedule_rport_del(vha, fcport, defer);
	}
2220
	/*
Linus Torvalds's avatar
Linus Torvalds committed
2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
	 * 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) {
2231 2232
		fcport->login_retry = vha->hw->login_retry_count;
		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
Linus Torvalds's avatar
Linus Torvalds committed
2233 2234 2235 2236

		DEBUG(printk("scsi(%ld): Port login retry: "
		    "%02x%02x%02x%02x%02x%02x%02x%02x, "
		    "id = 0x%04x retry cnt=%d\n",
2237
		    vha->host_no,
Linus Torvalds's avatar
Linus Torvalds committed
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
		    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
2265
qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
Linus Torvalds's avatar
Linus Torvalds committed
2266 2267 2268
{
	fc_port_t *fcport;

2269 2270
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
		if (vha->vp_idx != fcport->vp_idx)
Linus Torvalds's avatar
Linus Torvalds committed
2271 2272 2273 2274 2275 2276 2277
			continue;
		/*
		 * No point in marking the device as lost, if the device is
		 * already DEAD.
		 */
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
			continue;
2278 2279 2280 2281 2282
		if (atomic_read(&fcport->state) == FCS_ONLINE) {
			atomic_set(&fcport->state, FCS_DEVICE_LOST);
			qla2x00_schedule_rport_del(vha, fcport, defer);
		} else
			atomic_set(&fcport->state, FCS_DEVICE_LOST);
Linus Torvalds's avatar
Linus Torvalds committed
2283 2284 2285 2286 2287 2288 2289 2290 2291
	}
}

/*
* qla2x00_mem_alloc
*      Allocates adapter memory.
*
* Returns:
*      0  = success.
2292
*      !0  = failure.
Linus Torvalds's avatar
Linus Torvalds committed
2293
*/
2294
static int
2295 2296
qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
	struct req_que **req, struct rsp_que **rsp)
Linus Torvalds's avatar
Linus Torvalds committed
2297 2298 2299
{
	char	name[16];

2300
	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
2301
		&ha->init_cb_dma, GFP_KERNEL);
2302
	if (!ha->init_cb)
2303
		goto fail;
2304

2305 2306 2307
	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
		&ha->gid_list_dma, GFP_KERNEL);
	if (!ha->gid_list)
2308
		goto fail_free_init_cb;
Linus Torvalds's avatar
Linus Torvalds committed
2309

2310 2311
	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
	if (!ha->srb_mempool)
2312
		goto fail_free_gid_list;
2313 2314 2315 2316 2317 2318

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

2319 2320 2321 2322 2323 2324 2325
	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;

2326 2327
	/* Allocate memory for SNS commands */
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
2328
	/* Get consistent memory allocated for SNS commands */
2329
		ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,
2330
		sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL);
2331
		if (!ha->sns_cmd)
2332
			goto fail_dma_pool;
2333
	} else {
2334
	/* Get consistent memory allocated for MS IOCB */
2335
		ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
2336
			&ha->ms_iocb_dma);
2337
		if (!ha->ms_iocb)
2338 2339
			goto fail_dma_pool;
	/* Get consistent memory allocated for CT SNS commands */
2340
		ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,
2341
			sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
2342 2343
		if (!ha->ct_sns)
			goto fail_free_ms_iocb;
Linus Torvalds's avatar
Linus Torvalds committed
2344 2345
	}

2346
	/* Allocate memory for request ring */
2347 2348
	*req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
	if (!*req) {
2349 2350 2351
		DEBUG(printk("Unable to allocate memory for req\n"));
		goto fail_req;
	}
2352 2353 2354 2355 2356
	(*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) {
2357 2358 2359 2360
		DEBUG(printk("Unable to allocate memory for req_ring\n"));
		goto fail_req_ring;
	}
	/* Allocate memory for response ring */
2361 2362 2363 2364
	*rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
	if (!*rsp) {
		qla_printk(KERN_WARNING, ha,
			"Unable to allocate memory for rsp\n");
2365 2366
		goto fail_rsp;
	}
2367 2368 2369 2370 2371 2372 2373 2374
	(*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");
2375 2376
		goto fail_rsp_ring;
	}
2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389
	(*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;
2390

2391 2392 2393 2394 2395 2396 2397 2398
	/* 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;
	}

2399 2400 2401
	INIT_LIST_HEAD(&ha->vp_list);
	return 1;

2402 2403
fail_ex_init_cb:
	kfree(ha->npiv_info);
2404 2405 2406 2407 2408
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;
2409
fail_rsp_ring:
2410
	kfree(*rsp);
2411
fail_rsp:
2412 2413 2414 2415
	dma_free_coherent(&ha->pdev->dev, ((*req)->length + 1) *
		sizeof(request_t), (*req)->ring, (*req)->dma);
	(*req)->ring = NULL;
	(*req)->dma = 0;
2416
fail_req_ring:
2417
	kfree(*req);
2418 2419 2420 2421 2422
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;
2423 2424 2425 2426
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;
2427 2428 2429
fail_dma_pool:
	dma_pool_destroy(ha->s_dma_pool);
	ha->s_dma_pool = NULL;
2430 2431 2432 2433 2434 2435 2436 2437
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,
2438
	ha->gid_list_dma);
2439 2440
	ha->gid_list = NULL;
	ha->gid_list_dma = 0;
2441 2442 2443 2444 2445
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;
2446
fail:
2447
	DEBUG(printk("%s: Memory allocation failure\n", __func__));
2448
	return -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
2449 2450 2451 2452 2453 2454 2455 2456 2457
}

/*
* qla2x00_mem_free
*      Frees all adapter allocated memory.
*
* Input:
*      ha = adapter block pointer.
*/
Adrian Bunk's avatar
Adrian Bunk committed
2458
static void
2459
qla2x00_mem_free(struct qla_hw_data *ha)
Linus Torvalds's avatar
Linus Torvalds committed
2460
{
2461 2462
	if (ha->srb_mempool)
		mempool_destroy(ha->srb_mempool);
Linus Torvalds's avatar
Linus Torvalds committed
2463

2464 2465
	if (ha->fce)
		dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
2466
		ha->fce_dma);
2467

2468 2469 2470
	if (ha->fw_dump) {
		if (ha->eft)
			dma_free_coherent(&ha->pdev->dev,
2471
			ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
2472 2473 2474
		vfree(ha->fw_dump);
	}

2475 2476 2477 2478
	if (ha->dcbx_tlv)
		dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
		    ha->dcbx_tlv, ha->dcbx_tlv_dma);

2479 2480 2481 2482
	if (ha->xgmac_data)
		dma_free_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
		    ha->xgmac_data, ha->xgmac_data_dma);

Linus Torvalds's avatar
Linus Torvalds committed
2483 2484
	if (ha->sns_cmd)
		dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
2485
		ha->sns_cmd, ha->sns_cmd_dma);
Linus Torvalds's avatar
Linus Torvalds committed
2486 2487 2488

	if (ha->ct_sns)
		dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
2489
		ha->ct_sns, ha->ct_sns_dma);
Linus Torvalds's avatar
Linus Torvalds committed
2490

2491 2492 2493
	if (ha->sfp_data)
		dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);

2494 2495 2496
	if (ha->edc_data)
		dma_pool_free(ha->s_dma_pool, ha->edc_data, ha->edc_data_dma);

Linus Torvalds's avatar
Linus Torvalds committed
2497 2498 2499
	if (ha->ms_iocb)
		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);

2500 2501 2502
	if (ha->ex_init_cb)
		dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);

Linus Torvalds's avatar
Linus Torvalds committed
2503 2504 2505 2506 2507
	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,
2508
		ha->gid_list_dma);
Linus Torvalds's avatar
Linus Torvalds committed
2509

2510 2511 2512 2513 2514
	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);
2515
	kfree(ha->npiv_info);
Linus Torvalds's avatar
Linus Torvalds committed
2516

2517
	ha->srb_mempool = NULL;
2518 2519
	ha->eft = NULL;
	ha->eft_dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
2520 2521 2522 2523 2524 2525 2526 2527
	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;
2528 2529
	ha->ex_init_cb = NULL;
	ha->ex_init_cb_dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
2530 2531 2532 2533 2534 2535

	ha->s_dma_pool = NULL;

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

2536 2537 2538 2539
	ha->fw_dump = NULL;
	ha->fw_dumped = 0;
	ha->fw_dump_reading = 0;
}
Linus Torvalds's avatar
Linus Torvalds committed
2540

2541 2542 2543 2544 2545
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;
2546

2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565
	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);

2566 2567
	spin_lock_init(&vha->work_lock);

2568 2569 2570 2571 2572
	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
	return vha;

fail:
	return vha;
Linus Torvalds's avatar
Linus Torvalds committed
2573 2574
}

2575
static struct qla_work_evt *
2576
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
2577 2578 2579
{
	struct qla_work_evt *e;

2580
	e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC);
2581 2582 2583 2584 2585 2586 2587 2588 2589
	if (!e)
		return NULL;

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

2590
static int
2591
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
2592
{
2593
	unsigned long flags;
2594

2595
	spin_lock_irqsave(&vha->work_lock, flags);
2596
	list_add_tail(&e->list, &vha->work_list);
2597
	spin_unlock_irqrestore(&vha->work_lock, flags);
2598
	qla2xxx_wake_dpc(vha);
2599

2600 2601 2602 2603
	return QLA_SUCCESS;
}

int
2604
qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
2605 2606 2607 2608
    u32 data)
{
	struct qla_work_evt *e;

2609
	e = qla2x00_alloc_work(vha, QLA_EVT_AEN);
2610 2611 2612 2613 2614
	if (!e)
		return QLA_FUNCTION_FAILED;

	e->u.aen.code = code;
	e->u.aen.data = data;
2615
	return qla2x00_post_work(vha, e);
2616 2617
}

2618 2619 2620 2621 2622
int
qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
{
	struct qla_work_evt *e;

2623
	e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK);
2624 2625 2626 2627
	if (!e)
		return QLA_FUNCTION_FAILED;

	memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
2628
	return qla2x00_post_work(vha, e);
2629 2630
}

2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655
#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);

void
2656
qla2x00_do_work(struct scsi_qla_host *vha)
2657
{
2658 2659 2660
	struct qla_work_evt *e, *tmp;
	unsigned long flags;
	LIST_HEAD(work);
2661

2662 2663 2664 2665 2666
	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) {
2667 2668 2669 2670
		list_del_init(&e->list);

		switch (e->type) {
		case QLA_EVT_AEN:
2671
			fc_host_post_event(vha->host, fc_get_event_number(),
2672 2673
			    e->u.aen.code, e->u.aen.data);
			break;
2674 2675 2676
		case QLA_EVT_IDC_ACK:
			qla81xx_idc_ack(vha, e->u.idc_ack.mb);
			break;
2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691
		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;
2692 2693 2694
		}
		if (e->flags & QLA_EVT_FLAG_FREE)
			kfree(e);
2695 2696
	}
}
2697

2698 2699 2700 2701 2702 2703
/* Relogins all the fcports of a vport
 * Context: dpc thread
 */
void qla2x00_relogin(struct scsi_qla_host *vha)
{
	fc_port_t       *fcport;
2704
	int status;
2705 2706
	uint16_t        next_loopid = 0;
	struct qla_hw_data *ha = vha->hw;
2707
	uint16_t data[2];
2708 2709 2710 2711 2712 2713 2714 2715 2716

	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) {

2717
			fcport->login_retry--;
2718 2719 2720 2721 2722 2723 2724 2725
			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);

2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737
				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);
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765
			} 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;
2766 2767 2768
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
/**************************************************************************
* 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)
{
2785
	int		rval;
2786 2787
	scsi_qla_host_t *base_vha;
	struct qla_hw_data *ha;
Linus Torvalds's avatar
Linus Torvalds committed
2788

2789 2790
	ha = (struct qla_hw_data *)data;
	base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds's avatar
Linus Torvalds committed
2791 2792 2793

	set_user_nice(current, -20);

2794
	while (!kthread_should_stop()) {
Linus Torvalds's avatar
Linus Torvalds committed
2795 2796
		DEBUG3(printk("qla2x00: DPC handler sleeping\n"));

2797 2798 2799
		set_current_state(TASK_INTERRUPTIBLE);
		schedule();
		__set_current_state(TASK_RUNNING);
Linus Torvalds's avatar
Linus Torvalds committed
2800 2801 2802 2803

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

		/* Initialization not yet finished. Don't do anything yet. */
2804
		if (!base_vha->flags.init_done)
Linus Torvalds's avatar
Linus Torvalds committed
2805 2806
			continue;

2807
		DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
2808 2809 2810 2811 2812 2813 2814 2815

		ha->dpc_active = 1;

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

2816
		qla2x00_do_work(base_vha);
2817

2818 2819
		if (test_and_clear_bit(ISP_ABORT_NEEDED,
						&base_vha->dpc_flags)) {
Linus Torvalds's avatar
Linus Torvalds committed
2820 2821 2822

			DEBUG(printk("scsi(%ld): dpc: sched "
			    "qla2x00_abort_isp ha = %p\n",
2823
			    base_vha->host_no, ha));
Linus Torvalds's avatar
Linus Torvalds committed
2824
			if (!(test_and_set_bit(ABORT_ISP_ACTIVE,
2825
			    &base_vha->dpc_flags))) {
Linus Torvalds's avatar
Linus Torvalds committed
2826

2827
				if (qla2x00_abort_isp(base_vha)) {
Linus Torvalds's avatar
Linus Torvalds committed
2828 2829
					/* failed. retry later */
					set_bit(ISP_ABORT_NEEDED,
2830
					    &base_vha->dpc_flags);
2831
				}
2832 2833
				clear_bit(ABORT_ISP_ACTIVE,
						&base_vha->dpc_flags);
2834 2835
			}

Linus Torvalds's avatar
Linus Torvalds committed
2836
			DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",
2837
			    base_vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
2838 2839
		}

2840 2841 2842
		if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) {
			qla2x00_update_fcports(base_vha);
			clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
2843
		}
2844

2845 2846 2847
		if (test_and_clear_bit(RESET_MARKER_NEEDED,
							&base_vha->dpc_flags) &&
		    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
Linus Torvalds's avatar
Linus Torvalds committed
2848 2849

			DEBUG(printk("scsi(%ld): qla2x00_reset_marker()\n",
2850
			    base_vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
2851

2852 2853
			qla2x00_rst_aen(base_vha);
			clear_bit(RESET_ACTIVE, &base_vha->dpc_flags);
Linus Torvalds's avatar
Linus Torvalds committed
2854 2855 2856
		}

		/* Retry each device up to login retry count */
2857 2858 2859 2860
		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) {
Linus Torvalds's avatar
Linus Torvalds committed
2861 2862

			DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
2863 2864 2865
					base_vha->host_no));
			qla2x00_relogin(base_vha);

Linus Torvalds's avatar
Linus Torvalds committed
2866
			DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
2867
			    base_vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
2868 2869
		}

2870 2871
		if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
							&base_vha->dpc_flags)) {
Linus Torvalds's avatar
Linus Torvalds committed
2872 2873

			DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
2874
				base_vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
2875 2876

			if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE,
2877
			    &base_vha->dpc_flags))) {
Linus Torvalds's avatar
Linus Torvalds committed
2878

2879
				rval = qla2x00_loop_resync(base_vha);
Linus Torvalds's avatar
Linus Torvalds committed
2880

2881 2882
				clear_bit(LOOP_RESYNC_ACTIVE,
						&base_vha->dpc_flags);
Linus Torvalds's avatar
Linus Torvalds committed
2883 2884 2885
			}

			DEBUG(printk("scsi(%ld): qla2x00_loop_resync - end\n",
2886
			    base_vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
2887 2888
		}

2889 2890 2891 2892
		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);
2893 2894
		}

Linus Torvalds's avatar
Linus Torvalds committed
2895
		if (!ha->interrupts_on)
2896
			ha->isp_ops->enable_intrs(ha);
Linus Torvalds's avatar
Linus Torvalds committed
2897

2898 2899 2900
		if (test_and_clear_bit(BEACON_BLINK_NEEDED,
					&base_vha->dpc_flags))
			ha->isp_ops->beacon_blink(base_vha);
2901

2902
		qla2x00_do_dpc_all_vps(base_vha);
2903

Linus Torvalds's avatar
Linus Torvalds committed
2904 2905 2906
		ha->dpc_active = 0;
	} /* End of while(1) */

2907
	DEBUG(printk("scsi(%ld): DPC handler exiting\n", base_vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
2908 2909 2910 2911 2912 2913

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

2914 2915 2916
	/* Cleanup any residual CTX SRBs. */
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

2917 2918 2919 2920
	return 0;
}

void
2921
qla2xxx_wake_dpc(struct scsi_qla_host *vha)
2922
{
2923
	struct qla_hw_data *ha = vha->hw;
2924 2925
	struct task_struct *t = ha->dpc_thread;

2926
	if (!test_bit(UNLOADING, &vha->dpc_flags) && t)
2927
		wake_up_process(t);
Linus Torvalds's avatar
Linus Torvalds committed
2928 2929 2930 2931 2932 2933 2934 2935 2936 2937
}

/*
*  qla2x00_rst_aen
*      Processes asynchronous reset.
*
* Input:
*      ha  = adapter block pointer.
*/
static void
2938
qla2x00_rst_aen(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
2939
{
2940 2941 2942
	if (vha->flags.online && !vha->flags.reset_active &&
	    !atomic_read(&vha->loop_down_timer) &&
	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))) {
Linus Torvalds's avatar
Linus Torvalds committed
2943
		do {
2944
			clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Linus Torvalds's avatar
Linus Torvalds committed
2945 2946 2947 2948 2949

			/*
			 * Issue marker command only when we are going to start
			 * the I/O.
			 */
2950 2951 2952
			vha->marker_needed = 1;
		} while (!atomic_read(&vha->loop_down_timer) &&
		    (test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags)));
Linus Torvalds's avatar
Linus Torvalds committed
2953 2954 2955
	}
}

2956
static void
2957
qla2x00_sp_free_dma(srb_t *sp)
2958 2959 2960 2961
{
	struct scsi_cmnd *cmd = sp->cmd;

	if (sp->flags & SRB_DMA_VALID) {
2962
		scsi_dma_unmap(cmd);
2963 2964
		sp->flags &= ~SRB_DMA_VALID;
	}
2965
	CMD_SP(cmd) = NULL;
2966 2967 2968
}

void
2969
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
2970 2971 2972
{
	struct scsi_cmnd *cmd = sp->cmd;

2973
	qla2x00_sp_free_dma(sp);
2974 2975 2976 2977 2978

	mempool_free(sp, ha->srb_mempool);

	cmd->scsi_done(cmd);
}
2979

Linus Torvalds's avatar
Linus Torvalds committed
2980 2981 2982 2983 2984 2985 2986 2987
/**************************************************************************
*   qla2x00_timer
*
* Description:
*   One second timer
*
* Context: Interrupt
***************************************************************************/
2988
void
2989
qla2x00_timer(scsi_qla_host_t *vha)
Linus Torvalds's avatar
Linus Torvalds committed
2990 2991 2992 2993 2994 2995
{
	unsigned long	cpu_flags = 0;
	fc_port_t	*fcport;
	int		start_dpc = 0;
	int		index;
	srb_t		*sp;
2996
	int		t;
2997
	struct qla_hw_data *ha = vha->hw;
2998
	struct req_que *req;
Linus Torvalds's avatar
Linus Torvalds committed
2999 3000 3001 3002 3003
	/*
	 * 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
3004
	 * the port it marked DEAD.
Linus Torvalds's avatar
Linus Torvalds committed
3005 3006
	 */
	t = 0;
3007
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds's avatar
Linus Torvalds committed
3008 3009 3010 3011 3012 3013 3014 3015
		if (fcport->port_type != FCT_TARGET)
			continue;

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

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

3016
			if (atomic_dec_and_test(&fcport->port_down_timer) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
3017
				atomic_set(&fcport->state, FCS_DEVICE_DEAD);
3018

Linus Torvalds's avatar
Linus Torvalds committed
3019
			DEBUG(printk("scsi(%ld): fcport-%d - port retry count: "
3020
			    "%d remaining\n",
3021
			    vha->host_no,
Linus Torvalds's avatar
Linus Torvalds committed
3022 3023 3024 3025 3026 3027 3028
			    t, atomic_read(&fcport->port_down_timer)));
		}
		t++;
	} /* End of for fcport  */


	/* Loop down handler. */
3029 3030 3031
	if (atomic_read(&vha->loop_down_timer) > 0 &&
	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
		&& vha->flags.online) {
Linus Torvalds's avatar
Linus Torvalds committed
3032

3033 3034
		if (atomic_read(&vha->loop_down_timer) ==
		    vha->loop_down_abort_time) {
Linus Torvalds's avatar
Linus Torvalds committed
3035 3036 3037

			DEBUG(printk("scsi(%ld): Loop Down - aborting the "
			    "queues before time expire\n",
3038
			    vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
3039

3040 3041
			if (!IS_QLA2100(ha) && vha->link_down_timeout)
				atomic_set(&vha->loop_state, LOOP_DEAD);
Linus Torvalds's avatar
Linus Torvalds committed
3042 3043

			/* Schedule an ISP abort to return any tape commands. */
3044
			/* NPIV - scan physical port only */
3045
			if (!vha->vp_idx) {
3046 3047
				spin_lock_irqsave(&ha->hardware_lock,
				    cpu_flags);
3048
				req = ha->req_q_map[0];
3049 3050 3051 3052 3053
				for (index = 1;
				    index < MAX_OUTSTANDING_COMMANDS;
				    index++) {
					fc_port_t *sfcp;

3054
					sp = req->outstanding_cmds[index];
3055 3056
					if (!sp)
						continue;
3057 3058
					if (sp->ctx)
						continue;
3059 3060 3061
					sfcp = sp->fcport;
					if (!(sfcp->flags & FCF_TAPE_PRESENT))
						continue;
3062

3063
					set_bit(ISP_ABORT_NEEDED,
3064
							&vha->dpc_flags);
3065 3066 3067
					break;
				}
				spin_unlock_irqrestore(&ha->hardware_lock,
3068
								cpu_flags);
Linus Torvalds's avatar
Linus Torvalds committed
3069 3070 3071 3072 3073
			}
			start_dpc++;
		}

		/* if the loop has been down for 4 minutes, reinit adapter */
3074 3075 3076
		if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
			if (!(vha->device_flags & DFLG_NO_CABLE) &&
			    !vha->vp_idx) {
Linus Torvalds's avatar
Linus Torvalds committed
3077 3078
				DEBUG(printk("scsi(%ld): Loop down - "
				    "aborting ISP.\n",
3079
				    vha->host_no));
Linus Torvalds's avatar
Linus Torvalds committed
3080 3081 3082
				qla_printk(KERN_WARNING, ha,
				    "Loop down - aborting ISP.\n");

3083
				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Linus Torvalds's avatar
Linus Torvalds committed
3084 3085
			}
		}
3086
		DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
3087 3088
		    vha->host_no,
		    atomic_read(&vha->loop_down_timer)));
Linus Torvalds's avatar
Linus Torvalds committed
3089 3090
	}

3091 3092
	/* Check if beacon LED needs to be blinked */
	if (ha->beacon_blink_led == 1) {
3093
		set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
3094 3095 3096
		start_dpc++;
	}

3097
	/* Process any deferred work. */
3098
	if (!list_empty(&vha->work_list))
3099 3100
		start_dpc++;

Linus Torvalds's avatar
Linus Torvalds committed
3101
	/* Schedule the DPC routine if needed */
3102 3103 3104
	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) ||
Linus Torvalds's avatar
Linus Torvalds committed
3105
	    start_dpc ||
3106 3107 3108 3109 3110
	    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);
Linus Torvalds's avatar
Linus Torvalds committed
3111

3112
	qla2x00_restart_timer(vha, WATCH_INTERVAL);
Linus Torvalds's avatar
Linus Torvalds committed
3113 3114
}

3115 3116
/* Firmware interface routines. */

3117
#define FW_BLOBS	7
3118 3119 3120 3121
#define FW_ISP21XX	0
#define FW_ISP22XX	1
#define FW_ISP2300	2
#define FW_ISP2322	3
3122
#define FW_ISP24XX	4
3123
#define FW_ISP25XX	5
3124
#define FW_ISP81XX	6
3125

3126 3127 3128 3129 3130
#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"
3131
#define FW_FILE_ISP25XX	"ql2500_fw.bin"
3132
#define FW_FILE_ISP81XX	"ql8100_fw.bin"
3133

3134
static DEFINE_MUTEX(qla_fw_lock);
3135 3136

static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
3137 3138 3139 3140 3141
	{ .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, },
3142
	{ .name = FW_FILE_ISP25XX, },
3143
	{ .name = FW_FILE_ISP81XX, },
3144 3145 3146
};

struct fw_blob *
3147
qla2x00_request_firmware(scsi_qla_host_t *vha)
3148
{
3149
	struct qla_hw_data *ha = vha->hw;
3150 3151 3152 3153 3154 3155 3156
	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];
3157
	} else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3158
		blob = &qla_fw_blobs[FW_ISP2300];
3159
	} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
3160
		blob = &qla_fw_blobs[FW_ISP2322];
3161
	} else if (IS_QLA24XX_TYPE(ha)) {
3162
		blob = &qla_fw_blobs[FW_ISP24XX];
3163 3164
	} else if (IS_QLA25XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP25XX];
3165 3166
	} else if (IS_QLA81XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP81XX];
3167 3168
	}

3169
	mutex_lock(&qla_fw_lock);
3170 3171 3172 3173 3174
	if (blob->fw)
		goto out;

	if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
		DEBUG2(printk("scsi(%ld): Failed to load firmware image "
3175
		    "(%s).\n", vha->host_no, blob->name));
3176 3177 3178 3179 3180 3181
		blob->fw = NULL;
		blob = NULL;
		goto out;
	}

out:
3182
	mutex_unlock(&qla_fw_lock);
3183 3184 3185 3186 3187 3188 3189 3190
	return blob;
}

static void
qla2x00_release_firmware(void)
{
	int idx;

3191
	mutex_lock(&qla_fw_lock);
3192 3193 3194
	for (idx = 0; idx < FW_BLOBS; idx++)
		if (qla_fw_blobs[idx].fw)
			release_firmware(qla_fw_blobs[idx].fw);
3195
	mutex_unlock(&qla_fw_lock);
3196 3197
}

3198 3199 3200
static pci_ers_result_t
qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
3201 3202
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);

3203 3204 3205 3206 3207 3208 3209
	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:
3210
		qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221
		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;
3222 3223
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245
	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");
3246
		ha->isp_ops->fw_dump(base_vha, 0);
3247 3248 3249 3250 3251 3252 3253 3254 3255 3256

		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;
3257 3258
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3259 3260 3261 3262 3263 3264
	int rc;

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

3266
	if (rc) {
3267 3268 3269 3270 3271 3272 3273
		qla_printk(KERN_WARNING, ha,
		    "Can't re-enable PCI device after reset.\n");

		return ret;
	}
	pci_set_master(pdev);

3274
	if (ha->isp_ops->pci_config(base_vha))
3275 3276
		return ret;

3277 3278
	set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
	if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS)
3279
		ret =  PCI_ERS_RESULT_RECOVERED;
3280
	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3281 3282 3283 3284 3285 3286 3287

	return ret;
}

static void
qla2xxx_pci_resume(struct pci_dev *pdev)
{
3288 3289
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3290 3291
	int ret;

3292
	ret = qla2x00_wait_for_hba_online(base_vha);
3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307
	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,
};

3308
static struct pci_device_id qla2xxx_pci_tbl[] = {
3309 3310 3311 3312 3313 3314 3315 3316 3317
	{ 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) },
3318
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
3319 3320
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
3321
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
3322
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
3323 3324 3325 3326
	{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);

3327
static struct pci_driver qla2xxx_pci_driver = {
3328
	.name		= QLA2XXX_DRIVER_NAME,
3329 3330 3331
	.driver		= {
		.owner		= THIS_MODULE,
	},
3332
	.id_table	= qla2xxx_pci_tbl,
3333
	.probe		= qla2x00_probe_one,
3334
	.remove		= qla2x00_remove_one,
3335
	.err_handler	= &qla2xxx_err_handler,
3336 3337
};

Linus Torvalds's avatar
Linus Torvalds committed
3338 3339 3340 3341 3342 3343
/**
 * qla2x00_module_init - Module initialization.
 **/
static int __init
qla2x00_module_init(void)
{
3344 3345
	int ret = 0;

Linus Torvalds's avatar
Linus Torvalds committed
3346
	/* Allocate cache for SRBs. */
3347
	srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
3348
	    SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
3349 3350 3351 3352 3353 3354 3355 3356
	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);
3357
	if (ql2xextended_error_logging)
3358 3359
		strcat(qla2x00_version_str, "-debug");

3360 3361
	qla2xxx_transport_template =
	    fc_attach_transport(&qla2xxx_transport_functions);
3362 3363
	if (!qla2xxx_transport_template) {
		kmem_cache_destroy(srb_cachep);
Linus Torvalds's avatar
Linus Torvalds committed
3364
		return -ENODEV;
3365 3366 3367 3368 3369 3370
	}
	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);
Linus Torvalds's avatar
Linus Torvalds committed
3371
		return -ENODEV;
3372
	}
Linus Torvalds's avatar
Linus Torvalds committed
3373

3374 3375
	printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
	    qla2x00_version_str);
3376
	ret = pci_register_driver(&qla2xxx_pci_driver);
3377 3378 3379
	if (ret) {
		kmem_cache_destroy(srb_cachep);
		fc_release_transport(qla2xxx_transport_template);
3380
		fc_release_transport(qla2xxx_transport_vport_template);
3381 3382
	}
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
3383 3384 3385 3386 3387 3388 3389 3390
}

/**
 * qla2x00_module_exit - Module cleanup.
 **/
static void __exit
qla2x00_module_exit(void)
{
3391
	pci_unregister_driver(&qla2xxx_pci_driver);
3392
	qla2x00_release_firmware();
3393
	kmem_cache_destroy(srb_cachep);
Linus Torvalds's avatar
Linus Torvalds committed
3394
	fc_release_transport(qla2xxx_transport_template);
3395
	fc_release_transport(qla2xxx_transport_vport_template);
Linus Torvalds's avatar
Linus Torvalds committed
3396 3397 3398 3399 3400 3401 3402 3403 3404
}

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);
3405 3406 3407 3408 3409
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);
3410
MODULE_FIRMWARE(FW_FILE_ISP25XX);
3411
MODULE_FIRMWARE(FW_FILE_ISP81XX);