Hi,
On Mon, Oct 23, 2023 at 10:25:50AM -0700, Doug Anderson wrote:
> On Mon, Oct 23, 2023 at 9:31 AM Yuran Pereira <yuran.pereira(a)hotmail.com> wrote:
> >
> > Since "Clean up checks for already prepared/enabled in panels" has
> > already been done and merged [1], I think there is no longer a need
> > for this item to be in the gpu TODO.
> >
> > [1] https://patchwork.freedesktop.org/patch/551421/
> >
> > Signed-off-by: Yuran Pereira <yuran.pereira(a)hotmail.com>
> > ---
> > Documentation/gpu/todo.rst | 25 -------------------------
> > 1 file changed, 25 deletions(-)
>
> It's not actually all done. It's in a bit of a limbo state right now,
> unfortunately. I landed all of the "simple" cases where panels were
> needlessly tracking prepare/enable, but the less simple cases are
> still outstanding.
>
> Specifically the issue is that many panels have code to properly power
> cycle themselves off at shutdown time and in order to do that they
> need to keep track of the prepare/enable state. After a big, long
> discussion [1] it was decided that we could get rid of all the panel
> code handling shutdown if only all relevant DRM KMS drivers would
> properly call drm_atomic_helper_shutdown().
>
> I made an attempt to get DRM KMS drivers to call
> drm_atomic_helper_shutdown() [2] [3] [4]. I was able to land the
> patches that went through drm-misc, but currently many of the
> non-drm-misc ones are blocked waiting for attention.
>
> ...so things that could be done to help out:
>
> a) Could review patches that haven't landed in [4]. Maybe adding a
> Reviewed-by tag would help wake up maintainers?
>
> b) Could see if you can identify panels that are exclusively used w/
> DRM drivers that have already been converted and then we could post
> patches for just those panels. I have no idea how easy this task would
> be. Is it enough to look at upstream dts files by "compatible" string?
I think it is, yes.
Maxime
Feeling the need for speed and a bit of winter fun, even when the weather outside is frightful? Then maybe it’s time to check out Snow Rider 3D. This simple but surprisingly addictive game offers a thrill of downhill skiing and snowboarding right from your browser, no downloads required. Let’s break down how to jump in and start enjoying this surprisingly engaging title.
https://snowriderfree.com/
Gameplay: Simple Controls, Endless Possibilities
The core gameplay of Snow Rider 3D is deceptively straightforward. You control your character's direction using the left and right arrow keys (or A and D). Your objective? Navigate through a series of procedurally generated slopes littered with obstacles. These obstacles range from simple ramps and rails to more challenging hazards like trees, snowdrifts, and even abandoned shacks.
The beauty of Snow Rider 3D lies in its physics. While simple, they feel surprisingly realistic. You'll need to anticipate turns, adjust your speed, and time your jumps to successfully navigate the terrain. A crash will reset you to the beginning of the course, so precision and patience are key.
The game offers different levels, each presenting a unique challenge. Some focus on speed and long jumps, while others demand skillful maneuvering through tight spaces. As you progress, you unlock new skins and sleds, adding a touch of customization to your experience. Think of it as a casual time-killer that can quickly turn into an hour-long obsession!
Tips for Mastering the Mountain:
Alright, so you're ready to hit the slopes. Here are a few tips to help you improve your runs and avoid those frustrating wipeouts:
Practice Makes Perfect: Don't get discouraged by early crashes. The more you play, the better you'll understand the physics and learn to anticipate the terrain.
Master the Turns: Smooth, controlled turns are essential for maintaining speed and avoiding obstacles. Practice feathering the arrow keys to make subtle adjustments.
Timing is Everything: When approaching jumps and ramps, pay close attention to your speed and angle. A well-timed jump can make all the difference.
Don't Be Afraid to Slow Down: Sometimes, the fastest route isn't the safest. Don't be afraid to ease off the gas and navigate tricky sections with caution. Consider looking up guides for specific levels of Snow Rider 3D at websites like Snow Rider 3D if you’re really struggling.
Experiment with Sleds and Skins: Different sleds may offer slight variations in handling. Try out different options to find one that suits your playstyle.
Conclusion: A Fun and Accessible Winter Escape
Snow Rider 3D is a surprisingly addictive and accessible game that’s perfect for a quick dose of winter fun. It's simple controls and challenging gameplay make it easy to pick up and play, while its procedural generation ensures that each run is a unique experience. So, whether you're looking for a casual time-killer or a challenging skill-based game, Snow Rider 3D is definitely worth checking out.
Ever dreamed of running your own bustling enterprise, watching your profits soar, and building an empire from humble beginnings? If so, you've likely stumbled upon the fascinating and surprisingly addictive world of store management games. These titles offer a unique blend of strategy, incremental growth, and the satisfying feeling of seeing your hard work pay off. And when it comes to the purest, most delightful form of this genre, one game stands out: https://cookieclickers.io/
The Sweet Simplicity of Cookie Clicker: A Gateway to Management
At its heart, Cookie Clicker is incredibly simple. You start with a single, humble cookie, and your goal is to click it to generate more cookies. These initial clicks are crucial, as they fund your first upgrades. Soon, you’ll be able to purchase "grandmas," who automatically bake cookies for you, freeing up your clicking finger. From there, the sky's the limit! You'll acquire farms, factories, mines, and even portals to other dimensions, all dedicated to the singular purpose of baking more and more cookies.
What makes Cookie Clicker so captivating is its elegant progression system. Each new upgrade and building provides a tangible boost to your cookie production, creating a satisfying feedback loop. The numbers on your screen grow exponentially, transforming from humble dozens to mind-boggling septillions and beyond. It’s a masterclass in incremental design, making every new purchase feel impactful and exciting.
Beyond the Click: Strategic Thinking and Exponential Growth
While the initial appeal of Cookie Clicker might be the simple act of clicking, true mastery lies in strategic decision-making. As your cookie empire expands, you'll be faced with choices:
Upgrade Prioritization: Should you invest in another Grandma, a new farm, or a powerful upgrade that boosts all your existing structures? Understanding the cost-benefit analysis of each option is key.
Synergies: Many upgrades have synergistic effects, meaning they become more powerful when paired with specific buildings. Discovering these combinations is a delightful puzzle.
Ascension and Prestige: Eventually, you’ll unlock the ability to “ascend,” resetting your game but granting you powerful "heavenly chips" that provide permanent bonuses. This meta-progression adds a whole new layer of long-term strategy, encouraging you to rethink your approach with each new playthrough.
These elements elevate Cookie Clicker from a simple clicking game to a genuinely engaging management simulation. It teaches you about exponential growth, compound interest (in a fun, cookie-filled way!), and the satisfaction of building something from nothing.
Tips for Aspiring Cookie Tycoons
If you’re ready to dive into the sweet, sweet world of Cookie Clicker, here are a few friendly tips to get you started:
Don't Be Afraid to Click! In the early game, your clicks are your most valuable resource. Keep that finger moving!
Invest in Grandmas Early: They're your first step towards automation and a steady cookie income.
Always Buy Upgrades: The small boosts they provide add up quickly and are often more cost-effective than new buildings in the short term.
Look for Golden Cookies: These appear randomly and offer temporary, powerful buffs. Clicking them can drastically boost your production!
Consider Ascending: While it seems daunting to reset your progress, the permanent bonuses you gain make future runs much faster and more efficient.
The Endless Appeal of Automation
Cookie Clicker, and store management games in general, tap into a fundamental human desire: the joy of creation and the satisfaction of watching systems work efficiently. There's a particular kind of quiet pleasure in setting up a well-oiled machine and observing its output multiply. So, if you're looking for a game that's easy to pick up, surprisingly deep, and immensely satisfying, give Cookie Clicker a try. You might just find yourself baking billions before you know it!
So, you're looking for a new game to sink your teeth into? Something challenging, maybe a little bit infuriating, and definitely memorable? Look no further than Level Devil. This deceptively simple platformer is a masterclass in trickery, constantly changing the rules and keeping you on your toes. But don't be intimidated! With a little patience (and maybe a stress ball), you can conquer its devilish design.
https://leveldevilfull.com
Gameplay: Expect the Unexpected
At its core, Level Devil is a 2D platformer. You control a little pixelated character tasked with reaching the exit door in each level. Sounds easy, right? Wrong. The beauty (and the frustration) lies in the unpredictable nature of the environment. Platforms crumble beneath your feet, spikes appear out of nowhere, and the ground itself can vanish unexpectedly.
Each level introduces new challenges, forcing you to adapt your strategy on the fly. You'll encounter moving platforms, disappearing blocks, and even gravity-defying puzzles. The real kicker? The layout of the levels often changes on each attempt, meaning memorization alone won't cut it. You need to be quick-witted and reactive.
The charm of Level Devil is its lack of hand-holding. There are no tutorials, no hints, and no mercy. You're thrown straight into the deep end, forced to learn from your mistakes (and trust me, there will be plenty). That feeling of finally overcoming a particularly difficult section is incredibly rewarding. It's a game that demands your full attention and rewards persistence.
Tips for Taming the Devil
While Level Devil thrives on its unpredictability, here are a few tips to help you navigate its treacherous landscape:
• Patience is Key: This game is designed to test your limits. Don't get discouraged by frequent deaths. Treat each attempt as a learning experience.
• Observe Carefully: Before making a move, take a moment to scan the environment. Look for subtle cues that might indicate impending danger.
• Embrace Failure: You will die. A lot. Embrace it as part of the learning process. Each death provides valuable insight into the level's design.
• Don't Overthink It: Sometimes, the solution is simpler than you think. Avoid overcomplicating your approach.
• Take Breaks: If you find yourself getting too frustrated, step away from the game for a while. Come back with a fresh perspective.
• Listen to the Sound: The game’s audio cues often hint at upcoming dangers. Pay close attention! Level Devil utilizes sound design to enhance the experience (and sometimes, to cleverly mislead you!).
Conclusion: A Test of Skill and Sanity
Level Devil isn't for the faint of heart. It's a challenging and often frustrating experience. However, it's also incredibly rewarding. The constant surprises, the need for quick thinking, and the sheer satisfaction of overcoming its devilish design make it a truly unique and memorable game. If you're looking for a platformer that will push you to your limits and leave you feeling accomplished, then Level Devil is definitely worth a try. Just be prepared to rage quit... and then come back for more.
Using kunit to write tests for new work on dmabuf is coming up:
https://lore.kernel.org/all/26-v1-b5cab63049c0+191af-dmabuf_map_type_jgg@nv…
Replace the custom test framework with kunit to avoid maintaining two
concurrent test frameworks.
The conversion minimizes code changes and uses simple pattern-oriented
reworks to reduce the chance of breaking any tests. Aside from adding the
kunit_test_suite() boilerplate, the conversion follows a number of
patterns:
Test failures without cleanup. For example:
if (!ptr)
return -ENOMEM;
Becomes:
KUNIT_ASSERT_NOT_NULL(test, ptr);
In kunit ASSERT longjumps out of the test.
Check for error, fail and cleanup:
if (err) {
pr_err("msg\n");
goto cleanup;
}
Becomes:
if (err) {
KUNIT_FAIL(test, "msg");
goto cleanup;
}
Preserve the existing failure messages and cleanup code.
Cases where the test returns err but prints no message:
if (err)
goto cleanup;
Becomes:
if (err) {
KUNIT_FAIL(test, "msg");
goto cleanup;
}
Use KUNIT_FAIL to retain the 'cleanup on err' behavior.
Overall, the conversion is straightforward.
The result can be run with kunit.py:
$ tools/testing/kunit/kunit.py run --build_dir build_kunit_x86_64 --arch x86_64 --kunitconfig ./drivers/dma-buf/.kunitconfig
[20:37:23] Configuring KUnit Kernel ...
[20:37:23] Building KUnit Kernel ...
Populating config with:
$ make ARCH=x86_64 O=build_kunit_x86_64 olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=x86_64 O=build_kunit_x86_64 --jobs=20
[20:37:29] Starting KUnit Kernel (1/1)...
[20:37:29] ============================================================
Running tests with:
$ qemu-system-x86_64 -nodefaults -m 1024 -kernel build_kunit_x86_64/arch/x86/boot/bzImage -append 'kunit.enable=1 console=ttyS0 kunit_shutdown=reboot' -no-reboot -nographic -accel kvm -accel hvf -accel tcg -serial stdio -bios qboot.rom
[20:37:30] ================ dma-buf-resv (5 subtests) =================
[20:37:30] [PASSED] test_sanitycheck
[20:37:30] ===================== test_signaling ======================
[20:37:30] [PASSED] kernel
[20:37:30] [PASSED] write
[20:37:30] [PASSED] read
[20:37:30] [PASSED] bookkeep
[20:37:30] ================= [PASSED] test_signaling ==================
...
[20:37:35] Testing complete. Ran 50 tests: passed: 49, skipped: 1
[20:37:35] Elapsed time: 12.635s total, 0.001s configuring, 6.551s building, 6.017s running
One test that requires two CPUs is skipped since the default VM has a
single CPU and cannot run the test.
All other usual ways to run kunit work as well, and all tests are placed
in a module to provide more options for how they are run.
AI was used to do the large scale semantic search and replaces described
above, then everything was hand checked. AI also deduced the issue with
test_race_signal_callback() in a couple of seconds from the kunit
crash (!!), again was hand checked though I am not so familiar with this
test to be fully certain this is the best answer.
Jason Gunthorpe (5):
dma-buf: Change st-dma-resv.c to use kunit
dma-buf: Change st-dma-fence.c to use kunit
dma-buf: Change st-dma-fence-unwrap.c to use kunit
dma-buf: Change st-dma-fence-chain.c to use kunit
dma-buf: Remove the old selftest
drivers/dma-buf/.kunitconfig | 2 +
drivers/dma-buf/Kconfig | 11 +-
drivers/dma-buf/Makefile | 5 +-
drivers/dma-buf/selftest.c | 167 ---------------
drivers/dma-buf/selftest.h | 30 ---
drivers/dma-buf/selftests.h | 16 --
drivers/dma-buf/st-dma-fence-chain.c | 217 +++++++++----------
drivers/dma-buf/st-dma-fence-unwrap.c | 290 +++++++++++---------------
drivers/dma-buf/st-dma-fence.c | 200 ++++++++----------
drivers/dma-buf/st-dma-resv.c | 145 +++++++------
drivers/gpu/drm/i915/Kconfig.debug | 2 +-
11 files changed, 394 insertions(+), 691 deletions(-)
create mode 100644 drivers/dma-buf/.kunitconfig
delete mode 100644 drivers/dma-buf/selftest.c
delete mode 100644 drivers/dma-buf/selftest.h
delete mode 100644 drivers/dma-buf/selftests.h
base-commit: 41dae5ac5e157b0bb260f381eb3df2f4a4610205
--
2.43.0
Have you ever wondered what your life would look like if you made entirely different choices? Life simulation games have always been a fascinating genre for gamers, but few capture the unpredictable, hilarious, and sometimes chaotic nature of existence quite like Bitlife. Instead of relying on heavy 3D graphics, it is a text-based simulator that focuses entirely on the ripple effects of your decisions. It’s perfect for casual gaming sessions, so let's dive into how to play and get the most out of this quirky experience.
https://bitlifefree.io/
Gameplay: Growing Up, One Year at a Time
The premise of the game is incredibly simple but highly addictive. You are born with a random set of basic stats—Happiness, Health, Smarts, and Looks—in a random country to random parents. From there, you control your character's life year by year simply by tapping the "Age" button.
In your early years, your choices are understandably limited to things like interacting with your parents, going to the doctor, or playing with pets. But as you grow into a teenager and an adult, the world completely opens up. You can choose to study hard, drop out, date, travel the world, buy real estate, or even turn to a life of crime.
Every year, the game throws random scenarios at you: a classmate might insult you, you might be offered a questionable substance at a party, or you might find a wallet on the street. How you react directly impacts your stats and future opportunities. You might even have to pass mini-games, like navigating a maze for your driving test or escaping from prison. The ultimate goal is simply to live your life until your character passes away, leaving behind a unique legacy and a tombstone summarizing your deeds.
Tips for a Great Experience
If you are just starting out, here are a few tips to make your virtual life more successful—or at least more entertaining:
Keep an eye on your core stats: Your Health and Happiness are crucial. If they drop too low, your character might face early health issues. Go to the gym, meditate, go to the movies, or spend time with family to keep these bars in the green.
Education pays off (usually): If you want a high-paying, stable career like a doctor, judge, or CEO, use the "Study harder" option every year during school. Read books at the library to passively boost your Smarts stat.
Hunt for Ribbons: At the end of every life, you are awarded a ribbon based on how you lived (e.g., "Hero," "Scandalous," "Lazy," or "Rich"). Trying to collect all the different ribbons is a great way to give yourself specific goals.
Don't be afraid of the absurd: The real charm of the game is in its wild unpredictability. Sometimes, making terrible choices, trying to become a famous actor, or buying a crazy exotic pet leads to the most memorable playthroughs. Don't always play it safe!
Conclusion
Ultimately, the beauty of this simulator lies in its endless replayability. Every time you hit the button to start a new life, it is a completely blank slate. You can be a saint in one lifetime and an absolute menace to society in the next. Whether you have five minutes to kill on a bus commute or an hour to craft a sprawling, multi-generational family dynasty, diving into Bitlife offers a fun, lighthearted escape into a world where you pull all the strings. Give it a try, and see exactly where your choices take you!
Ready to unleash your inner fruit ninja without the mess? Then get ready to dive into the addictively simple, yet surprisingly challenging world of Slice Master. This game, readily available online, is perfect for a quick burst of fun or a more extended gaming session. It’s a testament to the fact that gameplay doesn't need to be complex to be engaging.
https://slicemasterfree.com
Gameplay: Simple Mechanics, Endless Fun
The core concept of Slice Master is refreshingly straightforward. Colorful fruits are launched into the air, and your mission is to slice them into pieces before they fall off the screen. You control a virtual blade with your mouse or finger (depending on the platform), and drawing lines through the fruit initiates the slicing action.
The catch? You have limited lives, and letting too many fruits fall untouched will result in a game over. Occasionally, you'll also encounter bombs mixed in with the fruit barrage. Accidentally slicing a bomb will end your run instantly, adding a layer of strategic thinking to the rapid-fire action.
As you progress, the game throws different types of fruit at you, some requiring multiple slices, and the speed increases gradually, demanding faster reflexes and more precise movements. Special fruits might offer score multipliers or other benefits, adding further depth to the gameplay. It’s a game where practice truly makes perfect, and mastering the art of fruit slicing is incredibly satisfying. You can try it out now by clicking on Slice Master.
Tips for Achieving Fruit-Slicing Mastery
While the game seems simple on the surface, a few strategies can significantly improve your score and extend your gameplay.
• Focus on Efficiency: Instead of frantically slashing at individual fruits, try to slice multiple fruits with a single, well-aimed swipe. This not only increases your score but also conserves your limited slicing time.
• Prioritize High-Value Fruits: Keep an eye out for special fruits that offer bonus points or multipliers. Slicing these at the right moment can dramatically boost your score.
• Be Mindful of Bombs: This one is crucial! Always be aware of the position of the bombs and avoid them at all costs. A moment of carelessness can instantly end your game. Try to train yourself to recognize them early and plan your slices accordingly.
• Practice Makes Perfect: Like any skill-based game, practice is essential for improving your reflexes and accuracy. The more you play, the better you'll become at predicting fruit trajectories and executing precise slices. So, keep practicing and you'll be reaching new high scores in no time!
In Conclusion: A Slice of Addictive Fun
Slice Master offers a surprisingly addictive and engaging gaming experience, despite its simple premise. Its accessible gameplay, combined with the escalating challenge, makes it a perfect choice for a quick dose of entertainment or a more extended gaming session. Whether you're looking for a casual distraction or a skill-based challenge, Slice Master provides a satisfying and fun way to test your reflexes and accuracy. So, grab your virtual blade and prepare to unleash your inner fruit-slicing ninja!
When dumping IB contents from a hung job, amdgpu_devcoredump_format()
acquires the VM root PD's reservation lock via amdgpu_vm_lock_by_pasid()
and then, for each IB referenced by the job, calls amdgpu_bo_reserve()
on the BO that backs the IB. Both reservations are taken on
reservation_ww_class_mutex objects but neither uses a ww_acquire_ctx,
which trips lockdep:
WARNING: possible recursive locking detected
--------------------------------------------
kworker/u128:0 is trying to acquire lock:
ffff88838b16e1f0 (reservation_ww_class_mutex){+.+.}-{4:4},
at: amdgpu_devcoredump_format+0x1594/0x23f0 [amdgpu]
but task is already holding lock:
ffff8882f82681f0 (reservation_ww_class_mutex){+.+.}-{4:4},
at: amdgpu_devcoredump_format+0x1594/0x23f0 [amdgpu]
Possible unsafe locking scenario:
CPU0
----
lock(reservation_ww_class_mutex);
lock(reservation_ww_class_mutex);
*** DEADLOCK ***
May be due to missing lock nesting notation
Workqueue: events_unbound amdgpu_devcoredump_deferred_work [amdgpu]
Call Trace:
__ww_mutex_lock.constprop.0
ww_mutex_lock
amdgpu_bo_reserve
amdgpu_devcoredump_format+0x1594 [amdgpu]
amdgpu_devcoredump_deferred_work+0xea [amdgpu]
process_one_work
worker_thread
kthread
The two reservations are on different BOs in the captured trace, so the
splat is a lockdep-correctness warning, not an observed deadlock. It
becomes a real self-deadlock whenever the IB BO shares its dma_resv
with the root PD (the always-valid case, see
amdgpu_vm_is_bo_always_valid()): amdgpu_bo_reserve(abo) re-acquires the
same ww_mutex without a ticket and blocks forever.
With amdgpu.gpu_recovery=0 the timeout handler refires every ~2 s and
each invocation produces this splat, drowning the kernel ring buffer.
Fix it by collecting the per-IB BO references under the root PD's
reservation, then releasing the root before reserving each IB BO
individually. The walk over the VM mapping tree must remain under the
root lock (mappings can be torn down without it), but the actual
content copies do not need to nest inside it. Each per-IB reservation
is now an independent top-level acquire, eliminating the nested
ww_mutex.
The collect/release logic is factored out into two small helpers
(amdgpu_devcoredump_collect_ib_refs / amdgpu_devcoredump_release_ib_refs)
to keep the main function's indentation reasonable.
This also fixes a BO refcount leak in the original code: when
amdgpu_bo_reserve() failed, control jumped to free_ib_content without
running amdgpu_bo_unref(). In the new structure the per-IB BO refs
are released unconditionally in the cleanup helper.
Reproducer (~150 LoC libdrm_amdgpu): submit a single GFX IB containing
PACKET3_INDIRECT_BUFFER chained at GPU VA 0 and wait for the fence.
The TDR fires within ~10 s and the deferred coredump worker produces
the splat above on every invocation.
Fixes: 7b15fc2d1f1a ("drm/amdgpu: dump job ibs in the devcoredump")
Cc: stable(a)vger.kernel.org # 7.1
Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov(a)gmail.com>
---
.../gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c | 147 +++++++++++++-----
1 file changed, 110 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index d386bc775d03..f6bb968de756 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -207,6 +207,72 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
}
}
+struct amdgpu_devcoredump_ib_ref {
+ struct amdgpu_bo *bo;
+ u64 offset;
+};
+
+/*
+ * Walk the VM's mapping tree under the root PD's reservation to obtain the BO
+ * that backs each IB and pin it with a refcount. The root PD reservation is
+ * dropped before this function returns; the caller can then reserve each IB
+ * BO individually without nesting ww_mutex acquires on
+ * reservation_ww_class_mutex.
+ *
+ * Returns an array of num_ibs entries (each ib_refs[i].bo may be NULL if its
+ * mapping was not found), or NULL on allocation failure / VM lookup failure.
+ * The caller must release the BO refs and free the array.
+ */
+static struct amdgpu_devcoredump_ib_ref *
+amdgpu_devcoredump_collect_ib_refs(struct amdgpu_device *adev,
+ struct amdgpu_coredump_info *coredump)
+{
+ struct amdgpu_devcoredump_ib_ref *ib_refs;
+ struct amdgpu_bo_va_mapping *mapping;
+ struct amdgpu_bo *root;
+ struct amdgpu_vm *vm;
+ u64 va_start;
+
+ ib_refs = kcalloc(coredump->num_ibs, sizeof(*ib_refs), GFP_KERNEL);
+ if (!ib_refs)
+ return NULL;
+
+ vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid);
+ if (!vm) {
+ kfree(ib_refs);
+ return NULL;
+ }
+
+ for (int i = 0; i < coredump->num_ibs; i++) {
+ va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
+ mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE);
+ if (!mapping)
+ continue;
+
+ ib_refs[i].bo = amdgpu_bo_ref(mapping->bo_va->base.bo);
+ ib_refs[i].offset = va_start -
+ mapping->start * AMDGPU_GPU_PAGE_SIZE;
+ }
+
+ amdgpu_bo_unreserve(root);
+ amdgpu_bo_unref(&root);
+
+ return ib_refs;
+}
+
+static void
+amdgpu_devcoredump_release_ib_refs(struct amdgpu_devcoredump_ib_ref *ib_refs,
+ int num_ibs)
+{
+ if (!ib_refs)
+ return;
+
+ for (int i = 0; i < num_ibs; i++)
+ if (ib_refs[i].bo)
+ amdgpu_bo_unref(&ib_refs[i].bo);
+ kfree(ib_refs);
+}
+
static ssize_t
amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_info *coredump)
{
@@ -214,13 +280,11 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
struct drm_printer p;
struct drm_print_iterator iter;
struct amdgpu_vm_fault_info *fault_info;
- struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_ip_block *ip_block;
struct amdgpu_res_cursor cursor;
- struct amdgpu_bo *abo, *root;
- uint64_t va_start, offset;
+ struct amdgpu_bo *abo;
+ uint64_t offset;
struct amdgpu_ring *ring;
- struct amdgpu_vm *vm;
u32 *ib_content;
uint8_t *kptr;
int ver, i, j, r;
@@ -343,43 +407,52 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
drm_printf(&p, "VRAM is lost due to GPU reset!\n");
if (coredump->num_ibs) {
- /* Don't try to lookup the VM or map the BOs when calculating the
- * size required to store the devcoredump.
+ struct amdgpu_devcoredump_ib_ref *ib_refs = NULL;
+
+ /*
+ * Snapshot per-IB BO references under the root PD's reservation,
+ * then release the root before reserving each IB BO individually
+ * to copy its contents.
+ *
+ * Reserving an IB BO while the root PD is still reserved would
+ * be a nested ww_mutex acquire on reservation_ww_class_mutex
+ * without a ww_acquire_ctx, which trips lockdep's recursive-
+ * locking check and self-deadlocks for IB BOs that share their
+ * dma_resv with the root PD (always-valid BOs).
+ *
+ * Skip lookup/reservation entirely on the sizing pass: it does
+ * not write IB content, and the size estimate doesn't depend on
+ * whether the BOs are reachable.
*/
- if (sizing_pass)
- vm = NULL;
- else
- vm = amdgpu_vm_lock_by_pasid(adev, &root, coredump->pasid);
+ if (!sizing_pass)
+ ib_refs = amdgpu_devcoredump_collect_ib_refs(adev, coredump);
- for (int i = 0; i < coredump->num_ibs && (sizing_pass || vm); i++) {
+ for (int i = 0; i < coredump->num_ibs; i++) {
ib_content = kvmalloc_array(coredump->ibs[i].ib_size_dw, 4,
GFP_KERNEL);
if (!ib_content)
continue;
- /* vm=NULL can only happen when 'sizing_pass' is true. Skip to the
- * drm_printf() calls (ib_content doesn't need to be initialized
- * as its content won't be written anywhere).
- */
- if (!vm)
+ if (sizing_pass)
goto output_ib_content;
- va_start = coredump->ibs[i].gpu_addr & AMDGPU_GMC_HOLE_MASK;
- mapping = amdgpu_vm_bo_lookup_mapping(vm, va_start / AMDGPU_GPU_PAGE_SIZE);
- if (!mapping)
- goto free_ib_content;
+ if (!ib_refs || !ib_refs[i].bo)
+ goto output_ib_content;
+
+ abo = ib_refs[i].bo;
+ offset = ib_refs[i].offset;
- offset = va_start - (mapping->start * AMDGPU_GPU_PAGE_SIZE);
- abo = amdgpu_bo_ref(mapping->bo_va->base.bo);
r = amdgpu_bo_reserve(abo, false);
if (r)
- goto free_ib_content;
+ goto output_ib_content;
if (abo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) {
off = 0;
- if (abo->tbo.resource->mem_type != TTM_PL_VRAM)
- goto unreserve_abo;
+ if (abo->tbo.resource->mem_type != TTM_PL_VRAM) {
+ amdgpu_bo_unreserve(abo);
+ goto output_ib_content;
+ }
amdgpu_res_first(abo->tbo.resource, offset,
coredump->ibs[i].ib_size_dw * 4,
@@ -395,8 +468,10 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
r = ttm_bo_kmap(&abo->tbo, 0,
PFN_UP(abo->tbo.base.size),
&abo->kmap);
- if (r)
- goto unreserve_abo;
+ if (r) {
+ amdgpu_bo_unreserve(abo);
+ goto output_ib_content;
+ }
kptr = amdgpu_bo_kptr(abo);
kptr += offset;
@@ -406,21 +481,19 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
amdgpu_bo_kunmap(abo);
}
+ amdgpu_bo_unreserve(abo);
+
output_ib_content:
drm_printf(&p, "\nIB #%d 0x%llx %d dw\n",
i, coredump->ibs[i].gpu_addr, coredump->ibs[i].ib_size_dw);
- for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
- drm_printf(&p, "0x%08x\n", ib_content[j]);
-unreserve_abo:
- if (vm)
- amdgpu_bo_unreserve(abo);
-free_ib_content:
+ if (!sizing_pass && ib_refs && ib_refs[i].bo) {
+ for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
+ drm_printf(&p, "0x%08x\n", ib_content[j]);
+ }
kvfree(ib_content);
}
- if (vm) {
- amdgpu_bo_unreserve(root);
- amdgpu_bo_unref(&root);
- }
+
+ amdgpu_devcoredump_release_ib_refs(ib_refs, coredump->num_ibs);
}
return count - iter.remain;
--
2.54.0