public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
From: Claude Code Review Bot <claude-review@example.com>
To: dri-devel-reviews@example.com
Subject: Claude review: gpu: host1x: Allow entries in BO caches to be freed
Date: Sat, 16 May 2026 10:12:28 +1000	[thread overview]
Message-ID: <review-patch1-20260515-host1x-bocache-leak-v1-1-a0375f68aeab@nvidia.com> (raw)
In-Reply-To: <20260515-host1x-bocache-leak-v1-1-a0375f68aeab@nvidia.com>

Patch Review

**Refcount centralization (tegra gem.c, submit.c):**

The removal of `host1x_bo_get(bo)` from `tegra_bo_pin` and `gather_bo_pin`, and `host1x_bo_put(map->bo)` from their unpin counterparts, is correct. The new contract documented in the `host1x_bo_ops` comment makes the expectation clear:

```c
/**
 * @pin: create a DMA mapping. Implementation must not touch the bo's refcount.
 * @unpin: destroy a DMA mapping. Implementation must not touch the bo's refcount.
 */
```

**host1x_bo_pin() changes (bus.c):**

The new `host1x_bo_get(bo)` calls on both the cache-hit path and the new-mapping path correctly take one user reference per pin:

```c
		if (mapping->bo == bo && mapping->direction == dir) {
			kref_get(&mapping->ref);
			host1x_bo_get(bo);
			goto unlock;
		}
```
```c
	host1x_bo_get(bo);

	spin_lock(&mapping->bo->lock);
```

The key insight is in the cache-store block — the mapping refcount is bumped for the cache but the BO refcount is intentionally *not* bumped:

```c
		/*
		 * Bump the mapping reference count to track the mapping in the cache,
		 * but do not bump the BO's refcount. This allows the BO to still get freed,
		 * triggering the release of the cache mapping through
		 * host1x_bo_clear_cached_mappings.
		 */
		kref_get(&mapping->ref);
```

This is the core of the fix and is correct. The comment clearly explains the weak-reference semantics.

**host1x_bo_unpin() changes:**

Saving `bo` before the `kref_put` is necessary since the put may free the mapping:

```c
	struct host1x_bo *bo = mapping->bo;
	...
	kref_put(&mapping->ref, __host1x_bo_unpin);
	...
	host1x_bo_put(bo);
```

This is correct. On a cache hit unpin, `kref_put` decrements 2→1 (no free), then `host1x_bo_put` drops the user's BO ref. On a non-cached unpin, `kref_put` decrements 1→0 triggering `__host1x_bo_unpin` (which frees the mapping), then `host1x_bo_put` drops the BO ref. The saved `bo` pointer is needed for the latter case since `mapping` is freed.

**host1x_bo_clear_cached_mappings() (new function):**

```c
void host1x_bo_clear_cached_mappings(struct host1x_bo *bo)
{
	struct host1x_bo_mapping *mapping, *tmp;
	struct host1x_bo_cache *cache;

	list_for_each_entry_safe(mapping, tmp, &bo->mappings, list) {
		cache = mapping->cache;
		if (WARN_ON(!cache))
			continue;

		mutex_lock(&mapping->cache->lock);
		WARN_ON(kref_read(&mapping->ref) != 1);
		__host1x_bo_unpin(&mapping->ref);
		mutex_unlock(&mapping->cache->lock);
	}
}
```

Two observations:

1. **Direct call to `__host1x_bo_unpin` bypassing `kref_put`**: The ref is expected to be 1 (validated by the WARN_ON), but `__host1x_bo_unpin` is called directly rather than through `kref_put(&mapping->ref, __host1x_bo_unpin)`. This means the kref is never decremented to 0 — the mapping struct (including its kref) is freed inside `ops->unpin()` with the kref still at 1. This works because we're tearing down the object anyway, and is actually more defensive than `kref_put` for the abnormal case (if ref were unexpectedly >1, `kref_put` would just decrement without cleaning up, whereas the direct call ensures cleanup always happens). It's unconventional but defensible for a teardown path. A brief comment explaining the choice would help future readers.

2. **Locking**: The iteration over `bo->mappings` happens without holding `bo->lock`, while `__host1x_bo_unpin` internally acquires `bo->lock` for `list_del`. This is safe because we're in the BO teardown path (refcount is 0, no concurrent access), but worth noting. The `list_for_each_entry_safe` handles the in-loop deletion correctly.

The `WARN_ON(!cache)` with `continue` is a good guard. The old code in `tegra_bo_free_object` had the same logic (checked `mapping->cache`, logged error for stale non-cached mappings). Changing from `dev_err` to `WARN_ON` is arguably an improvement since a stale non-cached mapping at free time indicates a real bug.

**Replacement in tegra_bo_free_object:**

The old inline cleanup:
```c
	list_for_each_entry_safe(mapping, tmp, &bo->base.mappings, list) {
		if (mapping->cache)
			host1x_bo_unpin(mapping);
		else
			dev_err(gem->dev->dev, "mapping %p stale for device %s\n", ...);
	}
```

Is cleanly replaced with:
```c
	host1x_bo_clear_cached_mappings(&bo->base);
```

Good factoring — this makes the cleanup callable from any host1x_bo implementer, not just TegraDRM.

**Kdoc comments:** The added documentation for `host1x_bo_pin`, `host1x_bo_unpin`, `host1x_bo_ops`, and `host1x_bo_clear_cached_mappings` is clear and accurate. Nice touch.

---
Generated by Claude Code Patch Reviewer

  reply	other threads:[~2026-05-16  0:12 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-15  2:34 [PATCH 0/2] Fix leaking of cached Host1x buffer objects Mikko Perttunen
2026-05-15  2:34 ` [PATCH 1/2] gpu: host1x: Allow entries in BO caches to be freed Mikko Perttunen
2026-05-16  0:12   ` Claude Code Review Bot [this message]
2026-05-15  2:34 ` [PATCH 2/2] crypto: tegra - Don't touch bo refcount in host1x bo pin/unpin Mikko Perttunen
2026-05-16  0:12   ` Claude review: " Claude Code Review Bot
2026-05-16  0:12 ` Claude review: Fix leaking of cached Host1x buffer objects Claude Code Review Bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=review-patch1-20260515-host1x-bocache-leak-v1-1-a0375f68aeab@nvidia.com \
    --to=claude-review@example.com \
    --cc=dri-devel-reviews@example.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox