Skip to content

qcwdfserial: fix latency small chunk reads regression after QUD-1837 ReadIntervalTimeout#65

Open
Cristian Manca (CristianManca) wants to merge 1 commit into
qualcomm:mainfrom
CristianManca:fix/latency-small-chunk
Open

qcwdfserial: fix latency small chunk reads regression after QUD-1837 ReadIntervalTimeout#65
Cristian Manca (CristianManca) wants to merge 1 commit into
qualcomm:mainfrom
CristianManca:fix/latency-small-chunk

Conversation

@CristianManca

@CristianManca Cristian Manca (CristianManca) commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR fixes a latency regression introduced by commit
9e60a01974f7bd802c5e6660c6c12812e4d819fc
(fix(wdfserial): implement ReadIntervalTimeout inter-byte gap semantics [QUD-1837]).

The regression is most visible with small read sizes (especially 1-byte reads): data already present in the ring buffer could still follow the timer-based path, adding unnecessary delay and reducing throughput.

Root cause

With ReadIntervalTimeout enabled, the read path could wait on the inter-byte timer even when bytes were already buffered, effectively serializing delivery and increasing per-read latency.

Code-level changes

In src/windows/wdfserial/QCRD.c, inside QCRD_ReadRequestHandlerThread (READ_THREAD_REQUEST_ARRIVE_EVENT path):

  • The RI path is now gated with:
    • if (useReadInterval && QCUTIL_RingBufferBytesUsed(rxBuffer) == 0)
  • If data is already buffered, the code now follows immediate-drain logic instead of waiting for timeout.
  • Added explicit guard to preserve QUD-1837 semantics when a request is already pending in TimeoutReadQueue and ReadQueue is empty:
    • keep waiting for REQUEST_TIMEOUT_EVENT.
  • Before immediate drain in RI mode, pending timer state is cleared:
    • KeCancelTimer(&pDevContext->ReadTimer);
    • KeClearEvent(&pDevContext->ReadRequestTimeoutEvent);
  • During RI bypass, requests are served from ReadQueue (not drained from TimeoutReadQueue) so timeout-queued requests remain timer-governed.

Impact

  • Significant latency reduction for small-buffer reads (1 byte and few-byte reads).
  • Throughput recovery for frequent small-chunk read patterns.

Comment thread src/windows/wdfserial/QCRD.c Outdated
{
// If useReadInterval is true but data is already buffered,
// cancel any pending inter-byte timer before draining: the
// TIMEOUT_EVENT DPC may still fire if it was already queued,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update comment to

// If useReadInterval is true but data is already buffered,
// cancel any pending inter-byte timer before draining.
// KeCancelTimer returns FALSE if the DPC is already queued;
// in that case ReadTimeoutDpc will fire after KeClearEvent and
// set ReadRequestTimeoutEvent again. READ_THREAD_REQUEST_TIMEOUT_EVENT
// will then find the ring buffer empty (drained below) and complete
// any pending TimeoutReadQueue request with STATUS_TIMEOUT / 0 bytes.
// This is correct RI semantics: the inter-byte gap elapsed and no
// data was available for that request (it was consumed by ReadQueue).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment updated

Comment thread src/windows/wdfserial/QCRD.c Outdated
{
status = WdfIoQueueRetrieveNextRequest(pDevContext->ReadQueue, &request);
}
// When bypassing the RI timer due to pre-buffered data, we must NOT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix else block indentation

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation fixed

…t change

Fix a latency regression on small chunk reads introduced by
"ReadIntervalTimeout inter-byte gap semantics [QUD-1837]".
Keep QUD-1837 ReadIntervalTimeout behavior intact by preventing immediate
bypass delivery when a request is already pending in TimeoutReadQueue
and no new request exists in ReadQueue.

In READ_THREAD_REQUEST_ARRIVE_EVENT (ring-buffer path):
 - preserve timer-based completion for pending TimeoutReadQueue requests
 - allow immediate bypass only when serving new ReadQueue requests

Signed-off-by: Cristian Manca <Cristian.Manca@telit.com>
@CristianManca Cristian Manca (CristianManca) marked this pull request as ready for review June 22, 2026 07:42
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.

3 participants