📄 qla_init.c
字号:
icb->timeout = __constant_cpu_to_le16(0); if (IS_QLA2100(ha) || IS_QLA2200(ha)) { /* Enable RIO */ icb->firmware_options[0] &= ~BIT_3; icb->add_firmware_options[0] &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); icb->add_firmware_options[0] |= BIT_2; icb->response_accumulation_timer = 3; icb->interrupt_delay_timer = 5; ha->flags.process_response_queue = 1; } else { /* Enable ZIO -- Support mode 5 only. */ timer_mode = icb->add_firmware_options[0] & (BIT_3 | BIT_2 | BIT_1 | BIT_0); icb->add_firmware_options[0] &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); if (ql2xenablezio) timer_mode = BIT_2 | BIT_0; if (timer_mode == (BIT_2 | BIT_0)) { DEBUG2(printk("scsi(%ld): ZIO enabled; timer delay " "(%d).\n", ha->host_no, ql2xintrdelaytimer)); qla_printk(KERN_INFO, ha, "ZIO enabled; timer delay (%d).\n", ql2xintrdelaytimer); icb->add_firmware_options[0] |= timer_mode; icb->interrupt_delay_timer = ql2xintrdelaytimer; ha->flags.process_response_queue = 1; } } if (rval) { DEBUG2_3(printk(KERN_WARNING "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); } return (rval);}/** qla2x00_init_tgt_map* Initializes target map.** Input:* ha = adapter block pointer.** Output:* TGT_Q initialized*/static voidqla2x00_init_tgt_map(scsi_qla_host_t *ha){ uint32_t t; for (t = 0; t < MAX_TARGETS; t++) TGT_Q(ha, t) = (os_tgt_t *)NULL;}/** * qla2x00_alloc_fcport() - Allocate a generic fcport. * @ha: HA context * @flags: allocation flags * * Returns a pointer to the allocated fcport, or NULL, if none available. */fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags){ fc_port_t *fcport; fcport = kmalloc(sizeof(fc_port_t), flags); if (fcport == NULL) return (fcport); /* Setup fcport template structure. */ memset(fcport, 0, sizeof (fc_port_t)); fcport->ha = ha; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; INIT_LIST_HEAD(&fcport->fcluns); return (fcport);}/* * qla2x00_configure_loop * Updates Fibre Channel Device Database with what is actually on loop. * * Input: * ha = adapter block pointer. * * Returns: * 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; char *id_iter; uint16_t loop_id; uint8_t domain, area, al_pa; found_devs = 0; new_fcport = NULL; entries = MAX_FIBRE_DEVICES; 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. */ memset(ha->gid_list, 0, GID_LIST_SIZE); rval = qla2x00_get_id_list(ha, ha->gid_list, ha->gid_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 *)ha->gid_list, entries * sizeof(struct gid_list_info))); /* 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 *)ha->gid_list; for (index = 0; index < entries; index++) { domain = ((struct gid_list_info *)id_iter)->domain; area = ((struct gid_list_info *)id_iter)->area; al_pa = ((struct gid_list_info *)id_iter)->al_pa; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { loop_id = (uint16_t) ((struct gid_list_info *)id_iter)->loop_id_2100; id_iter += 4; } else { loop_id = le16_to_cpu( ((struct gid_list_info *)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: 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 = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &inq_dma); if (inq == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - INQ\n"); return; } /* Always add a fc_lun_t structure for lun 0 -- mid-layer requirement */ qla2x00_add_lun(fcport, 0); /* 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); } } dma_pool_free(ha->s_dma_pool, 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -