📄 qla_init.c
字号:
{ int rval; uint32_t len, cnt; uint16_t lun; /* 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); rval = qla2x00_report_lun(ha, fcport); if (rval != QLA_SUCCESS) return (rval); /* Configure LUN list. */ len = be32_to_cpu(ha->rlc_rsp->list.hdr.len); len /= 8; for (cnt = 0; cnt < len; cnt++) { lun = CHAR_TO_SHORT(ha->rlc_rsp->list.lst[cnt].lsb, ha->rlc_rsp->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); return (rval);}/* * qla2x00_report_lun * Issue SCSI report LUN command. * * Input: * ha: adapter state pointer. * fcport: FC port structure pointer. * * Returns: * qla2x00 local function return status code. * * Context: * Kernel context. */static intqla2x00_report_lun(scsi_qla_host_t *ha, fc_port_t *fcport){ int rval; uint16_t retries; uint16_t comp_status; uint16_t scsi_status; rpt_lun_cmd_rsp_t *rlc; dma_addr_t rlc_dma; rval = QLA_FUNCTION_FAILED; rlc = ha->rlc_rsp; rlc_dma = ha->rlc_rsp_dma; 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; SET_TARGET_ID(ha, rlc->p.cmd.target, fcport->loop_id); rlc->p.cmd.control_flags = __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG); rlc->p.cmd.scsi_cdb[0] = REPORT_LUNS; rlc->p.cmd.scsi_cdb[8] = MSB(sizeof(rpt_lun_lst_t)); rlc->p.cmd.scsi_cdb[9] = LSB(sizeof(rpt_lun_lst_t)); rlc->p.cmd.dseg_count = __constant_cpu_to_le16(1); rlc->p.cmd.timeout = __constant_cpu_to_le16(10); rlc->p.cmd.byte_count = __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); rlc->p.cmd.dseg_0_address[0] = cpu_to_le32( LSD(rlc_dma + sizeof(sts_entry_t))); rlc->p.cmd.dseg_0_address[1] = cpu_to_le32( MSD(rlc_dma + sizeof(sts_entry_t))); rlc->p.cmd.dseg_0_length = __constant_cpu_to_le32(sizeof(rpt_lun_lst_t)); rval = qla2x00_issue_iocb(ha, rlc, rlc_dma, sizeof(rpt_lun_cmd_rsp_t)); comp_status = le16_to_cpu(rlc->p.rsp.comp_status); scsi_status = le16_to_cpu(rlc->p.rsp.scsi_status); if (rval != QLA_SUCCESS || comp_status != CS_COMPLETE || scsi_status & SS_CHECK_CONDITION) { /* Device underrun, treat as OK. */ if (rval == QLA_SUCCESS && comp_status == CS_DATA_UNDERRUN && scsi_status & SS_RESIDUAL_UNDER) { rval = QLA_SUCCESS; break; } DEBUG(printk("scsi(%ld): RLC failed to issue iocb! " "fcport=[%04x/%p] rval=%x cs=%x ss=%x\n", ha->host_no, fcport->loop_id, fcport, rval, comp_status, scsi_status)); rval = QLA_FUNCTION_FAILED; if (scsi_status & SS_CHECK_CONDITION) { DEBUG2(printk("scsi(%ld): RLC " "SS_CHECK_CONDITION Sense Data " "%02x %02x %02x %02x %02x %02x %02x %02x\n", ha->host_no, rlc->p.rsp.req_sense_data[0], rlc->p.rsp.req_sense_data[1], rlc->p.rsp.req_sense_data[2], rlc->p.rsp.req_sense_data[3], rlc->p.rsp.req_sense_data[4], rlc->p.rsp.req_sense_data[5], rlc->p.rsp.req_sense_data[6], rlc->p.rsp.req_sense_data[7])); if (rlc->p.rsp.req_sense_data[2] == ILLEGAL_REQUEST) { fcport->flags &= ~(FCF_RLC_SUPPORT); break; } } } else { break; } } return (rval);}/* * qla2x00_cfg_lun * Configures LUN into fcport LUN list. * * Input: * fcport: FC port structure pointer. * lun: LUN number. * * Context: * Kernel context. */static fc_lun_t *qla2x00_cfg_lun(scsi_qla_host_t *ha, fc_port_t *fcport, uint16_t lun, inq_cmd_rsp_t *inq, dma_addr_t inq_dma) { fc_lun_t *fclun; uint8_t device_type; /* Bypass LUNs that failed. */ if (qla2x00_inquiry(ha, fcport, lun, inq, inq_dma) != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Failed inquiry - loop id=0x%04x " "lun=%d\n", ha->host_no, fcport->loop_id, lun)); return (NULL); } device_type = (inq->inq[0] & 0x1f); switch (device_type) { case TYPE_DISK: case TYPE_PROCESSOR: case TYPE_WORM: case TYPE_ROM: case TYPE_SCANNER: case TYPE_MOD: case TYPE_MEDIUM_CHANGER: case TYPE_ENCLOSURE: case 0x20: case 0x0C: break; case TYPE_TAPE: fcport->flags |= FCF_TAPE_PRESENT; break; default: DEBUG2(printk("scsi(%ld): Unsupported lun type -- " "loop id=0x%04x lun=%d type=%x\n", ha->host_no, fcport->loop_id, lun, device_type)); return (NULL); } fcport->device_type = device_type; fclun = qla2x00_add_lun(fcport, lun); if (fclun != NULL) { atomic_set(&fcport->state, FCS_ONLINE); } return (fclun);}/* * qla2x00_add_lun * Adds LUN to database * * Input: * fcport: FC port structure pointer. * lun: LUN number. * * Context: * Kernel context. */static fc_lun_t *qla2x00_add_lun(fc_port_t *fcport, uint16_t lun){ int found; fc_lun_t *fclun; if (fcport == NULL) { DEBUG(printk("scsi: Unable to add lun to NULL port\n")); return (NULL); } /* Allocate LUN if not already allocated. */ found = 0; list_for_each_entry(fclun, &fcport->fcluns, list) { if (fclun->lun == lun) { found++; break; } } if (found) return (NULL); fclun = kmalloc(sizeof(fc_lun_t), GFP_ATOMIC); if (fclun == NULL) { printk(KERN_WARNING "%s(): Memory Allocation failed - FCLUN\n", __func__); return (NULL); } /* Setup LUN structure. */ memset(fclun, 0, sizeof(fc_lun_t)); fclun->lun = lun; fclun->fcport = fcport; fclun->o_fcport = fcport; fclun->device_type = fcport->device_type; atomic_set(&fcport->state, FCS_UNCONFIGURED); list_add_tail(&fclun->list, &fcport->fcluns); return (fclun);}/* * qla2x00_inquiry * Issue SCSI inquiry command. * * Input: * ha = adapter block pointer. * fcport = FC port structure pointer. * * Return: * 0 - Success * BIT_0 - error * * Context: * Kernel context. */static intqla2x00_inquiry(scsi_qla_host_t *ha, fc_port_t *fcport, uint16_t lun, inq_cmd_rsp_t *inq, dma_addr_t inq_dma){ int rval; uint16_t retries; uint16_t comp_status; uint16_t scsi_status; rval = QLA_FUNCTION_FAILED; for (retries = 3; retries; retries--) { memset(inq, 0, sizeof(inq_cmd_rsp_t)); inq->p.cmd.entry_type = COMMAND_A64_TYPE; inq->p.cmd.entry_count = 1; inq->p.cmd.lun = cpu_to_le16(lun); SET_TARGET_ID(ha, inq->p.cmd.target, fcport->loop_id); inq->p.cmd.control_flags = __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG); inq->p.cmd.scsi_cdb[0] = INQUIRY; inq->p.cmd.scsi_cdb[4] = INQ_DATA_SIZE; inq->p.cmd.dseg_count = __constant_cpu_to_le16(1); inq->p.cmd.timeout = __constant_cpu_to_le16(10); inq->p.cmd.byte_count = __constant_cpu_to_le32(INQ_DATA_SIZE); inq->p.cmd.dseg_0_address[0] = cpu_to_le32( LSD(inq_dma + sizeof(sts_entry_t))); inq->p.cmd.dseg_0_address[1] = cpu_to_le32( MSD(inq_dma + sizeof(sts_entry_t))); inq->p.cmd.dseg_0_length = __constant_cpu_to_le32(INQ_DATA_SIZE); DEBUG5(printk("scsi(%ld): Lun Inquiry - fcport=[%04x/%p]," " lun (%d)\n", ha->host_no, fcport->loop_id, fcport, lun)); rval = qla2x00_issue_iocb(ha, inq, inq_dma, sizeof(inq_cmd_rsp_t)); comp_status = le16_to_cpu(inq->p.rsp.comp_status); scsi_status = le16_to_cpu(inq->p.rsp.scsi_status); DEBUG5(printk("scsi(%ld): lun (%d) inquiry - " "inq[0]= 0x%x, comp status 0x%x, scsi status 0x%x, " "rval=%d\n", ha->host_no, lun, inq->inq[0], comp_status, scsi_status, rval)); if (rval != QLA_SUCCESS || comp_status != CS_COMPLETE || scsi_status & SS_CHECK_CONDITION) { DEBUG(printk("scsi(%ld): INQ failed to issue iocb! " "fcport=[%04x/%p] rval=%x cs=%x ss=%x\n", ha->host_no, fcport->loop_id, fcport, rval, comp_status, scsi_status)); if (rval == QLA_SUCCESS) rval = QLA_FUNCTION_FAILED; if (scsi_status & SS_CHECK_CONDITION) { DEBUG2(printk("scsi(%ld): INQ " "SS_CHECK_CONDITION Sense Data " "%02x %02x %02x %02x %02x %02x %02x %02x\n", ha->host_no, inq->p.rsp.req_sense_data[0], inq->p.rsp.req_sense_data[1], inq->p.rsp.req_sense_data[2], inq->p.rsp.req_sense_data[3], inq->p.rsp.req_sense_data[4], inq->p.rsp.req_sense_data[5], inq->p.rsp.req_sense_data[6], inq->p.rsp.req_sense_data[7])); } /* Device underrun drop LUN. */ if (comp_status == CS_DATA_UNDERRUN && scsi_status & SS_RESIDUAL_UNDER) { break; } } else { break; } } return (rval);}/* * 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]; LIST_HEAD(new_fcports); /* If FL port exists, then SNS is present */ rval = qla2x00_get_port_name(ha, SNS_FL_PORT, NULL, 0); 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); } /* 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 { /* Ensure we are logged into the SNS. */ qla2x00_login_fabric(ha, SIMPLE_NAME_SERVER, 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", SIMPLE_NAME_SERVER, 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, &ha->fcports, list) { 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); if (fcport->loop_id != FC_NO_LOOP_ID && (fcport->flags & FCF_TAPE_PRESENT) == 0 && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_BROADCAST) { qla2x00_fabric_logout(ha, fcport->loop_id); fcport->loop_id = FC_NO_LOOP_ID; } } } /* Starting free loop ID. */ next_loopid = ha->min_external_loopid; /* * Scan through our port list and login entries that need to be * logged in. */ list_for_each_entry(fcport, &ha->fcports, list) { 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-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -