Skip to content
Snippets Groups Projects
Commit f3fffaa5 authored by Marc-Oliver Westerburg's avatar Marc-Oliver Westerburg
Browse files

fix AC97 read timeouts

Previously we see AC97 read register calls timing out every once in a
while. Adding some debug outputs, these mostly seem to be cases, where
the SAI driver doesn't find the expected answer in the received frames.

Three potential causes have been identified:
 * frame "border" occuring exactly between enabling RMR and TMR,
 resulting in receiving an additional empty RX frame (4 instead of 3)
 until the answer arrives
 * kernel preemption between RMR and TMR resulting in potentially lots
 of empty frames accumulating in the RX-FIFO
 * runnig in a timeout, because the code gave up after 63us already (3
 frames), although due to the asynchronous timing we might have to wait
 up to almost 104us (5 frames)

This patch adds fixes for all three cases. During first manual tests no
more timeouts could be produced.

BCS: 746-001295
parent 5550ff9a
No related branches found
No related tags found
2 merge requests!455CI: Update gitlab-ci,!300fix AC97 read timeouts
Pipeline #60420 passed with stage
in 9 seconds
......@@ -1489,23 +1489,54 @@ static int fsl_sai_ac97_register_access(struct ac97_controller *ac97_ctrl,
/*
* Unmask the required words (aka AC97 slots) in the frame,
* so that we can receive and transmit data.
*
* We disable preemption until both RMR and TMR are set, because
* if RMR is enabled, then we get rescheduled and only afterward
* TMR is enabled, the RX-FIFO has already accumulated lots of
* frames without out data
* if TMR is enabled, then we get rescheduled and only afterward
* RMR is enabled, the RX-FIFO will be inactive while the codec
* sends its answer and we miss the data we're waiting for
*/
preempt_disable();
if( rw == AC97_CMD_READ )
regmap_update_bits(sai->regmap, FSL_SAI_RMR, 0xFFFF, 0xFFF8);
regmap_update_bits(sai->regmap, FSL_SAI_TMR, 0xFFFF, 0xFFF8);
preempt_enable();
timeout = jiffies + usecs_to_jiffies(63);
/*
* how long do we have to wait to be sure our answer has arrived:
* - one frame takes 20.83 usecs
* - frame (n) will send the AC97 reg access command
* - for reads frame (n+1) allows codec time for processing
* - for reads frame (n+2) will contain the read data
* - we enable RMR and TMR usually some time during frame (n-1)
* - as AC97 is running asynchronously to the CPU, it might happen
* that we enable RMR just at end of one frame and TMR just at
* beginnig of next frame. This will result in receiving an
* additional empty frame.
* = after 5 frames, i.e. 105 usecs, we should have our results in
* the FIFO
*/
timeout = jiffies + usecs_to_jiffies(105);
if (rw == AC97_CMD_READ) {
/*
* Wait until the RX fifo contains at least 3 words
* (since we only work with the first 3 slots of AC97,
* 3 words correspond to 1 frame).
* As mentioned above: usually reading an AC97 register
* takes 3 frames. It might be possible, though, that we
* enabled RMR just before the end of one frame, and TMR
* only just after start of next frame, therefore we might
* occasionally have to check up to 4 RX frames to receive
* our data
*/
while (0 == ret && frames < 3) {
while (0 == ret && frames < 4) {
while (fsl_sai_words_in_fifo(sai, RX) < 3) {
if (time_after(jiffies, timeout)) {
ret = -ETIME;
dev_dbg(dev, "timeout no data (frame %u)\n", frames);
break;
}
}
......@@ -1527,6 +1558,7 @@ static int fsl_sai_ac97_register_access(struct ac97_controller *ac97_ctrl,
ret = data;
goto valid;
}
dev_dbg(dev, "timeout no valid frame\n");
ret = -ETIME;
} else {
/* Wait until the TX FIFO is empty */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment