From mboxrd@z Thu Jan 1 00:00:00 1970 From: Claude Code Review Bot To: dri-devel-reviews@example.com Subject: Claude review: drm/panthor: Driver-wide xxx_[un]lock -> [scoped_]guard replacement Date: Sat, 16 May 2026 11:40:45 +1000 Message-ID: In-Reply-To: <20260513-panthor-guard-refactor-v1-1-f2d8c15a97ce@collabora.com> References: <20260513-panthor-guard-refactor-v1-0-f2d8c15a97ce@collabora.com> <20260513-panthor-guard-refactor-v1-1-f2d8c15a97ce@collabora.com> X-Mailer: Claude Code Patch Reviewer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Patch Review This is the workhorse patch =E2=80=94 484 insertions and 559 deletions acro= ss 8 files. The mechanical conversions are generally correct. A few observa= tions: **panthor_device.c =E2=80=94 `panthor_device_unplug()` restructuring:** The original code released `unplug.lock` before the slow teardown path, wit= h a comment "We do the rest of the unplug with the unplug lock released." T= he new version uses `scoped_guard` which correctly releases after the block= , achieving the same semantics. The `was_already_unplugged` variable is a c= lean way to handle this. Good. **panthor_device.c =E2=80=94 `panthor_mmio_vm_fault()` restructuring:** In the original, the `DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET` case set `pfn`= and `pgprot` inside the lock, then called `vmf_insert_pfn_prot()` after th= e `switch` but still inside the lock. The new version moves `vmf_insert_pfn= _prot()` inside the `case` block with a `break`, which is functionally corr= ect but adds indentation. This is fine. **panthor_gpu.c =E2=80=94 `panthor_gpu_flush_caches()` early return inside = `scoped_guard`:** ```c scoped_guard(spinlock_irqsave, &ptdev->gpu->reqs_lock) { if (ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED) return -EIO; ``` Returning from inside a `scoped_guard` block is valid =E2=80=94 the cleanup= runs. This is correct. **panthor_mmu.c =E2=80=94 `panthor_vm_idle()` refactoring:** The original used `refcount_dec_and_mutex_lock()` which is an atomic "decre= ment and if it reaches zero, return with lock held" operation. The replacem= ent: ```c if (refcount_dec_not_one(&vm->as.active_cnt)) return; guard(mutex)(&ptdev->mmu->as.slots_lock); if (!refcount_dec_and_test(&vm->as.active_cnt)) return; ``` This is a correct decomposition. `refcount_dec_not_one()` returns true if t= he count was >1 after decrementing (i.e., not last ref), so the fast path a= voids the lock. Then under the lock, `refcount_dec_and_test()` does the fin= al atomic check. The refcount is decremented exactly once in all paths. Cor= rect, though slightly less efficient than the original `refcount_dec_and_mu= tex_lock()` in the contended-last-ref case (two atomic ops instead of one).= Acceptable tradeoff. **panthor_mmu.c =E2=80=94 `panthor_mmu_reclaim_priv_bos()` restructuring:** This is the most delicate conversion. The original held `ptdev->reclaim.loc= k` across the loop iteration, dropping it only around `drm_gem_lru_scan()`.= The new version uses multiple `scoped_guard` blocks: ```c scoped_guard(mutex, &ptdev->reclaim.lock) list_splice_init(&ptdev->reclaim.vms, &vms); while (freed < nr_to_scan) { scoped_guard(mutex, &ptdev->reclaim.lock) { vm =3D list_first_entry_or_null(&vms, ...); if (vm && !kref_get_unless_zero(&vm->base.kref)) { list_del_init(&vm->reclaim.lru_node); vm =3D NULL; } } if (!vm) break; ``` There's a behavioral difference here: the original loop would `continue` wh= en `kref_get_unless_zero` failed (trying the next VM in the list), but the = new version sets `vm =3D NULL` and then `break`s out of the while loop. Thi= s means if the first VM in the list has a zero refcount, the reclaim loop s= tops entirely rather than trying subsequent VMs. **This looks like a bug** = =E2=80=94 it should keep looping. The `list_del_init` removes the dead VM f= rom `vms`, but then `vm =3D NULL` causes the `if (!vm) break;` to exit the = entire while loop instead of continuing. **panthor_pwr.c =E2=80=94 `panthor_pwr_irq_handler()` spinlock change:** The original used `spin_lock()`/`spin_unlock()` (without irqsave), but the = replacement uses `guard(spinlock_irqsave)`. Since this is an IRQ handler (h= ardirq context), interrupts are already disabled, so `spinlock_irqsave` is = unnecessary overhead (saves/restores flags that won't change). The original= `spin_lock()` was correct here. While functionally harmless, using `spinlo= ck_irqsave` in a hardirq handler is a style regression =E2=80=94 `spinlock`= would be sufficient and more efficient. **panthor_sched.c =E2=80=94 `tick()` extraction:** Clean refactoring to separate the guard-heavy wrapper from the core logic. = The `tick()` function now uses `guard(mutex)(&sched->lock)` with early retu= rns, which is clean. --- Generated by Claude Code Patch Reviewer