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

Commit 4ea2c9c7 authored by Joe Carnuccio's avatar Joe Carnuccio Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Add acquiring of risc semaphore before doing ISP reset.



Try to acquire the semaphore; if semaphore is hung then acquire it by force.
The ISP reset clears the semaphore, thereby implicitly releasing it.

Signed-off-by: default avatarJoe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: default avatarSaurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 807fb6d8
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1092,6 +1092,27 @@ struct device_reg_24xx {
	uint32_t unused_6[2];		/* Gap. */
	uint32_t iobase_sdata;
};
/* RISC-RISC semaphore register PCI offet */
#define RISC_REGISTER_BASE_OFFSET	0x7010
#define RISC_REGISTER_WINDOW_OFFET	0x6

/* RISC-RISC semaphore/flag register (risc address 0x7016) */

#define RISC_SEMAPHORE		0x1UL
#define RISC_SEMAPHORE_WE	(RISC_SEMAPHORE << 16)
#define RISC_SEMAPHORE_CLR	(RISC_SEMAPHORE_WE | 0x0UL)
#define RISC_SEMAPHORE_SET	(RISC_SEMAPHORE_WE | RISC_SEMAPHORE)

#define RISC_SEMAPHORE_FORCE		0x8000UL
#define RISC_SEMAPHORE_FORCE_WE		(RISC_SEMAPHORE_FORCE << 16)
#define RISC_SEMAPHORE_FORCE_CLR	(RISC_SEMAPHORE_FORCE_WE | 0x0UL)
#define RISC_SEMAPHORE_FORCE_SET	\
		(RISC_SEMAPHORE_FORCE_WE | RISC_SEMAPHORE_FORCE)

/* RISC semaphore timeouts (ms) */
#define TIMEOUT_SEMAPHORE		2500
#define TIMEOUT_SEMAPHORE_FORCE		2000
#define TIMEOUT_TOTAL_ELAPSED		4500

/* Trace Control *************************************************************/

+79 −0
Original line number Diff line number Diff line
@@ -1095,6 +1095,83 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
		ha->isp_ops->enable_intrs(ha);
}

static void
qla25xx_read_risc_sema_reg(scsi_qla_host_t *vha, uint32_t *data)
{
	struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;

	WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
	*data = RD_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET);

}

static void
qla25xx_write_risc_sema_reg(scsi_qla_host_t *vha, uint32_t data)
{
	struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;

	WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
	WRT_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET, data);
}

static void
qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha)
{
	struct qla_hw_data *ha = vha->hw;
	uint32_t wd32 = 0;
	uint delta_msec = 100;
	uint elapsed_msec = 0;
	uint timeout_msec;
	ulong n;

	if (!IS_QLA25XX(ha) && !IS_QLA2031(ha))
		return;

attempt:
	timeout_msec = TIMEOUT_SEMAPHORE;
	n = timeout_msec / delta_msec;
	while (n--) {
		qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_SET);
		qla25xx_read_risc_sema_reg(vha, &wd32);
		if (wd32 & RISC_SEMAPHORE)
			break;
		msleep(delta_msec);
		elapsed_msec += delta_msec;
		if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
			goto force;
	}

	if (!(wd32 & RISC_SEMAPHORE))
		goto force;

	if (!(wd32 & RISC_SEMAPHORE_FORCE))
		goto acquired;

	qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_CLR);
	timeout_msec = TIMEOUT_SEMAPHORE_FORCE;
	n = timeout_msec / delta_msec;
	while (n--) {
		qla25xx_read_risc_sema_reg(vha, &wd32);
		if (!(wd32 & RISC_SEMAPHORE_FORCE))
			break;
		msleep(delta_msec);
		elapsed_msec += delta_msec;
		if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
			goto force;
	}

	if (wd32 & RISC_SEMAPHORE_FORCE)
		qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_CLR);

	goto attempt;

force:
	qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_SET);

acquired:
	return;
}

/**
 * qla24xx_reset_chip() - Reset ISP24xx chip.
 * @ha: HA context
@@ -1113,6 +1190,8 @@ qla24xx_reset_chip(scsi_qla_host_t *vha)

	ha->isp_ops->disable_intrs(ha);

	qla25xx_manipulate_risc_semaphore(vha);

	/* Perform RISC reset. */
	qla24xx_reset_risc(vha);
}