Exemplo n.º 1
0
/**
 * 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++)
Exemplo n.º 2
0
/**
 * 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++)