aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorJoe Carnuccio <joe.carnuccio@qlogic.com>2012-11-21 02:40:37 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-11-30 10:11:16 -0500
commit4ea2c9c7b32f808cb2743f2e349a614aa3a46088 (patch)
tree8ecb3f529a11815db5c783c64df3f521fe0c9567 /drivers/scsi/qla2xxx
parent807fb6d8afad1552c6981256a83bc2c0ce4e2125 (diff)
[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>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h21
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c79
2 files changed, 100 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 59524aa0ab32..be6d61a89edc 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1092,6 +1092,27 @@ struct device_reg_24xx {
1092 uint32_t unused_6[2]; /* Gap. */ 1092 uint32_t unused_6[2]; /* Gap. */
1093 uint32_t iobase_sdata; 1093 uint32_t iobase_sdata;
1094}; 1094};
1095/* RISC-RISC semaphore register PCI offet */
1096#define RISC_REGISTER_BASE_OFFSET 0x7010
1097#define RISC_REGISTER_WINDOW_OFFET 0x6
1098
1099/* RISC-RISC semaphore/flag register (risc address 0x7016) */
1100
1101#define RISC_SEMAPHORE 0x1UL
1102#define RISC_SEMAPHORE_WE (RISC_SEMAPHORE << 16)
1103#define RISC_SEMAPHORE_CLR (RISC_SEMAPHORE_WE | 0x0UL)
1104#define RISC_SEMAPHORE_SET (RISC_SEMAPHORE_WE | RISC_SEMAPHORE)
1105
1106#define RISC_SEMAPHORE_FORCE 0x8000UL
1107#define RISC_SEMAPHORE_FORCE_WE (RISC_SEMAPHORE_FORCE << 16)
1108#define RISC_SEMAPHORE_FORCE_CLR (RISC_SEMAPHORE_FORCE_WE | 0x0UL)
1109#define RISC_SEMAPHORE_FORCE_SET \
1110 (RISC_SEMAPHORE_FORCE_WE | RISC_SEMAPHORE_FORCE)
1111
1112/* RISC semaphore timeouts (ms) */
1113#define TIMEOUT_SEMAPHORE 2500
1114#define TIMEOUT_SEMAPHORE_FORCE 2000
1115#define TIMEOUT_TOTAL_ELAPSED 4500
1095 1116
1096/* Trace Control *************************************************************/ 1117/* Trace Control *************************************************************/
1097 1118
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b7e42a80e165..7464a4731ef6 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1095,6 +1095,83 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
1095 ha->isp_ops->enable_intrs(ha); 1095 ha->isp_ops->enable_intrs(ha);
1096} 1096}
1097 1097
1098static void
1099qla25xx_read_risc_sema_reg(scsi_qla_host_t *vha, uint32_t *data)
1100{
1101 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
1102
1103 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
1104 *data = RD_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET);
1105
1106}
1107
1108static void
1109qla25xx_write_risc_sema_reg(scsi_qla_host_t *vha, uint32_t data)
1110{
1111 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
1112
1113 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
1114 WRT_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET, data);
1115}
1116
1117static void
1118qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha)
1119{
1120 struct qla_hw_data *ha = vha->hw;
1121 uint32_t wd32 = 0;
1122 uint delta_msec = 100;
1123 uint elapsed_msec = 0;
1124 uint timeout_msec;
1125 ulong n;
1126
1127 if (!IS_QLA25XX(ha) && !IS_QLA2031(ha))
1128 return;
1129
1130attempt:
1131 timeout_msec = TIMEOUT_SEMAPHORE;
1132 n = timeout_msec / delta_msec;
1133 while (n--) {
1134 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_SET);
1135 qla25xx_read_risc_sema_reg(vha, &wd32);
1136 if (wd32 & RISC_SEMAPHORE)
1137 break;
1138 msleep(delta_msec);
1139 elapsed_msec += delta_msec;
1140 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
1141 goto force;
1142 }
1143
1144 if (!(wd32 & RISC_SEMAPHORE))
1145 goto force;
1146
1147 if (!(wd32 & RISC_SEMAPHORE_FORCE))
1148 goto acquired;
1149
1150 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_CLR);
1151 timeout_msec = TIMEOUT_SEMAPHORE_FORCE;
1152 n = timeout_msec / delta_msec;
1153 while (n--) {
1154 qla25xx_read_risc_sema_reg(vha, &wd32);
1155 if (!(wd32 & RISC_SEMAPHORE_FORCE))
1156 break;
1157 msleep(delta_msec);
1158 elapsed_msec += delta_msec;
1159 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
1160 goto force;
1161 }
1162
1163 if (wd32 & RISC_SEMAPHORE_FORCE)
1164 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_CLR);
1165
1166 goto attempt;
1167
1168force:
1169 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_SET);
1170
1171acquired:
1172 return;
1173}
1174
1098/** 1175/**
1099 * qla24xx_reset_chip() - Reset ISP24xx chip. 1176 * qla24xx_reset_chip() - Reset ISP24xx chip.
1100 * @ha: HA context 1177 * @ha: HA context
@@ -1113,6 +1190,8 @@ qla24xx_reset_chip(scsi_qla_host_t *vha)
1113 1190
1114 ha->isp_ops->disable_intrs(ha); 1191 ha->isp_ops->disable_intrs(ha);
1115 1192
1193 qla25xx_manipulate_risc_semaphore(vha);
1194
1116 /* Perform RISC reset. */ 1195 /* Perform RISC reset. */
1117 qla24xx_reset_risc(vha); 1196 qla24xx_reset_risc(vha);
1118} 1197}