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

Commit c540e4a5 authored by David S. Miller's avatar David S. Miller Committed by Zvikomborero Vincent Zvikaramba
Browse files

irda: Fix lockdep annotations in hashbin_delete().



A nested lock depth was added to the hasbin_delete() code but it
doesn't actually work some well and results in tons of lockdep splats.

Fix the code instead to properly drop the lock around the operation
and just keep peeking the head of the hashbin queue.

Change-Id: If21e82c2c9fc38beac61483390c247b2b24a8c7a
Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
Tested-by: default avatarDmitry Vyukov <dvyukov@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 65c03053
Loading
Loading
Loading
Loading
+16 −18
Original line number Diff line number Diff line
@@ -385,9 +385,6 @@ EXPORT_SYMBOL(hashbin_new);
 *    for deallocating this structure if it's complex. If not the user can
 *    just supply kfree, which should take care of the job.
 */
#ifdef CONFIG_LOCKDEP
static int hashbin_lock_depth = 0;
#endif
int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
{
	irda_queue_t* queue;
@@ -398,22 +395,27 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
	IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);

	/* Synchronize */
	if ( hashbin->hb_type & HB_LOCK ) {
		spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags,
					 hashbin_lock_depth++);
	}
	if (hashbin->hb_type & HB_LOCK)
		spin_lock_irqsave(&hashbin->hb_spinlock, flags);

	/*
	 *  Free the entries in the hashbin, TODO: use hashbin_clear when
	 *  it has been shown to work
	 */
	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
		while (1) {
			queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
		while (queue ) {
			if (free_func)
				(*free_func)(queue);
			queue = dequeue_first(
				(irda_queue_t**) &hashbin->hb_queue[i]);

			if (!queue)
				break;

			if (free_func) {
				if (hashbin->hb_type & HB_LOCK)
					spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
				free_func(queue);
				if (hashbin->hb_type & HB_LOCK)
					spin_lock_irqsave(&hashbin->hb_spinlock, flags);
			}
		}
	}

@@ -422,12 +424,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
	hashbin->magic = ~HB_MAGIC;

	/* Release lock */
	if ( hashbin->hb_type & HB_LOCK) {
	if (hashbin->hb_type & HB_LOCK)
		spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
#ifdef CONFIG_LOCKDEP
		hashbin_lock_depth--;
#endif
	}

	/*
	 *  Free the hashbin structure