/** * qla4xxx_mailbox_command - issues mailbox commands * @ha: Pointer to host adapter structure. * @inCount: number of mailbox registers to load. * @outCount: number of mailbox registers to return. * @mbx_cmd: data pointer for mailbox in registers. * @mbx_sts: data pointer for mailbox out registers. * * This routine isssue mailbox commands and waits for completion. * If outCount is 0, this routine completes successfully WITHOUT waiting * for the mailbox command to complete. **/ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts) { int status = QLA_ERROR; uint8_t i; u_long wait_count; uint32_t intr_status; unsigned long flags = 0; /* Make sure that pointers are valid */ if (!mbx_cmd || !mbx_sts) { DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " "pointer\n", ha->host_no, __func__)); return status; } if (is_qla8022(ha) && test_bit(AF_FW_RECOVERY, &ha->flags)) { DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely " "completing mbx cmd as firmware recovery detected\n", ha->host_no, __func__)); return status; } if ((is_aer_supported(ha)) && (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " "timeout MBX Exiting.\n", ha->host_no, __func__)); return status; } /* Mailbox code active */ wait_count = MBOX_TOV * 100; while (wait_count--) { mutex_lock(&ha->mbox_sem); if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { set_bit(AF_MBOX_COMMAND, &ha->flags); mutex_unlock(&ha->mbox_sem); break; } mutex_unlock(&ha->mbox_sem); if (!wait_count) { DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n", ha->host_no, __func__)); return status; } msleep(10); } /* To prevent overwriting mailbox registers for a command that has * not yet been serviced, check to see if an active command * (AEN, IOCB, etc.) is interrupting, then service it. * ----------------------------------------------------------------- */ spin_lock_irqsave(&ha->hardware_lock, flags); if (is_qla8022(ha)) { intr_status = readl(&ha->qla4_8xxx_reg->host_int); if (intr_status & ISRX_82XX_RISC_INT) { /* Service existing interrupt */ DEBUG2(printk("scsi%ld: %s: " "servicing existing interrupt\n", ha->host_no, __func__)); intr_status = readl(&ha->qla4_8xxx_reg->host_status); ha->isp_ops->interrupt_service_routine(ha, intr_status); clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); if (test_bit(AF_INTERRUPTS_ON, &ha->flags) && test_bit(AF_INTx_ENABLED, &ha->flags)) qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); } } else { intr_status = readl(&ha->reg->ctrl_status); if (intr_status & CSR_SCSI_PROCESSOR_INTR) { /* Service existing interrupt */ ha->isp_ops->interrupt_service_routine(ha, intr_status); clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); } } ha->mbox_status_count = outCount; for (i = 0; i < outCount; i++) ha->mbox_status[i] = 0; if (is_qla8022(ha)) { /* Load all mailbox registers, except mailbox 0. */ DEBUG5( printk("scsi%ld: %s: Cmd ", ha->host_no, __func__); for (i = 0; i < inCount; i++) printk("mb%d=%04x ", i, mbx_cmd[i]); printk("\n")); for (i = 1; i < inCount; i++) writel(mbx_cmd[i], &ha->qla4_8xxx_reg->mailbox_in[i]); writel(mbx_cmd[0], &ha->qla4_8xxx_reg->mailbox_in[0]); readl(&ha->qla4_8xxx_reg->mailbox_in[0]); writel(HINT_MBX_INT_PENDING, &ha->qla4_8xxx_reg->hint); } else { /* Load all mailbox registers, except mailbox 0. */ for (i = 1; i < inCount; i++)
/** * qla4xxx_mailbox_command - issues mailbox commands * @ha: Pointer to host adapter structure. * @inCount: number of mailbox registers to load. * @outCount: number of mailbox registers to return. * @mbx_cmd: data pointer for mailbox in registers. * @mbx_sts: data pointer for mailbox out registers. * * This routine issue mailbox commands and waits for completion. * If outCount is 0, this routine completes successfully WITHOUT waiting * for the mailbox command to complete. **/ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts) { int status = QLA_ERROR; uint8_t i; u_long wait_count; uint32_t intr_status; unsigned long flags = 0; uint32_t dev_state; /* Make sure that pointers are valid */ if (!mbx_cmd || !mbx_sts) { DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " "pointer\n", ha->host_no, __func__)); return status; } if (is_qla8022(ha)) { if (test_bit(AF_FW_RECOVERY, &ha->flags)) { DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " "prematurely completing mbx cmd as firmware " "recovery detected\n", ha->host_no, __func__)); return status; } /* Do not send any mbx cmd if h/w is in failed state*/ qla4_8xxx_idc_lock(ha); dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); qla4_8xxx_idc_unlock(ha); if (dev_state == QLA82XX_DEV_FAILED) { ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in " "failed state, do not send any mailbox commands\n", ha->host_no, __func__); return status; } } if ((is_aer_supported(ha)) && (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " "timeout MBX Exiting.\n", ha->host_no, __func__)); return status; } /* Mailbox code active */ wait_count = MBOX_TOV * 100; while (wait_count--) { mutex_lock(&ha->mbox_sem); if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { set_bit(AF_MBOX_COMMAND, &ha->flags); mutex_unlock(&ha->mbox_sem); break; } mutex_unlock(&ha->mbox_sem); if (!wait_count) { DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n", ha->host_no, __func__)); return status; } msleep(10); } spin_lock_irqsave(&ha->hardware_lock, flags); ha->mbox_status_count = outCount; for (i = 0; i < outCount; i++) ha->mbox_status[i] = 0; if (is_qla8022(ha)) { /* Load all mailbox registers, except mailbox 0. */ DEBUG5( printk("scsi%ld: %s: Cmd ", ha->host_no, __func__); for (i = 0; i < inCount; i++) printk("mb%d=%04x ", i, mbx_cmd[i]); printk("\n")); for (i = 1; i < inCount; i++) writel(mbx_cmd[i], &ha->qla4_8xxx_reg->mailbox_in[i]); writel(mbx_cmd[0], &ha->qla4_8xxx_reg->mailbox_in[0]); readl(&ha->qla4_8xxx_reg->mailbox_in[0]); writel(HINT_MBX_INT_PENDING, &ha->qla4_8xxx_reg->hint); } else { /* Load all mailbox registers, except mailbox 0. */ for (i = 1; i < inCount; i++)