ql4_init.c
来自「linux 内核源代码」· C语言 代码 · 共 1,349 行 · 第 1/3 页
C
1,349 行
/* * QLogic iSCSI HBA Driver * Copyright (c) 2003-2006 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */#include "ql4_def.h"#include "ql4_glbl.h"#include "ql4_dbg.h"#include "ql4_inline.h"static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, uint32_t fw_ddb_index);static void ql4xxx_set_mac_number(struct scsi_qla_host *ha){ uint32_t value; uint8_t func_number; unsigned long flags; /* Get the function number */ spin_lock_irqsave(&ha->hardware_lock, flags); value = readw(&ha->reg->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); func_number = (uint8_t) ((value >> 4) & 0x30); switch (value & ISP_CONTROL_FN_MASK) { case ISP_CONTROL_FN0_SCSI: ha->mac_index = 1; break; case ISP_CONTROL_FN1_SCSI: ha->mac_index = 3; break; default: DEBUG2(printk("scsi%ld: %s: Invalid function number, " "ispControlStatus = 0x%x\n", ha->host_no, __func__, value)); break; } DEBUG2(printk("scsi%ld: %s: mac_index %d.\n", ha->host_no, __func__, ha->mac_index));}/** * qla4xxx_free_ddb - deallocate ddb * @ha: pointer to host adapter structure. * @ddb_entry: pointer to device database entry * * This routine deallocates and unlinks the specified ddb_entry from the * adapter's **/static void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry){ /* Remove device entry from list */ list_del_init(&ddb_entry->list); /* Remove device pointer from index mapping arrays */ ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = (struct ddb_entry *) INVALID_ENTRY; ha->tot_ddbs--; /* Free memory and scsi-ml struct for device entry */ qla4xxx_destroy_sess(ddb_entry);}/** * qla4xxx_free_ddb_list - deallocate all ddbs * @ha: pointer to host adapter structure. * * This routine deallocates and removes all devices on the sppecified adapter. **/void qla4xxx_free_ddb_list(struct scsi_qla_host *ha){ struct list_head *ptr; struct ddb_entry *ddb_entry; while (!list_empty(&ha->ddb_list)) { ptr = ha->ddb_list.next; /* Free memory for device entry and remove */ ddb_entry = list_entry(ptr, struct ddb_entry, list); qla4xxx_free_ddb(ha, ddb_entry); }}/** * qla4xxx_init_rings - initialize hw queues * @ha: pointer to host adapter structure. * * This routine initializes the internal queues for the specified adapter. * The QLA4010 requires us to restart the queues at index 0. * The QLA4000 doesn't care, so just default to QLA4010's requirement. **/int qla4xxx_init_rings(struct scsi_qla_host *ha){ unsigned long flags = 0; /* Initialize request queue. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->request_out = 0; ha->request_in = 0; ha->request_ptr = &ha->request_ring[ha->request_in]; ha->req_q_count = REQUEST_QUEUE_DEPTH; /* Initialize response queue. */ ha->response_in = 0; ha->response_out = 0; ha->response_ptr = &ha->response_ring[ha->response_out]; /* * Initialize DMA Shadow registers. The firmware is really supposed to * take care of this, but on some uniprocessor systems, the shadow * registers aren't cleared-- causing the interrupt_handler to think * there are responses to be processed when there aren't. */ ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0); ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0); wmb(); writel(0, &ha->reg->req_q_in); writel(0, &ha->reg->rsp_q_out); readl(&ha->reg->rsp_q_out); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_SUCCESS;}/** * qla4xxx_validate_mac_address - validate adapter MAC address(es) * @ha: pointer to host adapter structure. * **/static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha){ struct flash_sys_info *sys_info; dma_addr_t sys_info_dma; int status = QLA_ERROR; sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info), &sys_info_dma, GFP_KERNEL); if (sys_info == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); goto exit_validate_mac_no_free; } memset(sys_info, 0, sizeof(*sys_info)); /* Get flash sys info */ if (qla4xxx_get_flash(ha, sys_info_dma, FLASH_OFFSET_SYS_INFO, sizeof(*sys_info)) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: get_flash FLASH_OFFSET_SYS_INFO " "failed\n", ha->host_no, __func__)); goto exit_validate_mac; } /* Save M.A.C. address & serial_number */ memcpy(ha->my_mac, &sys_info->physAddr[0].address[0], min(sizeof(ha->my_mac), sizeof(sys_info->physAddr[0].address))); memcpy(ha->serial_number, &sys_info->acSerialNumber, min(sizeof(ha->serial_number), sizeof(sys_info->acSerialNumber))); status = QLA_SUCCESS; exit_validate_mac: dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info, sys_info_dma); exit_validate_mac_no_free: return status;}/** * qla4xxx_init_local_data - initialize adapter specific local data * @ha: pointer to host adapter structure. * **/static int qla4xxx_init_local_data(struct scsi_qla_host *ha){ /* Initilize aen queue */ ha->aen_q_count = MAX_AEN_ENTRIES; return qla4xxx_get_firmware_status(ha);}static int qla4xxx_fw_ready(struct scsi_qla_host *ha){ uint32_t timeout_count; int ready = 0; DEBUG2(dev_info(&ha->pdev->dev, "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) { /* * The firmware has not yet been issued an Initialize * Firmware command, so issue it now. */ 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_READY) { DEBUG2(dev_info(&ha->pdev->dev, "Firmware Ready..\n")); /* The firmware is ready to process SCSI commands. */ DEBUG2(dev_info(&ha->pdev->dev, "scsi%ld: %s: MEDIA TYPE - %s\n", ha->host_no, __func__, (ha->addl_fw_state & FW_ADDSTATE_OPTICAL_MEDIA) != 0 ? "OPTICAL" : "COPPER")); DEBUG2(dev_info(&ha->pdev->dev, "scsi%ld: %s: DHCP STATE Enabled " "%s\n", ha->host_no, __func__, (ha->addl_fw_state & FW_ADDSTATE_DHCP_ENABLED) != 0 ? "YES" : "NO")); DEBUG2(dev_info(&ha->pdev->dev, "scsi%ld: %s: LINK %s\n", ha->host_no, __func__, (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) != 0 ? "UP" : "DOWN")); DEBUG2(dev_info(&ha->pdev->dev, "scsi%ld: %s: iSNS Service " "Started %s\n", ha->host_no, __func__, (ha->addl_fw_state & FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ? "YES" : "NO")); ready = 1; break; } DEBUG2(printk("scsi%ld: %s: waiting on fw, state=%x:%x - " "seconds expired= %d\n", ha->host_no, __func__, ha->firmware_state, ha->addl_fw_state, timeout_count)); if (is_qla4032(ha) && !(ha->addl_fw_state & FW_ADDSTATE_LINK_UP) && (timeout_count < ADAPTER_INIT_TOV - 5)) { break; } msleep(1000); } /* end of for */ if (timeout_count == 0) DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", ha->host_no, __func__)); if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) { DEBUG2(printk("scsi%ld: %s: FW is reporting its waiting to" " grab an IP address from DHCP server\n", ha->host_no, __func__)); ready = 1; } return ready;}/** * qla4xxx_init_firmware - initializes the firmware. * @ha: pointer to host adapter structure. * **/static int qla4xxx_init_firmware(struct scsi_qla_host *ha){ int status = QLA_ERROR; dev_info(&ha->pdev->dev, "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; return qla4xxx_get_firmware_status(ha);}static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index, uint32_t *new_tgt){ struct dev_db_entry *fw_ddb_entry = NULL; dma_addr_t fw_ddb_entry_dma; struct ddb_entry *ddb_entry = NULL; int found = 0; uint32_t device_state; *new_tgt = 0; /* Make sure the dma buffer is valid */ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), &fw_ddb_entry_dma, GFP_KERNEL); if (fw_ddb_entry == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); return NULL; } if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, fw_ddb_entry_dma, NULL, NULL, &device_state, NULL, NULL, NULL) == QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for " "fw_ddb_index %d\n", ha->host_no, __func__, fw_ddb_index)); return NULL; } /* Allocate DDB if not already allocated. */ DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no, __func__, fw_ddb_index)); list_for_each_entry(ddb_entry, &ha->ddb_list, list) { if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name, ISCSI_NAME_SIZE) == 0) { found++; break; } } if (!found) { DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating " "new ddb\n", ha->host_no, __func__, fw_ddb_index)); *new_tgt = 1; ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); } /* if not found allocate new ddb */ dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, fw_ddb_entry_dma); return ddb_entry;}/** * qla4xxx_update_ddb_entry - update driver's internal ddb * @ha: pointer to host adapter structure. * @ddb_entry: pointer to device database structure to be filled * @fw_ddb_index: index of the ddb entry in fw ddb table * * This routine updates the driver's internal device database entry * with information retrieved from the firmware's device database * entry for the specified device. The ddb_entry->fw_ddb_index field * must be initialized prior to calling this routine * **/static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, uint32_t fw_ddb_index){ struct dev_db_entry *fw_ddb_entry = NULL; dma_addr_t fw_ddb_entry_dma; int status = QLA_ERROR; if (ddb_entry == NULL) { DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no, __func__)); goto exit_update_ddb; } /* Make sure the dma buffer is valid */ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), &fw_ddb_entry_dma, GFP_KERNEL); if (fw_ddb_entry == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); goto exit_update_ddb; } if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, fw_ddb_entry_dma, NULL, NULL, &ddb_entry->fw_ddb_device_state, NULL, &ddb_entry->tcp_source_port_num, &ddb_entry->connection_id) == QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for " "fw_ddb_index %d\n", ha->host_no, __func__, fw_ddb_index)); goto exit_update_ddb; } status = QLA_SUCCESS; ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid); ddb_entry->task_mgmt_timeout = le16_to_cpu(fw_ddb_entry->def_timeout); ddb_entry->CmdSn = 0; ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle); ddb_entry->default_relogin_timeout = le16_to_cpu(fw_ddb_entry->def_timeout); ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); /* Update index in case it changed */ ddb_entry->fw_ddb_index = fw_ddb_index; ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry; ddb_entry->port = le16_to_cpu(fw_ddb_entry->port); ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], min(sizeof(ddb_entry->iscsi_name), sizeof(fw_ddb_entry->iscsi_name))); memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0], min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr))); DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n", ha->host_no, __func__, fw_ddb_index, ddb_entry->fw_ddb_device_state, status)); exit_update_ddb: if (fw_ddb_entry) dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, fw_ddb_entry_dma); return status;}/**
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?