From 01573e231f18eb2d99162747186f59511f56b64d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 08 Dec 2023 10:40:48 +0000 Subject: [PATCH] 移去rt --- kernel/sound/usb/stream.c | 92 ++++++++++++++++++++++++++++----------------- 1 files changed, 57 insertions(+), 35 deletions(-) diff --git a/kernel/sound/usb/stream.c b/kernel/sound/usb/stream.c index 3c55274..d1a8dd5 100644 --- a/kernel/sound/usb/stream.c +++ b/kernel/sound/usb/stream.c @@ -1,17 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -38,6 +26,15 @@ #include "clock.h" #include "stream.h" #include "power.h" +#include "media.h" + +static void audioformat_free(struct audioformat *fp) +{ + list_del(&fp->list); /* unlink for avoiding double-free */ + kfree(fp->rate_table); + kfree(fp->chmap); + kfree(fp); +} /* * free a substream @@ -48,13 +45,11 @@ if (!subs->num_formats) return; /* not initialized */ - list_for_each_entry_safe(fp, n, &subs->fmt_list, list) { - kfree(fp->rate_table); - kfree(fp->chmap); - kfree(fp); - } + list_for_each_entry_safe(fp, n, &subs->fmt_list, list) + audioformat_free(fp); kfree(subs->rate_list.list); kfree(subs->str_pd); + snd_media_stream_delete(subs); } @@ -73,7 +68,6 @@ { struct snd_usb_stream *stream = pcm->private_data; struct snd_usb_audio *chip; - if (stream) { mutex_lock(&stream->chip->dev_lock); chip = stream->chip; @@ -104,6 +98,7 @@ subs->tx_length_quirk = as->chip->tx_length_quirk; subs->speed = snd_usb_get_speed(subs->dev); subs->pkt_offset_adj = 0; + subs->stream_offset_adj = 0; snd_usb_set_pcm_ops(as->pcm, stream); @@ -505,6 +500,10 @@ return 0; } } + + if (chip->card->registered) + chip->need_delayed_register = true; + /* look for an empty stream */ list_for_each_entry(as, &chip->pcm_list, list) { if (as->fmt_type != fp->fmt_type) @@ -847,8 +846,7 @@ /* ok, let's parse further... */ if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) { - kfree(fp->rate_table); - kfree(fp); + audioformat_free(fp); return NULL; } @@ -1059,9 +1057,7 @@ pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) { - kfree(fp->chmap); - kfree(fp->rate_table); - kfree(fp); + audioformat_free(fp); return NULL; } pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ? @@ -1080,9 +1076,7 @@ /* ok, let's parse further... */ if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { kfree(pd); - kfree(fp->chmap); - kfree(fp->rate_table); - kfree(fp); + audioformat_free(fp); return NULL; } } @@ -1093,7 +1087,9 @@ return fp; } -int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) +static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, + int iface_no, + bool *has_non_pcm, bool non_pcm) { struct usb_device *dev; struct usb_interface *iface; @@ -1115,7 +1111,7 @@ * Dallas DS4201 workaround: It presents 5 altsettings, but the last * one misses syncpipe, and does not produce any sound. */ - if (chip->usb_id == USB_ID(0x04fa, 0x4201)) + if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4) num = 4; for (i = 0; i < num; i++) { @@ -1156,9 +1152,8 @@ dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n", iface_no, altno, protocol); protocol = UAC_VERSION_1; - /* fall through */ + fallthrough; case UAC_VERSION_1: - /* fall through */ case UAC_VERSION_2: { int bm_quirk = 0; @@ -1194,6 +1189,16 @@ else if (IS_ERR(fp)) return PTR_ERR(fp); + if (fp->fmt_type != UAC_FORMAT_TYPE_I) + *has_non_pcm = true; + if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) { + audioformat_free(fp); + kfree(pd); + fp = NULL; + pd = NULL; + continue; + } + dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); if (protocol == UAC_VERSION_3) err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); @@ -1201,11 +1206,8 @@ err = snd_usb_add_audio_stream(chip, stream, fp); if (err < 0) { - list_del(&fp->list); /* unlink for avoiding double-free */ + audioformat_free(fp); kfree(pd); - kfree(fp->rate_table); - kfree(fp->chmap); - kfree(fp); return err; } /* try to set the interface... */ @@ -1216,3 +1218,23 @@ return 0; } +int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) +{ + int err; + bool has_non_pcm = false; + + /* parse PCM formats */ + err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false); + if (err < 0) + return err; + + if (has_non_pcm) { + /* parse non-PCM formats */ + err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true); + if (err < 0) + return err; + } + + return 0; +} + -- Gitblit v1.6.2