From 361dab3ec2c59044f420cdf232523cd4af4e833e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 9 May 2012 14:35:27 +0200 Subject: [PATCH] ALSA: hda - Call snd_array_init() early and only once This is a preliminary patch for introducing a protection to access races of snd_array instances. Call snd_array_init() appropriately at the initialization time and don't call it twice. Also the allocations of codec-spec structs are cleaned up by helper functions in patch_sigmatel.c and patch_analog.c. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 1 + sound/pci/hda/hda_jack.c | 1 - sound/pci/hda/patch_analog.c | 74 ++++++++++--------- sound/pci/hda/patch_realtek.c | 4 +- sound/pci/hda/patch_sigmatel.c | 128 ++++++++++++++++----------------- sound/pci/hda/patch_via.c | 2 +- 6 files changed, 106 insertions(+), 104 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c8f6c3bcb4f3..3634bfebc008 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1250,6 +1250,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); + snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16); INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); #ifdef CONFIG_PM diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 4e1948001338..6e9f57bbe667 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -95,7 +95,6 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); if (jack) return jack; - snd_array_init(&codec->jacktbl, sizeof(*jack), 16); jack = snd_array_new(&codec->jacktbl); if (!jack) return NULL; diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index eb5689df206a..89fc5030ec79 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1246,16 +1246,27 @@ static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; } +static int alloc_ad_spec(struct hda_codec *codec) +{ + struct ad198x_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + codec->spec = spec; + snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); + return 0; +} + static int patch_ad1986a(struct hda_codec *codec) { struct ad198x_spec *spec; int err, board_config; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; + err = alloc_ad_spec(codec); + if (err < 0) + return err; + spec = codec->spec; err = snd_hda_attach_beep_device(codec, 0x19); if (err < 0) { @@ -1548,11 +1559,10 @@ static int patch_ad1983(struct hda_codec *codec) struct ad198x_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; + err = alloc_ad_spec(codec); + if (err < 0) + return err; + spec = codec->spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -1954,11 +1964,10 @@ static int patch_ad1981(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) + err = alloc_ad_spec(codec); + if (err < 0) return -ENOMEM; - - codec->spec = spec; + spec = codec->spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -2836,7 +2845,6 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, { struct snd_kcontrol_new *knew; - snd_array_init(&spec->kctls, sizeof(*knew), 32); knew = snd_array_new(&spec->kctls); if (!knew) return -ENOMEM; @@ -3254,11 +3262,10 @@ static int patch_ad1988(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; + err = alloc_ad_spec(codec); + if (err < 0) + return err; + spec = codec->spec; if (is_rev2(codec)) snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); @@ -3574,11 +3581,10 @@ static int patch_ad1884(struct hda_codec *codec) struct ad198x_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; + err = alloc_ad_spec(codec); + if (err < 0) + return err; + spec = codec->spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -4574,11 +4580,10 @@ static int patch_ad1884a(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; + err = alloc_ad_spec(codec); + if (err < 0) + return err; + spec = codec->spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { @@ -4987,11 +4992,10 @@ static int patch_ad1882(struct hda_codec *codec) struct ad198x_spec *spec; int err, board_config; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; + err = alloc_ad_spec(codec); + if (err < 0) + return err; + spec = codec->spec; err = snd_hda_attach_beep_device(codec, 0x10); if (err < 0) { diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index af0686533803..c7369a6764ef 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -905,7 +905,6 @@ static const struct snd_kcontrol_new alc_automute_mode_enum = { static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec) { - snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); return snd_array_new(&spec->kctls); } @@ -3605,7 +3604,6 @@ static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec, { struct alc_spec *spec = codec->spec; struct hda_bind_ctls **ctlp, *ctl; - snd_array_init(&spec->bind_ctls, sizeof(ctl), 8); ctlp = snd_array_new(&spec->bind_ctls); if (!ctlp) return NULL; @@ -4376,6 +4374,8 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) codec->spec = spec; spec->mixer_nid = mixer_nid; snd_hda_gen_init(&spec->gen); + snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); + snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8); err = alc_codec_rename_from_preset(codec); if (err < 0) { diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 1f6fd584e1c2..df13c0f84899 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2811,7 +2811,6 @@ stac_control_new(struct sigmatel_spec *spec, { struct snd_kcontrol_new *knew; - snd_array_init(&spec->kctls, sizeof(*knew), 32); knew = snd_array_new(&spec->kctls); if (!knew) return NULL; @@ -5159,20 +5158,34 @@ static const struct hda_codec_ops stac92xx_patch_ops = { .reboot_notify = stac92xx_shutup, }; +static int alloc_stac_spec(struct hda_codec *codec, int num_pins, + const hda_nid_t *pin_nids) +{ + struct sigmatel_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + codec->spec = spec; + codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ + spec->num_pins = num_pins; + spec->pin_nids = pin_nids; + snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); + return 0; +} + static int patch_stac9200(struct hda_codec *codec) { struct sigmatel_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, ARRAY_SIZE(stac9200_pin_nids), + stac9200_pin_nids); + if (err < 0) + return err; - codec->no_trigger_sense = 1; - codec->spec = spec; + spec = codec->spec; spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); - spec->pin_nids = stac9200_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, stac9200_models, stac9200_cfg_tbl); @@ -5228,15 +5241,13 @@ static int patch_stac925x(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, ARRAY_SIZE(stac925x_pin_nids), + stac925x_pin_nids); + if (err < 0) + return err; - codec->no_trigger_sense = 1; - codec->spec = spec; + spec = codec->spec; spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); - spec->pin_nids = stac925x_pin_nids; /* Check first for codec ID */ spec->board_config = snd_hda_check_board_codec_sid_config(codec, @@ -5311,19 +5322,17 @@ static int patch_stac92hd73xx(struct hda_codec *codec) { struct sigmatel_spec *spec; hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; - int err = 0; + int err; int num_dacs; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, ARRAY_SIZE(stac92hd73xx_pin_nids), + stac92hd73xx_pin_nids); + if (err < 0) + return err; - codec->no_trigger_sense = 1; - codec->spec = spec; + spec = codec->spec; spec->linear_tone_beep = 0; codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; - spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); - spec->pin_nids = stac92hd73xx_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_92HD73XX_MODELS, stac92hd73xx_models, @@ -5600,9 +5609,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) int default_polarity = -1; /* no default cfg */ int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, 0, NULL); /* pins filled later */ + if (err < 0) + return err; if (hp_bnb2011_with_dock(codec)) { snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f); @@ -5610,11 +5619,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) } codec->epss = 0; /* longer delay needed for D3 */ - codec->no_trigger_sense = 1; - codec->spec = spec; - stac92hd8x_fill_auto_spec(codec); + spec = codec->spec; spec->linear_tone_beep = 0; codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; spec->digbeep_nid = 0x21; @@ -5783,21 +5790,19 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) struct sigmatel_spec *spec; const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; unsigned int pin_cfg; - int err = 0; + int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, STAC92HD71BXX_NUM_PINS, + stac92hd71bxx_pin_nids_4port); + if (err < 0) + return err; - codec->no_trigger_sense = 1; - codec->spec = spec; + spec = codec->spec; spec->linear_tone_beep = 0; codec->patch_ops = stac92xx_patch_ops; - spec->num_pins = STAC92HD71BXX_NUM_PINS; switch (codec->vendor_id) { case 0x111d76b6: case 0x111d76b7: - spec->pin_nids = stac92hd71bxx_pin_nids_4port; break; case 0x111d7603: case 0x111d7608: @@ -6028,15 +6033,13 @@ static int patch_stac922x(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, ARRAY_SIZE(stac922x_pin_nids), + stac922x_pin_nids); + if (err < 0) + return err; - codec->no_trigger_sense = 1; - codec->spec = spec; + spec = codec->spec; spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); - spec->pin_nids = stac922x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, stac922x_models, stac922x_cfg_tbl); @@ -6133,16 +6136,14 @@ static int patch_stac927x(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, ARRAY_SIZE(stac927x_pin_nids), + stac927x_pin_nids); + if (err < 0) + return err; - codec->no_trigger_sense = 1; - codec->spec = spec; + spec = codec->spec; spec->linear_tone_beep = 1; codec->slave_dig_outs = stac927x_slave_dig_outs; - spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); - spec->pin_nids = stac927x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, stac927x_models, stac927x_cfg_tbl); @@ -6269,15 +6270,13 @@ static int patch_stac9205(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; + err = alloc_stac_spec(codec, ARRAY_SIZE(stac9205_pin_nids), + stac9205_pin_nids); + if (err < 0) + return err; - codec->no_trigger_sense = 1; - codec->spec = spec; + spec = codec->spec; spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); - spec->pin_nids = stac9205_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, stac9205_models, stac9205_cfg_tbl); @@ -6425,14 +6424,13 @@ static int patch_stac9872(struct hda_codec *codec) struct sigmatel_spec *spec; int err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - codec->no_trigger_sense = 1; - codec->spec = spec; + err = alloc_stac_spec(codec, ARRAY_SIZE(stac9872_pin_nids), + stac9872_pin_nids); + if (err < 0) + return err; + + spec = codec->spec; spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); - spec->pin_nids = stac9872_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, stac9872_models, diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 7ae5f85105e9..274644f6bd48 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -241,6 +241,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec) if (spec == NULL) return NULL; + snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); mutex_init(&spec->config_mutex); codec->spec = spec; spec->codec = codec; @@ -387,7 +388,6 @@ static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec, { struct snd_kcontrol_new *knew; - snd_array_init(&spec->kctls, sizeof(*knew), 32); knew = snd_array_new(&spec->kctls); if (!knew) return NULL;