Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 477ffb9d authored by David C Somayajulu's avatar David C Somayajulu Committed by James Bottomley
Browse files

[SCSI] qla4xxx: bug fixes



The included patch fixes the following issues:

1. qla3xxx/qla4xxx co-existence issue which can result in a lockup
when qla3xxx driver is unloaded, or when ifdown; ifup is performed on
one of the interfaces correponding to qla3xxx. This is because qla4xxx
HBA supports one ethernet and iscsi interfaces per port. Both iscsi
and ethernet interfaces share the same state machine. The problem has
to do with synchronizing access to the state machine in the event of a
reset

2. mutex_lock() is sometimes not followed by mutex_unlock() prior to
invoking a msleep() in qla4xxx_mailbox_command()

Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 938e2ac0
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -418,7 +418,6 @@ struct scsi_qla_host {
	 * concurrently.
	 */
	struct mutex  mbox_sem;
	wait_queue_head_t mailbox_wait_queue;

	/* temporary mailbox status registers */
	volatile uint8_t mbox_status_count;
+1 −0
Original line number Diff line number Diff line
@@ -76,4 +76,5 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
extern int ql4xextended_error_logging;
extern int ql4xdiscoverywait;
extern int ql4xdontresethba;
extern int ql4_mod_unload;
#endif /* _QLA4x_GBL_H */
+9 −9
Original line number Diff line number Diff line
@@ -958,25 +958,25 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha)
	return status;
}

int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
{
#define QL4_LOCK_DRVR_WAIT	300
#define QL4_LOCK_DRVR_SLEEP	100
#define QL4_LOCK_DRVR_WAIT	30
#define QL4_LOCK_DRVR_SLEEP	1

	int drvr_wait = QL4_LOCK_DRVR_WAIT;
	while (drvr_wait) {
		if (ql4xxx_lock_drvr(a) == 0) {
			msleep(QL4_LOCK_DRVR_SLEEP);
		if (ql4xxx_lock_drvr(ha) == 0) {
			ssleep(QL4_LOCK_DRVR_SLEEP);
			if (drvr_wait) {
				DEBUG2(printk("scsi%ld: %s: Waiting for "
					      "Global Init Semaphore...n",
					      a->host_no,
					      __func__));
					      "Global Init Semaphore(%d)...n",
					      ha->host_no,
					      __func__, drvr_wait));
			}
			drvr_wait -= QL4_LOCK_DRVR_SLEEP;
		} else {
			DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
				      "acquired.n", a->host_no, __func__));
				      "acquired.n", ha->host_no, __func__));
			return QLA_SUCCESS;
		}
	}
+2 −2
Original line number Diff line number Diff line
@@ -433,7 +433,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
					readl(&ha->reg->mailbox[i]);

			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
			wake_up(&ha->mailbox_wait_queue);
		}
	} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
		/* Immediately process the AENs that don't require much work.
@@ -686,6 +685,7 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
			       &ha->reg->ctrl_status);
			readl(&ha->reg->ctrl_status);

			if (!ql4_mod_unload)
				set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);

			break;
+21 −14
Original line number Diff line number Diff line
@@ -29,18 +29,30 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
	u_long wait_count;
	uint32_t intr_status;
	unsigned long flags = 0;
	DECLARE_WAITQUEUE(wait, current);

	mutex_lock(&ha->mbox_sem);

	/* Mailbox code active */
	set_bit(AF_MBOX_COMMAND, &ha->flags);

	/* 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__));
		goto mbox_exit;
		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
@@ -73,8 +85,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

	/* Wait for completion */
	set_current_state(TASK_UNINTERRUPTIBLE);
	add_wait_queue(&ha->mailbox_wait_queue, &wait);

	/*
	 * If we don't want status, don't wait for the mailbox command to
@@ -83,8 +93,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
	 */
	if (outCount == 0) {
		status = QLA_SUCCESS;
		set_current_state(TASK_RUNNING);
		remove_wait_queue(&ha->mailbox_wait_queue, &wait);
		goto mbox_exit;
	}
	/* Wait for command to complete */
@@ -108,8 +116,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
		spin_unlock_irqrestore(&ha->hardware_lock, flags);
		msleep(10);
	}
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&ha->mailbox_wait_queue, &wait);

	/* Check for mailbox timeout. */
	if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
@@ -155,9 +161,10 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

mbox_exit:
	mutex_lock(&ha->mbox_sem);
	clear_bit(AF_MBOX_COMMAND, &ha->flags);
	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
	mutex_unlock(&ha->mbox_sem);
	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);

	return status;
}
Loading