From patchwork Fri Feb 28 12:46:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 3740671 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 60A3A9F35F for ; Fri, 28 Feb 2014 12:47:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3F77F2028D for ; Fri, 28 Feb 2014 12:47:00 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id B33B120295 for ; Fri, 28 Feb 2014 12:46:58 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 0314A265120; Fri, 28 Feb 2014 13:46:52 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 7F18E26508C; Fri, 28 Feb 2014 13:46:42 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id D25BE265090; Fri, 28 Feb 2014 13:46:41 +0100 (CET) Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) by alsa0.perex.cz (Postfix) with ESMTP id DC5EB261A27 for ; Fri, 28 Feb 2014 13:46:34 +0100 (CET) Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 71C2075016 for ; Fri, 28 Feb 2014 12:46:34 +0000 (UTC) From: Takashi Iwai To: alsa-devel@alsa-project.org Date: Fri, 28 Feb 2014 13:46:34 +0100 Message-Id: <1393591594-3346-1-git-send-email-tiwai@suse.de> X-Mailer: git-send-email 1.9.0 Subject: [alsa-devel] [PATCH] ALSA: hda - Fix registration of beep input device X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP The beep input device is registered via input_register_device(), but this is called in snd_hda_attach_beep_device() where the sound devices aren't registered yet. This leads to the binding to non-existing object, thus results in failure. And, even if the binding worked (against the PCI object), it's still racy; the input device appears before the sound objects. For fixing this, register the input device properly at dev_register ops of the codec object it's bound with. Also, call snd_hda_detach_beep_device() at dev_disconnection so that it's detached at the right timing. As a bonus, since it's called in the codec's ops, we can get rid of the further call from the other codec drivers. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 27 ++++++++++++++++++++------- sound/pci/hda/hda_beep.h | 5 +++++ sound/pci/hda/hda_codec.c | 7 ++++++- sound/pci/hda/hda_generic.c | 1 - sound/pci/hda/patch_conexant.c | 4 +--- 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 88bb08486f77..b9d3d0cd75c9 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -148,7 +148,6 @@ static int snd_hda_do_attach(struct hda_beep *beep) { struct input_dev *input_dev; struct hda_codec *codec = beep->codec; - int err; input_dev = input_allocate_device(); if (!input_dev) @@ -169,12 +168,6 @@ static int snd_hda_do_attach(struct hda_beep *beep) input_dev->dev.parent = &codec->dev; input_set_drvdata(input_dev, beep); - err = input_register_device(input_dev); - if (err < 0) { - input_free_device(input_dev); - codec_err(codec, "hda_beep: unable to register input device\n"); - return err; - } beep->dev = input_dev; return 0; } @@ -244,6 +237,26 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) } EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device); +int snd_hda_register_beep_device(struct hda_codec *codec) +{ + struct hda_beep *beep = codec->beep; + int err; + + if (!beep || !beep->dev) + return 0; + + err = input_register_device(beep->dev); + if (err < 0) { + codec_err(codec, "hda_beep: unable to register input device\n"); + input_free_device(beep->dev); + codec->beep = NULL; + kfree(beep); + return err; + } + return 0; +} +EXPORT_SYMBOL_GPL(snd_hda_register_beep_device); + static bool ctl_has_mute(struct snd_kcontrol *kcontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index cb88464676b6..76eb8589fb9e 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -45,6 +45,7 @@ struct hda_beep { int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); void snd_hda_detach_beep_device(struct hda_codec *codec); +int snd_hda_register_beep_device(struct hda_codec *codec); #else static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) { @@ -53,5 +54,9 @@ static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) static inline void snd_hda_detach_beep_device(struct hda_codec *codec) { } +static inline int snd_hda_register_beep_device(struct hda_codec *codec) +{ + return 0; +} #endif #endif diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 6db2dbcbf4d3..555e8c771cfd 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1379,14 +1379,19 @@ static unsigned int hda_set_power_state(struct hda_codec *codec, static int snd_hda_codec_dev_register(struct snd_device *device) { struct hda_codec *codec = device->device_data; + int err = device_add(&codec->dev); - return device_add(&codec->dev); + if (err < 0) + return err; + snd_hda_register_beep_device(codec); + return 0; } static int snd_hda_codec_dev_disconnect(struct snd_device *device) { struct hda_codec *codec = device->device_data; + snd_hda_detach_beep_device(codec); device_del(&codec->dev); return 0; } diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 9e0609a4b2ba..16133881e967 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -5350,7 +5350,6 @@ EXPORT_SYMBOL_GPL(snd_hda_gen_init); void snd_hda_gen_free(struct hda_codec *codec) { snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE); - snd_hda_detach_beep_device(codec); snd_hda_gen_spec_free(codec->spec); kfree(codec->spec); codec->spec = NULL; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 09d6d0db2b06..1dc7e974f3b1 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -445,9 +445,7 @@ static int conexant_init(struct hda_codec *codec) static void conexant_free(struct hda_codec *codec) { - struct conexant_spec *spec = codec->spec; - snd_hda_detach_beep_device(codec); - kfree(spec); + kfree(codec->spec); } static const struct snd_kcontrol_new cxt_capture_mixers[] = {