bnx2x: Move statistics implementation into semaphores
Commit dff173de84
("bnx2x: Fix statistics locking scheme") changed the
bnx2x locking around statistics state into using a mutex - but the lock
is being accessed via a timer which is forbidden.
[If compiled with CONFIG_DEBUG_MUTEXES, logs show a warning about
accessing the mutex in interrupt context]
This moves the implementation into using a semaphore [with size '1']
instead.
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
31a418986a
commit
c6e36d8c1a
@@ -1774,7 +1774,7 @@ struct bnx2x {
|
|||||||
int stats_state;
|
int stats_state;
|
||||||
|
|
||||||
/* used for synchronization of concurrent threads statistics handling */
|
/* used for synchronization of concurrent threads statistics handling */
|
||||||
struct mutex stats_lock;
|
struct semaphore stats_lock;
|
||||||
|
|
||||||
/* used by dmae command loader */
|
/* used by dmae command loader */
|
||||||
struct dmae_command stats_dmae;
|
struct dmae_command stats_dmae;
|
||||||
|
@@ -12054,7 +12054,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
|
|||||||
mutex_init(&bp->port.phy_mutex);
|
mutex_init(&bp->port.phy_mutex);
|
||||||
mutex_init(&bp->fw_mb_mutex);
|
mutex_init(&bp->fw_mb_mutex);
|
||||||
mutex_init(&bp->drv_info_mutex);
|
mutex_init(&bp->drv_info_mutex);
|
||||||
mutex_init(&bp->stats_lock);
|
sema_init(&bp->stats_lock, 1);
|
||||||
bp->drv_info_mng_owner = false;
|
bp->drv_info_mng_owner = false;
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
|
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
|
||||||
@@ -13690,9 +13690,10 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
|
|||||||
cancel_delayed_work_sync(&bp->sp_task);
|
cancel_delayed_work_sync(&bp->sp_task);
|
||||||
cancel_delayed_work_sync(&bp->period_task);
|
cancel_delayed_work_sync(&bp->period_task);
|
||||||
|
|
||||||
mutex_lock(&bp->stats_lock);
|
if (!down_timeout(&bp->stats_lock, HZ / 10)) {
|
||||||
bp->stats_state = STATS_STATE_DISABLED;
|
bp->stats_state = STATS_STATE_DISABLED;
|
||||||
mutex_unlock(&bp->stats_lock);
|
up(&bp->stats_lock);
|
||||||
|
}
|
||||||
|
|
||||||
bnx2x_save_statistics(bp);
|
bnx2x_save_statistics(bp);
|
||||||
|
|
||||||
|
@@ -1372,19 +1372,23 @@ void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
|
|||||||
* that context in case someone is in the middle of a transition.
|
* that context in case someone is in the middle of a transition.
|
||||||
* For other events, wait a bit until lock is taken.
|
* For other events, wait a bit until lock is taken.
|
||||||
*/
|
*/
|
||||||
if (!mutex_trylock(&bp->stats_lock)) {
|
if (down_trylock(&bp->stats_lock)) {
|
||||||
if (event == STATS_EVENT_UPDATE)
|
if (event == STATS_EVENT_UPDATE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DP(BNX2X_MSG_STATS,
|
DP(BNX2X_MSG_STATS,
|
||||||
"Unlikely stats' lock contention [event %d]\n", event);
|
"Unlikely stats' lock contention [event %d]\n", event);
|
||||||
mutex_lock(&bp->stats_lock);
|
if (unlikely(down_timeout(&bp->stats_lock, HZ / 10))) {
|
||||||
|
BNX2X_ERR("Failed to take stats lock [event %d]\n",
|
||||||
|
event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bnx2x_stats_stm[state][event].action(bp);
|
bnx2x_stats_stm[state][event].action(bp);
|
||||||
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
|
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
|
||||||
|
|
||||||
mutex_unlock(&bp->stats_lock);
|
up(&bp->stats_lock);
|
||||||
|
|
||||||
if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
|
if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
|
||||||
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
|
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
|
||||||
@@ -1970,7 +1974,11 @@ int bnx2x_stats_safe_exec(struct bnx2x *bp,
|
|||||||
/* Wait for statistics to end [while blocking further requests],
|
/* Wait for statistics to end [while blocking further requests],
|
||||||
* then run supplied function 'safely'.
|
* then run supplied function 'safely'.
|
||||||
*/
|
*/
|
||||||
mutex_lock(&bp->stats_lock);
|
rc = down_timeout(&bp->stats_lock, HZ / 10);
|
||||||
|
if (unlikely(rc)) {
|
||||||
|
BNX2X_ERR("Failed to take statistics lock for safe execution\n");
|
||||||
|
goto out_no_lock;
|
||||||
|
}
|
||||||
|
|
||||||
bnx2x_stats_comp(bp);
|
bnx2x_stats_comp(bp);
|
||||||
while (bp->stats_pending && cnt--)
|
while (bp->stats_pending && cnt--)
|
||||||
@@ -1988,7 +1996,7 @@ out:
|
|||||||
/* No need to restart statistics - if they're enabled, the timer
|
/* No need to restart statistics - if they're enabled, the timer
|
||||||
* will restart the statistics.
|
* will restart the statistics.
|
||||||
*/
|
*/
|
||||||
mutex_unlock(&bp->stats_lock);
|
up(&bp->stats_lock);
|
||||||
|
out_no_lock:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user