qla_os.c 108.8 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
A
Andrew Vasquez 已提交
2
 * QLogic Fibre Channel HBA Driver
3
 * Copyright (c)  2003-2010 QLogic Corporation
L
Linus Torvalds 已提交
4
 *
A
Andrew Vasquez 已提交
5
 * See LICENSE.qla2xxx for copyright and licensing details.
L
Linus Torvalds 已提交
6 7 8 9 10 11
 */
#include "qla_def.h"

#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
12
#include <linux/kthread.h>
13
#include <linux/mutex.h>
14
#include <linux/kobject.h>
15
#include <linux/slab.h>
L
Linus Torvalds 已提交
16 17 18 19 20 21 22 23 24 25 26

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

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

27 28
static int apidev_major;

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

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

L
Linus Torvalds 已提交
39
int ql2xlogintimeout = 20;
40
module_param(ql2xlogintimeout, int, S_IRUGO);
L
Linus Torvalds 已提交
41 42 43
MODULE_PARM_DESC(ql2xlogintimeout,
		"Login timeout value in seconds.");

44
int qlport_down_retry;
45
module_param(qlport_down_retry, int, S_IRUGO);
L
Linus Torvalds 已提交
46
MODULE_PARM_DESC(qlport_down_retry,
47
		"Maximum number of command retries to a port that returns "
L
Linus Torvalds 已提交
48 49 50 51 52 53
		"a PORT-DOWN status.");

int ql2xplogiabsentdevice;
module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xplogiabsentdevice,
		"Option to enable PLOGI to devices that are not present after "
54
		"a Fabric scan.  This is needed for several broken switches. "
L
Linus Torvalds 已提交
55 56 57
		"Default is 0 - no PLOGI. 1 - perfom PLOGI.");

int ql2xloginretrycount = 0;
58
module_param(ql2xloginretrycount, int, S_IRUGO);
L
Linus Torvalds 已提交
59 60 61
MODULE_PARM_DESC(ql2xloginretrycount,
		"Specify an alternate value for the NVRAM login retry count.");

62
int ql2xallocfwdump = 1;
63
module_param(ql2xallocfwdump, int, S_IRUGO);
64 65 66 67 68
MODULE_PARM_DESC(ql2xallocfwdump,
		"Option to enable allocation of memory for a firmware dump "
		"during HBA initialization.  Memory allocation requirements "
		"vary by ISP type.  Default is 1 - allocate memory.");

69
int ql2xextended_error_logging;
70
module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
71
MODULE_PARM_DESC(ql2xextended_error_logging,
72 73 74
		"Option to enable extended error logging, "
		"Default is 0 - no logging. 1 - log errors.");

75
int ql2xshiftctondsd = 6;
76
module_param(ql2xshiftctondsd, int, S_IRUGO);
77 78 79 80
MODULE_PARM_DESC(ql2xshiftctondsd,
		"Set to control shifting of command type processing "
		"based on total number of SG elements.");

L
Linus Torvalds 已提交
81 82
static void qla2x00_free_device(scsi_qla_host_t *);

83
int ql2xfdmienable=1;
84
module_param(ql2xfdmienable, int, S_IRUGO);
85
MODULE_PARM_DESC(ql2xfdmienable,
86 87
		"Enables FDMI registrations. "
		"0 - no FDMI. Default is 1 - perform FDMI.");
88

89 90 91 92 93 94
#define MAX_Q_DEPTH    32
static int ql2xmaxqdepth = MAX_Q_DEPTH;
module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xmaxqdepth,
		"Maximum queue depth to report for target devices.");

95 96 97 98 99 100 101 102 103 104 105 106 107
/* Do not change the value of this after module load */
int ql2xenabledif = 1;
module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenabledif,
		" Enable T10-CRC-DIF "
		" Default is 0 - No DIF Support. 1 - Enable it");

int ql2xenablehba_err_chk;
module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenablehba_err_chk,
		" Enable T10-CRC-DIF Error isolation by HBA"
		" Default is 0 - Error isolation disabled, 1 - Enable it");

108
int ql2xiidmaenable=1;
109
module_param(ql2xiidmaenable, int, S_IRUGO);
110 111 112 113
MODULE_PARM_DESC(ql2xiidmaenable,
		"Enables iIDMA settings "
		"Default is 1 - perform iIDMA. 0 - no iIDMA.");

114
int ql2xmaxqueues = 1;
115
module_param(ql2xmaxqueues, int, S_IRUGO);
116 117
MODULE_PARM_DESC(ql2xmaxqueues,
		"Enables MQ settings "
118 119
		"Default is 1 for single queue. Set it to number "
		"of queues in MQ mode.");
120 121

int ql2xmultique_tag;
122
module_param(ql2xmultique_tag, int, S_IRUGO);
123 124 125 126
MODULE_PARM_DESC(ql2xmultique_tag,
		"Enables CPU affinity settings for the driver "
		"Default is 0 for no affinity of request and response IO. "
		"Set it to 1 to turn on the cpu affinity.");
127 128

int ql2xfwloadbin;
129
module_param(ql2xfwloadbin, int, S_IRUGO);
130 131 132 133 134 135 136
MODULE_PARM_DESC(ql2xfwloadbin,
		"Option to specify location from which to load ISP firmware:\n"
		" 2 -- load firmware via the request_firmware() (hotplug)\n"
		"      interface.\n"
		" 1 -- load firmware from flash.\n"
		" 0 -- use default semantics.\n");

137
int ql2xetsenable;
138
module_param(ql2xetsenable, int, S_IRUGO);
139 140 141 142
MODULE_PARM_DESC(ql2xetsenable,
		"Enables firmware ETS burst."
		"Default is 0 - skip ETS enablement.");

143
int ql2xdbwr = 1;
144
module_param(ql2xdbwr, int, S_IRUGO);
145 146 147 148 149
MODULE_PARM_DESC(ql2xdbwr,
	"Option to specify scheme for request queue posting\n"
	" 0 -- Regular doorbell.\n"
	" 1 -- CAMRAM doorbell (faster).\n");

150
int ql2xtargetreset = 1;
151
module_param(ql2xtargetreset, int, S_IRUGO);
152 153 154 155
MODULE_PARM_DESC(ql2xtargetreset,
		 "Enable target reset."
		 "Default is 1 - use hw defaults.");

156
int ql2xgffidenable;
157
module_param(ql2xgffidenable, int, S_IRUGO);
158 159 160
MODULE_PARM_DESC(ql2xgffidenable,
		"Enables GFF_ID checks of port type. "
		"Default is 0 - Do not use GFF_ID information.");
161

162
int ql2xasynctmfenable;
163
module_param(ql2xasynctmfenable, int, S_IRUGO);
164 165 166
MODULE_PARM_DESC(ql2xasynctmfenable,
		"Enables issue of TM IOCBs asynchronously via IOCB mechanism"
		"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
L
Linus Torvalds 已提交
167
/*
A
Andrew Vasquez 已提交
168
 * SCSI host template entry points
L
Linus Torvalds 已提交
169 170
 */
static int qla2xxx_slave_configure(struct scsi_device * device);
已提交
171
static int qla2xxx_slave_alloc(struct scsi_device *);
172 173
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
static void qla2xxx_scan_start(struct Scsi_Host *);
已提交
174
static void qla2xxx_slave_destroy(struct scsi_device *);
J
Jeff Garzik 已提交
175
static int qla2xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);
L
Linus Torvalds 已提交
176 177
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
178
static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
L
Linus Torvalds 已提交
179 180 181
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);

182
static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
183 184
static int qla2x00_change_queue_type(struct scsi_device *, int);

185
struct scsi_host_template qla2xxx_driver_template = {
L
Linus Torvalds 已提交
186
	.module			= THIS_MODULE,
187
	.name			= QLA2XXX_DRIVER_NAME,
188
	.queuecommand		= qla2xxx_queuecommand,
189 190 191

	.eh_abort_handler	= qla2xxx_eh_abort,
	.eh_device_reset_handler = qla2xxx_eh_device_reset,
192
	.eh_target_reset_handler = qla2xxx_eh_target_reset,
193 194 195 196 197 198 199
	.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,
200 201
	.scan_finished		= qla2xxx_scan_finished,
	.scan_start		= qla2xxx_scan_start,
202 203
	.change_queue_depth	= qla2x00_change_queue_depth,
	.change_queue_type	= qla2x00_change_queue_type,
204 205 206 207 208 209
	.this_id		= -1,
	.cmd_per_lun		= 3,
	.use_clustering		= ENABLE_CLUSTERING,
	.sg_tablesize		= SG_ALL,

	.max_sectors		= 0xFFFF,
210
	.shost_attrs		= qla2x00_host_attrs,
211 212
};

L
Linus Torvalds 已提交
213
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
214
struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
L
Linus Torvalds 已提交
215 216 217 218 219 220

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

221
__inline__ void
222
qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval)
L
Linus Torvalds 已提交
223
{
224 225 226 227 228 229
	init_timer(&vha->timer);
	vha->timer.expires = jiffies + interval * HZ;
	vha->timer.data = (unsigned long)vha;
	vha->timer.function = (void (*)(unsigned long))func;
	add_timer(&vha->timer);
	vha->timer_active = 1;
L
Linus Torvalds 已提交
230 231 232
}

static inline void
233
qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)
L
Linus Torvalds 已提交
234
{
235 236 237 238
	/* Currently used for 82XX only. */
	if (vha->device_flags & DFLG_DEV_FAILED)
		return;

239
	mod_timer(&vha->timer, jiffies + interval * HZ);
L
Linus Torvalds 已提交
240 241
}

A
Adrian Bunk 已提交
242
static __inline__ void
243
qla2x00_stop_timer(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
244
{
245 246
	del_timer_sync(&vha->timer);
	vha->timer_active = 0;
L
Linus Torvalds 已提交
247 248 249 250 251 252
}

static int qla2x00_do_dpc(void *data);

static void qla2x00_rst_aen(scsi_qla_host_t *);

253 254
static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
	struct req_que **, struct rsp_que **);
255
static void qla2x00_free_fw_dump(struct qla_hw_data *);
256 257
static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
L
Linus Torvalds 已提交
258 259

/* -------------------------------------------------------------------------- */
260 261
static int qla2x00_alloc_queues(struct qla_hw_data *ha)
{
262
	ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
263 264 265 266 267 268 269
				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;
	}

270
	ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
				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;
}

288
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
289 290 291 292 293 294 295 296 297 298
{
	if (req && req->ring)
		dma_free_coherent(&ha->pdev->dev,
		(req->length + 1) * sizeof(request_t),
		req->ring, req->dma);

	kfree(req);
	req = NULL;
}

299 300 301 302 303 304 305 306 307 308 309
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;
}

310 311 312 313 314 315
static void qla2x00_free_queues(struct qla_hw_data *ha)
{
	struct req_que *req;
	struct rsp_que *rsp;
	int cnt;

316
	for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
317
		req = ha->req_q_map[cnt];
318
		qla2x00_free_req_que(ha, req);
319 320 321
	}
	kfree(ha->req_q_map);
	ha->req_q_map = NULL;
322 323 324 325 326 327 328

	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;
329 330
}

331 332 333 334 335 336
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;

337 338 339 340 341
	if (!(ha->fw_attributes & BIT_6)) {
		qla_printk(KERN_INFO, ha,
			"Firmware is not multi-queue capable\n");
		goto fail;
	}
342 343 344 345 346 347 348 349 350 351
	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;
		}
352
		ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
353 354 355 356 357 358 359 360 361 362
		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;
			}
		}
363 364
		ha->flags.cpu_affinity_enabled = 1;

365 366 367 368 369 370 371 372
		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);
373 374
	destroy_workqueue(ha->wq);
	ha->wq = NULL;
375 376
fail:
	ha->mqenable = 0;
377 378 379
	kfree(ha->req_q_map);
	kfree(ha->rsp_q_map);
	ha->max_req_queues = ha->max_rsp_queues = 1;
380 381 382
	return 1;
}

L
Linus Torvalds 已提交
383
static char *
384
qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str)
L
Linus Torvalds 已提交
385
{
386
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
	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);
}

407
static char *
408
qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
409 410
{
	static char *pci_bus_modes[] = { "33", "66", "100", "133", };
411
	struct qla_hw_data *ha = vha->hw;
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
	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)
428
			strcat(str, "2.5GT/s ");
429
		else if (lspeed == 2)
430
			strcat(str, "5.0GT/s ");
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
		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;
}

458
static char *
459
qla2x00_fw_version_str(struct scsi_qla_host *vha, char *str)
L
Linus Torvalds 已提交
460 461
{
	char un_str[10];
462
	struct qla_hw_data *ha = vha->hw;
A
Andrew Vasquez 已提交
463

L
Linus Torvalds 已提交
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
	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);
}

497
static char *
498
qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
499
{
500
	struct qla_hw_data *ha = vha->hw;
501

502 503
	sprintf(str, "%d.%02d.%02d (%x)", ha->fw_major_version,
	    ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes);
504 505 506 507
	return str;
}

static inline srb_t *
508
qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
509
	struct scsi_cmnd *cmd)
510 511
{
	srb_t *sp;
512
	struct qla_hw_data *ha = vha->hw;
513 514 515 516 517

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

518
	atomic_set(&sp->ref_count, 1);
519 520 521 522
	sp->fcport = fcport;
	sp->cmd = cmd;
	sp->flags = 0;
	CMD_SP(cmd) = (void *)sp;
523
	sp->ctx = NULL;
524 525 526 527

	return sp;
}

L
Linus Torvalds 已提交
528
static int
529
qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
530
{
531
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
532
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
533
	struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
534 535
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
536 537 538
	srb_t *sp;
	int rval;

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

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

553 554 555 556 557 558 559 560
	if (!vha->flags.difdix_supported &&
		scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
			DEBUG2(qla_printk(KERN_ERR, ha,
			    "DIF Cap Not Reg, fail DIF capable cmd's:%x\n",
			    cmd->cmnd[0]));
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
	}
561 562
	if (atomic_read(&fcport->state) != FCS_ONLINE) {
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
563
			atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
564 565 566
			cmd->result = DID_NO_CONNECT << 16;
			goto qc24_fail_command;
		}
567
		goto qc24_target_busy;
568 569
	}

570
	sp = qla2x00_get_new_sp(base_vha, fcport, cmd);
571
	if (!sp)
572
		goto qc24_host_busy;
573

574
	rval = ha->isp_ops->start_scsi(sp);
575 576 577 578 579 580
	if (rval != QLA_SUCCESS)
		goto qc24_host_busy_free_sp;

	return 0;

qc24_host_busy_free_sp:
581 582
	qla2x00_sp_free_dma(sp);
	mempool_free(sp, ha->srb_mempool);
583

584
qc24_host_busy:
585 586
	return SCSI_MLQUEUE_HOST_BUSY;

587 588 589
qc24_target_busy:
	return SCSI_MLQUEUE_TARGET_BUSY;

590
qc24_fail_command:
591
	cmd->scsi_done(cmd);
592 593 594 595

	return 0;
}

L
Linus Torvalds 已提交
596 597 598 599 600 601 602 603 604 605 606 607 608
/*
 * 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
609
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
L
Linus Torvalds 已提交
610
{
611 612
#define ABORT_POLLING_PERIOD	1000
#define ABORT_WAIT_ITER		((10 * 1000) / (ABORT_POLLING_PERIOD))
已提交
613
	unsigned long wait_iter = ABORT_WAIT_ITER;
614 615
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
已提交
616
	int ret = QLA_SUCCESS;
L
Linus Torvalds 已提交
617

618 619 620 621 622
	if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
		DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n"));
		return ret;
	}

623
	while (CMD_SP(cmd) && wait_iter--) {
624
		msleep(ABORT_POLLING_PERIOD);
已提交
625 626 627
	}
	if (CMD_SP(cmd))
		ret = QLA_FUNCTION_FAILED;
L
Linus Torvalds 已提交
628

已提交
629
	return ret;
L
Linus Torvalds 已提交
630 631 632 633
}

/*
 * qla2x00_wait_for_hba_online
A
Andrew Vasquez 已提交
634
 *    Wait till the HBA is online after going through
L
Linus Torvalds 已提交
635 636 637 638 639
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline
 *
 * Input:
 *     ha - pointer to host adapter structure
A
Andrew Vasquez 已提交
640 641
 *
 * Note:
L
Linus Torvalds 已提交
642 643 644 645 646 647 648
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online) : 0
 *    Failed  (Adapter is offline/disabled) : 1
 */
649
int
650
qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
651
{
652 653
	int		return_status;
	unsigned long	wait_online;
654 655
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
656

A
Andrew Vasquez 已提交
657
	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
658 659 660 661
	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
	    ha->dpc_active) && time_before(jiffies, wait_online)) {
L
Linus Torvalds 已提交
662 663 664

		msleep(1000);
	}
665
	if (base_vha->flags.online)
A
Andrew Vasquez 已提交
666
		return_status = QLA_SUCCESS;
L
Linus Torvalds 已提交
667 668 669 670 671 672
	else
		return_status = QLA_FUNCTION_FAILED;

	return (return_status);
}

673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
/*
 * qla2x00_wait_for_reset_ready
 *    Wait till the HBA is online after going through
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline or flash
 *    operations are in progress.
 *
 * Input:
 *     ha - pointer to host adapter structure
 *
 * Note:
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online/no flash ops) : 0
 *    Failed  (Adapter is offline/disabled/flash ops in progress) : 1
 */
691
static int
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha)
{
	int		return_status;
	unsigned long	wait_online;
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);

	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
	    ha->optrom_state != QLA_SWAITING ||
	    ha->dpc_active) && time_before(jiffies, wait_online))
		msleep(1000);

	if (base_vha->flags.online &&  ha->optrom_state == QLA_SWAITING)
		return_status = QLA_SUCCESS;
	else
		return_status = QLA_FUNCTION_FAILED;

	DEBUG2(printk("%s return_status=%d\n", __func__, return_status));

	return return_status;
}

717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
int
qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
{
	int		return_status;
	unsigned long	wait_reset;
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);

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

		msleep(1000);

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

	return return_status;
}

L
Linus Torvalds 已提交
745 746 747
/*
 * qla2x00_wait_for_loop_ready
 *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
A
Andrew Vasquez 已提交
748
 *    to be in LOOP_READY state.
L
Linus Torvalds 已提交
749 750
 * Input:
 *     ha - pointer to host adapter structure
A
Andrew Vasquez 已提交
751 752
 *
 * Note:
L
Linus Torvalds 已提交
753 754
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
A
Andrew Vasquez 已提交
755
 *
L
Linus Torvalds 已提交
756 757 758 759 760
 *
 * Return:
 *    Success (LOOP_READY) : 0
 *    Failed  (LOOP_NOT_READY) : 1
 */
A
Andrew Vasquez 已提交
761
static inline int
762
qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
763 764 765
{
	int 	 return_status = QLA_SUCCESS;
	unsigned long loop_timeout ;
766 767
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
768 769

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

772 773 774 775
	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) {
776 777 778
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
L
Linus Torvalds 已提交
779 780 781 782 783 784
		msleep(1000);
		if (time_after_eq(jiffies, loop_timeout)) {
			return_status = QLA_FUNCTION_FAILED;
			break;
		}
	}
A
Andrew Vasquez 已提交
785
	return (return_status);
L
Linus Torvalds 已提交
786 787
}

788 789 790 791 792 793
static void
sp_get(struct srb *sp)
{
	atomic_inc(&sp->ref_count);
}

L
Linus Torvalds 已提交
794 795 796 797 798 799 800 801 802 803 804 805 806
/**************************************************************************
* 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:
807
*    Only return FAILED if command not returned by firmware.
L
Linus Torvalds 已提交
808
**************************************************************************/
809
static int
L
Linus Torvalds 已提交
810 811
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
{
812
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
已提交
813
	srb_t *sp;
814
	int ret;
已提交
815
	unsigned int id, lun;
816
	unsigned long flags;
817
	int wait = 0;
818
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
819

已提交
820
	if (!CMD_SP(cmd))
821
		return SUCCESS;
L
Linus Torvalds 已提交
822

823 824 825 826 827
	ret = fc_block_scsi_eh(cmd);
	if (ret != 0)
		return ret;
	ret = SUCCESS;

已提交
828 829
	id = cmd->device->id;
	lun = cmd->device->lun;
L
Linus Torvalds 已提交
830

831
	spin_lock_irqsave(&ha->hardware_lock, flags);
832 833 834 835 836
	sp = (srb_t *) CMD_SP(cmd);
	if (!sp) {
		spin_unlock_irqrestore(&ha->hardware_lock, flags);
		return SUCCESS;
	}
L
Linus Torvalds 已提交
837

838 839
	DEBUG2(printk("%s(%ld): aborting sp %p from RISC.",
	    __func__, vha->host_no, sp));
840

841 842
	/* Get a reference to the sp and drop the lock.*/
	sp_get(sp);
843

844
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
845 846 847 848 849 850 851 852 853 854
	if (ha->isp_ops->abort_command(sp)) {
		DEBUG2(printk("%s(%ld): abort_command "
		"mbx failed.\n", __func__, vha->host_no));
		ret = FAILED;
	} else {
		DEBUG3(printk("%s(%ld): abort_command "
		"mbx success.\n", __func__, vha->host_no));
		wait = 1;
	}
	qla2x00_sp_compl(ha, sp);
L
Linus Torvalds 已提交
855

已提交
856
	/* Wait for the command to be returned. */
857
	if (wait) {
858
		if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
A
Andrew Vasquez 已提交
859
			qla_printk(KERN_ERR, ha,
860 861
			    "scsi(%ld:%d:%d): Abort handler timed out -- %x.\n",
			    vha->host_no, id, lun, ret);
862
			ret = FAILED;
已提交
863
		}
L
Linus Torvalds 已提交
864 865
	}

A
Andrew Vasquez 已提交
866
	qla_printk(KERN_INFO, ha,
867 868
	    "scsi(%ld:%d:%d): Abort command issued -- %d %x.\n",
	    vha->host_no, id, lun, wait, ret);
L
Linus Torvalds 已提交
869

已提交
870 871
	return ret;
}
L
Linus Torvalds 已提交
872

873
int
874
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
875
	unsigned int l, enum nexus_wait_type type)
已提交
876
{
877
	int cnt, match, status;
878
	unsigned long flags;
879
	struct qla_hw_data *ha = vha->hw;
880
	struct req_que *req;
881
	srb_t *sp;
L
Linus Torvalds 已提交
882

883
	status = QLA_SUCCESS;
884

885
	spin_lock_irqsave(&ha->hardware_lock, flags);
886
	req = vha->req;
887 888 889 890
	for (cnt = 1; status == QLA_SUCCESS &&
		cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
		sp = req->outstanding_cmds[cnt];
		if (!sp)
891
			continue;
892
		if ((sp->ctx) && !IS_PROT_IO(sp))
893
			continue;
894 895 896 897 898 899 900 901 902 903 904 905 906 907
		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;
908
		}
909 910 911 912 913 914
		if (!match)
			continue;

		spin_unlock_irqrestore(&ha->hardware_lock, flags);
		status = qla2x00_eh_wait_on_command(sp->cmd);
		spin_lock_irqsave(&ha->hardware_lock, flags);
L
Linus Torvalds 已提交
915
	}
916
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
917 918

	return status;
L
Linus Torvalds 已提交
919 920
}

921 922 923 924 925 926
static char *reset_errors[] = {
	"HBA not online",
	"HBA not ready",
	"Task management failed",
	"Waiting for command completions",
};
L
Linus Torvalds 已提交
927

928
static int
929
__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
930
    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int))
L
Linus Torvalds 已提交
931
{
932
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
933
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
934
	int err;
L
Linus Torvalds 已提交
935

936
	if (!fcport)
937
		return FAILED;
L
Linus Torvalds 已提交
938

939 940 941 942
	err = fc_block_scsi_eh(cmd);
	if (err != 0)
		return err;

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

946
	err = 0;
947
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
948 949
		goto eh_reset_failed;
	err = 1;
950
	if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS)
951 952
		goto eh_reset_failed;
	err = 2;
953 954
	if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
		!= QLA_SUCCESS)
955 956
		goto eh_reset_failed;
	err = 3;
957
	if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id,
958
	    cmd->device->lun, type) != QLA_SUCCESS)
959 960
		goto eh_reset_failed;

961 962
	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
	    vha->host_no, cmd->device->id, cmd->device->lun, name);
963 964 965

	return SUCCESS;

966
eh_reset_failed:
967 968
	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,
969 970 971
	    reset_errors[err]);
	return FAILED;
}
L
Linus Torvalds 已提交
972

973 974 975
static int
qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
{
976 977
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
978

979 980
	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
	    ha->isp_ops->lun_reset);
L
Linus Torvalds 已提交
981 982 983
}

static int
984
qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
L
Linus Torvalds 已提交
985
{
986 987
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
988

989 990
	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
	    ha->isp_ops->target_reset);
L
Linus Torvalds 已提交
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
}

/**************************************************************************
* 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).
*
**************************************************************************/
1008
static int
L
Linus Torvalds 已提交
1009 1010
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
{
1011
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1012
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1013
	int ret = FAILED;
已提交
1014 1015 1016 1017
	unsigned int id, lun;

	id = cmd->device->id;
	lun = cmd->device->lun;
L
Linus Torvalds 已提交
1018

1019
	if (!fcport)
已提交
1020
		return ret;
L
Linus Torvalds 已提交
1021

1022 1023 1024 1025 1026
	ret = fc_block_scsi_eh(cmd);
	if (ret != 0)
		return ret;
	ret = FAILED;

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

1030
	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
L
Linus Torvalds 已提交
1031
		DEBUG2(printk("%s failed:board disabled\n",__func__));
已提交
1032
		goto eh_bus_reset_done;
L
Linus Torvalds 已提交
1033 1034
	}

1035 1036
	if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) {
		if (qla2x00_loop_reset(vha) == QLA_SUCCESS)
已提交
1037
			ret = SUCCESS;
L
Linus Torvalds 已提交
1038
	}
已提交
1039 1040
	if (ret == FAILED)
		goto eh_bus_reset_done;
L
Linus Torvalds 已提交
1041

1042
	/* Flush outstanding commands. */
1043
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) !=
1044
	    QLA_SUCCESS)
1045
		ret = FAILED;
L
Linus Torvalds 已提交
1046

已提交
1047
eh_bus_reset_done:
1048
	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
已提交
1049
	    (ret == FAILED) ? "failed" : "succeded");
L
Linus Torvalds 已提交
1050

已提交
1051
	return ret;
L
Linus Torvalds 已提交
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
}

/**************************************************************************
* 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:
**************************************************************************/
1069
static int
L
Linus Torvalds 已提交
1070 1071
qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
{
1072
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
1073
	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
1074
	struct qla_hw_data *ha = vha->hw;
1075
	int ret = FAILED;
已提交
1076
	unsigned int id, lun;
1077
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
1078

已提交
1079 1080 1081
	id = cmd->device->id;
	lun = cmd->device->lun;

1082
	if (!fcport)
已提交
1083
		return ret;
L
Linus Torvalds 已提交
1084

1085 1086 1087 1088 1089
	ret = fc_block_scsi_eh(cmd);
	if (ret != 0)
		return ret;
	ret = FAILED;

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

1093
	if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS)
已提交
1094
		goto eh_host_reset_lock;
L
Linus Torvalds 已提交
1095 1096 1097

	/*
	 * Fixme-may be dpc thread is active and processing
A
Andrew Vasquez 已提交
1098
	 * loop_resync,so wait a while for it to
L
Linus Torvalds 已提交
1099 1100 1101 1102 1103
	 * 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.
	 */
1104 1105 1106
	qla2x00_wait_for_loop_ready(vha);
	if (vha != base_vha) {
		if (qla2x00_vp_abort_isp(vha))
已提交
1107
			goto eh_host_reset_lock;
1108
	} else {
1109 1110 1111 1112 1113 1114 1115 1116
		if (IS_QLA82XX(vha->hw)) {
			if (!qla82xx_fcoe_ctx_reset(vha)) {
				/* Ctx reset success */
				ret = SUCCESS;
				goto eh_host_reset_lock;
			}
			/* fall thru if ctx reset failed */
		}
1117 1118 1119
		if (ha->wq)
			flush_workqueue(ha->wq);

1120
		set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
1121
		if (ha->isp_ops->abort_isp(base_vha)) {
1122 1123 1124 1125 1126 1127 1128 1129
			clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
			/* failed. schedule dpc to try */
			set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);

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

1132
	/* Waiting for command to be returned to OS.*/
1133
	if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) ==
1134
		QLA_SUCCESS)
已提交
1135
		ret = SUCCESS;
L
Linus Torvalds 已提交
1136

已提交
1137 1138 1139
eh_host_reset_lock:
	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
	    (ret == FAILED) ? "failed" : "succeded");
L
Linus Torvalds 已提交
1140

已提交
1141 1142
	return ret;
}
L
Linus Torvalds 已提交
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153

/*
* qla2x00_loop_reset
*      Issue loop reset.
*
* Input:
*      ha = adapter block pointer.
*
* Returns:
*      0 = success
*/
1154
int
1155
qla2x00_loop_reset(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
1156
{
1157
	int ret;
1158
	struct fc_port *fcport;
1159
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
1160

1161
	if (ql2xtargetreset == 1 && ha->flags.enable_target_reset) {
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
		list_for_each_entry(fcport, &vha->vp_fcports, list) {
			if (fcport->port_type != FCT_TARGET)
				continue;

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

1175
	if (ha->flags.enable_lip_full_login && !IS_QLA8XXX_TYPE(ha)) {
1176
		ret = qla2x00_full_login_lip(vha);
1177
		if (ret != QLA_SUCCESS) {
1178
			DEBUG2_3(printk("%s(%ld): failed: "
1179
			    "full_login_lip=%d.\n", __func__, vha->host_no,
1180
			    ret));
1181 1182 1183 1184 1185
		}
		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);
1186 1187
	}

1188
	if (ha->flags.enable_lip_reset) {
1189
		ret = qla2x00_lip_reset(vha);
1190
		if (ret != QLA_SUCCESS) {
1191
			DEBUG2_3(printk("%s(%ld): failed: "
1192 1193 1194
			    "lip_reset=%d.\n", __func__, vha->host_no, ret));
		} else
			qla2x00_wait_for_loop_ready(vha);
L
Linus Torvalds 已提交
1195 1196 1197
	}

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

1200
	return QLA_SUCCESS;
L
Linus Torvalds 已提交
1201 1202
}

1203
void
1204
qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
1205
{
1206
	int que, cnt;
1207 1208
	unsigned long flags;
	srb_t *sp;
1209
	struct srb_ctx *ctx;
1210
	struct qla_hw_data *ha = vha->hw;
1211
	struct req_que *req;
1212 1213

	spin_lock_irqsave(&ha->hardware_lock, flags);
1214
	for (que = 0; que < ha->max_req_queues; que++) {
1215
		req = ha->req_q_map[que];
1216 1217 1218 1219
		if (!req)
			continue;
		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
			sp = req->outstanding_cmds[cnt];
1220
			if (sp) {
1221
				req->outstanding_cmds[cnt] = NULL;
1222
				if (!sp->ctx ||
1223 1224
					(sp->flags & SRB_FCP_CMND_DMA_VALID) ||
					IS_PROT_IO(sp)) {
1225 1226 1227 1228
					sp->cmd->result = res;
					qla2x00_sp_compl(ha, sp);
				} else {
					ctx = sp->ctx;
1229 1230
					if (ctx->type == SRB_LOGIN_CMD ||
					    ctx->type == SRB_LOGOUT_CMD) {
1231
						ctx->u.iocb_cmd->free(sp);
1232
					} else {
1233
						struct fc_bsg_job *bsg_job =
1234
						    ctx->u.bsg_job;
1235 1236
						if (bsg_job->request->msgcode
						    == FC_BSG_HST_CT)
1237
							kfree(sp->fcport);
1238 1239
						bsg_job->req->errors = 0;
						bsg_job->reply->result = res;
1240
						bsg_job->job_done(bsg_job);
1241
						kfree(sp->ctx);
1242
						mempool_free(sp,
1243
							ha->srb_mempool);
1244
					}
1245
				}
1246
			}
1247 1248 1249 1250 1251
		}
	}
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

已提交
1252 1253
static int
qla2xxx_slave_alloc(struct scsi_device *sdev)
L
Linus Torvalds 已提交
1254
{
1255
	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
L
Linus Torvalds 已提交
1256

1257
	if (!rport || fc_remote_port_chkready(rport))
已提交
1258
		return -ENXIO;
1259

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

已提交
1262 1263
	return 0;
}
L
Linus Torvalds 已提交
1264

已提交
1265 1266 1267
static int
qla2xxx_slave_configure(struct scsi_device *sdev)
{
1268
	scsi_qla_host_t *vha = shost_priv(sdev->host);
1269
	struct req_que *req = vha->req;
已提交
1270

已提交
1271
	if (sdev->tagged_supported)
1272
		scsi_activate_tcq(sdev, req->max_q_depth);
已提交
1273
	else
1274
		scsi_deactivate_tcq(sdev, req->max_q_depth);
已提交
1275 1276
	return 0;
}
L
Linus Torvalds 已提交
1277

已提交
1278 1279 1280 1281
static void
qla2xxx_slave_destroy(struct scsi_device *sdev)
{
	sdev->hostdata = NULL;
L
Linus Torvalds 已提交
1282 1283
}

1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
{
	fc_port_t *fcport = (struct fc_port *) sdev->hostdata;

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

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

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

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

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

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

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

1322
static int
1323
qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
1324
{
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
	switch (reason) {
	case SCSI_QDEPTH_DEFAULT:
		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
		break;
	case SCSI_QDEPTH_QFULL:
		qla2x00_handle_queue_full(sdev, qdepth);
		break;
	case SCSI_QDEPTH_RAMP_UP:
		qla2x00_adjust_sdev_qdepth_up(sdev, qdepth);
		break;
	default:
1336
		return -EOPNOTSUPP;
1337
	}
1338

1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
	return sdev->queue_depth;
}

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

	return tag_type;
}

L
Linus Torvalds 已提交
1357 1358 1359 1360 1361 1362 1363 1364
/**
 * 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
1365
qla2x00_config_dma_addressing(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
1366
{
1367
	/* Assume a 32bit DMA mask. */
L
Linus Torvalds 已提交
1368 1369
	ha->flags.enable_64bit_addressing = 0;

1370
	if (!dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
1371 1372
		/* Any upper-dword bits set? */
		if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
1373
		    !pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
1374
			/* Ok, a 64bit DMA mask is applicable. */
L
Linus Torvalds 已提交
1375
			ha->flags.enable_64bit_addressing = 1;
1376 1377
			ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
			ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64;
1378
			return;
L
Linus Torvalds 已提交
1379 1380
		}
	}
1381

1382 1383
	dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32));
	pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(32));
L
Linus Torvalds 已提交
1384 1385
}

1386
static void
1387
qla2x00_enable_intrs(struct qla_hw_data *ha)
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
{
	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
1402
qla2x00_disable_intrs(struct qla_hw_data *ha)
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
{
	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
1416
qla24xx_enable_intrs(struct qla_hw_data *ha)
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
{
	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
1429
qla24xx_disable_intrs(struct qla_hw_data *ha)
1430 1431 1432 1433
{
	unsigned long flags = 0;
	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

1434 1435
	if (IS_NOPOLLING_TYPE(ha))
		return;
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
	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,
1458 1459
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
	.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,
1475
	.start_scsi		= qla2x00_start_scsi,
1476
	.abort_isp		= qla2x00_abort_isp,
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
};

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,
1494 1495
	.target_reset		= qla2x00_abort_target,
	.lun_reset		= qla2x00_lun_reset,
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
	.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,
1511
	.start_scsi		= qla2x00_start_scsi,
1512
	.abort_isp		= qla2x00_abort_isp,
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
};

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,
1530 1531
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
	.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,
1547
	.start_scsi		= qla24xx_start_scsi,
1548
	.abort_isp		= qla2x00_abort_isp,
1549 1550
};

1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565
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,
1566 1567
	.target_reset		= qla24xx_abort_target,
	.lun_reset		= qla24xx_lun_reset,
1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579
	.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,
1580
	.read_optrom		= qla25xx_read_optrom_data,
1581 1582
	.write_optrom		= qla24xx_write_optrom_data,
	.get_flash_version	= qla24xx_get_flash_version,
1583
	.start_scsi		= qla24xx_dif_start_scsi,
1584
	.abort_isp		= qla2x00_abort_isp,
1585 1586
};

1587 1588 1589 1590 1591 1592 1593 1594
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,
1595
	.load_risc		= qla81xx_load_risc,
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
	.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,
1610 1611
	.read_nvram		= NULL,
	.write_nvram		= NULL,
1612 1613 1614 1615 1616 1617 1618
	.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,
1619
	.start_scsi		= qla24xx_dif_start_scsi,
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
	.abort_isp		= qla2x00_abort_isp,
};

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

1659
static inline void
1660
qla2x00_set_isp_flags(struct qla_hw_data *ha)
1661 1662 1663 1664 1665 1666
{
	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;
1667
		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
1668 1669 1670 1671
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2200:
		ha->device_type |= DT_ISP2200;
		ha->device_type &= ~DT_EXTENDED_IDS;
1672
		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
1673 1674 1675
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2300:
		ha->device_type |= DT_ISP2300;
1676
		ha->device_type |= DT_ZIO_SUPPORTED;
1677
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1678 1679 1680
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2312:
		ha->device_type |= DT_ISP2312;
1681
		ha->device_type |= DT_ZIO_SUPPORTED;
1682
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1683 1684 1685
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2322:
		ha->device_type |= DT_ISP2322;
1686
		ha->device_type |= DT_ZIO_SUPPORTED;
1687 1688 1689
		if (ha->pdev->subsystem_vendor == 0x1028 &&
		    ha->pdev->subsystem_device == 0x0170)
			ha->device_type |= DT_OEM_001;
1690
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1691 1692 1693
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP6312:
		ha->device_type |= DT_ISP6312;
1694
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1695 1696 1697
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP6322:
		ha->device_type |= DT_ISP6322;
1698
		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
1699 1700 1701
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2422:
		ha->device_type |= DT_ISP2422;
1702
		ha->device_type |= DT_ZIO_SUPPORTED;
1703
		ha->device_type |= DT_FWI2;
1704
		ha->device_type |= DT_IIDMA;
1705
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1706 1707 1708
		break;
	case PCI_DEVICE_ID_QLOGIC_ISP2432:
		ha->device_type |= DT_ISP2432;
1709
		ha->device_type |= DT_ZIO_SUPPORTED;
1710
		ha->device_type |= DT_FWI2;
1711
		ha->device_type |= DT_IIDMA;
1712
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1713
		break;
1714 1715 1716 1717 1718 1719 1720
	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;
1721 1722
	case PCI_DEVICE_ID_QLOGIC_ISP5422:
		ha->device_type |= DT_ISP5422;
1723
		ha->device_type |= DT_FWI2;
1724
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1725
		break;
1726 1727
	case PCI_DEVICE_ID_QLOGIC_ISP5432:
		ha->device_type |= DT_ISP5432;
1728
		ha->device_type |= DT_FWI2;
1729
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1730
		break;
1731 1732 1733 1734 1735
	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;
1736
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
1737
		break;
1738 1739 1740 1741 1742 1743 1744
	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;
1745 1746 1747 1748 1749 1750 1751 1752
	case PCI_DEVICE_ID_QLOGIC_ISP8021:
		ha->device_type |= DT_ISP8021;
		ha->device_type |= DT_ZIO_SUPPORTED;
		ha->device_type |= DT_FWI2;
		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
		/* Initialize 82XX ISP flags */
		qla82xx_init_flags(ha);
		break;
1753
	}
1754

1755 1756 1757 1758 1759 1760
	if (IS_QLA82XX(ha))
		ha->port_no = !(ha->portnum & 1);
	else
		/* Get adapter physical port no from interrupt pin register. */
		pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no);

1761 1762 1763 1764
	if (ha->port_no & 1)
		ha->flags.port0 = 1;
	else
		ha->flags.port0 = 0;
1765 1766
}

L
Linus Torvalds 已提交
1767
static int
1768
qla2x00_iospace_config(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
1769
{
1770
	resource_size_t pio;
1771
	uint16_t msix;
1772
	int cpus;
L
Linus Torvalds 已提交
1773

1774 1775 1776
	if (IS_QLA82XX(ha))
		return qla82xx_iospace_config(ha);

1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787
	if (pci_request_selected_regions(ha->pdev, ha->bars,
	    QLA2XXX_DRIVER_NAME)) {
		qla_printk(KERN_WARNING, ha,
		    "Failed to reserve PIO/MMIO regions (%s)\n",
		    pci_name(ha->pdev));

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

L
Linus Torvalds 已提交
1788 1789
	/* We only need PIO for Flash operations on ISP2312 v2 chips. */
	pio = pci_resource_start(ha->pdev, 0);
1790 1791
	if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) {
		if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) {
L
Linus Torvalds 已提交
1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802
			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;
	}
1803
	ha->pio_address = pio;
L
Linus Torvalds 已提交
1804

1805
skip_pio:
L
Linus Torvalds 已提交
1806
	/* Use MMIO operations for all accesses. */
1807
	if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) {
L
Linus Torvalds 已提交
1808
		qla_printk(KERN_ERR, ha,
1809
		    "region #1 not an MMIO resource (%s), aborting\n",
L
Linus Torvalds 已提交
1810 1811 1812
		    pci_name(ha->pdev));
		goto iospace_error_exit;
	}
1813
	if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) {
L
Linus Torvalds 已提交
1814 1815 1816 1817 1818 1819
		qla_printk(KERN_ERR, ha,
		    "Invalid PCI mem region size (%s), aborting\n",
			pci_name(ha->pdev));
		goto iospace_error_exit;
	}

1820
	ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN);
L
Linus Torvalds 已提交
1821 1822 1823 1824 1825 1826 1827
	if (!ha->iobase) {
		qla_printk(KERN_ERR, ha,
		    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));

		goto iospace_error_exit;
	}

1828
	/* Determine queue resources */
1829
	ha->max_req_queues = ha->max_rsp_queues = 1;
1830 1831
	if ((ql2xmaxqueues <= 1 && !ql2xmultique_tag) ||
		(ql2xmaxqueues > 1 && ql2xmultique_tag) ||
1832
		(!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
1833
		goto mqiobase_exit;
1834

1835 1836 1837 1838 1839 1840
	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;
1841 1842 1843 1844
		/* Max queues are bounded by available msix vectors */
		/* queue 0 uses two msix vectors */
		if (ql2xmultique_tag) {
			cpus = num_online_cpus();
1845
			ha->max_rsp_queues = (ha->msix_count - 1 > cpus) ?
1846 1847 1848
				(cpus + 1) : (ha->msix_count - 1);
			ha->max_req_queues = 2;
		} else if (ql2xmaxqueues > 1) {
1849 1850 1851 1852 1853
			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));
		}
1854 1855
		qla_printk(KERN_INFO, ha,
			"MSI-X vector count: %d\n", msix);
1856 1857
	} else
		qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
1858 1859

mqiobase_exit:
1860
	ha->msix_count = ha->max_rsp_queues + 1;
L
Linus Torvalds 已提交
1861 1862 1863 1864 1865 1866
	return (0);

iospace_error_exit:
	return (-ENOMEM);
}

1867 1868 1869
static void
qla2xxx_scan_start(struct Scsi_Host *shost)
{
1870
	scsi_qla_host_t *vha = shost_priv(shost);
1871

1872 1873 1874
	if (vha->hw->flags.running_gold_fw)
		return;

1875 1876 1877 1878
	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);
1879 1880 1881 1882 1883
}

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

1886
	if (!vha->host)
1887
		return 1;
1888
	if (time > vha->hw->loop_reset_delay * HZ)
1889 1890
		return 1;

1891
	return atomic_read(&vha->loop_state) == LOOP_READY;
1892 1893
}

L
Linus Torvalds 已提交
1894 1895 1896
/*
 * PCI driver interface
 */
1897 1898
static int __devinit
qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
L
Linus Torvalds 已提交
1899
{
1900
	int	ret = -ENODEV;
L
Linus Torvalds 已提交
1901
	struct Scsi_Host *host;
1902 1903
	scsi_qla_host_t *base_vha = NULL;
	struct qla_hw_data *ha;
1904
	char pci_info[30];
L
Linus Torvalds 已提交
1905
	char fw_str[30];
1906
	struct scsi_host_template *sht;
1907
	int bars, max_id, mem_only = 0;
1908
	uint16_t req_length = 0, rsp_length = 0;
1909 1910
	struct req_que *req = NULL;
	struct rsp_que *rsp = NULL;
L
Linus Torvalds 已提交
1911

1912
	bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
1913
	sht = &qla2xxx_driver_template;
1914
	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
1915
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
1916
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
1917
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
1918
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
1919
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
1920 1921
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 ||
	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021) {
1922
		bars = pci_select_bars(pdev, IORESOURCE_MEM);
1923
		mem_only = 1;
1924 1925
	}

1926 1927 1928 1929 1930 1931 1932
	if (mem_only) {
		if (pci_enable_device_mem(pdev))
			goto probe_out;
	} else {
		if (pci_enable_device(pdev))
			goto probe_out;
	}
1933

1934 1935
	/* This may fail but that's ok */
	pci_enable_pcie_error_reporting(pdev);
1936

1937 1938 1939 1940
	ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL);
	if (!ha) {
		DEBUG(printk("Unable to allocate memory for ha\n"));
		goto probe_out;
L
Linus Torvalds 已提交
1941
	}
1942
	ha->pdev = pdev;
L
Linus Torvalds 已提交
1943 1944

	/* Clear our data area */
1945
	ha->bars = bars;
1946
	ha->mem_only = mem_only;
1947
	spin_lock_init(&ha->hardware_lock);
1948
	spin_lock_init(&ha->vport_slock);
L
Linus Torvalds 已提交
1949

1950 1951
	/* Set ISP-type information. */
	qla2x00_set_isp_flags(ha);
1952 1953 1954 1955 1956 1957

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

L
Linus Torvalds 已提交
1958 1959
	/* Configure PCI I/O space */
	ret = qla2x00_iospace_config(ha);
1960
	if (ret)
1961
		goto probe_hw_failed;
L
Linus Torvalds 已提交
1962 1963

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

	ha->prev_topology = 0;
1968
	ha->init_cb_size = sizeof(init_cb_t);
1969
	ha->link_data_rate = PORT_SPEED_UNKNOWN;
1970
	ha->optrom_size = OPTROM_SIZE_2300;
L
Linus Torvalds 已提交
1971

1972
	/* Assign ISP specific operations. */
1973
	max_id = MAX_TARGETS_2200;
L
Linus Torvalds 已提交
1974
	if (IS_QLA2100(ha)) {
1975
		max_id = MAX_TARGETS_2100;
L
Linus Torvalds 已提交
1976
		ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
1977 1978 1979
		req_length = REQUEST_ENTRY_CNT_2100;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1980
		ha->gid_list_info_size = 4;
1981 1982 1983 1984
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1985
		ha->isp_ops = &qla2100_isp_ops;
L
Linus Torvalds 已提交
1986 1987
	} else if (IS_QLA2200(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1988 1989 1990
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2100;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
1991
		ha->gid_list_info_size = 4;
1992 1993 1994 1995
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
1996
		ha->isp_ops = &qla2100_isp_ops;
1997
	} else if (IS_QLA23XX(ha)) {
L
Linus Torvalds 已提交
1998
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
1999 2000 2001
		req_length = REQUEST_ENTRY_CNT_2200;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
2002
		ha->gid_list_info_size = 6;
2003 2004
		if (IS_QLA2322(ha) || IS_QLA6322(ha))
			ha->optrom_size = OPTROM_SIZE_2322;
2005 2006 2007 2008
		ha->flash_conf_off = ~0;
		ha->flash_data_off = ~0;
		ha->nvram_conf_off = ~0;
		ha->nvram_data_off = ~0;
2009
		ha->isp_ops = &qla2300_isp_ops;
2010
	} else if (IS_QLA24XX_TYPE(ha)) {
2011
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
2012 2013 2014
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
2015
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
2016
		ha->gid_list_info_size = 8;
2017
		ha->optrom_size = OPTROM_SIZE_24XX;
2018
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA24XX;
2019
		ha->isp_ops = &qla24xx_isp_ops;
2020 2021 2022 2023
		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;
2024 2025
	} else if (IS_QLA25XX(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
2026 2027 2028
		req_length = REQUEST_ENTRY_CNT_24XX;
		rsp_length = RESPONSE_ENTRY_CNT_2300;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
2029 2030 2031
		ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
		ha->gid_list_info_size = 8;
		ha->optrom_size = OPTROM_SIZE_25XX;
2032
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
2033
		ha->isp_ops = &qla25xx_isp_ops;
2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045
		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;
2046
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
2047 2048 2049 2050 2051
		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;
2052 2053 2054 2055 2056 2057 2058 2059
	} else if (IS_QLA82XX(ha)) {
		ha->mbx_count = MAILBOX_REGISTER_COUNT;
		req_length = REQUEST_ENTRY_CNT_82XX;
		rsp_length = RESPONSE_ENTRY_CNT_82XX;
		ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
		ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
		ha->gid_list_info_size = 8;
		ha->optrom_size = OPTROM_SIZE_82XX;
2060
		ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
2061 2062 2063 2064 2065
		ha->isp_ops = &qla82xx_isp_ops;
		ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
		ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
		ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
		ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
L
Linus Torvalds 已提交
2066 2067
	}

2068
	mutex_init(&ha->vport_lock);
2069 2070 2071
	init_completion(&ha->mbx_cmd_comp);
	complete(&ha->mbx_cmd_comp);
	init_completion(&ha->mbx_intr_comp);
2072
	init_completion(&ha->dcbx_comp);
L
Linus Torvalds 已提交
2073

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

2076
	qla2x00_config_dma_addressing(ha);
2077
	ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp);
2078
	if (!ret) {
L
Linus Torvalds 已提交
2079 2080 2081
		qla_printk(KERN_WARNING, ha,
		    "[ERROR] Failed to allocate memory for adapter\n");

2082 2083 2084
		goto probe_hw_failed;
	}

2085
	req->max_q_depth = MAX_Q_DEPTH;
2086
	if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU)
2087 2088
		req->max_q_depth = ql2xmaxqdepth;

2089 2090 2091 2092 2093 2094

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

2095
		ret = -ENOMEM;
2096
		qla2x00_mem_free(ha);
2097 2098
		qla2x00_free_req_que(ha, req);
		qla2x00_free_rsp_que(ha, rsp);
2099
		goto probe_hw_failed;
L
Linus Torvalds 已提交
2100 2101
	}

2102 2103 2104
	pci_set_drvdata(pdev, base_vha);

	host = base_vha->host;
2105
	base_vha->req = req;
2106 2107
	host->can_queue = req->length + 128;
	if (IS_QLA2XXX_MIDTYPE(ha))
2108
		base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
2109
	else
2110 2111
		base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
						base_vha->vp_idx;
2112 2113 2114 2115 2116 2117 2118 2119 2120 2121

	/* Set the SG table size based on ISP type */
	if (!IS_FWI2_CAPABLE(ha)) {
		if (IS_QLA2100(ha))
			host->sg_tablesize = 32;
	} else {
		if (!IS_QLA82XX(ha))
			host->sg_tablesize = QLA_SG_ALL;
	}

2122 2123 2124 2125
	host->max_id = max_id;
	host->this_id = 255;
	host->cmd_per_lun = 3;
	host->unique_id = host->host_no;
2126 2127 2128 2129
	if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif)
		host->max_cmd_len = 32;
	else
		host->max_cmd_len = MAX_CMDSZ;
2130 2131 2132
	host->max_channel = MAX_BUSES - 1;
	host->max_lun = MAX_LUNS;
	host->transportt = qla2xxx_transport_template;
2133
	sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC);
2134

2135 2136 2137
	/* Set up the irqs */
	ret = qla2x00_request_irqs(ha, rsp);
	if (ret)
2138
		goto probe_init_failed;
2139 2140 2141

	pci_save_state(pdev);

2142
	/* Alloc arrays of request and response ring ptrs */
2143
que_init:
2144 2145 2146 2147
	if (!qla2x00_alloc_queues(ha)) {
		qla_printk(KERN_WARNING, ha,
		"[ERROR] Failed to allocate memory for queue"
		" pointers\n");
2148
		goto probe_init_failed;
2149
	}
2150

2151 2152
	ha->rsp_q_map[0] = rsp;
	ha->req_q_map[0] = req;
2153 2154 2155 2156
	rsp->req = req;
	req->rsp = rsp;
	set_bit(0, ha->req_qid_map);
	set_bit(0, ha->rsp_qid_map);
2157 2158 2159 2160 2161
	/* 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;
2162
	if (ha->mqenable) {
2163 2164 2165 2166
		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;
2167 2168
	}

2169 2170 2171 2172 2173 2174
	if (IS_QLA82XX(ha)) {
		req->req_q_out = &ha->iobase->isp82.req_q_out[0];
		rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0];
		rsp->rsp_q_out = &ha->iobase->isp82.rsp_q_out[0];
	}

2175
	if (qla2x00_initialize_adapter(base_vha)) {
L
Linus Torvalds 已提交
2176 2177 2178 2179 2180
		qla_printk(KERN_WARNING, ha,
		    "Failed to initialize adapter\n");

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

2183 2184 2185 2186 2187 2188 2189 2190
		if (IS_QLA82XX(ha)) {
			qla82xx_idc_lock(ha);
			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
				QLA82XX_DEV_FAILED);
			qla82xx_idc_unlock(ha);
			qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
		}

2191
		ret = -ENODEV;
L
Linus Torvalds 已提交
2192 2193 2194
		goto probe_failed;
	}

2195 2196
	if (ha->mqenable) {
		if (qla25xx_setup_mode(base_vha)) {
2197 2198 2199
			qla_printk(KERN_WARNING, ha,
				"Can't create queues, falling back to single"
				" queue mode\n");
2200 2201 2202
			goto que_init;
		}
	}
2203

2204 2205 2206
	if (ha->flags.running_gold_fw)
		goto skip_dpc;

L
Linus Torvalds 已提交
2207 2208 2209
	/*
	 * Startup the kernel thread for this host adapter
	 */
2210
	ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha,
2211
			"%s_dpc", base_vha->host_str);
2212
	if (IS_ERR(ha->dpc_thread)) {
L
Linus Torvalds 已提交
2213 2214
		qla_printk(KERN_WARNING, ha,
		    "Unable to start DPC thread!\n");
2215
		ret = PTR_ERR(ha->dpc_thread);
L
Linus Torvalds 已提交
2216 2217 2218
		goto probe_failed;
	}

2219
skip_dpc:
2220 2221
	list_add_tail(&base_vha->list, &ha->vp_list);
	base_vha->host->irq = ha->pdev->irq;
L
Linus Torvalds 已提交
2222 2223

	/* Initialized the timer */
2224
	qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL);
L
Linus Torvalds 已提交
2225 2226

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

2229
	if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) {
2230 2231 2232 2233 2234 2235 2236
		if (ha->fw_attributes & BIT_4) {
			base_vha->flags.difdix_supported = 1;
			DEBUG18(qla_printk(KERN_INFO, ha,
			    "Registering for DIF/DIX type 1 and 3"
			    " protection.\n"));
			scsi_host_set_prot(host,
			    SHOST_DIF_TYPE1_PROTECTION
2237
			    | SHOST_DIF_TYPE2_PROTECTION
2238 2239
			    | SHOST_DIF_TYPE3_PROTECTION
			    | SHOST_DIX_TYPE1_PROTECTION
2240
			    | SHOST_DIX_TYPE2_PROTECTION
2241 2242 2243 2244 2245 2246
			    | SHOST_DIX_TYPE3_PROTECTION);
			scsi_host_set_guard(host, SHOST_DIX_GUARD_CRC);
		} else
			base_vha->flags.difdix_supported = 0;
	}

2247 2248
	ha->isp_ops->enable_intrs(ha);

2249 2250 2251 2252
	ret = scsi_add_host(host, &pdev->dev);
	if (ret)
		goto probe_failed;

2253 2254 2255
	base_vha->flags.init_done = 1;
	base_vha->flags.online = 1;

2256 2257
	scsi_scan_host(host);

2258
	qla2x00_alloc_sysfs_attr(base_vha);
2259

2260
	qla2x00_init_host_attr(base_vha);
2261

2262
	qla2x00_dfs_setup(base_vha);
2263

L
Linus Torvalds 已提交
2264 2265 2266
	qla_printk(KERN_INFO, ha, "\n"
	    " QLogic Fibre Channel HBA Driver: %s\n"
	    "  QLogic %s - %s\n"
2267 2268
	    "  ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
	    qla2x00_version_str, ha->model_number,
2269 2270 2271 2272
	    ha->model_desc ? ha->model_desc : "", pdev->device,
	    ha->isp_ops->pci_info_str(base_vha, pci_info), pci_name(pdev),
	    ha->flags.enable_64bit_addressing ? '+' : '-', base_vha->host_no,
	    ha->isp_ops->fw_version_str(base_vha, fw_str));
L
Linus Torvalds 已提交
2273 2274 2275

	return 0;

2276
probe_init_failed:
2277 2278 2279
	qla2x00_free_req_que(ha, req);
	qla2x00_free_rsp_que(ha, rsp);
	ha->max_req_queues = ha->max_rsp_queues = 0;
2280

L
Linus Torvalds 已提交
2281
probe_failed:
2282 2283 2284 2285 2286 2287 2288 2289 2290 2291
	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);
	}

2292
	qla2x00_free_device(base_vha);
L
Linus Torvalds 已提交
2293

2294
	scsi_host_put(base_vha->host);
L
Linus Torvalds 已提交
2295

2296
probe_hw_failed:
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
	if (IS_QLA82XX(ha)) {
		qla82xx_idc_lock(ha);
		qla82xx_clear_drv_active(ha);
		qla82xx_idc_unlock(ha);
		iounmap((device_reg_t __iomem *)ha->nx_pcibase);
		if (!ql2xdbwr)
			iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr);
	} else {
		if (ha->iobase)
			iounmap(ha->iobase);
	}
2308 2309 2310
	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
L
Linus Torvalds 已提交
2311

2312
probe_out:
2313
	pci_disable_device(pdev);
2314
	return ret;
L
Linus Torvalds 已提交
2315 2316
}

2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352
static void
qla2x00_shutdown(struct pci_dev *pdev)
{
	scsi_qla_host_t *vha;
	struct qla_hw_data  *ha;

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

	/* Turn-off FCE trace */
	if (ha->flags.fce_enabled) {
		qla2x00_disable_fce_trace(vha, NULL, NULL);
		ha->flags.fce_enabled = 0;
	}

	/* Turn-off EFT trace */
	if (ha->eft)
		qla2x00_disable_eft_trace(vha);

	/* Stop currently executing firmware. */
	qla2x00_try_to_stop_firmware(vha);

	/* Turn adapter off line */
	vha->flags.online = 0;

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

	qla2x00_free_irqs(vha);

	qla2x00_free_fw_dump(ha);
}

A
Adrian Bunk 已提交
2353
static void
2354
qla2x00_remove_one(struct pci_dev *pdev)
L
Linus Torvalds 已提交
2355
{
2356
	scsi_qla_host_t *base_vha, *vha;
2357
	struct qla_hw_data  *ha;
2358
	unsigned long flags;
2359 2360 2361 2362

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

2363 2364 2365 2366
	spin_lock_irqsave(&ha->vport_slock, flags);
	list_for_each_entry(vha, &ha->vp_list, list) {
		atomic_inc(&vha->vref_count);

2367
		if (vha->fc_vport) {
2368 2369
			spin_unlock_irqrestore(&ha->vport_slock, flags);

2370
			fc_vport_terminate(vha->fc_vport);
2371 2372 2373 2374 2375

			spin_lock_irqsave(&ha->vport_slock, flags);
		}

		atomic_dec(&vha->vref_count);
2376
	}
2377
	spin_unlock_irqrestore(&ha->vport_slock, flags);
L
Linus Torvalds 已提交
2378

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

2381 2382
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

2383
	qla2x00_dfs_remove(base_vha);
2384

2385
	qla84xx_put_chip(base_vha);
2386

2387 2388 2389 2390 2391 2392
	/* Disable timer */
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);

	base_vha->flags.online = 0;

2393 2394 2395 2396 2397 2398 2399
	/* Flush the work queue and remove it */
	if (ha->wq) {
		flush_workqueue(ha->wq);
		destroy_workqueue(ha->wq);
		ha->wq = NULL;
	}

2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411
	/* 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);
	}

2412
	qla2x00_free_sysfs_attr(base_vha);
2413

2414
	fc_remove_host(base_vha->host);
2415

2416
	scsi_remove_host(base_vha->host);
L
Linus Torvalds 已提交
2417

2418
	qla2x00_free_device(base_vha);
2419

2420
	scsi_host_put(base_vha->host);
L
Linus Torvalds 已提交
2421

2422
	if (IS_QLA82XX(ha)) {
2423 2424 2425 2426
		qla82xx_idc_lock(ha);
		qla82xx_clear_drv_active(ha);
		qla82xx_idc_unlock(ha);

2427 2428 2429 2430 2431 2432
		iounmap((device_reg_t __iomem *)ha->nx_pcibase);
		if (!ql2xdbwr)
			iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr);
	} else {
		if (ha->iobase)
			iounmap(ha->iobase);
L
Linus Torvalds 已提交
2433

2434 2435 2436
		if (ha->mqiobase)
			iounmap(ha->mqiobase);
	}
2437

2438 2439 2440
	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
	ha = NULL;
L
Linus Torvalds 已提交
2441

2442 2443
	pci_disable_pcie_error_reporting(pdev);

2444
	pci_disable_device(pdev);
L
Linus Torvalds 已提交
2445 2446 2447 2448
	pci_set_drvdata(pdev, NULL);
}

static void
2449
qla2x00_free_device(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
2450
{
2451
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
2452

2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470
	qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);

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

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

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

2471 2472
	qla25xx_delete_queues(vha);

2473
	if (ha->flags.fce_enabled)
2474
		qla2x00_disable_fce_trace(vha, NULL, NULL);
2475

2476
	if (ha->eft)
2477
		qla2x00_disable_eft_trace(vha);
2478

2479
	/* Stop currently executing firmware. */
2480
	qla2x00_try_to_stop_firmware(vha);
L
Linus Torvalds 已提交
2481

2482 2483
	vha->flags.online = 0;

2484
	/* turn-off interrupts on the card */
2485 2486
	if (ha->interrupts_on) {
		vha->flags.init_done = 0;
2487
		ha->isp_ops->disable_intrs(ha);
2488
	}
2489

2490
	qla2x00_free_irqs(vha);
L
Linus Torvalds 已提交
2491

2492 2493
	qla2x00_free_fcports(vha);

2494
	qla2x00_mem_free(ha);
2495 2496

	qla2x00_free_queues(ha);
L
Linus Torvalds 已提交
2497 2498
}

2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509
void qla2x00_free_fcports(struct scsi_qla_host *vha)
{
	fc_port_t *fcport, *tfcport;

	list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) {
		list_del(&fcport->list);
		kfree(fcport);
		fcport = NULL;
	}
}

2510
static inline void
2511
qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
2512 2513 2514
    int defer)
{
	struct fc_rport *rport;
2515
	scsi_qla_host_t *base_vha;
2516
	unsigned long flags;
2517 2518 2519 2520 2521 2522

	if (!fcport->rport)
		return;

	rport = fcport->rport;
	if (defer) {
2523
		base_vha = pci_get_drvdata(vha->hw->pdev);
2524
		spin_lock_irqsave(vha->host->host_lock, flags);
2525
		fcport->drport = rport;
2526
		spin_unlock_irqrestore(vha->host->host_lock, flags);
2527 2528
		set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
		qla2xxx_wake_dpc(base_vha);
2529
	} else
2530 2531 2532
		fc_remote_port_delete(rport);
}

L
Linus Torvalds 已提交
2533 2534 2535 2536 2537 2538 2539 2540 2541
/*
 * qla2x00_mark_device_lost Updates fcport state when device goes offline.
 *
 * Input: ha = adapter block pointer.  fcport = port structure pointer.
 *
 * Return: None.
 *
 * Context:
 */
2542
void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
2543
    int do_login, int defer)
L
Linus Torvalds 已提交
2544
{
2545
	if (atomic_read(&fcport->state) == FCS_ONLINE &&
2546 2547 2548 2549
	    vha->vp_idx == fcport->vp_idx) {
		atomic_set(&fcport->state, FCS_DEVICE_LOST);
		qla2x00_schedule_rport_del(vha, fcport, defer);
	}
A
Andrew Vasquez 已提交
2550
	/*
L
Linus Torvalds 已提交
2551 2552 2553 2554 2555 2556 2557 2558 2559 2560
	 * 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) {
2561 2562
		fcport->login_retry = vha->hw->login_retry_count;
		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
2563 2564 2565 2566

		DEBUG(printk("scsi(%ld): Port login retry: "
		    "%02x%02x%02x%02x%02x%02x%02x%02x, "
		    "id = 0x%04x retry cnt=%d\n",
2567
		    vha->host_no,
L
Linus Torvalds 已提交
2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594
		    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
2595
qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
L
Linus Torvalds 已提交
2596 2597 2598
{
	fc_port_t *fcport;

2599
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
2600
		if (vha->vp_idx != 0 && vha->vp_idx != fcport->vp_idx)
L
Linus Torvalds 已提交
2601
			continue;
2602

L
Linus Torvalds 已提交
2603 2604 2605 2606 2607 2608
		/*
		 * No point in marking the device as lost, if the device is
		 * already DEAD.
		 */
		if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
			continue;
2609
		if (atomic_read(&fcport->state) == FCS_ONLINE) {
2610
			atomic_set(&fcport->state, FCS_DEVICE_LOST);
2611 2612 2613 2614 2615
			if (defer)
				qla2x00_schedule_rport_del(vha, fcport, defer);
			else if (vha->vp_idx == fcport->vp_idx)
				qla2x00_schedule_rport_del(vha, fcport, defer);
		}
L
Linus Torvalds 已提交
2616 2617 2618 2619 2620 2621 2622 2623 2624
	}
}

/*
* qla2x00_mem_alloc
*      Allocates adapter memory.
*
* Returns:
*      0  = success.
2625
*      !0  = failure.
L
Linus Torvalds 已提交
2626
*/
2627
static int
2628 2629
qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
	struct req_que **req, struct rsp_que **rsp)
L
Linus Torvalds 已提交
2630 2631 2632
{
	char	name[16];

2633
	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
2634
		&ha->init_cb_dma, GFP_KERNEL);
2635
	if (!ha->init_cb)
2636
		goto fail;
2637

2638 2639 2640
	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
		&ha->gid_list_dma, GFP_KERNEL);
	if (!ha->gid_list)
2641
		goto fail_free_init_cb;
L
Linus Torvalds 已提交
2642

2643 2644
	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
	if (!ha->srb_mempool)
2645
		goto fail_free_gid_list;
2646

2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661
	if (IS_QLA82XX(ha)) {
		/* Allocate cache for CT6 Ctx. */
		if (!ctx_cachep) {
			ctx_cachep = kmem_cache_create("qla2xxx_ctx",
				sizeof(struct ct6_dsd), 0,
				SLAB_HWCACHE_ALIGN, NULL);
			if (!ctx_cachep)
				goto fail_free_gid_list;
		}
		ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ,
			ctx_cachep);
		if (!ha->ctx_mempool)
			goto fail_free_srb_mempool;
	}

2662 2663 2664
	/* Get memory for cached NVRAM */
	ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL);
	if (!ha->nvram)
2665
		goto fail_free_ctx_mempool;
2666

2667 2668 2669 2670 2671 2672 2673
	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;

2674
	if (IS_QLA82XX(ha) || ql2xenabledif) {
2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691
		ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
			DSD_LIST_DMA_POOL_SIZE, 8, 0);
		if (!ha->dl_dma_pool) {
			qla_printk(KERN_WARNING, ha,
			    "Memory Allocation failed - dl_dma_pool\n");
			goto fail_s_dma_pool;
		}

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

2692 2693
	/* Allocate memory for SNS commands */
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
2694
	/* Get consistent memory allocated for SNS commands */
2695
		ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,
2696
		sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL);
2697
		if (!ha->sns_cmd)
2698
			goto fail_dma_pool;
2699
	} else {
2700
	/* Get consistent memory allocated for MS IOCB */
2701
		ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
2702
			&ha->ms_iocb_dma);
2703
		if (!ha->ms_iocb)
2704 2705
			goto fail_dma_pool;
	/* Get consistent memory allocated for CT SNS commands */
2706
		ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,
2707
			sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
2708 2709
		if (!ha->ct_sns)
			goto fail_free_ms_iocb;
L
Linus Torvalds 已提交
2710 2711
	}

2712
	/* Allocate memory for request ring */
2713 2714
	*req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
	if (!*req) {
2715 2716 2717
		DEBUG(printk("Unable to allocate memory for req\n"));
		goto fail_req;
	}
2718 2719 2720 2721 2722
	(*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) {
2723 2724 2725 2726
		DEBUG(printk("Unable to allocate memory for req_ring\n"));
		goto fail_req_ring;
	}
	/* Allocate memory for response ring */
2727 2728 2729 2730
	*rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
	if (!*rsp) {
		qla_printk(KERN_WARNING, ha,
			"Unable to allocate memory for rsp\n");
2731 2732
		goto fail_rsp;
	}
2733 2734 2735 2736 2737 2738 2739 2740
	(*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");
2741 2742
		goto fail_rsp_ring;
	}
2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755
	(*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;
2756

2757
	/* Get consistent memory allocated for EX-INIT-CB. */
2758
	if (IS_QLA8XXX_TYPE(ha)) {
2759 2760 2761 2762 2763 2764
		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;
	}

2765 2766
	INIT_LIST_HEAD(&ha->gbl_dsd_list);

2767 2768 2769 2770 2771 2772 2773 2774
	/* Get consistent memory allocated for Async Port-Database. */
	if (!IS_FWI2_CAPABLE(ha)) {
		ha->async_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
			&ha->async_pd_dma);
		if (!ha->async_pd)
			goto fail_async_pd;
	}

2775 2776 2777
	INIT_LIST_HEAD(&ha->vp_list);
	return 1;

2778 2779
fail_async_pd:
	dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
2780 2781
fail_ex_init_cb:
	kfree(ha->npiv_info);
2782 2783 2784 2785 2786
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;
2787
fail_rsp_ring:
2788
	kfree(*rsp);
2789
fail_rsp:
2790 2791 2792 2793
	dma_free_coherent(&ha->pdev->dev, ((*req)->length + 1) *
		sizeof(request_t), (*req)->ring, (*req)->dma);
	(*req)->ring = NULL;
	(*req)->dma = 0;
2794
fail_req_ring:
2795
	kfree(*req);
2796 2797 2798 2799 2800
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;
2801 2802 2803 2804
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;
2805
fail_dma_pool:
2806
	if (IS_QLA82XX(ha) || ql2xenabledif) {
2807 2808 2809 2810
		dma_pool_destroy(ha->fcp_cmnd_dma_pool);
		ha->fcp_cmnd_dma_pool = NULL;
	}
fail_dl_dma_pool:
2811
	if (IS_QLA82XX(ha) || ql2xenabledif) {
2812 2813 2814 2815
		dma_pool_destroy(ha->dl_dma_pool);
		ha->dl_dma_pool = NULL;
	}
fail_s_dma_pool:
2816 2817
	dma_pool_destroy(ha->s_dma_pool);
	ha->s_dma_pool = NULL;
2818 2819 2820
fail_free_nvram:
	kfree(ha->nvram);
	ha->nvram = NULL;
2821 2822 2823
fail_free_ctx_mempool:
	mempool_destroy(ha->ctx_mempool);
	ha->ctx_mempool = NULL;
2824 2825 2826 2827 2828
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,
2829
	ha->gid_list_dma);
2830 2831
	ha->gid_list = NULL;
	ha->gid_list_dma = 0;
2832 2833 2834 2835 2836
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;
2837
fail:
2838
	DEBUG(printk("%s: Memory allocation failure\n", __func__));
2839
	return -ENOMEM;
L
Linus Torvalds 已提交
2840 2841 2842
}

/*
2843 2844
* qla2x00_free_fw_dump
*	Frees fw dump stuff.
L
Linus Torvalds 已提交
2845 2846
*
* Input:
2847
*	ha = adapter block pointer.
L
Linus Torvalds 已提交
2848
*/
A
Adrian Bunk 已提交
2849
static void
2850
qla2x00_free_fw_dump(struct qla_hw_data *ha)
L
Linus Torvalds 已提交
2851
{
2852 2853
	if (ha->fce)
		dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
2854
		    ha->fce_dma);
2855

2856 2857 2858
	if (ha->fw_dump) {
		if (ha->eft)
			dma_free_coherent(&ha->pdev->dev,
2859
			    ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
2860 2861
		vfree(ha->fw_dump);
	}
2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884
	ha->fce = NULL;
	ha->fce_dma = 0;
	ha->eft = NULL;
	ha->eft_dma = 0;
	ha->fw_dump = NULL;
	ha->fw_dumped = 0;
	ha->fw_dump_reading = 0;
}

/*
* qla2x00_mem_free
*      Frees all adapter allocated memory.
*
* Input:
*      ha = adapter block pointer.
*/
static void
qla2x00_mem_free(struct qla_hw_data *ha)
{
	qla2x00_free_fw_dump(ha);

	if (ha->srb_mempool)
		mempool_destroy(ha->srb_mempool);
2885

2886 2887 2888 2889
	if (ha->dcbx_tlv)
		dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
		    ha->dcbx_tlv, ha->dcbx_tlv_dma);

2890 2891 2892 2893
	if (ha->xgmac_data)
		dma_free_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
		    ha->xgmac_data, ha->xgmac_data_dma);

L
Linus Torvalds 已提交
2894 2895
	if (ha->sns_cmd)
		dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
2896
		ha->sns_cmd, ha->sns_cmd_dma);
L
Linus Torvalds 已提交
2897 2898 2899

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

2902 2903 2904
	if (ha->sfp_data)
		dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);

2905 2906 2907
	if (ha->edc_data)
		dma_pool_free(ha->s_dma_pool, ha->edc_data, ha->edc_data_dma);

L
Linus Torvalds 已提交
2908 2909 2910
	if (ha->ms_iocb)
		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);

2911
	if (ha->ex_init_cb)
2912 2913
		dma_pool_free(ha->s_dma_pool,
			ha->ex_init_cb, ha->ex_init_cb_dma);
2914

2915 2916 2917
	if (ha->async_pd)
		dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);

L
Linus Torvalds 已提交
2918 2919 2920 2921 2922
	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,
2923
		ha->gid_list_dma);
L
Linus Torvalds 已提交
2924

2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948
	if (IS_QLA82XX(ha)) {
		if (!list_empty(&ha->gbl_dsd_list)) {
			struct dsd_dma *dsd_ptr, *tdsd_ptr;

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

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

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

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

2949 2950
	if (ha->init_cb)
		dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
2951
			ha->init_cb, ha->init_cb_dma);
2952 2953
	vfree(ha->optrom_buffer);
	kfree(ha->nvram);
2954
	kfree(ha->npiv_info);
L
Linus Torvalds 已提交
2955

2956
	ha->srb_mempool = NULL;
2957
	ha->ctx_mempool = NULL;
L
Linus Torvalds 已提交
2958 2959 2960 2961 2962 2963 2964 2965
	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;
2966 2967
	ha->ex_init_cb = NULL;
	ha->ex_init_cb_dma = 0;
2968 2969
	ha->async_pd = NULL;
	ha->async_pd_dma = 0;
L
Linus Torvalds 已提交
2970 2971

	ha->s_dma_pool = NULL;
2972 2973
	ha->dl_dma_pool = NULL;
	ha->fcp_cmnd_dma_pool = NULL;
L
Linus Torvalds 已提交
2974 2975 2976

	ha->gid_list = NULL;
	ha->gid_list_dma = 0;
2977
}
L
Linus Torvalds 已提交
2978

2979 2980 2981 2982 2983
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;
2984

2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003
	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);

3004 3005
	spin_lock_init(&vha->work_lock);

3006 3007 3008 3009 3010
	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
	return vha;

fail:
	return vha;
L
Linus Torvalds 已提交
3011 3012
}

3013
static struct qla_work_evt *
3014
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
3015 3016
{
	struct qla_work_evt *e;
3017 3018 3019 3020 3021
	uint8_t bail;

	QLA_VHA_MARK_BUSY(vha, bail);
	if (bail)
		return NULL;
3022

3023
	e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC);
3024 3025
	if (!e) {
		QLA_VHA_MARK_NOT_BUSY(vha);
3026
		return NULL;
3027
	}
3028 3029 3030 3031 3032 3033 3034

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

3035
static int
3036
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
3037
{
3038
	unsigned long flags;
3039

3040
	spin_lock_irqsave(&vha->work_lock, flags);
3041
	list_add_tail(&e->list, &vha->work_list);
3042
	spin_unlock_irqrestore(&vha->work_lock, flags);
3043
	qla2xxx_wake_dpc(vha);
3044

3045 3046 3047 3048
	return QLA_SUCCESS;
}

int
3049
qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
3050 3051 3052 3053
    u32 data)
{
	struct qla_work_evt *e;

3054
	e = qla2x00_alloc_work(vha, QLA_EVT_AEN);
3055 3056 3057 3058 3059
	if (!e)
		return QLA_FUNCTION_FAILED;

	e->u.aen.code = code;
	e->u.aen.data = data;
3060
	return qla2x00_post_work(vha, e);
3061 3062
}

3063 3064 3065 3066 3067
int
qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
{
	struct qla_work_evt *e;

3068
	e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK);
3069 3070 3071 3072
	if (!e)
		return QLA_FUNCTION_FAILED;

	memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
3073
	return qla2x00_post_work(vha, e);
3074 3075
}

3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098
#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);
3099 3100
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE);
3101

3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132
int
qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code)
{
	struct qla_work_evt *e;

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

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

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

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

3133
void
3134
qla2x00_do_work(struct scsi_qla_host *vha)
3135
{
3136 3137 3138
	struct qla_work_evt *e, *tmp;
	unsigned long flags;
	LIST_HEAD(work);
3139

3140 3141 3142 3143 3144
	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) {
3145 3146 3147 3148
		list_del_init(&e->list);

		switch (e->type) {
		case QLA_EVT_AEN:
3149
			fc_host_post_event(vha->host, fc_get_event_number(),
3150 3151
			    e->u.aen.code, e->u.aen.data);
			break;
3152 3153 3154
		case QLA_EVT_IDC_ACK:
			qla81xx_idc_ack(vha, e->u.idc_ack.mb);
			break;
3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169
		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;
3170 3171 3172 3173 3174 3175 3176 3177
		case QLA_EVT_ASYNC_ADISC:
			qla2x00_async_adisc(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
		case QLA_EVT_ASYNC_ADISC_DONE:
			qla2x00_async_adisc_done(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
3178 3179 3180
		case QLA_EVT_UEVENT:
			qla2x00_uevent_emit(vha, e->u.uevent.code);
			break;
3181 3182 3183
		}
		if (e->flags & QLA_EVT_FLAG_FREE)
			kfree(e);
3184 3185 3186

		/* For each work completed decrement vha ref count */
		QLA_VHA_MARK_NOT_BUSY(vha);
3187 3188
	}
}
3189

3190 3191 3192 3193 3194 3195
/* Relogins all the fcports of a vport
 * Context: dpc thread
 */
void qla2x00_relogin(struct scsi_qla_host *vha)
{
	fc_port_t       *fcport;
3196
	int status;
3197 3198
	uint16_t        next_loopid = 0;
	struct qla_hw_data *ha = vha->hw;
3199
	uint16_t data[2];
3200 3201 3202 3203 3204 3205

	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.
	 */
3206 3207
		if (atomic_read(&fcport->state) != FCS_ONLINE &&
		    fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
3208
			fcport->login_retry--;
3209
			if (fcport->flags & FCF_FABRIC_DEVICE) {
3210
				if (fcport->flags & FCF_FCP2_DEVICE)
3211 3212 3213 3214 3215 3216
					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);

3217
				if (IS_ALOGIO_CAPABLE(ha)) {
3218
					fcport->flags |= FCF_ASYNC_SENT;
3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229
					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);
3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257
			} 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;
3258 3259 3260
	}
}

L
Linus Torvalds 已提交
3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276
/**************************************************************************
* 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)
{
3277
	int		rval;
3278 3279
	scsi_qla_host_t *base_vha;
	struct qla_hw_data *ha;
L
Linus Torvalds 已提交
3280

3281 3282
	ha = (struct qla_hw_data *)data;
	base_vha = pci_get_drvdata(ha->pdev);
L
Linus Torvalds 已提交
3283 3284 3285

	set_user_nice(current, -20);

3286
	set_current_state(TASK_INTERRUPTIBLE);
3287
	while (!kthread_should_stop()) {
L
Linus Torvalds 已提交
3288 3289
		DEBUG3(printk("qla2x00: DPC handler sleeping\n"));

3290 3291
		schedule();
		__set_current_state(TASK_RUNNING);
L
Linus Torvalds 已提交
3292 3293 3294 3295

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

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

3299 3300 3301 3302 3303 3304 3305
		if (ha->flags.eeh_busy) {
			DEBUG17(qla_printk(KERN_WARNING, ha,
			    "qla2x00_do_dpc: dpc_flags: %lx\n",
			    base_vha->dpc_flags));
			continue;
		}

3306
		DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
L
Linus Torvalds 已提交
3307 3308 3309 3310 3311 3312 3313 3314

		ha->dpc_active = 1;

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

3315
		qla2x00_do_work(base_vha);
3316

3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355
		if (IS_QLA82XX(ha)) {
			if (test_and_clear_bit(ISP_UNRECOVERABLE,
				&base_vha->dpc_flags)) {
				qla82xx_idc_lock(ha);
				qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
					QLA82XX_DEV_FAILED);
				qla82xx_idc_unlock(ha);
				qla_printk(KERN_INFO, ha,
					"HW State: FAILED\n");
				qla82xx_device_state_handler(base_vha);
				continue;
			}

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

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

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

3356 3357
		if (test_and_clear_bit(ISP_ABORT_NEEDED,
						&base_vha->dpc_flags)) {
L
Linus Torvalds 已提交
3358 3359 3360

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

3365
				if (ha->isp_ops->abort_isp(base_vha)) {
L
Linus Torvalds 已提交
3366 3367
					/* failed. retry later */
					set_bit(ISP_ABORT_NEEDED,
3368
					    &base_vha->dpc_flags);
3369
				}
3370 3371
				clear_bit(ABORT_ISP_ACTIVE,
						&base_vha->dpc_flags);
3372 3373
			}

L
Linus Torvalds 已提交
3374
			DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",
3375
			    base_vha->host_no));
L
Linus Torvalds 已提交
3376 3377
		}

3378 3379 3380
		if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) {
			qla2x00_update_fcports(base_vha);
			clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
3381
		}
3382

3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397
		if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
			DEBUG(printk(KERN_INFO "scsi(%ld): dpc: sched "
			    "qla2x00_quiesce_needed ha = %p\n",
			    base_vha->host_no, ha));
			qla82xx_device_state_handler(base_vha);
			clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags);
			if (!ha->flags.quiesce_owner) {
				qla2x00_perform_loop_resync(base_vha);

				qla82xx_idc_lock(ha);
				qla82xx_clear_qsnt_ready(base_vha);
				qla82xx_idc_unlock(ha);
			}
		}

3398 3399 3400
		if (test_and_clear_bit(RESET_MARKER_NEEDED,
							&base_vha->dpc_flags) &&
		    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
L
Linus Torvalds 已提交
3401 3402

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

3405 3406
			qla2x00_rst_aen(base_vha);
			clear_bit(RESET_ACTIVE, &base_vha->dpc_flags);
L
Linus Torvalds 已提交
3407 3408 3409
		}

		/* Retry each device up to login retry count */
3410 3411 3412 3413
		if ((test_and_clear_bit(RELOGIN_NEEDED,
						&base_vha->dpc_flags)) &&
		    !test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags) &&
		    atomic_read(&base_vha->loop_state) != LOOP_DOWN) {
L
Linus Torvalds 已提交
3414 3415

			DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
3416 3417 3418
					base_vha->host_no));
			qla2x00_relogin(base_vha);

L
Linus Torvalds 已提交
3419
			DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
3420
			    base_vha->host_no));
L
Linus Torvalds 已提交
3421 3422
		}

3423 3424
		if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
							&base_vha->dpc_flags)) {
L
Linus Torvalds 已提交
3425 3426

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

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

3432
				rval = qla2x00_loop_resync(base_vha);
L
Linus Torvalds 已提交
3433

3434 3435
				clear_bit(LOOP_RESYNC_ACTIVE,
						&base_vha->dpc_flags);
L
Linus Torvalds 已提交
3436 3437 3438
			}

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

3442 3443 3444 3445
		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);
3446 3447
		}

L
Linus Torvalds 已提交
3448
		if (!ha->interrupts_on)
3449
			ha->isp_ops->enable_intrs(ha);
L
Linus Torvalds 已提交
3450

3451 3452 3453
		if (test_and_clear_bit(BEACON_BLINK_NEEDED,
					&base_vha->dpc_flags))
			ha->isp_ops->beacon_blink(base_vha);
3454

3455
		qla2x00_do_dpc_all_vps(base_vha);
3456

L
Linus Torvalds 已提交
3457
		ha->dpc_active = 0;
3458
		set_current_state(TASK_INTERRUPTIBLE);
L
Linus Torvalds 已提交
3459
	} /* End of while(1) */
3460
	__set_current_state(TASK_RUNNING);
L
Linus Torvalds 已提交
3461

3462
	DEBUG(printk("scsi(%ld): DPC handler exiting\n", base_vha->host_no));
L
Linus Torvalds 已提交
3463 3464 3465 3466 3467 3468

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

3469 3470 3471
	/* Cleanup any residual CTX SRBs. */
	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

3472 3473 3474 3475
	return 0;
}

void
3476
qla2xxx_wake_dpc(struct scsi_qla_host *vha)
3477
{
3478
	struct qla_hw_data *ha = vha->hw;
3479 3480
	struct task_struct *t = ha->dpc_thread;

3481
	if (!test_bit(UNLOADING, &vha->dpc_flags) && t)
3482
		wake_up_process(t);
L
Linus Torvalds 已提交
3483 3484 3485 3486 3487 3488 3489 3490 3491 3492
}

/*
*  qla2x00_rst_aen
*      Processes asynchronous reset.
*
* Input:
*      ha  = adapter block pointer.
*/
static void
3493
qla2x00_rst_aen(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
3494
{
3495 3496 3497
	if (vha->flags.online && !vha->flags.reset_active &&
	    !atomic_read(&vha->loop_down_timer) &&
	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))) {
L
Linus Torvalds 已提交
3498
		do {
3499
			clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
3500 3501 3502 3503 3504

			/*
			 * Issue marker command only when we are going to start
			 * the I/O.
			 */
3505 3506 3507
			vha->marker_needed = 1;
		} while (!atomic_read(&vha->loop_down_timer) &&
		    (test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags)));
L
Linus Torvalds 已提交
3508 3509 3510
	}
}

已提交
3511
static void
3512
qla2x00_sp_free_dma(srb_t *sp)
已提交
3513 3514
{
	struct scsi_cmnd *cmd = sp->cmd;
3515
	struct qla_hw_data *ha = sp->fcport->vha->hw;
已提交
3516 3517

	if (sp->flags & SRB_DMA_VALID) {
3518
		scsi_dma_unmap(cmd);
已提交
3519 3520
		sp->flags &= ~SRB_DMA_VALID;
	}
3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539

	if (sp->flags & SRB_CRC_PROT_DMA_VALID) {
		dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
		    scsi_prot_sg_count(cmd), cmd->sc_data_direction);
		sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
	}

	if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
		/* List assured to be having elements */
		qla2x00_clean_dsd_pool(ha, sp);
		sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
	}

	if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
		dma_pool_free(ha->dl_dma_pool, sp->ctx,
		    ((struct crc_context *)sp->ctx)->crc_ctx_dma);
		sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
	}

3540
	CMD_SP(cmd) = NULL;
已提交
3541 3542
}

3543
static void
3544
qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp)
已提交
3545 3546 3547
{
	struct scsi_cmnd *cmd = sp->cmd;

3548
	qla2x00_sp_free_dma(sp);
已提交
3549

3550 3551 3552 3553 3554 3555 3556 3557 3558 3559
	if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
		struct ct6_dsd *ctx = sp->ctx;
		dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd,
			ctx->fcp_cmnd_dma);
		list_splice(&ctx->dsd_list, &ha->gbl_dsd_list);
		ha->gbl_dsd_inuse -= ctx->dsd_use_cnt;
		ha->gbl_dsd_avail += ctx->dsd_use_cnt;
		mempool_free(sp->ctx, ha->ctx_mempool);
		sp->ctx = NULL;
	}
已提交
3560

3561
	mempool_free(sp, ha->srb_mempool);
已提交
3562 3563
	cmd->scsi_done(cmd);
}
3564

3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578
void
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
{
	if (atomic_read(&sp->ref_count) == 0) {
		DEBUG2(qla_printk(KERN_WARNING, ha,
		    "SP reference-count to ZERO -- sp=%p\n", sp));
		DEBUG2(BUG());
		return;
	}
	if (!atomic_dec_and_test(&sp->ref_count))
		return;
	qla2x00_sp_final_compl(ha, sp);
}

L
Linus Torvalds 已提交
3579 3580 3581 3582 3583 3584 3585 3586
/**************************************************************************
*   qla2x00_timer
*
* Description:
*   One second timer
*
* Context: Interrupt
***************************************************************************/
3587
void
3588
qla2x00_timer(scsi_qla_host_t *vha)
L
Linus Torvalds 已提交
3589 3590 3591 3592 3593
{
	unsigned long	cpu_flags = 0;
	int		start_dpc = 0;
	int		index;
	srb_t		*sp;
3594
	uint16_t        w;
3595
	struct qla_hw_data *ha = vha->hw;
3596
	struct req_que *req;
3597

3598 3599 3600 3601 3602
	if (ha->flags.eeh_busy) {
		qla2x00_restart_timer(vha, WATCH_INTERVAL);
		return;
	}

3603 3604 3605
	/* Hardware read to raise pending EEH errors during mailbox waits. */
	if (!pci_channel_offline(ha->pdev))
		pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
L
Linus Torvalds 已提交
3606

3607 3608 3609 3610 3611 3612
	if (IS_QLA82XX(ha)) {
		if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags))
			start_dpc++;
		qla82xx_watchdog(vha);
	}

L
Linus Torvalds 已提交
3613
	/* Loop down handler. */
3614 3615 3616
	if (atomic_read(&vha->loop_down_timer) > 0 &&
	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
		&& vha->flags.online) {
L
Linus Torvalds 已提交
3617

3618 3619
		if (atomic_read(&vha->loop_down_timer) ==
		    vha->loop_down_abort_time) {
L
Linus Torvalds 已提交
3620 3621 3622

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

3625 3626
			if (!IS_QLA2100(ha) && vha->link_down_timeout)
				atomic_set(&vha->loop_state, LOOP_DEAD);
L
Linus Torvalds 已提交
3627

3628 3629 3630 3631
			/*
			 * Schedule an ISP abort to return any FCP2-device
			 * commands.
			 */
3632
			/* NPIV - scan physical port only */
3633
			if (!vha->vp_idx) {
3634 3635
				spin_lock_irqsave(&ha->hardware_lock,
				    cpu_flags);
3636
				req = ha->req_q_map[0];
3637 3638 3639 3640 3641
				for (index = 1;
				    index < MAX_OUTSTANDING_COMMANDS;
				    index++) {
					fc_port_t *sfcp;

3642
					sp = req->outstanding_cmds[index];
3643 3644
					if (!sp)
						continue;
3645
					if (sp->ctx && !IS_PROT_IO(sp))
3646
						continue;
3647
					sfcp = sp->fcport;
3648
					if (!(sfcp->flags & FCF_FCP2_DEVICE))
3649
						continue;
3650

3651
					set_bit(ISP_ABORT_NEEDED,
3652
							&vha->dpc_flags);
3653 3654 3655
					break;
				}
				spin_unlock_irqrestore(&ha->hardware_lock,
3656
								cpu_flags);
L
Linus Torvalds 已提交
3657 3658 3659 3660 3661
			}
			start_dpc++;
		}

		/* if the loop has been down for 4 minutes, reinit adapter */
3662
		if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
3663
			if (!(vha->device_flags & DFLG_NO_CABLE)) {
L
Linus Torvalds 已提交
3664 3665
				DEBUG(printk("scsi(%ld): Loop down - "
				    "aborting ISP.\n",
3666
				    vha->host_no));
L
Linus Torvalds 已提交
3667 3668 3669
				qla_printk(KERN_WARNING, ha,
				    "Loop down - aborting ISP.\n");

3670
				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
3671 3672
			}
		}
3673
		DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
3674 3675
		    vha->host_no,
		    atomic_read(&vha->loop_down_timer)));
L
Linus Torvalds 已提交
3676 3677
	}

3678 3679
	/* Check if beacon LED needs to be blinked */
	if (ha->beacon_blink_led == 1) {
3680
		set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
3681 3682 3683
		start_dpc++;
	}

3684
	/* Process any deferred work. */
3685
	if (!list_empty(&vha->work_list))
3686 3687
		start_dpc++;

L
Linus Torvalds 已提交
3688
	/* Schedule the DPC routine if needed */
3689 3690 3691
	if ((test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
	    test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
	    test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags) ||
L
Linus Torvalds 已提交
3692
	    start_dpc ||
3693 3694
	    test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) ||
	    test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags) ||
3695 3696
	    test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) ||
	    test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) ||
3697 3698 3699
	    test_bit(VP_DPC_NEEDED, &vha->dpc_flags) ||
	    test_bit(RELOGIN_NEEDED, &vha->dpc_flags)))
		qla2xxx_wake_dpc(vha);
L
Linus Torvalds 已提交
3700

3701
	qla2x00_restart_timer(vha, WATCH_INTERVAL);
L
Linus Torvalds 已提交
3702 3703
}

3704 3705
/* Firmware interface routines. */

3706
#define FW_BLOBS	8
3707 3708 3709 3710
#define FW_ISP21XX	0
#define FW_ISP22XX	1
#define FW_ISP2300	2
#define FW_ISP2322	3
3711
#define FW_ISP24XX	4
3712
#define FW_ISP25XX	5
3713
#define FW_ISP81XX	6
3714
#define FW_ISP82XX	7
3715

3716 3717 3718 3719 3720
#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"
3721
#define FW_FILE_ISP25XX	"ql2500_fw.bin"
3722
#define FW_FILE_ISP81XX	"ql8100_fw.bin"
3723
#define FW_FILE_ISP82XX	"ql8200_fw.bin"
3724

3725
static DEFINE_MUTEX(qla_fw_lock);
3726 3727

static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
3728 3729 3730 3731 3732
	{ .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, },
3733
	{ .name = FW_FILE_ISP25XX, },
3734
	{ .name = FW_FILE_ISP81XX, },
3735
	{ .name = FW_FILE_ISP82XX, },
3736 3737 3738
};

struct fw_blob *
3739
qla2x00_request_firmware(scsi_qla_host_t *vha)
3740
{
3741
	struct qla_hw_data *ha = vha->hw;
3742 3743 3744 3745 3746 3747 3748
	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];
3749
	} else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3750
		blob = &qla_fw_blobs[FW_ISP2300];
3751
	} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
3752
		blob = &qla_fw_blobs[FW_ISP2322];
3753
	} else if (IS_QLA24XX_TYPE(ha)) {
3754
		blob = &qla_fw_blobs[FW_ISP24XX];
3755 3756
	} else if (IS_QLA25XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP25XX];
3757 3758
	} else if (IS_QLA81XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP81XX];
3759 3760
	} else if (IS_QLA82XX(ha)) {
		blob = &qla_fw_blobs[FW_ISP82XX];
3761 3762
	}

3763
	mutex_lock(&qla_fw_lock);
3764 3765 3766 3767 3768
	if (blob->fw)
		goto out;

	if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
		DEBUG2(printk("scsi(%ld): Failed to load firmware image "
3769
		    "(%s).\n", vha->host_no, blob->name));
3770 3771 3772 3773 3774 3775
		blob->fw = NULL;
		blob = NULL;
		goto out;
	}

out:
3776
	mutex_unlock(&qla_fw_lock);
3777 3778 3779 3780 3781 3782 3783 3784
	return blob;
}

static void
qla2x00_release_firmware(void)
{
	int idx;

3785
	mutex_lock(&qla_fw_lock);
3786 3787 3788
	for (idx = 0; idx < FW_BLOBS; idx++)
		if (qla_fw_blobs[idx].fw)
			release_firmware(qla_fw_blobs[idx].fw);
3789
	mutex_unlock(&qla_fw_lock);
3790 3791
}

3792 3793 3794
static pci_ers_result_t
qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
3795 3796 3797 3798 3799
	scsi_qla_host_t *vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = vha->hw;

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

3801 3802
	switch (state) {
	case pci_channel_io_normal:
3803
		ha->flags.eeh_busy = 0;
3804 3805
		return PCI_ERS_RESULT_CAN_RECOVER;
	case pci_channel_io_frozen:
3806
		ha->flags.eeh_busy = 1;
3807 3808
		/* For ISP82XX complete any pending mailbox cmd */
		if (IS_QLA82XX(ha)) {
3809
			ha->flags.isp82xx_fw_hung = 1;
3810 3811 3812 3813 3814 3815 3816 3817
			if (ha->flags.mbox_busy) {
				ha->flags.mbox_int = 1;
				DEBUG2(qla_printk(KERN_ERR, ha,
					"Due to pci channel io frozen, doing premature "
					"completion of mbx command\n"));
				complete(&ha->mbx_intr_comp);
			}
		}
3818
		qla2x00_free_irqs(vha);
3819
		pci_disable_device(pdev);
3820 3821
		/* Return back all IOs */
		qla2x00_abort_all_cmds(vha, DID_RESET << 16);
3822 3823
		return PCI_ERS_RESULT_NEED_RESET;
	case pci_channel_io_perm_failure:
3824 3825
		ha->flags.pci_channel_io_perm_failure = 1;
		qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836
		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;
3837 3838
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3839 3840 3841
	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
	struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;

3842 3843 3844
	if (IS_QLA82XX(ha))
		return PCI_ERS_RESULT_RECOVERED;

3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863
	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");
3864
		ha->isp_ops->fw_dump(base_vha, 0);
3865 3866 3867 3868 3869 3870

		return PCI_ERS_RESULT_NEED_RESET;
	} else
		return PCI_ERS_RESULT_RECOVERED;
}

3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948
uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
{
	uint32_t rval = QLA_FUNCTION_FAILED;
	uint32_t drv_active = 0;
	struct qla_hw_data *ha = base_vha->hw;
	int fn;
	struct pci_dev *other_pdev = NULL;

	DEBUG17(qla_printk(KERN_INFO, ha,
	    "scsi(%ld): In qla82xx_error_recovery\n", base_vha->host_no));

	set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);

	if (base_vha->flags.online) {
		/* Abort all outstanding commands,
		 * so as to be requeued later */
		qla2x00_abort_isp_cleanup(base_vha);
	}


	fn = PCI_FUNC(ha->pdev->devfn);
	while (fn > 0) {
		fn--;
		DEBUG17(qla_printk(KERN_INFO, ha,
		    "Finding pci device at function = 0x%x\n", fn));
		other_pdev =
		    pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
		    ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
		    fn));

		if (!other_pdev)
			continue;
		if (atomic_read(&other_pdev->enable_cnt)) {
			DEBUG17(qla_printk(KERN_INFO, ha,
			    "Found PCI func availabe and enabled at 0x%x\n",
			    fn));
			pci_dev_put(other_pdev);
			break;
		}
		pci_dev_put(other_pdev);
	}

	if (!fn) {
		/* Reset owner */
		DEBUG17(qla_printk(KERN_INFO, ha,
		    "This devfn is reset owner = 0x%x\n", ha->pdev->devfn));
		qla82xx_idc_lock(ha);

		qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
		    QLA82XX_DEV_INITIALIZING);

		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
		    QLA82XX_IDC_VERSION);

		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
		DEBUG17(qla_printk(KERN_INFO, ha,
		    "drv_active = 0x%x\n", drv_active));

		qla82xx_idc_unlock(ha);
		/* Reset if device is not already reset
		 * drv_active would be 0 if a reset has already been done
		 */
		if (drv_active)
			rval = qla82xx_start_firmware(base_vha);
		else
			rval = QLA_SUCCESS;
		qla82xx_idc_lock(ha);

		if (rval != QLA_SUCCESS) {
			qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
			qla82xx_clear_drv_active(ha);
			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
			    QLA82XX_DEV_FAILED);
		} else {
			qla_printk(KERN_INFO, ha, "HW State: READY\n");
			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
			    QLA82XX_DEV_READY);
			qla82xx_idc_unlock(ha);
3949
			ha->flags.isp82xx_fw_hung = 0;
3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961
			rval = qla82xx_restart_isp(base_vha);
			qla82xx_idc_lock(ha);
			/* Clear driver state register */
			qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
			qla82xx_set_drv_active(base_vha);
		}
		qla82xx_idc_unlock(ha);
	} else {
		DEBUG17(qla_printk(KERN_INFO, ha,
		    "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
		if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
		    QLA82XX_DEV_READY)) {
3962
			ha->flags.isp82xx_fw_hung = 0;
3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973
			rval = qla82xx_restart_isp(base_vha);
			qla82xx_idc_lock(ha);
			qla82xx_set_drv_active(base_vha);
			qla82xx_idc_unlock(ha);
		}
	}
	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);

	return rval;
}

3974 3975 3976 3977
static pci_ers_result_t
qla2xxx_pci_slot_reset(struct pci_dev *pdev)
{
	pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
3978 3979
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
3980 3981
	struct rsp_que *rsp;
	int rc, retries = 10;
3982

3983 3984
	DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n"));

3985 3986 3987 3988 3989 3990 3991 3992
	/* Workaround: qla2xxx driver which access hardware earlier
	 * needs error state to be pci_channel_io_online.
	 * Otherwise mailbox command timesout.
	 */
	pdev->error_state = pci_channel_io_normal;

	pci_restore_state(pdev);

3993 3994 3995 3996 3997
	/* pci_restore_state() clears the saved_state flag of the device
	 * save restored state which resets saved_state flag
	 */
	pci_save_state(pdev);

3998 3999 4000 4001
	if (ha->mem_only)
		rc = pci_enable_device_mem(pdev);
	else
		rc = pci_enable_device(pdev);
4002

4003
	if (rc) {
4004 4005
		qla_printk(KERN_WARNING, ha,
		    "Can't re-enable PCI device after reset.\n");
4006
		goto exit_slot_reset;
4007 4008
	}

4009 4010
	rsp = ha->rsp_q_map[0];
	if (qla2x00_request_irqs(ha, rsp))
4011
		goto exit_slot_reset;
4012

4013
	if (ha->isp_ops->pci_config(base_vha))
4014 4015 4016 4017 4018 4019 4020 4021 4022
		goto exit_slot_reset;

	if (IS_QLA82XX(ha)) {
		if (qla82xx_error_recovery(base_vha) == QLA_SUCCESS) {
			ret = PCI_ERS_RESULT_RECOVERED;
			goto exit_slot_reset;
		} else
			goto exit_slot_reset;
	}
4023

4024 4025
	while (ha->flags.mbox_busy && retries--)
		msleep(1000);
4026

4027
	set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
4028
	if (ha->isp_ops->abort_isp(base_vha) == QLA_SUCCESS)
4029
		ret =  PCI_ERS_RESULT_RECOVERED;
4030
	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
4031

4032

4033
exit_slot_reset:
4034 4035 4036
	DEBUG17(qla_printk(KERN_WARNING, ha,
	    "slot_reset-return:ret=%x\n", ret));

4037 4038 4039 4040 4041 4042
	return ret;
}

static void
qla2xxx_pci_resume(struct pci_dev *pdev)
{
4043 4044
	scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
	struct qla_hw_data *ha = base_vha->hw;
4045 4046
	int ret;

4047 4048
	DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n"));

4049
	ret = qla2x00_wait_for_hba_online(base_vha);
4050 4051 4052 4053 4054
	if (ret != QLA_SUCCESS) {
		qla_printk(KERN_ERR, ha,
		    "the device failed to resume I/O "
		    "from slot/link_reset");
	}
4055

4056 4057
	pci_cleanup_aer_uncorrect_error_status(pdev);

4058
	ha->flags.eeh_busy = 0;
4059 4060 4061 4062 4063 4064 4065 4066 4067
}

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

4068
static struct pci_device_id qla2xxx_pci_tbl[] = {
4069 4070 4071 4072 4073 4074 4075 4076 4077
	{ 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) },
4078
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
4079 4080
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
4081
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
4082
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
4083
	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) },
4084 4085 4086 4087
	{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);

4088
static struct pci_driver qla2xxx_pci_driver = {
4089
	.name		= QLA2XXX_DRIVER_NAME,
4090 4091 4092
	.driver		= {
		.owner		= THIS_MODULE,
	},
4093
	.id_table	= qla2xxx_pci_tbl,
4094
	.probe		= qla2x00_probe_one,
A
Adrian Bunk 已提交
4095
	.remove		= qla2x00_remove_one,
4096
	.shutdown	= qla2x00_shutdown,
4097
	.err_handler	= &qla2xxx_err_handler,
4098 4099
};

4100 4101
static struct file_operations apidev_fops = {
	.owner = THIS_MODULE,
4102
	.llseek = noop_llseek,
4103 4104
};

L
Linus Torvalds 已提交
4105 4106 4107 4108 4109 4110
/**
 * qla2x00_module_init - Module initialization.
 **/
static int __init
qla2x00_module_init(void)
{
4111 4112
	int ret = 0;

L
Linus Torvalds 已提交
4113
	/* Allocate cache for SRBs. */
4114
	srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
4115
	    SLAB_HWCACHE_ALIGN, NULL);
L
Linus Torvalds 已提交
4116 4117 4118 4119 4120 4121 4122 4123
	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);
4124
	if (ql2xextended_error_logging)
4125 4126
		strcat(qla2x00_version_str, "-debug");

4127 4128
	qla2xxx_transport_template =
	    fc_attach_transport(&qla2xxx_transport_functions);
4129 4130
	if (!qla2xxx_transport_template) {
		kmem_cache_destroy(srb_cachep);
L
Linus Torvalds 已提交
4131
		return -ENODEV;
4132
	}
4133 4134 4135 4136 4137 4138 4139

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

4140 4141 4142 4143 4144
	qla2xxx_transport_vport_template =
	    fc_attach_transport(&qla2xxx_transport_vport_functions);
	if (!qla2xxx_transport_vport_template) {
		kmem_cache_destroy(srb_cachep);
		fc_release_transport(qla2xxx_transport_template);
L
Linus Torvalds 已提交
4145
		return -ENODEV;
4146
	}
L
Linus Torvalds 已提交
4147

4148 4149
	printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
	    qla2x00_version_str);
4150
	ret = pci_register_driver(&qla2xxx_pci_driver);
4151 4152 4153
	if (ret) {
		kmem_cache_destroy(srb_cachep);
		fc_release_transport(qla2xxx_transport_template);
4154
		fc_release_transport(qla2xxx_transport_vport_template);
4155 4156
	}
	return ret;
L
Linus Torvalds 已提交
4157 4158 4159 4160 4161 4162 4163 4164
}

/**
 * qla2x00_module_exit - Module cleanup.
 **/
static void __exit
qla2x00_module_exit(void)
{
4165
	unregister_chrdev(apidev_major, QLA2XXX_APIDEV);
4166
	pci_unregister_driver(&qla2xxx_pci_driver);
4167
	qla2x00_release_firmware();
4168
	kmem_cache_destroy(srb_cachep);
4169 4170
	if (ctx_cachep)
		kmem_cache_destroy(ctx_cachep);
L
Linus Torvalds 已提交
4171
	fc_release_transport(qla2xxx_transport_template);
4172
	fc_release_transport(qla2xxx_transport_vport_template);
L
Linus Torvalds 已提交
4173 4174 4175 4176 4177 4178 4179 4180 4181
}

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);
4182 4183 4184 4185 4186
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);
4187
MODULE_FIRMWARE(FW_FILE_ISP25XX);