0130-bcm2835-access-controls-under-the-audio-mutex.patch 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. From 16a8daf3e66584f5c1bd3b113675d3fc3b44adc1 Mon Sep 17 00:00:00 2001
  2. From: wm4 <wm4@nowhere>
  3. Date: Wed, 13 Jan 2016 19:43:35 +0100
  4. Subject: [PATCH 130/381] bcm2835: access controls under the audio mutex
  5. I don't think the ALSA framework provides any kind of automatic
  6. synchronization within the control callbacks. We most likely need
  7. to ensure this manually, so add locking around all access to shared
  8. mutable data. In particular, bcm2835_audio_set_ctls() should
  9. probably always be called under our own audio lock.
  10. ---
  11. sound/arm/bcm2835-ctl.c | 74 +++++++++++++++++++++++++++++++++++++++++--------
  12. sound/arm/bcm2835-pcm.c | 4 +++
  13. 2 files changed, 66 insertions(+), 12 deletions(-)
  14. --- a/sound/arm/bcm2835-ctl.c
  15. +++ b/sound/arm/bcm2835-ctl.c
  16. @@ -94,6 +94,9 @@ static int snd_bcm2835_ctl_get(struct sn
  17. {
  18. struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
  19. + if (mutex_lock_interruptible(&chip->audio_mutex))
  20. + return -EINTR;
  21. +
  22. BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
  23. if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
  24. @@ -103,6 +106,7 @@ static int snd_bcm2835_ctl_get(struct sn
  25. else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
  26. ucontrol->value.integer.value[0] = chip->dest;
  27. + mutex_unlock(&chip->audio_mutex);
  28. return 0;
  29. }
  30. @@ -112,11 +116,15 @@ static int snd_bcm2835_ctl_put(struct sn
  31. struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
  32. int changed = 0;
  33. + if (mutex_lock_interruptible(&chip->audio_mutex))
  34. + return -EINTR;
  35. +
  36. if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
  37. audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
  38. if (chip->mute == CTRL_VOL_MUTE) {
  39. /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
  40. - return 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
  41. + changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
  42. + goto unlock;
  43. }
  44. if (changed
  45. || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
  46. @@ -142,6 +150,8 @@ static int snd_bcm2835_ctl_put(struct sn
  47. printk(KERN_ERR "Failed to set ALSA controls..\n");
  48. }
  49. +unlock:
  50. + mutex_unlock(&chip->audio_mutex);
  51. return changed;
  52. }
  53. @@ -198,10 +208,14 @@ static int snd_bcm2835_spdif_default_get
  54. struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
  55. int i;
  56. + if (mutex_lock_interruptible(&chip->audio_mutex))
  57. + return -EINTR;
  58. +
  59. for (i = 0; i < 4; i++)
  60. ucontrol->value.iec958.status[i] =
  61. (chip->spdif_status >> (i * 8)) && 0xff;
  62. + mutex_unlock(&chip->audio_mutex);
  63. return 0;
  64. }
  65. @@ -212,12 +226,16 @@ static int snd_bcm2835_spdif_default_put
  66. unsigned int val = 0;
  67. int i, change;
  68. + if (mutex_lock_interruptible(&chip->audio_mutex))
  69. + return -EINTR;
  70. +
  71. for (i = 0; i < 4; i++)
  72. val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
  73. change = val != chip->spdif_status;
  74. chip->spdif_status = val;
  75. + mutex_unlock(&chip->audio_mutex);
  76. return change;
  77. }
  78. @@ -253,9 +271,14 @@ static int snd_bcm2835_spdif_stream_get(
  79. struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
  80. int i;
  81. + if (mutex_lock_interruptible(&chip->audio_mutex))
  82. + return -EINTR;
  83. +
  84. for (i = 0; i < 4; i++)
  85. ucontrol->value.iec958.status[i] =
  86. (chip->spdif_status >> (i * 8)) & 0xff;
  87. +
  88. + mutex_unlock(&chip->audio_mutex);
  89. return 0;
  90. }
  91. @@ -266,11 +289,15 @@ static int snd_bcm2835_spdif_stream_put(
  92. unsigned int val = 0;
  93. int i, change;
  94. + if (mutex_lock_interruptible(&chip->audio_mutex))
  95. + return -EINTR;
  96. +
  97. for (i = 0; i < 4; i++)
  98. val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
  99. change = val != chip->spdif_status;
  100. chip->spdif_status = val;
  101. + mutex_unlock(&chip->audio_mutex);
  102. return change;
  103. }
  104. @@ -454,11 +481,17 @@ static int snd_bcm2835_chmap_ctl_get(str
  105. unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  106. struct snd_pcm_substream *substream = snd_pcm_chmap_substream(info, idx);
  107. struct cea_channel_speaker_allocation *ch = NULL;
  108. + int res = 0;
  109. int cur = 0;
  110. int i;
  111. - if (!substream || !substream->runtime)
  112. - return -ENODEV;
  113. + if (mutex_lock_interruptible(&chip->audio_mutex))
  114. + return -EINTR;
  115. +
  116. + if (!substream || !substream->runtime) {
  117. + res = -ENODEV;
  118. + goto unlock;
  119. + }
  120. for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
  121. if (channel_allocations[i].ca_index == chip->cea_chmap)
  122. @@ -476,7 +509,10 @@ static int snd_bcm2835_chmap_ctl_get(str
  123. }
  124. while (cur < 8)
  125. ucontrol->value.integer.value[cur++] = SNDRV_CHMAP_NA;
  126. - return 0;
  127. +
  128. +unlock:
  129. + mutex_unlock(&chip->audio_mutex);
  130. + return res;
  131. }
  132. static int snd_bcm2835_chmap_ctl_put(struct snd_kcontrol *kcontrol,
  133. @@ -487,10 +523,16 @@ static int snd_bcm2835_chmap_ctl_put(str
  134. unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  135. struct snd_pcm_substream *substream = snd_pcm_chmap_substream(info, idx);
  136. int i, prepared = 0, cea_chmap = -1;
  137. + int res = 0;
  138. int remap[8];
  139. - if (!substream || !substream->runtime)
  140. - return -ENODEV;
  141. + if (mutex_lock_interruptible(&chip->audio_mutex))
  142. + return -EINTR;
  143. +
  144. + if (!substream || !substream->runtime) {
  145. + res = -ENODEV;
  146. + goto unlock;
  147. + }
  148. switch (substream->runtime->status->state) {
  149. case SNDRV_PCM_STATE_OPEN:
  150. @@ -500,7 +542,8 @@ static int snd_bcm2835_chmap_ctl_put(str
  151. prepared = 1;
  152. break;
  153. default:
  154. - return -EBUSY;
  155. + res = -EBUSY;
  156. + goto unlock;
  157. }
  158. for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
  159. @@ -538,19 +581,26 @@ static int snd_bcm2835_chmap_ctl_put(str
  160. }
  161. }
  162. - if (cea_chmap < 0)
  163. - return -EINVAL;
  164. + if (cea_chmap < 0) {
  165. + res = -EINVAL;
  166. + goto unlock;
  167. + }
  168. /* don't change the layout if another substream is active */
  169. - if (chip->opened != (1 << substream->number) && chip->cea_chmap != cea_chmap)
  170. - return -EBUSY; /* unsure whether this is a good error code */
  171. + if (chip->opened != (1 << substream->number) && chip->cea_chmap != cea_chmap) {
  172. + res = -EBUSY; /* unsure whether this is a good error code */
  173. + goto unlock;
  174. + }
  175. chip->cea_chmap = cea_chmap;
  176. for (i = 0; i < 8; i++)
  177. chip->map_channels[i] = remap[i];
  178. if (prepared)
  179. snd_bcm2835_pcm_prepare_again(substream);
  180. - return 0;
  181. +
  182. +unlock:
  183. + mutex_unlock(&chip->audio_mutex);
  184. + return res;
  185. }
  186. static int snd_bcm2835_add_chmap_ctl(bcm2835_chip_t * chip)
  187. --- a/sound/arm/bcm2835-pcm.c
  188. +++ b/sound/arm/bcm2835-pcm.c
  189. @@ -379,6 +379,9 @@ static int snd_bcm2835_pcm_prepare(struc
  190. audio_info(" .. IN\n");
  191. + if (mutex_lock_interruptible(&chip->audio_mutex))
  192. + return -EINTR;
  193. +
  194. snd_bcm2835_pcm_prepare_again(substream);
  195. bcm2835_audio_setup(alsa_stream);
  196. @@ -401,6 +404,7 @@ static int snd_bcm2835_pcm_prepare(struc
  197. alsa_stream->buffer_size, alsa_stream->period_size,
  198. alsa_stream->pos, runtime->frame_bits);
  199. + mutex_unlock(&chip->audio_mutex);
  200. audio_info(" .. OUT\n");
  201. return 0;
  202. }