Skip to content

himci: finish the request when the FIFO reset times out - #59

Merged
widgetii merged 2 commits into
hisilicon-hi3516av100from
himci/finish-the-request-hi3516av100
Sep 22, 2026
Merged

widgetii merged 2 commits into
hisilicon-hi3516av100from
himci/finish-the-request-hi3516av100

Conversation

@widgetii

Copy link
Copy Markdown
Member

The same one-line fault as #57, in this branch's copy of himci.c.

himci_request() has ten ways out. Nine reach request_end, which calls
himci_finish_request() and through it mmc_request_done(). The tenth — the
FIFO-reset loop on the data path — is a bare return, so nothing completes the
request: the MMC core waits forever on an uninterruptible
wait_for_completion(), the caller becomes an unkillable D state, and
because the host is never released every later request queues behind it. On a
camera that is recording stopping until someone cuts the power.

The fix sets the data error the way every other timeout in this driver does
(-ETIMEDOUT) and jumps to request_end. No DMA to unwind — himci_idma_start()
is below this point.

Found by reading, not by triggering. #57 explains why forcing the path costs
a board nobody can reach; the same applies here. The path leaves
fifo reset is timeout! in dmesg, which is what to grep for if it shows up in
the field.

Scope

I checked which branches actually ship this driver rather than patching every
one that contains the text. CONFIG_HIMCI=y appears in the firmware's board
configs for hi3516av100 and hi3516dv100 — this branch — and for hi3516cv500 (#57). It is set nowhere
for hisilicon-hi3516ev200 or hisilicon-hi3536dv100, and neither branch even
carries a himci variant its SoC selects, so the driver cannot be built there and
those two are left alone.

Testing

Compile-tested with the hi3516av100 board kernel config (CONFIG_HIMCI=y, arm-openipc-linux-musleabi,
make drivers/mmc/host/himci/himci.o), no new warnings. No hardware for this
SoC here; the change is textually identical to the one on #57, which was
exercised on an hi3516av300 to the extent that normal SD traffic, a CMD13
passthrough and a 512-byte CMD56 read all behave unchanged.

Same one-line fault as #57 on hisilicon-hi3516cv500, in this
branch's copy of the driver.

himci_request() has ten ways out and nine of them reach request_end, which
calls himci_finish_request() and through it mmc_request_done(). The tenth, in
the FIFO-reset loop on the data path, is a bare return.

Nothing else completes the request. The MMC core is sitting in
mmc_wait_for_req() on an uninterruptible wait_for_completion(), so the caller
becomes an unkillable D state, and because the host is never released every
later request queues behind it. On a camera that is recording stopping and
staying stopped until someone cuts the power.

Set the data error the way every other timeout in this driver does and jump to
request_end. There is no DMA to unwind: himci_idma_start() is below this
point.

Found by reading, not by triggering it; see #57 for why forcing the path costs
a board nobody can reach. The path leaves "fifo reset is timeout!" in dmesg,
which is what to grep for if it is ever seen in the field.

Compile-tested with hi3516av100 and hi3516dv100' kernel config (CONFIG_HIMCI=y,
arm-openipc-linux-musleabi, make drivers/mmc/host/himci/himci.o) with no new
warnings.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

himci: Complete requests after FIFO reset timeout

🐞 Bug fix 🕐 Less than 10 minutes

Grey Divider

AI Description

• Completes MMC requests when FIFO reset polling exceeds its retry limit.
• Reports -ETIMEDOUT and routes failures through shared interrupt cleanup.
• Prevents indefinite D-state waits and host-wide request queue stalls.
Diagram

graph TD
  A["MMC request"] --> B["FIFO reset"] --> C{"Reset timed out?"}
  C -->|Yes| D["Set ETIMEDOUT"] --> E["Request cleanup"] --> F["Complete request"]
  C -->|No| G["Start DMA"]
Loading
High-Level Assessment

The chosen approach is optimal: assign the conventional data timeout error and jump to the existing request_end path. Calling completion directly or adding separate cleanup would duplicate logic and risk skipping interrupt cleanup; DMA teardown is unnecessary because DMA has not started.

Files changed (1) +16 / -1

Bug fix (1) +16 / -1
himci.cComplete timed-out FIFO reset requests +16/-1

Complete timed-out FIFO reset requests

• Replaces the FIFO reset timeout's early return with a '-ETIMEDOUT' data error and transfer to the shared request cleanup path. The added rationale documents how the former path stranded MMC waiters and why no DMA teardown is required.

drivers/mmc/host/himci/himci.c

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Reset timeouts leave buffers mapped ✓ Resolved 🐞 Bug ☼ Reliability
Description
himci_setup_data() has already called dma_map_sg() when the new FIFO-reset timeout branch jumps
to request_end, but only himci_data_done() calls dma_unmap_sg(). Every reset timeout therefore
completes the request with its scatterlist still mapped, allowing repeated recoverable failures to
retain DMA-mapping resources across later requests.
Code

drivers/mmc/host/himci/himci.c[R870-871]

+				mrq->data->error = -ETIMEDOUT;
+				goto request_end;
Evidence
The data setup path maps the request scatterlist at lines 376-377. The sole matching unmap is inside
himci_data_done() at line 600, while the newly added branch at lines 870-871 skips that function
and completes through request_end.

drivers/mmc/host/himci/himci.c[376-377]
drivers/mmc/host/himci/himci.c[592-600]
drivers/mmc/host/himci/himci.c[870-871]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The FIFO-reset timeout completes the request after `himci_setup_data()` mapped its scatterlist, but it does not unmap that scatterlist because `himci_data_done()` is never reached.
## Fix Focus Areas
- drivers/mmc/host/himci/himci.c[870-871]
- drivers/mmc/host/himci/himci.c[376-377]
- drivers/mmc/host/himci/himci.c[592-600]
## Recommended Fix
Before jumping to `request_end`, call `dma_unmap_sg()` with the same device, scatterlist, length, and direction used by `himci_setup_data()`. Keep the timeout error assignment and request completion behavior unchanged.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread drivers/mmc/host/himci/himci.c
From review of the previous commit, and a fault in it.

himci_setup_data() does two things that have to be undone: it maps the
scatterlist for the device, and it takes host->data. himci_data_done() is the
only thing that gives either back. Jumping to request_end from the FIFO-reset
timeout skipped it, so the buffer went back to the MMC core still mapped for
the device, and host->data was left pointing at a request that had just been
completed.

Call it, with no status bits, so it unmaps, clears host->data, zeroes
bytes_xfered and keeps the -ETIMEDOUT set above rather than deciding an error
of its own. Still no himci_idma_stop(): the engine is genuinely not running
there, because himci_idma_start() is below this point.

Worth noting while this is open: the command-error paths further down have the
same shape. When himci_exec_cmd() fails or the command completes with an
error, the data branch calls himci_idma_stop() and falls through to
request_end without himci_data_done(), so those leak the mapping too. That is
older than this change and is left alone here rather than folded into a
one-line fix.

Compile-tested as before, no new warnings.
@widgetii

Copy link
Copy Markdown
Member Author

Right, and it is a fault in the fix rather than in the old code. Addressed in
the follow-up commit.

himci_setup_data() does two things that have to be undone: it maps the
scatterlist for the device, and it takes host->data. himci_data_done() is
the only thing that gives either back. Jumping to request_end skipped it, so
the buffer went back to the MMC core still mapped for the device — and
host->data was left pointing at a request that had just been completed, which
is the worse half: a later himci_data_done() or an IRQ would have dereferenced
it.

It now calls himci_data_done(host, 0) before the jump. With no status bits
neither error branch inside it fires, so it unmaps, clears host->data, zeroes
bytes_xfered and keeps the -ETIMEDOUT set just above rather than deciding an
error of its own. Still no himci_idma_stop(): the engine genuinely is not
running there, because himci_idma_start() is below this point.

Worth recording while this is open, since it is the same class and I looked:
the command-error paths further down leak the same mapping. When
himci_exec_cmd() fails, or the command completes with an error, the data
branch calls himci_idma_stop() and falls through to request_end without
himci_data_done(). That is older than this change and is left alone rather
than folded into a one-line fix — happy to send it separately if you want it.

Compile-tested as before, no new warnings.

@widgetii
widgetii merged commit 9c32eb4 into hisilicon-hi3516av100 Sep 22, 2026
@widgetii
widgetii deleted the himci/finish-the-request-hi3516av100 branch September 22, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant