diff options
author | Yaniv Rosner <yanivr@broadcom.com> | 2011-06-13 21:34:33 -0400 |
---|---|---|
committer | David S. Miller <davem@conan.davemloft.net> | 2011-06-15 10:56:58 -0400 |
commit | 3deb8167ea66974b0bc8c13c8ee0beafc02a73a1 (patch) | |
tree | 487225b3f4d3305ba2baadc0aa48904c9ad20203 /drivers/net/bnx2x/bnx2x_main.c | |
parent | 0d40f0d425ec632956547bd8efd8965e5945e1dc (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.c | 74 |
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 | ||
8067 | static 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); | ||
8094 | period_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 | ||
10569 | void 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 | |||
10518 | module_init(bnx2x_init); | 10574 | module_init(bnx2x_init); |
10519 | module_exit(bnx2x_cleanup); | 10575 | module_exit(bnx2x_cleanup); |
10520 | 10576 | ||