diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/bnx2x.c | 229 |
1 files changed, 150 insertions, 79 deletions
diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c index 6f987fa10a6d..b99e3b72fac6 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 | ||
4175 | static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) | 4171 | static 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 | |||
4221 | static 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 | |||
4235 | static 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 | |||
4258 | static 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 | |||
4288 | static 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 | ||
4370 | static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) | 4441 | static 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)) |