[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: Joe Carnuccio <joe.carnuccio@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
Joe Carnuccio 2012-11-21 02:40:37 -05:00 committed by James Bottomley
parent 807fb6d8af
commit 4ea2c9c7b3
2 changed files with 100 additions and 0 deletions

View File

@ -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 *************************************************************/

View File

@ -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);
}