📄 qla_rscn.c
字号:
mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma))); mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); wmb(); qla2x00_add_iodesc_timer(iodesc); /* Issue command to ISP. */ qla2x00_isp_cmd(ha); if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n", ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); return (QLA_SUCCESS);}/** * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback. * @ha: HA context * @iodesc: io descriptor * @mbxstat: mailbox status IOCB * * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc * will be used for a retry. */static intqla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, struct mbx_entry *mbxstat){ fc_port_t *remote_fcport; remote_fcport = iodesc->remote_fcport; /* Ensure the port IDs are consistent. */ if (remote_fcport->d_id.b24 != iodesc->d_id.b24) { DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port " "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n", ha->host_no, remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa)); return (QLA_SUCCESS); } /* Only process the last command. */ if (remote_fcport->iodesc_idx_sent != iodesc->idx) { DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to " "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, iodesc->idx)); return (QLA_SUCCESS); } if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) { DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " "[%x/%02x%02x%02x] online.\n", ha->host_no, remote_fcport->loop_id, remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); atomic_set(&remote_fcport->state, FCS_ONLINE); } else { DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no, remote_fcport->loop_id, remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0))); if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD) atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); } remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; return (QLA_SUCCESS);}/** * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware. * @ha: HA context * @iodesc: io descriptor * @ha_locked: is function called with the hardware lock * * Returns QLA_SUCCESS if the IOCB was issued. */static intqla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, int ha_locked){ unsigned long flags = 0; struct mbx_entry *mbxentry; /* Send marker if required. */ if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) return (QLA_FUNCTION_FAILED); if (!ha_locked) spin_lock_irqsave(&ha->hardware_lock, flags); /* Build fabric port logout mailbox IOCB. */ mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); if (mbxentry == NULL) { if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); return (QLA_FUNCTION_FAILED); } mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); mbxentry->mb1 = mbxentry->loop_id.extended = cpu_to_le16(iodesc->remote_fcport->loop_id); wmb(); qla2x00_add_iodesc_timer(iodesc); /* Issue command to ISP. */ qla2x00_isp_cmd(ha); if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n", ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); return (QLA_SUCCESS);}/** * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback. * @ha: HA context * @iodesc: io descriptor * @mbxstat: mailbox status IOCB * * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc * will be used for a retry. */static intqla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, struct mbx_entry *mbxstat){ DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], " "status=%x mb0=%x mb1=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id, iodesc->remote_fcport->d_id.b.domain, iodesc->remote_fcport->d_id.b.area, iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1))); return (QLA_SUCCESS);}/** * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware. * @ha: HA context * @iodesc: io descriptor * @d_id: port id for device * @ha_locked: is function called with the hardware lock * * Returns QLA_SUCCESS if the IOCB was issued. */static intqla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, port_id_t *d_id, int ha_locked){ unsigned long flags = 0; struct mbx_entry *mbxentry; /* Send marker if required. */ if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) return (QLA_FUNCTION_FAILED); if (!ha_locked) spin_lock_irqsave(&ha->hardware_lock, flags); /* Build fabric port login mailbox IOCB. */ mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); if (mbxentry == NULL) { if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); return (QLA_FUNCTION_FAILED); } mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT); mbxentry->mb1 = mbxentry->loop_id.extended = cpu_to_le16(iodesc->remote_fcport->loop_id); mbxentry->mb2 = cpu_to_le16(d_id->b.domain); mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa); mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); wmb(); qla2x00_add_iodesc_timer(iodesc); /* Issue command to ISP. */ qla2x00_isp_cmd(ha); if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to " "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area, d_id->b.al_pa)); return (QLA_SUCCESS);}/** * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback. * @ha: HA context * @iodesc: io descriptor * @mbxstat: mailbox status IOCB * * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc * will be used for a retry. */static intqla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, struct mbx_entry *mbxstat){ int rval; fc_port_t *fcport, *remote_fcport, *exist_fcport; struct io_descriptor *abort_iodesc, *login_iodesc; uint16_t status, mb[8]; uint16_t reuse; uint16_t remote_loopid; port_id_t remote_did, inuse_did; remote_fcport = iodesc->remote_fcport; /* Only process the last command. */ if (remote_fcport->iodesc_idx_sent != iodesc->idx) { DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to " "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, iodesc->idx)); /* Free RSCN fcport resources. */ if (remote_fcport->port_type == FCT_RSCN) { DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN " "fcport %p [%x/%02x%02x%02x] given ignored Login " "IOCB.\n", ha->host_no, remote_fcport, remote_fcport->loop_id, remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); list_del(&remote_fcport->list); kfree(remote_fcport); } return (QLA_SUCCESS); } status = le16_to_cpu(mbxstat->status); mb[0] = le16_to_cpu(mbxstat->mb0); mb[1] = le16_to_cpu(mbxstat->mb1); mb[2] = le16_to_cpu(mbxstat->mb2); mb[6] = le16_to_cpu(mbxstat->mb6); mb[7] = le16_to_cpu(mbxstat->mb7); /* Good status? */ if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) && mb[0] == MBS_COMMAND_COMPLETE) { DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn=" "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status, mb[1], mbxstat->port_name[0], mbxstat->port_name[1], mbxstat->port_name[2], mbxstat->port_name[3], mbxstat->port_name[4], mbxstat->port_name[5], mbxstat->port_name[6], mbxstat->port_name[7])); memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE); memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE); /* Is the device already in our fcports list? */ if (remote_fcport->port_type != FCT_RSCN) { DEBUG14(printk("scsi(%ld): Login IOCB -- marking " "[%x/%02x%02x%02x] online.\n", ha->host_no, remote_fcport->loop_id, remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); return (QLA_SUCCESS); } /* Does the RSCN portname already exist in our fcports list? */ exist_fcport = NULL; list_for_each_entry(fcport, &ha->fcports, list) { if (memcmp(remote_fcport->port_name, fcport->port_name, WWN_SIZE) == 0) { exist_fcport = fcport; break; } } if (exist_fcport != NULL) { DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN " "fcport in fcports list [%p].\n", ha->host_no, exist_fcport)); /* Abort any ADISC that could have been sent. */ if (exist_fcport->iodesc_idx_sent != iodesc->idx && exist_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS && ha->io_descriptors[exist_fcport->iodesc_idx_sent]. cb_idx == ADISC_PORT_IOCB_CB) { abort_iodesc = qla2x00_alloc_iodesc(ha); if (abort_iodesc) { DEBUG14(printk("scsi(%ld): Login IOCB " "-- issuing abort to outstanding " "Adisc [%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id, exist_fcport->d_id.b.domain, exist_fcport->d_id.b.area, exist_fcport->d_id.b.al_pa)); abort_iodesc->cb_idx = ABORT_IOCB_CB; abort_iodesc->d_id.b24 = exist_fcport->d_id.b24; abort_iodesc->remote_fcport = exist_fcport; exist_fcport->iodesc_idx_sent = abort_iodesc->idx; qla2x00_send_abort_iocb(ha, abort_iodesc, ha->io_descriptors[ exist_fcport->iodesc_idx_sent]. signature, 1); } else { DEBUG14(printk("scsi(%ld): Login IOCB " "-- unable to abort outstanding " "Adisc [%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id, exist_fcport->d_id.b.domain, exist_fcport->d_id.b.area, exist_fcport->d_id.b.al_pa)); } } /* * If the existing fcport is waiting to send an ADISC * or LOGIN, then reuse remote fcport (RSCN) to * continue waiting. */ reuse = 0; remote_loopid = remote_fcport->loop_id; remote_did.b24 = remote_fcport->d_id.b24; if (exist_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || exist_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) { DEBUG14(printk("scsi(%ld): Login IOCB -- " "existing fcport [%x/%02x%02x%02x] " "waiting for IO descriptor, reuse RSCN " "fcport.\n", ha->host_no, exist_fcport->loop_id, exist_fcport->d_id.b.domain, exist_fcport->d_id.b.area, exist_fcport->d_id.b.al_pa)); reuse++; remote_fcport->iodesc_idx_sent = exist_fcport->iodesc_idx_sent; exist_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; remote_fcport->loop_id = exist_fcport->loop_id; remote_fcport->d_id.b24 = exist_fcport->d_id.b24; } /* Logout the old loopid. */ if (!reuse && exist_fcport->loop_id != remote_fcport->loop_id && exist_fcport->loop_id != FC_NO_LOOP_ID) { login_iodesc = qla2x00_alloc_iodesc(ha); if (login_iodesc) { DEBUG14(printk("scsi(%ld): Login IOCB " "-- issuing logout to free old " "loop id [%x/%02x%02x%02x].\n", ha->host_no, exist_fcport->loop_id, exist_fcport->d_id.b.domain, exist_fcport->d_id.b.area, exist_fcport->d_id.b.al_pa)); login_iodesc->cb_idx = LOGOUT_PORT_IOCB_CB; login_iodesc->d_id.b24 = exist_fcport->d_id.b24; login_iodesc->remote_fcport = exist_fcport; exist_fcport->iodesc_idx_sent = login_iodesc->idx; qla2x00_send_logout_iocb(ha, login_iodesc, 1); } else { /* Ran out of IO descriptiors. */ DEBUG14(printk("scsi(%ld): Login IOCB " "-- unable to logout to free old " "loop id [%x/%02x%02x%02x].\n", ha->host_no, exist_fcport->loop_id, exist_fcport->d_id.b.domain, exist_fcport->d_id.b.area, exist_fcport->d_id.b.al_pa)); exist_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; } } /* Update existing fcport with remote fcport info. */ DEBUG14(printk("scsi(%ld): Login IOCB -- marking " "existing fcport [%x/%02x%02x%02x] online.\n", ha->host_no, remote_loopid, remote_did.b.domain, remote_did.b.area, remote_did.b.al_pa)); memcpy(exist_fcport->node_name, remote_fcport->node_name, WWN_SIZE); exist_fcport->loop_id = remote_loopid; exist_fcport->d_id.b24 = remote_did.b24; qla2x00_update_login_fcport(ha, mbxstat, exist_fcport); /* Finally, free the remote (RSCN) fcport. */ if (!reuse) { DEBUG14(printk("scsi(%ld): Login IOCB -- " "Freeing RSCN fcport %p " "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport, remote_fcport->loop_id, remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); list_del(&remote_fcport->list); kfree(remote_fcport); } return (QLA_SUCCESS); } /* * A new device has been added, move the RSCN fcport to our * fcports list. */ DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport " "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no, remote_fcport->loop_id, remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); list_del(&remote_fcport->list); remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED); qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); list_add_tail(&remote_fcport->list, &ha->fcports); set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags); } else { /* Handle login failure. */ if (remote_fcport->login_retry != 0) { if (mb[0] == MBS_LOOP_ID_USED) { inuse_did.b.domain = LSB(mb[1]); inuse_did.b.area = MSB(mb[2]); inuse_did.b.al_pa = LSB(mb[2]); DEBUG14(printk("scsi(%ld): Login IOCB -- loop " "id [%x] used by port id [%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id, inuse_did.b.domain, inuse_did.b.area, inuse_did.b.al_pa)); if (remote_fcport->d_id.b24 == INVALID_PORT_ID) { /* * Invalid port id means we are trying
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -