diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index 1ca3b76306b1..060bcd5a0f7b 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -658,8 +658,23 @@ int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct)
  * enter xrun or suspended state, if slave xrun occurred or suspended
  * @return: 0 for no xrun/suspend or a negative error code for xrun/suspend
  */
-int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
+int snd_pcm_direct_check_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
 {
+	int err;
+
+	switch (snd_pcm_state(direct->spcm)) {
+	case SND_PCM_STATE_DISCONNECTED:
+		direct->state = SNDRV_PCM_STATE_DISCONNECTED;
+		return -ENODEV;
+	case SND_PCM_STATE_XRUN:
+	case SND_PCM_STATE_SUSPENDED:
+		if ((err = snd_pcm_direct_slave_recover(direct)) < 0)
+			return err;
+		break;
+	default:
+		break;
+	}
+
 	if (direct->state == SND_PCM_STATE_XRUN)
 		return -EPIPE;
 	else if (direct->state == SND_PCM_STATE_SUSPENDED)
@@ -750,19 +765,11 @@ timer_changed:
 		}
 		empty = avail < pcm->avail_min;
 	}
-	switch (snd_pcm_state(dmix->spcm)) {
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		/* recover slave and update client state to xrun
-		 * before returning POLLERR
-		 */
-		snd_pcm_direct_slave_recover(dmix);
-		snd_pcm_direct_client_chk_xrun(dmix, pcm);
-		/* fallthrough */
-	case SND_PCM_STATE_SETUP:
+
+	if (snd_pcm_direct_check_xrun(dmix, pcm) < 0 ||
+	    snd_pcm_state(dmix->spcm) == SND_PCM_STATE_SETUP) {
 		events |= POLLERR;
-		break;
-	default:
+	} else {
 		if (empty) {
 			/* here we have a race condition:
 			 * if period event arrived after the avail_update call
@@ -786,7 +793,6 @@ timer_changed:
 				break;
 			}
 		}
-		break;
 	}
 	*revents = events;
 	return 0;
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
index fb013a6666c2..3e0c8bfcc9bc 100644
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -345,7 +345,7 @@ snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
 snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
 int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
 int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct);
-int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm);
+int snd_pcm_direct_check_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm);
 int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
 void snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix);
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index e3bf49269f0c..d00d53bef604 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -426,19 +426,7 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
 	snd_pcm_direct_t *dmix = pcm->private_data;
 	int err;
 
-	switch (snd_pcm_state(dmix->spcm)) {
-	case SND_PCM_STATE_DISCONNECTED:
-		dmix->state = SND_PCM_STATE_DISCONNECTED;
-		return -ENODEV;
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	err = snd_pcm_direct_client_chk_xrun(dmix, pcm);
+	err = snd_pcm_direct_check_xrun(dmix, pcm);
 	if (err < 0)
 		return err;
 	if (dmix->slowptr)
@@ -454,22 +442,8 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
 static snd_pcm_state_t snd_pcm_dmix_state(snd_pcm_t *pcm)
 {
 	snd_pcm_direct_t *dmix = pcm->private_data;
-	int err;
-	snd_pcm_state_t state;
-	state = snd_pcm_state(dmix->spcm);
-	switch (state) {
-	case SND_PCM_STATE_DISCONNECTED:
-		dmix->state = state;
-		return state;
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	snd_pcm_direct_client_chk_xrun(dmix, pcm);
+
+	snd_pcm_direct_check_xrun(dmix, pcm);
 	if (dmix->state == STATE_RUN_PENDING)
 		return SNDRV_PCM_STATE_RUNNING;
 	return dmix->state;
@@ -832,16 +806,7 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
 	snd_pcm_direct_t *dmix = pcm->private_data;
 	int err;
 
-	switch (snd_pcm_state(dmix->spcm)) {
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dmix)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	err = snd_pcm_direct_client_chk_xrun(dmix, pcm);
+	err = snd_pcm_direct_check_xrun(dmix, pcm);
 	if (err < 0)
 		return err;
 	if (! size)
diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index 5a52ae9173be..0ff43a90d270 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -201,19 +201,7 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
 	snd_pcm_direct_t *dshare = pcm->private_data;
 	int err;
 
-	switch (snd_pcm_state(dshare->spcm)) {
-	case SND_PCM_STATE_DISCONNECTED:
-		dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
-		return -ENODEV;
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	err = snd_pcm_direct_client_chk_xrun(dshare, pcm);
+	err = snd_pcm_direct_check_xrun(dshare, pcm);
 	if (err < 0)
 		return err;
 	if (dshare->slowptr)
@@ -257,22 +245,8 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 static snd_pcm_state_t snd_pcm_dshare_state(snd_pcm_t *pcm)
 {
 	snd_pcm_direct_t *dshare = pcm->private_data;
-	int err;
-	snd_pcm_state_t state;
-	state = snd_pcm_state(dshare->spcm);
-	switch (state) {
-	case SND_PCM_STATE_DISCONNECTED:
-		dshare->state = state;
-		return state;
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	snd_pcm_direct_client_chk_xrun(dshare, pcm);
+
+	snd_pcm_direct_check_xrun(dshare, pcm);
 	if (dshare->state == STATE_RUN_PENDING)
 		return SNDRV_PCM_STATE_RUNNING;
 	return dshare->state;
@@ -531,16 +505,7 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
 	snd_pcm_direct_t *dshare = pcm->private_data;
 	int err;
 
-	switch (snd_pcm_state(dshare->spcm)) {
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dshare)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	err = snd_pcm_direct_client_chk_xrun(dshare, pcm);
+	err = snd_pcm_direct_check_xrun(dshare, pcm);
 	if (err < 0)
 		return err;
 	if (! size)
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index 1653f6fba86c..729ff447b41f 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -134,19 +134,7 @@ static int snd_pcm_dsnoop_sync_ptr(snd_pcm_t *pcm)
 	snd_pcm_sframes_t diff;
 	int err;
 
-	switch (snd_pcm_state(dsnoop->spcm)) {
-	case SND_PCM_STATE_DISCONNECTED:
-		dsnoop->state = SNDRV_PCM_STATE_DISCONNECTED;
-		return -ENODEV;
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	err = snd_pcm_direct_client_chk_xrun(dsnoop, pcm);
+	err = snd_pcm_direct_check_xrun(dsnoop, pcm);
 	if (err < 0)
 		return err;
 	if (dsnoop->slowptr)
@@ -208,22 +196,8 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 static snd_pcm_state_t snd_pcm_dsnoop_state(snd_pcm_t *pcm)
 {
 	snd_pcm_direct_t *dsnoop = pcm->private_data;
-	int err;
-	snd_pcm_state_t state;
-	state = snd_pcm_state(dsnoop->spcm);
-	switch (state) {
-	case SND_PCM_STATE_DISCONNECTED:
-		dsnoop->state = state;
-		return state;
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	snd_pcm_direct_client_chk_xrun(dsnoop, pcm);
+
+	snd_pcm_direct_check_xrun(dsnoop, pcm);
 	return dsnoop->state;
 }
 
@@ -422,16 +396,7 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_mmap_commit(snd_pcm_t *pcm,
 	snd_pcm_direct_t *dsnoop = pcm->private_data;
 	int err;
 
-	switch (snd_pcm_state(dsnoop->spcm)) {
-	case SND_PCM_STATE_XRUN:
-	case SND_PCM_STATE_SUSPENDED:
-		if ((err = snd_pcm_direct_slave_recover(dsnoop)) < 0)
-			return err;
-		break;
-	default:
-		break;
-	}
-	err = snd_pcm_direct_client_chk_xrun(dsnoop, pcm);
+	err = snd_pcm_direct_check_xrun(dsnoop, pcm);
 	if (err < 0)
 		return err;
 	if (dsnoop->state == SND_PCM_STATE_RUNNING) {
