aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x/bnx2x_main.c
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2011-06-13 21:34:33 -0400
committerDavid S. Miller <davem@conan.davemloft.net>2011-06-15 10:56:58 -0400
commit3deb8167ea66974b0bc8c13c8ee0beafc02a73a1 (patch)
tree487225b3f4d3305ba2baadc0aa48904c9ad20203 /drivers/net/bnx2x/bnx2x_main.c
parent0d40f0d425ec632956547bd8efd8965e5945e1dc (diff)
bnx2x: Add a periodic task for link PHY events
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@conan.davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_main.c')
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c74
1 files changed, 65 insertions, 9 deletions
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 29c67029c756..af5721754f65 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -1563,6 +1563,7 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
1563 1563
1564 /* make sure sp_task is not running */ 1564 /* make sure sp_task is not running */
1565 cancel_delayed_work(&bp->sp_task); 1565 cancel_delayed_work(&bp->sp_task);
1566 cancel_delayed_work(&bp->period_task);
1566 flush_workqueue(bnx2x_wq); 1567 flush_workqueue(bnx2x_wq);
1567} 1568}
1568 1569
@@ -2150,7 +2151,8 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
2150 if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) { 2151 if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) {
2151 bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); 2152 bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
2152 bnx2x_link_report(bp); 2153 bnx2x_link_report(bp);
2153 } 2154 } else
2155 queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
2154 bp->link_params.req_line_speed[cfx_idx] = req_line_speed; 2156 bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
2155 return rc; 2157 return rc;
2156 } 2158 }
@@ -2524,6 +2526,15 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
2524 bp->port.pmf = 1; 2526 bp->port.pmf = 1;
2525 DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); 2527 DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
2526 2528
2529 /*
2530 * We need the mb() to ensure the ordering between the writing to
2531 * bp->port.pmf here and reading it from the bnx2x_periodic_task().
2532 */
2533 smp_mb();
2534
2535 /* queue a periodic task */
2536 queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
2537
2527 bnx2x_dcbx_pmf_update(bp); 2538 bnx2x_dcbx_pmf_update(bp);
2528 2539
2529 /* enable nig attention */ 2540 /* enable nig attention */
@@ -3242,8 +3253,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
3242 bnx2x_fan_failure(bp); 3253 bnx2x_fan_failure(bp);
3243 } 3254 }
3244 3255
3245 if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 | 3256 if ((attn & bp->link_vars.aeu_int_mask) && bp->port.pmf) {
3246 AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1)) {
3247 bnx2x_acquire_phy_lock(bp); 3257 bnx2x_acquire_phy_lock(bp);
3248 bnx2x_handle_module_detect_int(&bp->link_params); 3258 bnx2x_handle_module_detect_int(&bp->link_params);
3249 bnx2x_release_phy_lock(bp); 3259 bnx2x_release_phy_lock(bp);
@@ -3360,17 +3370,27 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
3360 if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) 3370 if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
3361 bnx2x_pmf_update(bp); 3371 bnx2x_pmf_update(bp);
3362 3372
3363 /* Always call it here: bnx2x_link_report() will
3364 * prevent the link indication duplication.
3365 */
3366 bnx2x__link_status_update(bp);
3367
3368 if (bp->port.pmf && 3373 if (bp->port.pmf &&
3369 (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && 3374 (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) &&
3370 bp->dcbx_enabled > 0) 3375 bp->dcbx_enabled > 0)
3371 /* start dcbx state machine */ 3376 /* start dcbx state machine */
3372 bnx2x_dcbx_set_params(bp, 3377 bnx2x_dcbx_set_params(bp,
3373 BNX2X_DCBX_STATE_NEG_RECEIVED); 3378 BNX2X_DCBX_STATE_NEG_RECEIVED);
3379 if (bp->link_vars.periodic_flags &
3380 PERIODIC_FLAGS_LINK_EVENT) {
3381 /* sync with link */
3382 bnx2x_acquire_phy_lock(bp);
3383 bp->link_vars.periodic_flags &=
3384 ~PERIODIC_FLAGS_LINK_EVENT;
3385 bnx2x_release_phy_lock(bp);
3386 if (IS_MF(bp))
3387 bnx2x_link_sync_notify(bp);
3388 bnx2x_link_report(bp);
3389 }
3390 /* Always call it here: bnx2x_link_report() will
3391 * prevent the link indication duplication.
3392 */
3393 bnx2x__link_status_update(bp);
3374 } else if (attn & BNX2X_MC_ASSERT_BITS) { 3394 } else if (attn & BNX2X_MC_ASSERT_BITS) {
3375 3395
3376 BNX2X_ERR("MC assert!\n"); 3396 BNX2X_ERR("MC assert!\n");
@@ -8044,6 +8064,37 @@ reset_task_exit:
8044 8064
8045/* end of nic load/unload */ 8065/* end of nic load/unload */
8046 8066
8067static void bnx2x_period_task(struct work_struct *work)
8068{
8069 struct bnx2x *bp = container_of(work, struct bnx2x, period_task.work);
8070
8071 if (!netif_running(bp->dev))
8072 goto period_task_exit;
8073
8074 if (CHIP_REV_IS_SLOW(bp)) {
8075 BNX2X_ERR("period task called on emulation, ignoring\n");
8076 goto period_task_exit;
8077 }
8078
8079 bnx2x_acquire_phy_lock(bp);
8080 /*
8081 * The barrier is needed to ensure the ordering between the writing to
8082 * the bp->port.pmf in the bnx2x_nic_load() or bnx2x_pmf_update() and
8083 * the reading here.
8084 */
8085 smp_mb();
8086 if (bp->port.pmf) {
8087 bnx2x_period_func(&bp->link_params, &bp->link_vars);
8088
8089 /* Re-queue task in 1 sec */
8090 queue_delayed_work(bnx2x_wq, &bp->period_task, 1*HZ);
8091 }
8092
8093 bnx2x_release_phy_lock(bp);
8094period_task_exit:
8095 return;
8096}
8097
8047/* 8098/*
8048 * Init service functions 8099 * Init service functions
8049 */ 8100 */
@@ -9237,7 +9288,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
9237 9288
9238 INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); 9289 INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
9239 INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task); 9290 INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task);
9240 9291 INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
9241 rc = bnx2x_get_hwinfo(bp); 9292 rc = bnx2x_get_hwinfo(bp);
9242 if (rc) 9293 if (rc)
9243 return rc; 9294 return rc;
@@ -10515,6 +10566,11 @@ static void __exit bnx2x_cleanup(void)
10515 destroy_workqueue(bnx2x_wq); 10566 destroy_workqueue(bnx2x_wq);
10516} 10567}
10517 10568
10569void bnx2x_notify_link_changed(struct bnx2x *bp)
10570{
10571 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + BP_FUNC(bp)*sizeof(u32), 1);
10572}
10573
10518module_init(bnx2x_init); 10574module_init(bnx2x_init);
10519module_exit(bnx2x_cleanup); 10575module_exit(bnx2x_cleanup);
10520 10576