aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEliezer Tamir <eliezert@broadcom.com>2008-02-28 14:55:53 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-28 14:55:53 -0500
commit877e9aa4c31d8d1670b21824b819929435f46579 (patch)
tree47b576986291de8ff51e1a1d76642963e2bbe649 /drivers/net
parent615f8fd9c2ab475c420d5baa7def37c5cb0d50d3 (diff)
[BNX2X]: fix HW attentions and error handling
Some of the HW attentions, used to indicate an error were not properly acked. This will cause the driver to endlessly receive interrupts when such an error happens. Had to break the code into smaller chunks because it got too nested. Signed-off-by: Eliezer Tamir <eliezert@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/bnx2x.c229
1 files changed, 150 insertions, 79 deletions
diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c
index 6f987fa10a6..b99e3b72fac 100644
--- a/drivers/net/bnx2x.c
+++ b/drivers/net/bnx2x.c
@@ -4089,8 +4089,8 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
4089 u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_PORT_BASE * port) * 8; 4089 u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_PORT_BASE * port) * 8;
4090 u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : 4090 u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
4091 MISC_REG_AEU_MASK_ATTN_FUNC_0; 4091 MISC_REG_AEU_MASK_ATTN_FUNC_0;
4092 u32 nig_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 : 4092 u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
4093 NIG_REG_MASK_INTERRUPT_PORT0; 4093 NIG_REG_MASK_INTERRUPT_PORT0;
4094 4094
4095 if (~bp->aeu_mask & (asserted & 0xff)) 4095 if (~bp->aeu_mask & (asserted & 0xff))
4096 BNX2X_ERR("IGU ERROR\n"); 4096 BNX2X_ERR("IGU ERROR\n");
@@ -4108,15 +4108,11 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
4108 4108
4109 if (asserted & ATTN_HARD_WIRED_MASK) { 4109 if (asserted & ATTN_HARD_WIRED_MASK) {
4110 if (asserted & ATTN_NIG_FOR_FUNC) { 4110 if (asserted & ATTN_NIG_FOR_FUNC) {
4111 u32 nig_status_port;
4112 u32 nig_int_addr = port ?
4113 NIG_REG_STATUS_INTERRUPT_PORT1 :
4114 NIG_REG_STATUS_INTERRUPT_PORT0;
4115 4111
4116 bp->nig_mask = REG_RD(bp, nig_mask_addr); 4112 /* save nig interrupt mask */
4117 REG_WR(bp, nig_mask_addr, 0); 4113 bp->nig_mask = REG_RD(bp, nig_int_mask_addr);
4114 REG_WR(bp, nig_int_mask_addr, 0);
4118 4115
4119 nig_status_port = REG_RD(bp, nig_int_addr);
4120 bnx2x_link_update(bp); 4116 bnx2x_link_update(bp);
4121 4117
4122 /* handle unicore attn? */ 4118 /* handle unicore attn? */
@@ -4169,15 +4165,132 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
4169 4165
4170 /* now set back the mask */ 4166 /* now set back the mask */
4171 if (asserted & ATTN_NIG_FOR_FUNC) 4167 if (asserted & ATTN_NIG_FOR_FUNC)
4172 REG_WR(bp, nig_mask_addr, bp->nig_mask); 4168 REG_WR(bp, nig_int_mask_addr, bp->nig_mask);
4173} 4169}
4174 4170
4175static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) 4171static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
4176{ 4172{
4177 int port = bp->port; 4173 int port = bp->port;
4178 int index; 4174 int reg_offset;
4175 u32 val;
4176
4177 if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) {
4178
4179 reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
4180 MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
4181
4182 val = REG_RD(bp, reg_offset);
4183 val &= ~AEU_INPUTS_ATTN_BITS_SPIO5;
4184 REG_WR(bp, reg_offset, val);
4185
4186 BNX2X_ERR("SPIO5 hw attention\n");
4187
4188 switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) {
4189 case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G:
4190 /* Fan failure attention */
4191
4192 /* The PHY reset is controled by GPIO 1 */
4193 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
4194 MISC_REGISTERS_GPIO_OUTPUT_LOW);
4195 /* Low power mode is controled by GPIO 2 */
4196 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4197 MISC_REGISTERS_GPIO_OUTPUT_LOW);
4198 /* mark the failure */
4199 bp->ext_phy_config &=
4200 ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
4201 bp->ext_phy_config |=
4202 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
4203 SHMEM_WR(bp,
4204 dev_info.port_hw_config[port].
4205 external_phy_config,
4206 bp->ext_phy_config);
4207 /* log the failure */
4208 printk(KERN_ERR PFX "Fan Failure on Network"
4209 " Controller %s has caused the driver to"
4210 " shutdown the card to prevent permanent"
4211 " damage. Please contact Dell Support for"
4212 " assistance\n", bp->dev->name);
4213 break;
4214
4215 default:
4216 break;
4217 }
4218 }
4219}
4220
4221static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
4222{
4223 u32 val;
4224
4225 if (attn & BNX2X_DOORQ_ASSERT) {
4226
4227 val = REG_RD(bp, DORQ_REG_DORQ_INT_STS_CLR);
4228 BNX2X_ERR("DB hw attention 0x%x\n", val);
4229 /* DORQ discard attention */
4230 if (val & 0x2)
4231 BNX2X_ERR("FATAL error from DORQ\n");
4232 }
4233}
4234
4235static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
4236{
4237 u32 val;
4238
4239 if (attn & AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) {
4240
4241 val = REG_RD(bp, CFC_REG_CFC_INT_STS_CLR);
4242 BNX2X_ERR("CFC hw attention 0x%x\n", val);
4243 /* CFC error attention */
4244 if (val & 0x2)
4245 BNX2X_ERR("FATAL error from CFC\n");
4246 }
4247
4248 if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
4249
4250 val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
4251 BNX2X_ERR("PXP hw attention 0x%x\n", val);
4252 /* RQ_USDMDP_FIFO_OVERFLOW */
4253 if (val & 0x18000)
4254 BNX2X_ERR("FATAL error from PXP\n");
4255 }
4256}
4257
4258static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
4259{
4260 if (attn & EVEREST_GEN_ATTN_IN_USE_MASK) {
4261
4262 if (attn & BNX2X_MC_ASSERT_BITS) {
4263
4264 BNX2X_ERR("MC assert!\n");
4265 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0);
4266 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_9, 0);
4267 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_8, 0);
4268 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_7, 0);
4269 bnx2x_panic();
4270
4271 } else if (attn & BNX2X_MCP_ASSERT) {
4272
4273 BNX2X_ERR("MCP assert!\n");
4274 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_11, 0);
4275 bnx2x_mc_assert(bp);
4276
4277 } else
4278 BNX2X_ERR("Unknown HW assert! (attn 0x%x)\n", attn);
4279 }
4280
4281 if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) {
4282
4283 REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff);
4284 BNX2X_ERR("LATCHED attention 0x%x (masked)\n", attn);
4285 }
4286}
4287
4288static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
4289{
4179 struct attn_route attn; 4290 struct attn_route attn;
4180 struct attn_route group_mask; 4291 struct attn_route group_mask;
4292 int port = bp->port;
4293 int index;
4181 u32 reg_addr; 4294 u32 reg_addr;
4182 u32 val; 4295 u32 val;
4183 4296
@@ -4198,64 +4311,14 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
4198 DP(NETIF_MSG_HW, "group[%d]: %llx\n", index, 4311 DP(NETIF_MSG_HW, "group[%d]: %llx\n", index,
4199 (unsigned long long)group_mask.sig[0]); 4312 (unsigned long long)group_mask.sig[0]);
4200 4313
4201 if (attn.sig[3] & group_mask.sig[3] & 4314 bnx2x_attn_int_deasserted3(bp,
4202 EVEREST_GEN_ATTN_IN_USE_MASK) { 4315 attn.sig[3] & group_mask.sig[3]);
4203 4316 bnx2x_attn_int_deasserted1(bp,
4204 if (attn.sig[3] & BNX2X_MC_ASSERT_BITS) { 4317 attn.sig[1] & group_mask.sig[1]);
4205 4318 bnx2x_attn_int_deasserted2(bp,
4206 BNX2X_ERR("MC assert!\n"); 4319 attn.sig[2] & group_mask.sig[2]);
4207 bnx2x_panic(); 4320 bnx2x_attn_int_deasserted0(bp,
4208 4321 attn.sig[0] & group_mask.sig[0]);
4209 } else if (attn.sig[3] & BNX2X_MCP_ASSERT) {
4210
4211 BNX2X_ERR("MCP assert!\n");
4212 REG_WR(bp,
4213 MISC_REG_AEU_GENERAL_ATTN_11, 0);
4214 bnx2x_mc_assert(bp);
4215
4216 } else {
4217 BNX2X_ERR("UNKOWEN HW ASSERT!\n");
4218 }
4219 }
4220
4221 if (attn.sig[1] & group_mask.sig[1] &
4222 BNX2X_DOORQ_ASSERT) {
4223
4224 val = REG_RD(bp, DORQ_REG_DORQ_INT_STS_CLR);
4225 BNX2X_ERR("DB hw attention 0x%x\n", val);
4226 /* DORQ discard attention */
4227 if (val & 0x2)
4228 BNX2X_ERR("FATAL error from DORQ\n");
4229 }
4230
4231 if (attn.sig[2] & group_mask.sig[2] &
4232 AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) {
4233
4234 val = REG_RD(bp, CFC_REG_CFC_INT_STS_CLR);
4235 BNX2X_ERR("CFC hw attention 0x%x\n", val);
4236 /* CFC error attention */
4237 if (val & 0x2)
4238 BNX2X_ERR("FATAL error from CFC\n");
4239 }
4240
4241 if (attn.sig[2] & group_mask.sig[2] &
4242 AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
4243
4244 val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
4245 BNX2X_ERR("PXP hw attention 0x%x\n", val);
4246 /* RQ_USDMDP_FIFO_OVERFLOW */
4247 if (val & 0x18000)
4248 BNX2X_ERR("FATAL error from PXP\n");
4249 }
4250
4251 if (attn.sig[3] & group_mask.sig[3] &
4252 EVEREST_LATCHED_ATTN_IN_USE_MASK) {
4253
4254 REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL,
4255 0x7ff);
4256 DP(NETIF_MSG_HW, "got latched bits 0x%x\n",
4257 attn.sig[3]);
4258 }
4259 4322
4260 if ((attn.sig[0] & group_mask.sig[0] & 4323 if ((attn.sig[0] & group_mask.sig[0] &
4261 HW_INTERRUT_ASSERT_SET_0) || 4324 HW_INTERRUT_ASSERT_SET_0) ||
@@ -4263,7 +4326,15 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
4263 HW_INTERRUT_ASSERT_SET_1) || 4326 HW_INTERRUT_ASSERT_SET_1) ||
4264 (attn.sig[2] & group_mask.sig[2] & 4327 (attn.sig[2] & group_mask.sig[2] &
4265 HW_INTERRUT_ASSERT_SET_2)) 4328 HW_INTERRUT_ASSERT_SET_2))
4266 BNX2X_ERR("FATAL HW block attention\n"); 4329 BNX2X_ERR("FATAL HW block attention"
4330 " set0 0x%x set1 0x%x"
4331 " set2 0x%x\n",
4332 (attn.sig[0] & group_mask.sig[0] &
4333 HW_INTERRUT_ASSERT_SET_0),
4334 (attn.sig[1] & group_mask.sig[1] &
4335 HW_INTERRUT_ASSERT_SET_1),
4336 (attn.sig[2] & group_mask.sig[2] &
4337 HW_INTERRUT_ASSERT_SET_2));
4267 4338
4268 if ((attn.sig[0] & group_mask.sig[0] & 4339 if ((attn.sig[0] & group_mask.sig[0] &
4269 HW_PRTY_ASSERT_SET_0) || 4340 HW_PRTY_ASSERT_SET_0) ||
@@ -4271,7 +4342,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
4271 HW_PRTY_ASSERT_SET_1) || 4342 HW_PRTY_ASSERT_SET_1) ||
4272 (attn.sig[2] & group_mask.sig[2] & 4343 (attn.sig[2] & group_mask.sig[2] &
4273 HW_PRTY_ASSERT_SET_2)) 4344 HW_PRTY_ASSERT_SET_2))
4274 BNX2X_ERR("FATAL HW block parity attention\n"); 4345 BNX2X_ERR("FATAL HW block parity attention\n");
4275 } 4346 }
4276 } 4347 }
4277 4348
@@ -4336,7 +4407,7 @@ static void bnx2x_sp_task(struct work_struct *work)
4336 4407
4337 /* Return here if interrupt is disabled */ 4408 /* Return here if interrupt is disabled */
4338 if (unlikely(atomic_read(&bp->intr_sem) != 0)) { 4409 if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
4339 DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n"); 4410 DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
4340 return; 4411 return;
4341 } 4412 }
4342 4413
@@ -4346,12 +4417,11 @@ static void bnx2x_sp_task(struct work_struct *work)
4346 4417
4347 DP(NETIF_MSG_INTR, "got a slowpath interrupt (updated %x)\n", status); 4418 DP(NETIF_MSG_INTR, "got a slowpath interrupt (updated %x)\n", status);
4348 4419
4349 if (status & 0x1) { 4420 /* HW attentions */
4350 /* HW attentions */ 4421 if (status & 0x1)
4351 bnx2x_attn_int(bp); 4422 bnx2x_attn_int(bp);
4352 }
4353 4423
4354 /* CStorm events: query_stats, cfc delete ramrods */ 4424 /* CStorm events: query_stats, port delete ramrod */
4355 if (status & 0x2) 4425 if (status & 0x2)
4356 bp->stat_pending = 0; 4426 bp->stat_pending = 0;
4357 4427
@@ -4365,6 +4435,7 @@ static void bnx2x_sp_task(struct work_struct *work)
4365 IGU_INT_NOP, 1); 4435 IGU_INT_NOP, 1);
4366 bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, le16_to_cpu(bp->def_t_idx), 4436 bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, le16_to_cpu(bp->def_t_idx),
4367 IGU_INT_ENABLE, 1); 4437 IGU_INT_ENABLE, 1);
4438
4368} 4439}
4369 4440
4370static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) 4441static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
@@ -4374,11 +4445,11 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
4374 4445
4375 /* Return here if interrupt is disabled */ 4446 /* Return here if interrupt is disabled */
4376 if (unlikely(atomic_read(&bp->intr_sem) != 0)) { 4447 if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
4377 DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n"); 4448 DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n");
4378 return IRQ_HANDLED; 4449 return IRQ_HANDLED;
4379 } 4450 }
4380 4451
4381 bnx2x_ack_sb(bp, 16, XSTORM_ID, 0, IGU_INT_DISABLE, 0); 4452 bnx2x_ack_sb(bp, DEF_SB_ID, XSTORM_ID, 0, IGU_INT_DISABLE, 0);
4382 4453
4383#ifdef BNX2X_STOP_ON_ERROR 4454#ifdef BNX2X_STOP_ON_ERROR
4384 if (unlikely(bp->panic)) 4455 if (unlikely(bp->panic))