Browse Source

ASoC: compr: wake up drain only if it's the last buffer

There's a corner case where there're pause and resume operations in the
middle of last full buffer drain. Waking up drain without checking
against the real byte available violates the assumption only one
partial buffer in the last write.

The solution is to just resume the write pipe if there's more than one
fragment pending.

CRs-Fixed: 2536883
Change-Id: Id24c63bad774ec916942b8f94ddaa396d2560517
Signed-off-by: Weiyin Jiang <[email protected]>
Weiyin Jiang 5 years ago
parent
commit
7b51a258a1
1 changed files with 17 additions and 9 deletions
  1. 17 9
      asoc/msm-compress-q6-v2.c

+ 17 - 9
asoc/msm-compress-q6-v2.c

@@ -825,15 +825,23 @@ static void compr_event_handler(uint32_t opcode,
 			 * RESUME
 			 */
 			if ((prtd->copied_total == prtd->bytes_sent) &&
-			    atomic_read(&prtd->drain)) {
-				pr_debug("RUN ack, wake up & continue pending drain\n");
-
-				if (prtd->last_buffer)
-					prtd->last_buffer = 0;
-
-				prtd->drain_ready = 1;
-				wake_up(&prtd->drain_wait);
-				atomic_set(&prtd->drain, 0);
+					atomic_read(&prtd->drain)) {
+				bytes_available = prtd->bytes_received - prtd->copied_total;
+				if (bytes_available < cstream->runtime->fragment_size) {
+					pr_debug("%s: RUN ack, wake up & continue pending drain\n",
+							__func__);
+
+					if (prtd->last_buffer)
+						prtd->last_buffer = 0;
+
+					prtd->drain_ready = 1;
+					wake_up(&prtd->drain_wait);
+					atomic_set(&prtd->drain, 0);
+				} else if (atomic_read(&prtd->xrun)) {
+					pr_debug("%s: RUN ack, continue write cycle\n", __func__);
+					atomic_set(&prtd->xrun, 0);
+					msm_compr_send_buffer(prtd);
+				}
 			}
 
 			spin_unlock_irqrestore(&prtd->lock, flags);