diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 280 |
1 files changed, 275 insertions, 5 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 6038aedc1239..2d4f32b4df5c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -778,16 +778,19 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
778 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * | 778 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * |
779 | sizeof(uint16_t); | 779 | sizeof(uint16_t); |
780 | } else if (IS_FWI2_CAPABLE(ha)) { | 780 | } else if (IS_FWI2_CAPABLE(ha)) { |
781 | fixed_size = IS_QLA25XX(ha) ? | 781 | if (IS_QLA81XX(ha)) |
782 | offsetof(struct qla25xx_fw_dump, ext_mem) : | 782 | fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); |
783 | offsetof(struct qla24xx_fw_dump, ext_mem); | 783 | else if (IS_QLA25XX(ha)) |
784 | fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem); | ||
785 | else | ||
786 | fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); | ||
784 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * | 787 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * |
785 | sizeof(uint32_t); | 788 | sizeof(uint32_t); |
786 | if (ha->mqenable) | 789 | if (ha->mqenable) |
787 | mq_size = sizeof(struct qla2xxx_mq_chain); | 790 | mq_size = sizeof(struct qla2xxx_mq_chain); |
788 | 791 | ||
789 | /* Allocate memory for Fibre Channel Event Buffer. */ | 792 | /* Allocate memory for Fibre Channel Event Buffer. */ |
790 | if (!IS_QLA25XX(ha)) | 793 | if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha)) |
791 | goto try_eft; | 794 | goto try_eft; |
792 | 795 | ||
793 | tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, | 796 | tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, |
@@ -988,7 +991,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
988 | &ha->fw_major_version, | 991 | &ha->fw_major_version, |
989 | &ha->fw_minor_version, | 992 | &ha->fw_minor_version, |
990 | &ha->fw_subminor_version, | 993 | &ha->fw_subminor_version, |
991 | &ha->fw_attributes, &ha->fw_memory_size); | 994 | &ha->fw_attributes, &ha->fw_memory_size, |
995 | ha->mpi_version, &ha->mpi_capabilities); | ||
992 | ha->flags.npiv_supported = 0; | 996 | ha->flags.npiv_supported = 0; |
993 | if (IS_QLA2XXX_MIDTYPE(ha) && | 997 | if (IS_QLA2XXX_MIDTYPE(ha) && |
994 | (ha->fw_attributes & BIT_2)) { | 998 | (ha->fw_attributes & BIT_2)) { |
@@ -4252,3 +4256,269 @@ qla84xx_init_chip(scsi_qla_host_t *vha) | |||
4252 | return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED: | 4256 | return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED: |
4253 | QLA_SUCCESS; | 4257 | QLA_SUCCESS; |
4254 | } | 4258 | } |
4259 | |||
4260 | /* 81XX Support **************************************************************/ | ||
4261 | |||
4262 | int | ||
4263 | qla81xx_nvram_config(scsi_qla_host_t *vha) | ||
4264 | { | ||
4265 | int rval; | ||
4266 | struct init_cb_81xx *icb; | ||
4267 | struct nvram_81xx *nv; | ||
4268 | uint32_t *dptr; | ||
4269 | uint8_t *dptr1, *dptr2; | ||
4270 | uint32_t chksum; | ||
4271 | uint16_t cnt; | ||
4272 | struct qla_hw_data *ha = vha->hw; | ||
4273 | |||
4274 | rval = QLA_SUCCESS; | ||
4275 | icb = (struct init_cb_81xx *)ha->init_cb; | ||
4276 | nv = ha->nvram; | ||
4277 | |||
4278 | /* Determine NVRAM starting address. */ | ||
4279 | ha->nvram_size = sizeof(struct nvram_81xx); | ||
4280 | ha->nvram_base = FA_NVRAM_FUNC0_ADDR; | ||
4281 | ha->vpd_size = FA_NVRAM_VPD_SIZE; | ||
4282 | ha->vpd_base = FA_NVRAM_VPD0_ADDR; | ||
4283 | if (PCI_FUNC(ha->pdev->devfn) & 1) { | ||
4284 | ha->nvram_base = FA_NVRAM_FUNC1_ADDR; | ||
4285 | ha->vpd_base = FA_NVRAM_VPD1_ADDR; | ||
4286 | } | ||
4287 | |||
4288 | /* Get VPD data into cache */ | ||
4289 | ha->vpd = ha->nvram + VPD_OFFSET; | ||
4290 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, | ||
4291 | ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4); | ||
4292 | |||
4293 | /* Get NVRAM data into cache and calculate checksum. */ | ||
4294 | dptr = (uint32_t *)nv; | ||
4295 | ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base, | ||
4296 | ha->nvram_size); | ||
4297 | for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) | ||
4298 | chksum += le32_to_cpu(*dptr++); | ||
4299 | |||
4300 | DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); | ||
4301 | DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size)); | ||
4302 | |||
4303 | /* Bad NVRAM data, set defaults parameters. */ | ||
4304 | if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' | ||
4305 | || nv->id[3] != ' ' || | ||
4306 | nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { | ||
4307 | /* Reset NVRAM data. */ | ||
4308 | qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " | ||
4309 | "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], | ||
4310 | le16_to_cpu(nv->nvram_version)); | ||
4311 | qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " | ||
4312 | "invalid -- WWPN) defaults.\n"); | ||
4313 | |||
4314 | /* | ||
4315 | * Set default initialization control block. | ||
4316 | */ | ||
4317 | memset(nv, 0, ha->nvram_size); | ||
4318 | nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); | ||
4319 | nv->version = __constant_cpu_to_le16(ICB_VERSION); | ||
4320 | nv->frame_payload_size = __constant_cpu_to_le16(2048); | ||
4321 | nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); | ||
4322 | nv->exchange_count = __constant_cpu_to_le16(0); | ||
4323 | nv->port_name[0] = 0x21; | ||
4324 | nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); | ||
4325 | nv->port_name[2] = 0x00; | ||
4326 | nv->port_name[3] = 0xe0; | ||
4327 | nv->port_name[4] = 0x8b; | ||
4328 | nv->port_name[5] = 0x1c; | ||
4329 | nv->port_name[6] = 0x55; | ||
4330 | nv->port_name[7] = 0x86; | ||
4331 | nv->node_name[0] = 0x20; | ||
4332 | nv->node_name[1] = 0x00; | ||
4333 | nv->node_name[2] = 0x00; | ||
4334 | nv->node_name[3] = 0xe0; | ||
4335 | nv->node_name[4] = 0x8b; | ||
4336 | nv->node_name[5] = 0x1c; | ||
4337 | nv->node_name[6] = 0x55; | ||
4338 | nv->node_name[7] = 0x86; | ||
4339 | nv->login_retry_count = __constant_cpu_to_le16(8); | ||
4340 | nv->interrupt_delay_timer = __constant_cpu_to_le16(0); | ||
4341 | nv->login_timeout = __constant_cpu_to_le16(0); | ||
4342 | nv->firmware_options_1 = | ||
4343 | __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); | ||
4344 | nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); | ||
4345 | nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); | ||
4346 | nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); | ||
4347 | nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); | ||
4348 | nv->efi_parameters = __constant_cpu_to_le32(0); | ||
4349 | nv->reset_delay = 5; | ||
4350 | nv->max_luns_per_target = __constant_cpu_to_le16(128); | ||
4351 | nv->port_down_retry_count = __constant_cpu_to_le16(30); | ||
4352 | nv->link_down_timeout = __constant_cpu_to_le16(30); | ||
4353 | nv->enode_mac[0] = 0x01; | ||
4354 | nv->enode_mac[1] = 0x02; | ||
4355 | nv->enode_mac[2] = 0x03; | ||
4356 | nv->enode_mac[3] = 0x04; | ||
4357 | nv->enode_mac[4] = 0x05; | ||
4358 | nv->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn); | ||
4359 | |||
4360 | rval = 1; | ||
4361 | } | ||
4362 | |||
4363 | /* Reset Initialization control block */ | ||
4364 | memset(icb, 0, sizeof(struct init_cb_81xx)); | ||
4365 | |||
4366 | /* Copy 1st segment. */ | ||
4367 | dptr1 = (uint8_t *)icb; | ||
4368 | dptr2 = (uint8_t *)&nv->version; | ||
4369 | cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version; | ||
4370 | while (cnt--) | ||
4371 | *dptr1++ = *dptr2++; | ||
4372 | |||
4373 | icb->login_retry_count = nv->login_retry_count; | ||
4374 | |||
4375 | /* Copy 2nd segment. */ | ||
4376 | dptr1 = (uint8_t *)&icb->interrupt_delay_timer; | ||
4377 | dptr2 = (uint8_t *)&nv->interrupt_delay_timer; | ||
4378 | cnt = (uint8_t *)&icb->reserved_5 - | ||
4379 | (uint8_t *)&icb->interrupt_delay_timer; | ||
4380 | while (cnt--) | ||
4381 | *dptr1++ = *dptr2++; | ||
4382 | |||
4383 | memcpy(icb->enode_mac, nv->enode_mac, sizeof(icb->enode_mac)); | ||
4384 | /* Some boards (with valid NVRAMs) still have NULL enode_mac!! */ | ||
4385 | if (!memcmp(icb->enode_mac, "\0\0\0\0\0\0", sizeof(icb->enode_mac))) { | ||
4386 | icb->enode_mac[0] = 0x01; | ||
4387 | icb->enode_mac[1] = 0x02; | ||
4388 | icb->enode_mac[2] = 0x03; | ||
4389 | icb->enode_mac[3] = 0x04; | ||
4390 | icb->enode_mac[4] = 0x05; | ||
4391 | icb->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn); | ||
4392 | } | ||
4393 | |||
4394 | /* | ||
4395 | * Setup driver NVRAM options. | ||
4396 | */ | ||
4397 | qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), | ||
4398 | "QLE81XX"); | ||
4399 | |||
4400 | /* Use alternate WWN? */ | ||
4401 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { | ||
4402 | memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); | ||
4403 | memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); | ||
4404 | } | ||
4405 | |||
4406 | /* Prepare nodename */ | ||
4407 | if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { | ||
4408 | /* | ||
4409 | * Firmware will apply the following mask if the nodename was | ||
4410 | * not provided. | ||
4411 | */ | ||
4412 | memcpy(icb->node_name, icb->port_name, WWN_SIZE); | ||
4413 | icb->node_name[0] &= 0xF0; | ||
4414 | } | ||
4415 | |||
4416 | /* Set host adapter parameters. */ | ||
4417 | ha->flags.disable_risc_code_load = 0; | ||
4418 | ha->flags.enable_lip_reset = 0; | ||
4419 | ha->flags.enable_lip_full_login = | ||
4420 | le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0; | ||
4421 | ha->flags.enable_target_reset = | ||
4422 | le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0; | ||
4423 | ha->flags.enable_led_scheme = 0; | ||
4424 | ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0; | ||
4425 | |||
4426 | ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & | ||
4427 | (BIT_6 | BIT_5 | BIT_4)) >> 4; | ||
4428 | |||
4429 | /* save HBA serial number */ | ||
4430 | ha->serial0 = icb->port_name[5]; | ||
4431 | ha->serial1 = icb->port_name[6]; | ||
4432 | ha->serial2 = icb->port_name[7]; | ||
4433 | memcpy(vha->node_name, icb->node_name, WWN_SIZE); | ||
4434 | memcpy(vha->port_name, icb->port_name, WWN_SIZE); | ||
4435 | |||
4436 | icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); | ||
4437 | |||
4438 | ha->retry_count = le16_to_cpu(nv->login_retry_count); | ||
4439 | |||
4440 | /* Set minimum login_timeout to 4 seconds. */ | ||
4441 | if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout) | ||
4442 | nv->login_timeout = cpu_to_le16(ql2xlogintimeout); | ||
4443 | if (le16_to_cpu(nv->login_timeout) < 4) | ||
4444 | nv->login_timeout = __constant_cpu_to_le16(4); | ||
4445 | ha->login_timeout = le16_to_cpu(nv->login_timeout); | ||
4446 | icb->login_timeout = nv->login_timeout; | ||
4447 | |||
4448 | /* Set minimum RATOV to 100 tenths of a second. */ | ||
4449 | ha->r_a_tov = 100; | ||
4450 | |||
4451 | ha->loop_reset_delay = nv->reset_delay; | ||
4452 | |||
4453 | /* Link Down Timeout = 0: | ||
4454 | * | ||
4455 | * When Port Down timer expires we will start returning | ||
4456 | * I/O's to OS with "DID_NO_CONNECT". | ||
4457 | * | ||
4458 | * Link Down Timeout != 0: | ||
4459 | * | ||
4460 | * The driver waits for the link to come up after link down | ||
4461 | * before returning I/Os to OS with "DID_NO_CONNECT". | ||
4462 | */ | ||
4463 | if (le16_to_cpu(nv->link_down_timeout) == 0) { | ||
4464 | ha->loop_down_abort_time = | ||
4465 | (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT); | ||
4466 | } else { | ||
4467 | ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout); | ||
4468 | ha->loop_down_abort_time = | ||
4469 | (LOOP_DOWN_TIME - ha->link_down_timeout); | ||
4470 | } | ||
4471 | |||
4472 | /* Need enough time to try and get the port back. */ | ||
4473 | ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count); | ||
4474 | if (qlport_down_retry) | ||
4475 | ha->port_down_retry_count = qlport_down_retry; | ||
4476 | |||
4477 | /* Set login_retry_count */ | ||
4478 | ha->login_retry_count = le16_to_cpu(nv->login_retry_count); | ||
4479 | if (ha->port_down_retry_count == | ||
4480 | le16_to_cpu(nv->port_down_retry_count) && | ||
4481 | ha->port_down_retry_count > 3) | ||
4482 | ha->login_retry_count = ha->port_down_retry_count; | ||
4483 | else if (ha->port_down_retry_count > (int)ha->login_retry_count) | ||
4484 | ha->login_retry_count = ha->port_down_retry_count; | ||
4485 | if (ql2xloginretrycount) | ||
4486 | ha->login_retry_count = ql2xloginretrycount; | ||
4487 | |||
4488 | /* Enable ZIO. */ | ||
4489 | if (!vha->flags.init_done) { | ||
4490 | ha->zio_mode = le32_to_cpu(icb->firmware_options_2) & | ||
4491 | (BIT_3 | BIT_2 | BIT_1 | BIT_0); | ||
4492 | ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ? | ||
4493 | le16_to_cpu(icb->interrupt_delay_timer): 2; | ||
4494 | } | ||
4495 | icb->firmware_options_2 &= __constant_cpu_to_le32( | ||
4496 | ~(BIT_3 | BIT_2 | BIT_1 | BIT_0)); | ||
4497 | vha->flags.process_response_queue = 0; | ||
4498 | if (ha->zio_mode != QLA_ZIO_DISABLED) { | ||
4499 | ha->zio_mode = QLA_ZIO_MODE_6; | ||
4500 | |||
4501 | DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay " | ||
4502 | "(%d us).\n", vha->host_no, ha->zio_mode, | ||
4503 | ha->zio_timer * 100)); | ||
4504 | qla_printk(KERN_INFO, ha, | ||
4505 | "ZIO mode %d enabled; timer delay (%d us).\n", | ||
4506 | ha->zio_mode, ha->zio_timer * 100); | ||
4507 | |||
4508 | icb->firmware_options_2 |= cpu_to_le32( | ||
4509 | (uint32_t)ha->zio_mode); | ||
4510 | icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer); | ||
4511 | vha->flags.process_response_queue = 1; | ||
4512 | } | ||
4513 | |||
4514 | if (rval) { | ||
4515 | DEBUG2_3(printk(KERN_WARNING | ||
4516 | "scsi(%ld): NVRAM configuration failed!\n", vha->host_no)); | ||
4517 | } | ||
4518 | return (rval); | ||
4519 | } | ||
4520 | |||
4521 | void | ||
4522 | qla81xx_update_fw_options(scsi_qla_host_t *ha) | ||
4523 | { | ||
4524 | } | ||