Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6e36d8c authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller
Browse files

bnx2x: Move statistics implementation into semaphores



Commit dff173de ("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: default avatarYuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: default avatarAriel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 31a41898
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1774,7 +1774,7 @@ struct bnx2x {
	int			stats_state;

	/* used for synchronization of concurrent threads statistics handling */
	struct mutex		stats_lock;
	struct semaphore	stats_lock;

	/* used by dmae command loader */
	struct dmae_command	stats_dmae;
+5 −4
Original line number Diff line number Diff line
@@ -12054,7 +12054,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
	mutex_init(&bp->port.phy_mutex);
	mutex_init(&bp->fw_mb_mutex);
	mutex_init(&bp->drv_info_mutex);
	mutex_init(&bp->stats_lock);
	sema_init(&bp->stats_lock, 1);
	bp->drv_info_mng_owner = false;

	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->period_task);

	mutex_lock(&bp->stats_lock);
	if (!down_timeout(&bp->stats_lock, HZ / 10)) {
		bp->stats_state = STATS_STATE_DISABLED;
	mutex_unlock(&bp->stats_lock);
		up(&bp->stats_lock);
	}

	bnx2x_save_statistics(bp);

+14 −6
Original line number Diff line number Diff line
@@ -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.
	 * 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)
			return;

		DP(BNX2X_MSG_STATS,
		   "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);
	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))
		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],
	 * 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);
	while (bp->stats_pending && cnt--)
@@ -1988,7 +1996,7 @@ int bnx2x_stats_safe_exec(struct bnx2x *bp,
	/* No need to restart statistics - if they're enabled, the timer
	 * will restart the statistics.
	 */
	mutex_unlock(&bp->stats_lock);

	up(&bp->stats_lock);
out_no_lock:
	return rc;
}