mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-11 03:45:21 +02:00
usb: gadget: u_audio: Fix race condition use of controls after free during gadget unbind.
[ Upstream commit1b739388aa
] Hang on to the control IDs instead of pointers since those are correctly handled with locks. Fixes:8fe9a03f43
("usb: gadget: u_audio: Rate ctl notifies about current srate (0=stopped)") Fixes:c565ad07ef
("usb: gadget: u_audio: Support multiple sampling rates") Fixes:02de698ca8
("usb: gadget: u_audio: add bi-directional volume and mute support") Signed-off-by: Chris Wulff <chris.wulff@biamp.com> Link: https://lore.kernel.org/stable/CO1PR17MB5419C2BF44D400E4E620C1ADE1172%40CO1PR17MB5419.namprd17.prod.outlook.com Link: https://lore.kernel.org/r/CO1PR17MB5419C2BF44D400E4E620C1ADE1172@CO1PR17MB5419.namprd17.prod.outlook.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
9eb15f24a0
commit
453d3fa926
|
@ -57,13 +57,13 @@ struct uac_rtd_params {
|
||||||
|
|
||||||
/* Volume/Mute controls and their state */
|
/* Volume/Mute controls and their state */
|
||||||
int fu_id; /* Feature Unit ID */
|
int fu_id; /* Feature Unit ID */
|
||||||
struct snd_kcontrol *snd_kctl_volume;
|
struct snd_ctl_elem_id snd_kctl_volume_id;
|
||||||
struct snd_kcontrol *snd_kctl_mute;
|
struct snd_ctl_elem_id snd_kctl_mute_id;
|
||||||
s16 volume_min, volume_max, volume_res;
|
s16 volume_min, volume_max, volume_res;
|
||||||
s16 volume;
|
s16 volume;
|
||||||
int mute;
|
int mute;
|
||||||
|
|
||||||
struct snd_kcontrol *snd_kctl_rate; /* read-only current rate */
|
struct snd_ctl_elem_id snd_kctl_rate_id; /* read-only current rate */
|
||||||
int srate; /* selected samplerate */
|
int srate; /* selected samplerate */
|
||||||
int active; /* playback/capture running */
|
int active; /* playback/capture running */
|
||||||
|
|
||||||
|
@ -494,14 +494,13 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep)
|
||||||
static void set_active(struct uac_rtd_params *prm, bool active)
|
static void set_active(struct uac_rtd_params *prm, bool active)
|
||||||
{
|
{
|
||||||
// notifying through the Rate ctrl
|
// notifying through the Rate ctrl
|
||||||
struct snd_kcontrol *kctl = prm->snd_kctl_rate;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&prm->lock, flags);
|
spin_lock_irqsave(&prm->lock, flags);
|
||||||
if (prm->active != active) {
|
if (prm->active != active) {
|
||||||
prm->active = active;
|
prm->active = active;
|
||||||
snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||||
&kctl->id);
|
&prm->snd_kctl_rate_id);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&prm->lock, flags);
|
spin_unlock_irqrestore(&prm->lock, flags);
|
||||||
}
|
}
|
||||||
|
@ -807,7 +806,7 @@ int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val)
|
||||||
|
|
||||||
if (change)
|
if (change)
|
||||||
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||||
&prm->snd_kctl_volume->id);
|
&prm->snd_kctl_volume_id);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -856,7 +855,7 @@ int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val)
|
||||||
|
|
||||||
if (change)
|
if (change)
|
||||||
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||||
&prm->snd_kctl_mute->id);
|
&prm->snd_kctl_mute_id);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1331,7 +1330,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
||||||
err = snd_ctl_add(card, kctl);
|
err = snd_ctl_add(card, kctl);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto snd_fail;
|
goto snd_fail;
|
||||||
prm->snd_kctl_mute = kctl;
|
prm->snd_kctl_mute_id = kctl->id;
|
||||||
prm->mute = 0;
|
prm->mute = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1359,7 +1358,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
||||||
err = snd_ctl_add(card, kctl);
|
err = snd_ctl_add(card, kctl);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto snd_fail;
|
goto snd_fail;
|
||||||
prm->snd_kctl_volume = kctl;
|
prm->snd_kctl_volume_id = kctl->id;
|
||||||
prm->volume = fu->volume_max;
|
prm->volume = fu->volume_max;
|
||||||
prm->volume_max = fu->volume_max;
|
prm->volume_max = fu->volume_max;
|
||||||
prm->volume_min = fu->volume_min;
|
prm->volume_min = fu->volume_min;
|
||||||
|
@ -1383,7 +1382,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
|
||||||
err = snd_ctl_add(card, kctl);
|
err = snd_ctl_add(card, kctl);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto snd_fail;
|
goto snd_fail;
|
||||||
prm->snd_kctl_rate = kctl;
|
prm->snd_kctl_rate_id = kctl->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
strscpy(card->driver, card_name, sizeof(card->driver));
|
strscpy(card->driver, card_name, sizeof(card->driver));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user