qla_init.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,528 行 · 第 1/5 页
C
2,528 行
* 0 = success. * 1 = error. * 2 = database was full and device was not configured. */static intqla2x00_configure_loop(scsi_qla_host_t *ha) { int rval; unsigned long flags, save_flags; rval = QLA_SUCCESS; /* Get Initiator ID */ if (test_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags)) { rval = qla2x00_configure_hba(ha); if (rval != QLA_SUCCESS) { DEBUG(printk("scsi(%ld): Unable to configure HBA.\n", ha->host_no)); return (rval); } } save_flags = flags = ha->dpc_flags; DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n", ha->host_no, flags)); /* * If we have both an RSCN and PORT UPDATE pending then handle them * both at the same time. */ clear_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); clear_bit(RSCN_UPDATE, &ha->dpc_flags); ha->mem_err = 0 ; /* Determine what we need to do */ if (ha->current_topology == ISP_CFG_FL && (test_bit(LOCAL_LOOP_UPDATE, &flags))) { ha->flags.rscn_queue_overflow = 1; set_bit(RSCN_UPDATE, &flags); } else if (ha->current_topology == ISP_CFG_F && (test_bit(LOCAL_LOOP_UPDATE, &flags))) { ha->flags.rscn_queue_overflow = 1; set_bit(RSCN_UPDATE, &flags); clear_bit(LOCAL_LOOP_UPDATE, &flags); } else if (!ha->flags.online || (test_bit(ABORT_ISP_ACTIVE, &flags))) { ha->flags.rscn_queue_overflow = 1; set_bit(RSCN_UPDATE, &flags); set_bit(LOCAL_LOOP_UPDATE, &flags); } if (test_bit(LOCAL_LOOP_UPDATE, &flags)) { if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { rval = QLA_FUNCTION_FAILED; } else { rval = qla2x00_configure_local_loop(ha); } } if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) { if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { rval = QLA_FUNCTION_FAILED; } else { rval = qla2x00_configure_fabric(ha); } } if (rval == QLA_SUCCESS) { if (atomic_read(&ha->loop_down_timer) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { rval = QLA_FUNCTION_FAILED; } else { qla2x00_config_os(ha); atomic_set(&ha->loop_state, LOOP_READY); DEBUG(printk("scsi(%ld): LOOP READY\n", ha->host_no)); } } if (rval) { DEBUG2_3(printk("%s(%ld): *** FAILED ***\n", __func__, ha->host_no)); } else { DEBUG3(printk("%s: exiting normally\n", __func__)); } /* Restore state if a resync event occured during processing */ if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); if (test_bit(RSCN_UPDATE, &save_flags)) set_bit(RSCN_UPDATE, &ha->dpc_flags); } return (rval);}/* * qla2x00_configure_local_loop * Updates Fibre Channel Device Database with local loop devices. * * Input: * ha = adapter block pointer. * * Returns: * 0 = success. */static intqla2x00_configure_local_loop(scsi_qla_host_t *ha) { int rval, rval2; int found_devs; int found; fc_port_t *fcport, *new_fcport; uint16_t index; uint16_t entries; struct dev_id { uint8_t al_pa; uint8_t area; uint8_t domain; uint8_t loop_id_2100; /* ISP2100/ISP2200 -- 4 bytes. */ uint16_t loop_id; /* ISP23XX -- 6 bytes. */ } *id_list;#define MAX_ID_LIST_SIZE (sizeof(struct dev_id) * MAX_FIBRE_DEVICES) dma_addr_t id_list_dma; char *id_iter; uint16_t loop_id; uint8_t domain, area, al_pa; found_devs = 0; new_fcport = NULL; entries = MAX_FIBRE_DEVICES; id_list = pci_alloc_consistent(ha->pdev, MAX_ID_LIST_SIZE, &id_list_dma); if (id_list == NULL) { DEBUG2(printk("scsi(%ld): Failed to allocate memory, No local " "loop\n", ha->host_no)); qla_printk(KERN_WARNING, ha, "Memory Allocation failed - port_list"); ha->mem_err++; return (QLA_MEMORY_ALLOC_FAILED); } memset(id_list, 0, MAX_ID_LIST_SIZE); DEBUG3(printk("scsi(%ld): Getting FCAL position map\n", ha->host_no)); DEBUG3(qla2x00_get_fcal_position_map(ha, NULL)); /* Get list of logged in devices. */ rval = qla2x00_get_id_list(ha, id_list, id_list_dma, &entries); if (rval != QLA_SUCCESS) { goto cleanup_allocation; } DEBUG3(printk("scsi(%ld): Entries in ID list (%d)\n", ha->host_no, entries)); DEBUG3(qla2x00_dump_buffer((uint8_t *)id_list, entries * sizeof(struct dev_id))); /* Allocate temporary fcport for any new fcports discovered. */ new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); if (new_fcport == NULL) { rval = QLA_MEMORY_ALLOC_FAILED; goto cleanup_allocation; } new_fcport->flags &= ~FCF_FABRIC_DEVICE; /* * Mark local devices that were present with FCF_DEVICE_LOST for now. */ list_for_each_entry(fcport, &ha->fcports, list) { if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->port_type != FCT_BROADCAST && (fcport->flags & FCF_FABRIC_DEVICE) == 0) { DEBUG(printk("scsi(%ld): Marking port lost, " "loop_id=0x%04x\n", ha->host_no, fcport->loop_id)); atomic_set(&fcport->state, FCS_DEVICE_LOST); fcport->flags &= ~FCF_FARP_DONE; } } /* Add devices to port list. */ id_iter = (char *)id_list; for (index = 0; index < entries; index++) { domain = ((struct dev_id *)id_iter)->domain; area = ((struct dev_id *)id_iter)->area; al_pa = ((struct dev_id *)id_iter)->al_pa; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { loop_id = (uint16_t)((struct dev_id *)id_iter)->loop_id_2100; id_iter += 4; } else { loop_id = le16_to_cpu(((struct dev_id *)id_iter)->loop_id); id_iter += 6; } /* Bypass reserved domain fields. */ if ((domain & 0xf0) == 0xf0) continue; /* Bypass if not same domain and area of adapter. */ if (area != ha->d_id.b.area || domain != ha->d_id.b.domain) continue; /* Bypass invalid local loop ID. */ if (loop_id > LAST_LOCAL_LOOP_ID) continue; /* Fill in member data. */ new_fcport->d_id.b.domain = domain; new_fcport->d_id.b.area = area; new_fcport->d_id.b.al_pa = al_pa; new_fcport->loop_id = loop_id; rval2 = qla2x00_get_port_database(ha, new_fcport, 0); if (rval2 != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Failed to retrieve fcport " "information -- get_port_database=%x, " "loop_id=0x%04x\n", ha->host_no, rval2, new_fcport->loop_id)); continue; } /* Check for matching device in port list. */ found = 0; fcport = NULL; list_for_each_entry(fcport, &ha->fcports, list) { if (memcmp(new_fcport->port_name, fcport->port_name, WWN_SIZE)) continue; fcport->flags &= ~(FCF_FABRIC_DEVICE | FCF_PERSISTENT_BOUND); fcport->loop_id = new_fcport->loop_id; fcport->port_type = new_fcport->port_type; fcport->d_id.b24 = new_fcport->d_id.b24; memcpy(fcport->node_name, new_fcport->node_name, WWN_SIZE); found++; break; } if (!found) { /* New device, add to fcports list. */ new_fcport->flags &= ~FCF_PERSISTENT_BOUND; list_add_tail(&new_fcport->list, &ha->fcports); /* Allocate a new replacement fcport. */ fcport = new_fcport; new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); if (new_fcport == NULL) { rval = QLA_MEMORY_ALLOC_FAILED; goto cleanup_allocation; } new_fcport->flags &= ~FCF_FABRIC_DEVICE; } qla2x00_update_fcport(ha, fcport); found_devs++; }cleanup_allocation: pci_free_consistent(ha->pdev, MAX_ID_LIST_SIZE, id_list, id_list_dma); if (new_fcport) kfree(new_fcport); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Configure local loop error exit: " "rval=%x\n", ha->host_no, rval)); } if (found_devs) { ha->device_flags |= DFLG_LOCAL_DEVICES; ha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES; } return (rval);}static voidqla2x00_probe_for_all_luns(scsi_qla_host_t *ha) { fc_port_t *fcport; qla2x00_mark_all_devices_lost(ha); list_for_each_entry(fcport, &ha->fcports, list) { if (fcport->port_type != FCT_TARGET) continue; qla2x00_update_fcport(ha, fcport); }}/* * qla2x00_update_fcport * Updates device on list. * * Input: * ha = adapter block pointer. * fcport = port structure pointer. * * Return: * 0 - Success * BIT_0 - error * * Context: * Kernel context. */static voidqla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport){ uint16_t index; unsigned long flags; srb_t *sp; fcport->ha = ha; fcport->login_retry = 0; fcport->port_login_retry_count = ha->port_down_retry_count * PORT_RETRY_TIME; atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * PORT_RETRY_TIME); fcport->flags &= ~FCF_LOGIN_NEEDED; /* * Check for outstanding cmd on tape Bypass LUN discovery if active * command on tape. */ if (fcport->flags & FCF_TAPE_PRESENT) { spin_lock_irqsave(&ha->hardware_lock, flags); for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { if ((sp = ha->outstanding_cmds[index]) != 0) { if (sp->fclun->fcport == fcport) { atomic_set(&fcport->state, FCS_ONLINE); spin_unlock_irqrestore( &ha->hardware_lock, flags); return; } } } spin_unlock_irqrestore(&ha->hardware_lock, flags); } /* Do LUN discovery. */ if (fcport->port_type == FCT_INITIATOR || fcport->port_type == FCT_BROADCAST) { fcport->device_type = TYPE_PROCESSOR; } else { qla2x00_lun_discovery(ha, fcport); } atomic_set(&fcport->state, FCS_ONLINE);}/* * qla2x00_lun_discovery * Issue SCSI inquiry command for LUN discovery. * * Input: * ha: adapter state pointer. * fcport: FC port structure pointer. * * Context: * Kernel context. */static voidqla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport){ inq_cmd_rsp_t *inq; dma_addr_t inq_dma; uint16_t lun; inq = pci_alloc_consistent(ha->pdev, sizeof(inq_cmd_rsp_t), &inq_dma); if (inq == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - INQ\n"); return; } /* If report LUN works, exit. */ if (qla2x00_rpt_lun_discovery(ha, fcport, inq, inq_dma) != QLA_SUCCESS) { for (lun = 0; lun < ha->max_probe_luns; lun++) { /* Configure LUN. */ qla2x00_cfg_lun(ha, fcport, lun, inq, inq_dma); } } pci_free_consistent(ha->pdev, sizeof(inq_cmd_rsp_t), inq, inq_dma);}/* * qla2x00_rpt_lun_discovery * Issue SCSI report LUN command for LUN discovery. * * Input: * ha: adapter state pointer. * fcport: FC port structure pointer. * * Returns: * qla2x00 local function return status code. * * Context: * Kernel context. */static intqla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, inq_cmd_rsp_t *inq, dma_addr_t inq_dma){ int rval; uint32_t len, cnt; uint16_t lun; rpt_lun_cmd_rsp_t *rlc; dma_addr_t rlc_dma; /* Assume a failed status */ rval = QLA_FUNCTION_FAILED; /* No point in continuing if the device doesn't support RLC */ if ((fcport->flags & FCF_RLC_SUPPORT) == 0) return (rval); rlc = pci_alloc_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), &rlc_dma); if (rlc == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - RLC"); return QLA_MEMORY_ALLOC_FAILED; } rval = qla2x00_report_lun(ha, fcport, rlc, rlc_dma); if (rval != QLA_SUCCESS) { pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), rlc, rlc_dma); return (rval); } /* Always add a fc_lun_t structure for lun 0 -- mid-layer requirement */ qla2x00_add_lun(fcport, 0); /* Configure LUN list. */ len = be32_to_cpu(rlc->list.hdr.len); len /= 8; for (cnt = 0; cnt < len; cnt++) { lun = CHAR_TO_SHORT(rlc->list.lst[cnt].lsb, rlc->list.lst[cnt].msb.b); DEBUG3(printk("scsi(%ld): RLC lun = (%d)\n", ha->host_no, lun)); /* We only support 0 through MAX_LUNS-1 range */ if (lun < MAX_LUNS) { qla2x00_cfg_lun(ha, fcport, lun, inq, inq_dma); } } atomic_set(&fcport->state, FCS_ONLINE); pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), rlc, rlc_dma); return (rval);}/* * qla2x00_report_lun * Issue SCSI report LUN command. * * Input: * ha: adapter state pointer. * fcport: FC port structure pointer. * mem: pointer to dma memory object for report LUN IOCB * packet. * * Returns: * qla2x00 local function return status code. * * Context: * Kernel context. */static intqla2x00_report_lun(scsi_qla_host_t *ha, fc_port_t *fcport, rpt_lun_cmd_rsp_t *rlc, dma_addr_t rlc_dma){ int rval; uint16_t retries; uint16_t comp_status; uint16_t scsi_status; rval = QLA_FUNCTION_FAILED; for (retries = 3; retries; retries--) { memset(rlc, 0, sizeof(rpt_lun_cmd_rsp_t)); rlc->p.cmd.entry_type = COMMAND_A64_TYPE; rlc->p.cmd.entry_count = 1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?