hal: handle EINRESET error on pcm_open
Watchdog is hitting due to excessive logging
in kernel space, while SSR/PDR stress test.
Framework try to call pcm_open or compress_open
until the sound card offline event is received in
case of SSR/PDR, there is a window between actual
SSR/PDR and the offline event and this window at
times gets bigger due to excessive logging in
driver space, due to excessive logging offline event
get delayed, and during this window if framework
try to call pcm_open or compress_open multiple times
then there is excessive logging in driver layer
leading to watchdog hit .
In case of SSR\PDR, pcm_open will result in
error with return type EINRESET. As a workaround,
handle error EINRESET return type in hal when
pcm_open or compress_open is called to avoid
excessive logging in driver layer.
CRs-fixed: 2223369
Change-Id: Icc18b5a343cedc1ead004e06e22261850a7bda33
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index ad3a260..fc84562 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2497,6 +2497,14 @@
in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
flags, &config);
ATRACE_END();
+ if (errno == ENETRESET) {
+ ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
+ adev->card_status = CARD_STATUS_OFFLINE;
+ in->card_status = CARD_STATUS_OFFLINE;
+ ret = -EIO;
+ goto error_open;
+ }
+
if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
if (in->pcm != NULL) {
@@ -3079,6 +3087,14 @@
out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
flags, &out->config);
ATRACE_END();
+ if (errno == ENETRESET) {
+ ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
+ out->card_status = CARD_STATUS_OFFLINE;
+ adev->card_status = CARD_STATUS_OFFLINE;
+ ret = -EIO;
+ goto error_open;
+ }
+
if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
if (out->pcm != NULL) {
@@ -3124,6 +3140,14 @@
out->pcm_device_id,
COMPRESS_IN, &out->compr_config);
ATRACE_END();
+ if (errno == ENETRESET) {
+ ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
+ adev->card_status = CARD_STATUS_OFFLINE;
+ out->card_status = CARD_STATUS_OFFLINE;
+ ret = -EIO;
+ goto error_open;
+ }
+
if (out->compr && !is_compress_ready(out->compr)) {
ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
compress_close(out->compr);
@@ -4905,8 +4929,15 @@
uint32_t mmap_size;
ALOGV("%s", __func__);
+ lock_output_stream(out);
pthread_mutex_lock(&adev->lock);
+ if (CARD_STATUS_OFFLINE == out->card_status ||
+ CARD_STATUS_OFFLINE == adev->card_status) {
+ ALOGW("out->card_status or adev->card_status offline, try again");
+ ret = -EIO;
+ goto exit;
+ }
if (info == NULL || min_size_frames == 0) {
ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
ret = -EINVAL;
@@ -4931,6 +4962,14 @@
__func__, adev->snd_card, out->pcm_device_id, out->config.channels);
out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
(PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
+ if (errno == ENETRESET) {
+ ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
+ out->card_status = CARD_STATUS_OFFLINE;
+ adev->card_status = CARD_STATUS_OFFLINE;
+ ret = -EIO;
+ goto exit;
+ }
+
if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
step = "open";
ret = -ENODEV;
@@ -4977,6 +5016,7 @@
}
}
pthread_mutex_unlock(&adev->lock);
+ pthread_mutex_unlock(&out->lock);
return ret;
}
@@ -5512,6 +5552,13 @@
pthread_mutex_lock(&adev->lock);
ALOGV("%s in %p", __func__, in);
+ if (CARD_STATUS_OFFLINE == in->card_status||
+ CARD_STATUS_OFFLINE == adev->card_status) {
+ ALOGW("in->card_status or adev->card_status offline, try again");
+ ret = -EIO;
+ goto exit;
+ }
+
if (info == NULL || min_size_frames == 0) {
ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
ret = -EINVAL;
@@ -5537,6 +5584,14 @@
__func__, adev->snd_card, in->pcm_device_id, in->config.channels);
in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
(PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
+ if (errno == ENETRESET) {
+ ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
+ in->card_status = CARD_STATUS_OFFLINE;
+ adev->card_status = CARD_STATUS_OFFLINE;
+ ret = -EIO;
+ goto exit;
+ }
+
if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
step = "open";
ret = -ENODEV;