qla_init.c
来自「linux 内核源代码」· C语言 代码 · 共 2,472 行 · 第 1/5 页
C
2,472 行
if (fcport->vp_idx != ha->vp_idx) continue; 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; else loop_id = le16_to_cpu( ((struct gid_list_info *)id_iter)->loop_id); id_iter += ha->gid_list_info_size; /* Bypass reserved domain fields. */ if ((domain & 0xf0) == 0xf0) continue; /* Bypass if not same domain and area of adapter. */ if (area && domain && (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; new_fcport->vp_idx = ha->vp_idx; 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)); DEBUG2(printk("scsi(%ld): Scheduling resync...\n", ha->host_no)); set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); continue; } /* Check for matching device in port list. */ found = 0; fcport = NULL; list_for_each_entry(fcport, &pha->fcports, list) { if (fcport->vp_idx != ha->vp_idx) continue; 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; if (ha->parent) { new_fcport->ha = ha; new_fcport->vp_idx = ha->vp_idx; list_add_tail(&new_fcport->vp_fcport, &ha->vp_fcports); } list_add_tail(&new_fcport->list, &pha->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; } /* Base iIDMA settings on HBA port speed. */ fcport->fp_speed = ha->link_data_rate; qla2x00_update_fcport(ha, fcport); found_devs++; }cleanup_allocation: 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, 0); list_for_each_entry(fcport, &ha->fcports, list) { if (fcport->port_type != FCT_TARGET) continue; qla2x00_update_fcport(ha, fcport); }}static voidqla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport){#define LS_UNKNOWN 2 static char *link_speeds[5] = { "1", "2", "?", "4", "8" }; int rval; uint16_t mb[6]; if (!IS_IIDMA_CAPABLE(ha)) return; if (fcport->fp_speed == PORT_SPEED_UNKNOWN || fcport->fp_speed > ha->link_data_rate) return; rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed, mb); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA " "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n", ha->host_no, fcport->port_name[0], fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1])); } else { DEBUG2(qla_printk(KERN_INFO, ha, "iIDMA adjusted to %s GB/s on " "%02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speeds[fcport->fp_speed], fcport->port_name[0], fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], fcport->port_name[7])); }}static voidqla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport){ struct fc_rport_identifiers rport_ids; struct fc_rport *rport; unsigned long flags; if (fcport->drport) qla2x00_rport_del(fcport); if (fcport->rport) return; rport_ids.node_name = wwn_to_u64(fcport->node_name); rport_ids.port_name = wwn_to_u64(fcport->port_name); rport_ids.port_id = fcport->d_id.b.domain << 16 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; rport = fc_remote_port_add(ha->host, 0, &rport_ids); if (!rport) { qla_printk(KERN_WARNING, ha, "Unable to allocate fc remote port!\n"); return; } spin_lock_irqsave(&fcport->rport_lock, flags); fcport->rport = rport; *((fc_port_t **)rport->dd_data) = fcport; spin_unlock_irqrestore(&fcport->rport_lock, flags); rport->supported_classes = fcport->supported_classes; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; if (fcport->port_type == FCT_INITIATOR) rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; if (fcport->port_type == FCT_TARGET) rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; fc_remote_port_rolechg(rport, rport_ids.roles); if (rport->scsi_target_id != -1 && rport->scsi_target_id < ha->host->max_id) fcport->os_target_id = rport->scsi_target_id;}/* * 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. */voidqla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport){ scsi_qla_host_t *pha = to_qla_parent(ha); fcport->ha = ha; fcport->login_retry = 0; fcport->port_login_retry_count = pha->port_down_retry_count * PORT_RETRY_TIME; atomic_set(&fcport->port_down_timer, pha->port_down_retry_count * PORT_RETRY_TIME); fcport->flags &= ~FCF_LOGIN_NEEDED; qla2x00_iidma_fcport(ha, fcport); atomic_set(&fcport->state, FCS_ONLINE); qla2x00_reg_remote_port(ha, fcport);}/* * qla2x00_configure_fabric * Setup SNS devices with loop ID's. * * Input: * ha = adapter block pointer. * * Returns: * 0 = success. * BIT_0 = error */static intqla2x00_configure_fabric(scsi_qla_host_t *ha){ int rval, rval2; fc_port_t *fcport, *fcptemp; uint16_t next_loopid; uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t loop_id; LIST_HEAD(new_fcports); scsi_qla_host_t *pha = to_qla_parent(ha); /* If FL port exists, then SNS is present */ if (IS_FWI2_CAPABLE(ha)) loop_id = NPH_F_PORT; else loop_id = SNS_FL_PORT; rval = qla2x00_get_port_name(ha, loop_id, ha->fabric_node_name, 1); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL " "Port\n", ha->host_no)); ha->device_flags &= ~SWITCH_FOUND; return (QLA_SUCCESS); } ha->device_flags |= SWITCH_FOUND; /* Mark devices that need re-synchronization. */ rval2 = qla2x00_device_resync(ha); if (rval2 == QLA_RSCNS_HANDLED) { /* No point doing the scan, just continue. */ return (QLA_SUCCESS); } do { /* FDMI support. */ if (ql2xfdmienable && test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags)) qla2x00_fdmi_register(ha); /* Ensure we are logged into the SNS. */ if (IS_FWI2_CAPABLE(ha)) loop_id = NPH_SNS; else loop_id = SIMPLE_NAME_SERVER; ha->isp_ops->fabric_login(ha, loop_id, 0xff, 0xff, 0xfc, mb, BIT_1 | BIT_0); if (mb[0] != MBS_COMMAND_COMPLETE) { DEBUG2(qla_printk(KERN_INFO, ha, "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x " "mb[2]=%x mb[6]=%x mb[7]=%x\n", loop_id, mb[0], mb[1], mb[2], mb[6], mb[7])); return (QLA_SUCCESS); } if (test_and_clear_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags)) { if (qla2x00_rft_id(ha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register FC-4 " "TYPE failed.\n", ha->host_no)); } if (qla2x00_rff_id(ha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register FC-4 " "Features failed.\n", ha->host_no)); } if (qla2x00_rnn_id(ha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register Node Name " "failed.\n", ha->host_no)); } else if (qla2x00_rsnn_nn(ha)) { /* EMPTY */ DEBUG2(printk("scsi(%ld): Register Symbolic " "Node Name failed.\n", ha->host_no)); } } rval = qla2x00_find_all_fabric_devs(ha, &new_fcports); if (rval != QLA_SUCCESS) break; /* * Logout all previous fabric devices marked lost, except * tape devices. */ list_for_each_entry(fcport, &pha->fcports, list) { if (fcport->vp_idx !=ha->vp_idx) continue; if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) break; if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) continue; if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) { qla2x00_mark_device_lost(ha, fcport, ql2xplogiabsentdevice, 0); if (fcport->loop_id != FC_NO_LOOP_ID && (fcport->flags & FCF_TAPE_PRESENT) == 0 && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_BROADCAST) { ha->isp_ops->fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->loop_id = FC_NO_LOOP_ID; } } } /* Starting free loop ID. */ next_loopid = pha->min_external_loopid; /* * Scan through our port list and login entries that need to be * logged in. */ list_for_each_entry(fcport, &pha->fcports, list) { if (fcport->vp_idx != ha->vp_idx) continue; if (atomic_read(&ha->loop_down_timer) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) break; if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || (fcport->flags & FCF_LOGIN_NEEDED) == 0) continue; if (fcport->loop_id == FC_NO_LOOP_ID) { fcport->loop_id = next_loopid; rval = qla2x00_find_new_loop_id(ha, fcport); if (rval != QLA_SUCCESS) { /* Ran out of IDs to use */ break; } } /* Login and update database */ qla2x00_fabric_dev_login(ha, fcport, &next_loopid); } /* Exit if out of loop IDs. */ if (rval != QLA_SUCCESS) { break; } /* * Login and add the new devices to our port list. */ list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { if (atomic_read(&ha->loop_down_timer) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) break; /* Find a new loop ID to use. */ fcport->loop_id = next_loopid; rval = qla2x00_find_new_loop_id(ha, fcport); if (rval != QLA_SUCCESS) { /* Ran out of IDs to use */ break; } /* Login and update database */ qla2x00_fabric_dev_login(ha, fcport, &next_loopid); if (ha->parent) { fcport->ha = ha; fcport->vp_idx = ha->vp_idx; list_add_tail(&fcport->vp_fcport, &ha->vp_fcports); list_move_tail(&fcport->list, &ha->parent->fcports); } else list_move_tail(&fcport->list, &ha->fcports); } } while (0); /* Free all new device structures not processed. */ list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { list_del(&fcport->list); kfree(fcport); } if (rval) { DEBUG2(printk("scsi(%ld): Configure fabric error exit: " "rval=%d\n", ha->host_no, rval)); } return (rval);}/* * qla2x00_find_all_fabric_devs * * Input: * ha = adapter block pointer. * dev = database device entry pointer. * * Returns: * 0 = success. * * Context: * Kernel context. */static intqla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports){ int rval; uint16_t loop_id; fc_port_t *fcport, *new_fcport, *fcptemp; int found; sw_info_t *swl; int swl_idx; int first_dev, last_dev; port_id_t wrap, nxt_d_id; int vp_index; int empty_vp_index; int found_vp; scsi_qla_host_t *vha; scsi_qla_host_t *pha = to_qla_parent(ha);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?