/* Get the function number */
spin_lock_irqsave(&ha->hardware_lock, flags);
value = readw(&ha->reg->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* If both IPv4 & IPv6 are enabled, possibly only one *IPaddressmaybeacquired,sochecktoseeifwe
* need to wait for another */ if (is_ipv4_enabled(ha) && is_ipv6_enabled(ha)) { if (((ha->addl_fw_state & FW_ADDSTATE_DHCPv4_ENABLED) != 0) &&
((ha->addl_fw_state &
FW_ADDSTATE_DHCPv4_LEASE_ACQUIRED) == 0)) {
ipv4_wait = 1;
} if (((ha->ip_config.ipv6_addl_options &
IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
((ha->ip_config.ipv6_link_local_state ==
IP_ADDRSTATE_ACQUIRING) ||
(ha->ip_config.ipv6_addr0_state ==
IP_ADDRSTATE_ACQUIRING) ||
(ha->ip_config.ipv6_addr1_state ==
IP_ADDRSTATE_ACQUIRING))) {
if (!(le32_to_cpu(*cap_offset) & BIT_0)) {
ql4_printk(KERN_INFO, ha, "PEX DMA Not supported %d\n",
*cap_offset);
rval = 0;
}
return rval;
}
/** *qla4xxx_alloc_fw_dump-Allocatememoryforminidumpdata. *@ha:pointertohostadapterstructure.
**/ void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha)
{ int status;
uint32_t capture_debug_level; int hdr_entry_bit, k; void *md_tmp;
dma_addr_t md_tmp_dma; struct qla4_8xxx_minidump_template_hdr *md_hdr; int dma_capable;
if (ha->fw_dump) {
ql4_printk(KERN_WARNING, ha, "Firmware dump previously allocated.\n"); return;
}
status = qla4xxx_req_template_size(ha); if (status != QLA_SUCCESS) {
ql4_printk(KERN_INFO, ha, "scsi%ld: Failed to get template size\n",
ha->host_no); return;
}
clear_bit(AF_82XX_FW_DUMPED, &ha->flags);
/* Allocate memory for saving the template */
md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size,
&md_tmp_dma, GFP_KERNEL); if (!md_tmp) {
ql4_printk(KERN_INFO, ha, "scsi%ld: Failed to allocate DMA memory\n",
ha->host_no); return;
}
/* Request template */
status = qla4xxx_get_minidump_template(ha, md_tmp_dma); if (status != QLA_SUCCESS) {
ql4_printk(KERN_INFO, ha, "scsi%ld: Failed to get minidump template\n",
ha->host_no); goto alloc_cleanup;
}
/* Get capture mask based on module loadtime setting. */ if ((ql4xmdcapmask >= 0x3 && ql4xmdcapmask <= 0x7F) ||
(ql4xmdcapmask == 0xFF && dma_capable)) {
ha->fw_dump_capture_mask = ql4xmdcapmask;
} else { if (ql4xmdcapmask == 0xFF)
ql4_printk(KERN_INFO, ha, "Falling back to default capture mask, as PEX DMA is not supported\n");
ha->fw_dump_capture_mask = capture_debug_level;
}
DEBUG2(ql4_printk(KERN_INFO, ha, "Minimum num of entries = %d\n",
md_hdr->num_of_entries));
DEBUG2(ql4_printk(KERN_INFO, ha, "Dump template size = %d\n",
ha->fw_dump_tmplt_size));
DEBUG2(ql4_printk(KERN_INFO, ha, "Selected Capture mask =0x%x\n",
ha->fw_dump_capture_mask));
/* Calculate fw_dump_size */ for (hdr_entry_bit = 0x2, k = 1; (hdr_entry_bit & 0xFF);
hdr_entry_bit <<= 1, k++) { if (hdr_entry_bit & ha->fw_dump_capture_mask)
ha->fw_dump_size += md_hdr->capture_size_array[k];
}
/* Total firmware dump size including command header */
ha->fw_dump_size += ha->fw_dump_tmplt_size;
ha->fw_dump = vmalloc(ha->fw_dump_size); if (!ha->fw_dump) goto alloc_cleanup;
DEBUG2(ql4_printk(KERN_INFO, ha, "Minidump Template Size = 0x%x KB\n",
ha->fw_dump_tmplt_size));
DEBUG2(ql4_printk(KERN_INFO, ha, "Total Minidump size = 0x%x KB\n", ha->fw_dump_size));
DEBUG2(ql4_printk(KERN_INFO, ha, "Waiting for Firmware Ready..\n")); for (timeout_count = ADAPTER_INIT_TOV; timeout_count > 0;
timeout_count--) { if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
qla4xxx_get_dhcp_ip_address(ha);
/* Get firmware state. */ if (qla4xxx_get_firmware_state(ha) != QLA_SUCCESS) {
DEBUG2(printk("scsi%ld: %s: unable to get firmware " "state\n", ha->host_no, __func__)); break;
}
if (ha->firmware_state & FW_STATE_ERROR) {
DEBUG2(printk("scsi%ld: %s: an unrecoverable error has" " occurred\n", ha->host_no, __func__)); break;
} if (ha->firmware_state & FW_STATE_CONFIG_WAIT) { /* *ThefirmwarehasnotyetbeenissuedanInitialize *Firmwarecommand,soissueitnow.
*/ if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) break;
/* Go back and test for ready state - no wait. */ continue;
}
if (ha->firmware_state & FW_STATE_WAIT_AUTOCONNECT) {
DEBUG2(printk(KERN_INFO "scsi%ld: %s: fwstate:" "AUTOCONNECT in progress\n",
ha->host_no, __func__));
}
if (ha->firmware_state == FW_STATE_READY) { /* If DHCP IP Addr is available, retrieve it now. */ if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR,
&ha->dpc_flags))
qla4xxx_get_dhcp_ip_address(ha);
if (!qla4xxx_wait_for_ip_config(ha) ||
timeout_count == 1) {
DEBUG2(ql4_printk(KERN_INFO, ha, "Firmware Ready..\n")); /* The firmware is ready to process SCSI
commands. */
DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: MEDIA TYPE" " - %s\n", ha->host_no,
__func__, (ha->addl_fw_state &
FW_ADDSTATE_OPTICAL_MEDIA)
!= 0 ? "OPTICAL" : "COPPER"));
DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: DHCPv4 STATE" " Enabled %s\n", ha->host_no,
__func__, (ha->addl_fw_state &
FW_ADDSTATE_DHCPv4_ENABLED) != 0 ? "YES" : "NO"));
DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: LINK %s\n",
ha->host_no, __func__,
(ha->addl_fw_state &
FW_ADDSTATE_LINK_UP) != 0 ? "UP" : "DOWN"));
DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: iSNS Service " "Started %s\n",
ha->host_no, __func__,
(ha->addl_fw_state &
FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ? "YES" : "NO"));
if (ha->firmware_state & FW_STATE_CONFIGURING_IP) {
DEBUG2(printk("scsi%ld: %s: FW initialized, but is reporting " "it's waiting to configure an IP address\n",
ha->host_no, __func__));
ready = 1;
} elseif (ha->firmware_state & FW_STATE_WAIT_AUTOCONNECT) {
DEBUG2(printk("scsi%ld: %s: FW initialized, but " "auto-discovery still in process\n",
ha->host_no, __func__));
ready = 1;
}
return ready;
}
/** *qla4xxx_init_firmware-initializesthefirmware. *@ha:pointertohostadapterstructure. *
**/ staticint qla4xxx_init_firmware(struct scsi_qla_host *ha)
{ int status = QLA_ERROR;
if (is_aer_supported(ha) &&
test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) return status;
/* For 82xx, stop firmware before initializing because if BIOS *haspreviouslyinitializedfirmware,thendriver'sinitialize
* firmware will fail. */ if (is_qla80XX(ha))
qla4_8xxx_stop_firmware(ha);
ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) {
DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " "control block\n", ha->host_no, __func__)); return status;
}
if (!qla4xxx_fw_ready(ha)) return status;
if (is_qla80XX(ha) && !test_bit(AF_INIT_DONE, &ha->flags))
qla4xxx_alloc_fw_dump(ha);
return qla4xxx_get_firmware_status(ha);
}
staticvoid qla4xxx_set_model_info(struct scsi_qla_host *ha)
{
uint16_t board_id_string[8]; int i; int size = sizeof(ha->nvram->isp4022.boardIdStr); int offset = offsetof(struct eeprom_data, isp4022.boardIdStr) / 2;
for (i = 0; i < (size / 2) ; i++) {
board_id_string[i] = rd_nvram_word(ha, offset);
offset += 1;
}
memcpy(ha->model_name, board_id_string, size);
}
staticint qla4xxx_config_nvram(struct scsi_qla_host *ha)
{ unsignedlong flags; union external_hw_config_reg extHwConfig;
DEBUG2(printk("scsi%ld: %s: Get EEProm parameters \n", ha->host_no,
__func__)); if (ql4xxx_lock_flash(ha) != QLA_SUCCESS) return QLA_ERROR; if (ql4xxx_lock_nvram(ha) != QLA_SUCCESS) {
ql4xxx_unlock_flash(ha); return QLA_ERROR;
}
/* Get EEPRom Parameters from NVRAM and validate */
ql4_printk(KERN_INFO, ha, "Configuring NVRAM ...\n"); if (qla4xxx_is_nvram_configuration_valid(ha) == QLA_SUCCESS) {
spin_lock_irqsave(&ha->hardware_lock, flags);
extHwConfig.Asuint32_t =
rd_nvram_word(ha, eeprom_ext_hw_conf_offset(ha));
spin_unlock_irqrestore(&ha->hardware_lock, flags);
} else {
ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: EEProm checksum invalid. " "Please update your EEPROM\n", ha->host_no,
__func__);
/* Attempt to set defaults */ if (is_qla4010(ha))
extHwConfig.Asuint32_t = 0x1912; elseif (is_qla4022(ha) | is_qla4032(ha))
extHwConfig.Asuint32_t = 0x0023; else return QLA_ERROR;
}
if (is_qla4022(ha) || is_qla4032(ha))
qla4xxx_set_model_info(ha); else
strcpy(ha->model_name, "QLA4010");
DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n",
ha->host_no, __func__, extHwConfig.Asuint32_t));
/* Wait for firmware to come UP. */
DEBUG2(printk(KERN_INFO "scsi%ld: %s: Wait up to %d seconds for " "boot firmware to complete...\n",
ha->host_no, __func__, FIRMWARE_UP_TOV));
max_wait_time = jiffies + (FIRMWARE_UP_TOV * HZ); do {
uint32_t ctrl_status;
for (idx = 0; idx < max_ddbs; idx = next_idx) {
ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL,
&next_idx, &state, &conn_err,
NULL, NULL); if (ret == QLA_ERROR) {
next_idx++; continue;
} if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
state == DDB_DS_SESSION_FAILED) {
DEBUG2(ql4_printk(KERN_INFO, ha, "Freeing DDB index = 0x%x\n", idx));
ret = qla4xxx_clear_ddb_entry(ha, idx); if (ret == QLA_ERROR)
ql4_printk(KERN_ERR, ha, "Unable to clear DDB index = " "0x%x\n", idx);
} if (next_idx == 0) break;
}
}
/** *qla4xxx_initialize_adapter-initiailizeshba *@ha:Pointertohostadapterstructure. *@is_reset:Isthisinitpathorresetpath * *Thisroutineparformsallofthestepsnecessarytoinitializetheadapter. *
**/ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset)
{ int status = QLA_ERROR;
ha->eeprom_cmd_data = 0;
ql4_printk(KERN_INFO, ha, "Configuring PCI space...\n");
ha->isp_ops->pci_config(ha);
ha->isp_ops->disable_intrs(ha);
/* Initialize the Host adapter request/response queues and firmware */ if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) goto exit_init_hba;
int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, struct ddb_entry *ddb_entry, uint32_t state)
{
uint32_t old_fw_ddb_device_state; int status = QLA_ERROR;
old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB - old state = 0x%x, new state = 0x%x for " "index [%d]\n", __func__,
ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
ddb_entry->fw_ddb_device_state = state;
switch (old_fw_ddb_device_state) { case DDB_DS_LOGIN_IN_PROCESS: switch (state) { case DDB_DS_SESSION_ACTIVE: case DDB_DS_DISCOVERY:
qla4xxx_update_session_conn_param(ha, ddb_entry);
ddb_entry->unblock_sess(ddb_entry->sess);
status = QLA_SUCCESS; break; case DDB_DS_SESSION_FAILED: case DDB_DS_NO_CONNECTION_ACTIVE:
iscsi_conn_login_event(ddb_entry->conn,
ISCSI_CONN_STATE_FREE);
status = QLA_SUCCESS; break;
} break; case DDB_DS_SESSION_ACTIVE: case DDB_DS_DISCOVERY: switch (state) { case DDB_DS_SESSION_FAILED: /* *iscsi_sessionfailurewillcauseuserspaceto *stoptheconnectionwhichinturnwouldblockthe *iscsi_sessionandstartrelogin
*/
iscsi_session_failure(ddb_entry->sess->dd_data,
ISCSI_ERR_CONN_FAILED);
status = QLA_SUCCESS; break; case DDB_DS_NO_CONNECTION_ACTIVE:
clear_bit(fw_ddb_index, ha->ddb_idx_map);
status = QLA_SUCCESS; break;
} break; case DDB_DS_SESSION_FAILED: switch (state) { case DDB_DS_SESSION_ACTIVE: case DDB_DS_DISCOVERY:
ddb_entry->unblock_sess(ddb_entry->sess);
qla4xxx_update_session_conn_param(ha, ddb_entry);
status = QLA_SUCCESS; break; case DDB_DS_SESSION_FAILED:
iscsi_session_failure(ddb_entry->sess->dd_data,
ISCSI_ERR_CONN_FAILED);
status = QLA_SUCCESS; break;
} break; default:
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
__func__)); break;
} return status;
}
int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, struct ddb_entry *ddb_entry, uint32_t state)
{
uint32_t old_fw_ddb_device_state; int status = QLA_ERROR;
old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB - old state = 0x%x, new state = 0x%x for " "index [%d]\n", __func__,
ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
ddb_entry->fw_ddb_device_state = state;
switch (old_fw_ddb_device_state) { case DDB_DS_LOGIN_IN_PROCESS: case DDB_DS_NO_CONNECTION_ACTIVE: switch (state) { case DDB_DS_SESSION_ACTIVE:
ddb_entry->unblock_sess(ddb_entry->sess);
qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
status = QLA_SUCCESS; break; case DDB_DS_SESSION_FAILED:
iscsi_block_session(ddb_entry->sess); if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
qla4xxx_arm_relogin_timer(ddb_entry);
status = QLA_SUCCESS; break;
} break; case DDB_DS_SESSION_ACTIVE: switch (state) { case DDB_DS_SESSION_FAILED:
iscsi_block_session(ddb_entry->sess); if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
qla4xxx_arm_relogin_timer(ddb_entry);
status = QLA_SUCCESS; break;
} break; case DDB_DS_SESSION_FAILED: switch (state) { case DDB_DS_SESSION_ACTIVE:
ddb_entry->unblock_sess(ddb_entry->sess);
qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
status = QLA_SUCCESS; break; case DDB_DS_SESSION_FAILED: if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
qla4xxx_arm_relogin_timer(ddb_entry);
status = QLA_SUCCESS; break;
} break; default:
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
__func__)); break;
} return status;
}
/* check for out of range index */ if (fw_ddb_index >= MAX_DDB_ENTRIES) goto exit_ddb_event;
/* Get the corresponging ddb entry */
ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index); /* Device does not currently exist in our database. */ if (ddb_entry == NULL) {
ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
__func__, fw_ddb_index);
if (state == DDB_DS_NO_CONNECTION_ACTIVE)
clear_bit(fw_ddb_index, ha->ddb_idx_map);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.