From cecd70d492e343e802f71e9cca94b94fb46efa93 Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Thu, 20 Nov 2014 09:57:09 +0900
Subject: [PATCH] oxfw: use mutex only instead of atomic_t to handle critical
 section easily

OXFW driver has some critical sections. Some of them are protected by atomic_t
and the others are protected by mutex. But they can be merged.

Originally, I added atomic_t for a reference counter to enclose
mutex_lock()/mutex_unlock() inner -stream.c. But it's cumbersome that this
driver has some mutual primitives for stream handling.

This commit obsoletes atomic_t and use mutex only.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/oxfw/oxfw-midi.c   | 16 ++++++++++++----
 sound/firewire/oxfw/oxfw-pcm.c    | 34 ++++++++++++++++++++++++++--------
 sound/firewire/oxfw/oxfw-stream.c | 39 +++++++++++----------------------------
 sound/firewire/oxfw/oxfw.c        |  4 ++++
 sound/firewire/oxfw/oxfw.h        |  4 ++--
 5 files changed, 55 insertions(+), 42 deletions(-)

diff --git a/sound/firewire/oxfw/oxfw-midi.c b/sound/firewire/oxfw/oxfw-midi.c
index 94bc8d0..331838e 100644
--- a/sound/firewire/oxfw/oxfw-midi.c
+++ b/sound/firewire/oxfw/oxfw-midi.c
@@ -17,8 +17,10 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream)
 	if (err < 0)
 		goto end;
 
-	atomic_inc(&oxfw->capture_substreams);
+	mutex_lock(&oxfw->mutex);
+	oxfw->capture_substreams++;
 	err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream, 0, 0);
+	mutex_unlock(&oxfw->mutex);
 	if (err < 0)
 		snd_oxfw_stream_lock_release(oxfw);
 end:
@@ -34,8 +36,10 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream)
 	if (err < 0)
 		goto end;
 
-	atomic_inc(&oxfw->playback_substreams);
+	mutex_lock(&oxfw->mutex);
+	oxfw->playback_substreams++;
 	err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream, 0, 0);
+	mutex_unlock(&oxfw->mutex);
 	if (err < 0)
 		snd_oxfw_stream_lock_release(oxfw);
 end:
@@ -46,8 +50,10 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream)
 {
 	struct snd_oxfw *oxfw = substream->rmidi->private_data;
 
-	atomic_dec(&oxfw->capture_substreams);
+	mutex_lock(&oxfw->mutex);
+	oxfw->capture_substreams--;
 	snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream);
+	mutex_unlock(&oxfw->mutex);
 
 	snd_oxfw_stream_lock_release(oxfw);
 	return 0;
@@ -57,8 +63,10 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream)
 {
 	struct snd_oxfw *oxfw = substream->rmidi->private_data;
 
-	atomic_dec(&oxfw->playback_substreams);
+	mutex_lock(&oxfw->mutex);
+	oxfw->playback_substreams--;
 	snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream);
+	mutex_unlock(&oxfw->mutex);
 
 	snd_oxfw_stream_lock_release(oxfw);
 	return 0;
diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c
index c508a1f..475d1aa 100644
--- a/sound/firewire/oxfw/oxfw-pcm.c
+++ b/sound/firewire/oxfw/oxfw-pcm.c
@@ -232,8 +232,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_oxfw *oxfw = substream->private_data;
 
-	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
-		atomic_inc(&oxfw->capture_substreams);
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		mutex_lock(&oxfw->mutex);
+		oxfw->capture_substreams++;
+		mutex_unlock(&oxfw->mutex);
+	}
+
 	amdtp_stream_set_pcm_format(&oxfw->tx_stream, params_format(hw_params));
 
 	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
@@ -244,8 +248,12 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_oxfw *oxfw = substream->private_data;
 
-	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
-		atomic_inc(&oxfw->playback_substreams);
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		mutex_lock(&oxfw->mutex);
+		oxfw->playback_substreams++;
+		mutex_unlock(&oxfw->mutex);
+	}
+
 	amdtp_stream_set_pcm_format(&oxfw->rx_stream, params_format(hw_params));
 
 	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
@@ -256,8 +264,11 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
 {
 	struct snd_oxfw *oxfw = substream->private_data;
 
-	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
-		atomic_dec(&oxfw->capture_substreams);
+	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) {
+		mutex_lock(&oxfw->mutex);
+		oxfw->capture_substreams--;
+		mutex_unlock(&oxfw->mutex);
+	}
 
 	snd_oxfw_stream_stop_simplex(oxfw, &oxfw->tx_stream);
 
@@ -267,8 +278,11 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
 {
 	struct snd_oxfw *oxfw = substream->private_data;
 
-	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
-		atomic_dec(&oxfw->playback_substreams);
+	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) {
+		mutex_lock(&oxfw->mutex);
+		oxfw->playback_substreams--;
+		mutex_unlock(&oxfw->mutex);
+	}
 
 	snd_oxfw_stream_stop_simplex(oxfw, &oxfw->rx_stream);
 
@@ -281,8 +295,10 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int err;
 
+	mutex_lock(&oxfw->mutex);
 	err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->tx_stream,
 					    runtime->rate, runtime->channels);
+	mutex_unlock(&oxfw->mutex);
 	if (err < 0)
 		goto end;
 
@@ -296,8 +312,10 @@ static int pcm_playback_prepare(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int err;
 
+	mutex_lock(&oxfw->mutex);
 	err = snd_oxfw_stream_start_simplex(oxfw, &oxfw->rx_stream,
 					    runtime->rate, runtime->channels);
+	mutex_unlock(&oxfw->mutex);
 	if (err < 0)
 		goto end;
 
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c
index b1dcc68..00870df 100644
--- a/sound/firewire/oxfw/oxfw-stream.c
+++ b/sound/firewire/oxfw/oxfw-stream.c
@@ -219,8 +219,6 @@ int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw,
 		s_dir = AMDTP_OUT_STREAM;
 	}
 
-	mutex_lock(&oxfw->mutex);
-
 	err = cmp_connection_init(conn, oxfw->unit, c_dir, 0);
 	if (err < 0)
 		goto end;
@@ -236,7 +234,6 @@ int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw,
 	if (stream == &oxfw->tx_stream)
 		oxfw->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK;
 end:
-	mutex_unlock(&oxfw->mutex);
 	return err;
 }
 
@@ -247,17 +244,17 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw,
 	struct amdtp_stream *opposite;
 	struct snd_oxfw_stream_formation formation;
 	enum avc_general_plug_dir dir;
-	atomic_t *substreams, *opposite_substreams;
+	unsigned int substreams, opposite_substreams;
 	int err = 0;
 
 	if (stream == &oxfw->tx_stream) {
-		substreams = &oxfw->capture_substreams;
+		substreams = oxfw->capture_substreams;
 		opposite = &oxfw->rx_stream;
-		opposite_substreams = &oxfw->playback_substreams;
+		opposite_substreams = oxfw->playback_substreams;
 		dir = AVC_GENERAL_PLUG_DIR_OUT;
 	} else {
-		substreams = &oxfw->playback_substreams;
-		opposite_substreams = &oxfw->capture_substreams;
+		substreams = oxfw->playback_substreams;
+		opposite_substreams = oxfw->capture_substreams;
 
 		if (oxfw->has_output)
 			opposite = &oxfw->rx_stream;
@@ -267,11 +264,9 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw,
 		dir = AVC_GENERAL_PLUG_DIR_IN;
 	}
 
-	if (atomic_read(substreams) == 0)
+	if (substreams == 0)
 		goto end;
 
-	mutex_lock(&oxfw->mutex);
-
 	/*
 	 * Considering JACK/FFADO streaming:
 	 * TODO: This can be removed hwdep functionality becomes popular.
@@ -310,7 +305,7 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw,
 
 		/* Start opposite stream if needed. */
 		if (opposite && !amdtp_stream_running(opposite) &&
-		    (atomic_read(opposite_substreams) > 0)) {
+		    (opposite_substreams > 0)) {
 			err = start_stream(oxfw, opposite, rate, 0);
 			if (err < 0) {
 				dev_err(&oxfw->unit->device,
@@ -328,22 +323,17 @@ int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw,
 				"fail to start stream: %d\n", err);
 	}
 end:
-	mutex_unlock(&oxfw->mutex);
 	return err;
 }
 
 void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw,
 				  struct amdtp_stream *stream)
 {
-	if (((stream == &oxfw->tx_stream) &&
-	     (atomic_read(&oxfw->capture_substreams) > 0)) ||
-	    ((stream == &oxfw->rx_stream) &&
-	     (atomic_read(&oxfw->playback_substreams) > 0)))
+	if (((stream == &oxfw->tx_stream) && (oxfw->capture_substreams > 0)) ||
+	    ((stream == &oxfw->rx_stream) && (oxfw->playback_substreams > 0)))
 		return;
 
-	mutex_lock(&oxfw->mutex);
 	stop_stream(oxfw, stream);
-	mutex_unlock(&oxfw->mutex);
 }
 
 void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw,
@@ -356,14 +346,10 @@ void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw,
 	else
 		conn = &oxfw->in_conn;
 
-	mutex_lock(&oxfw->mutex);
-
 	stop_stream(oxfw, stream);
 
 	amdtp_stream_destroy(stream);
 	cmp_connection_destroy(conn);
-
-	mutex_unlock(&oxfw->mutex);
 }
 
 void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw,
@@ -376,13 +362,10 @@ void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw,
 	else
 		conn = &oxfw->in_conn;
 
-	if (cmp_connection_update(conn) < 0) {
-		mutex_lock(&oxfw->mutex);
+	if (cmp_connection_update(conn) < 0)
 		stop_stream(oxfw, stream);
-		mutex_unlock(&oxfw->mutex);
-	} else {
+	else
 		amdtp_stream_update(stream);
-	}
 }
 
 int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index 40cd2c0..60c68ce 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -214,10 +214,14 @@ static void oxfw_bus_reset(struct fw_unit *unit)
 {
 	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
 
+	mutex_lock(&oxfw->mutex);
+
 	fcp_bus_reset(oxfw->unit);
 	snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream);
 	if (oxfw->has_output)
 		snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream);
+
+	mutex_unlock(&oxfw->mutex);
 }
 
 static void oxfw_remove(struct fw_unit *unit)
diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h
index d2f8ee5..65b95f2 100644
--- a/sound/firewire/oxfw/oxfw.h
+++ b/sound/firewire/oxfw/oxfw.h
@@ -56,8 +56,8 @@ struct snd_oxfw {
 	struct cmp_connection in_conn;
 	struct amdtp_stream tx_stream;
 	struct amdtp_stream rx_stream;
-	atomic_t capture_substreams;
-	atomic_t playback_substreams;
+	unsigned int capture_substreams;
+	unsigned int playback_substreams;
 
 	unsigned int midi_input_ports;
 	unsigned int midi_output_ports;
-- 
2.1.0

