| @@ -685,33 +685,40 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, · 684 unmodified lines |
| 685 | 685 | return 0; |
| 686 | 686 | } |
| 687 | 687 | |
| 688 | +#if IS_ENABLED(CONFIG_SND_PCM_OSS) |
| 689 | +#define is_oss_stream(substream) ((substream)->oss.oss) |
| 690 | +#else |
| 691 | +#define is_oss_stream(substream) false |
| 692 | +#endif |
| 693 | + |
| 688 | 694 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, |
| 689 | 695 | struct snd_pcm_hw_params *params) |
| 690 | 696 | { |
| 691 | 697 | struct snd_pcm_runtime *runtime; |
| 692 | | − int err, usecs; |
| 698 | + int err = 0, usecs; |
| 693 | 699 | unsigned int bits; |
| 694 | 700 | snd_pcm_uframes_t frames; |
| 695 | 701 | |
| 696 | 702 | if (PCM_RUNTIME_CHECK(substream)) |
| 697 | 703 | return -ENXIO; |
| 698 | 704 | runtime = substream->runtime; |
| 705 | + mutex_lock(&runtime->buffer_mutex); |
| 699 | 706 | snd_pcm_stream_lock_irq(substream); |
| 700 | 707 | switch (runtime->status->state) { |
| 701 | 708 | case SNDRV_PCM_STATE_OPEN: |
| 702 | 709 | case SNDRV_PCM_STATE_SETUP: |
| 703 | 710 | case SNDRV_PCM_STATE_PREPARED: |
| 711 | + if (!is_oss_stream(substream) && |
| 712 | + atomic_read(&substream->mmap_count)) |
| 713 | + err = -EBADFD; |
| 704 | 714 | break; |
| 705 | 715 | default: |
| 706 | | − snd_pcm_stream_unlock_irq(substream); |
| 707 | | − return -EBADFD; |
| 716 | + err = -EBADFD; |
| 717 | + break; |
| 708 | 718 | } |
| 709 | 719 | snd_pcm_stream_unlock_irq(substream); |
| 710 | | −#if IS_ENABLED(CONFIG_SND_PCM_OSS) |
| 711 | | − if (!substream->oss.oss) |
| 712 | | −#endif |
| 713 | | − if (atomic_read(&substream->mmap_count)) |
| 714 | | − return -EBADFD; |
| 720 | + if (err) |
| 721 | + goto unlock; |
| 715 | 722 | |
| 716 | 723 | snd_pcm_sync_stop(substream, true); |
| 717 | 724 | |
| @@ -799,16 +806,21 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, · 81 unmodified lines |
| 799 | 806 | if (usecs >= 0) |
| 800 | 807 | cpu_latency_qos_add_request(&substream->latency_pm_qos_req, |
| 801 | 808 | usecs); |
| 802 | | − return 0; |
| 809 | + err = 0; |
| 803 | 810 | _error: |
| 804 | | − /* hardware might be unusable from this time, |
| 805 | | − so we force application to retry to set |
| 806 | | − the correct hardware parameter settings */ |
| 807 | | − snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); |
| 808 | | − if (substream->ops->hw_free != NULL) |
| 809 | | − substream->ops->hw_free(substream); |
| 810 | | − if (substream->managed_buffer_alloc) |
| 811 | | − snd_pcm_lib_free_pages(substream); |
| 811 | + if (err) { |
| 812 | + /* hardware might be unusable from this time, |
| 813 | + * so we force application to retry to set |
| 814 | + * the correct hardware parameter settings |
| 815 | + */ |
| 816 | + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); |
| 817 | + if (substream->ops->hw_free != NULL) |
| 818 | + substream->ops->hw_free(substream); |
| 819 | + if (substream->managed_buffer_alloc) |
| 820 | + snd_pcm_lib_free_pages(substream); |
| 821 | + } |
| 822 | + unlock: |
| 823 | + mutex_unlock(&runtime->buffer_mutex); |
| 812 | 824 | return err; |
| 813 | 825 | } |
| 814 | 826 | |
| @@ -848,26 +860,31 @@ static int do_hw_free(struct snd_pcm_substream *substream) · 33 unmodified lines |
| 848 | 860 | static int snd_pcm_hw_free(struct snd_pcm_substream *substream) |
| 849 | 861 | { |
| 850 | 862 | struct snd_pcm_runtime *runtime; |
| 851 | | − int result; |
| 863 | + int result = 0; |
| 852 | 864 | |
| 853 | 865 | if (PCM_RUNTIME_CHECK(substream)) |
| 854 | 866 | return -ENXIO; |
| 855 | 867 | runtime = substream->runtime; |
| 868 | + mutex_lock(&runtime->buffer_mutex); |
| 856 | 869 | snd_pcm_stream_lock_irq(substream); |
| 857 | 870 | switch (runtime->status->state) { |
| 858 | 871 | case SNDRV_PCM_STATE_SETUP: |
| 859 | 872 | case SNDRV_PCM_STATE_PREPARED: |
| 873 | + if (atomic_read(&substream->mmap_count)) |
| 874 | + result = -EBADFD; |
| 860 | 875 | break; |
| 861 | 876 | default: |
| 862 | | − snd_pcm_stream_unlock_irq(substream); |
| 863 | | − return -EBADFD; |
| 877 | + result = -EBADFD; |
| 878 | + break; |
| 864 | 879 | } |
| 865 | 880 | snd_pcm_stream_unlock_irq(substream); |
| 866 | | − if (atomic_read(&substream->mmap_count)) |
| 867 | | − return -EBADFD; |
| 881 | + if (result) |
| 882 | + goto unlock; |
| 868 | 883 | result = do_hw_free(substream); |
| 869 | 884 | snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); |
| 870 | 885 | cpu_latency_qos_remove_request(&substream->latency_pm_qos_req); |
| 886 | + unlock: |
| 887 | + mutex_unlock(&runtime->buffer_mutex); |
| 871 | 888 | return result; |
| 872 | 889 | } |
| 873 | 890 | |