提交 361dab3e 编写于 作者: T Takashi Iwai

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: NTakashi Iwai <tiwai@suse.de>
上级 04324ccc
...@@ -1250,6 +1250,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, ...@@ -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->cvt_setups, sizeof(struct hda_cvt_setup), 8);
snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); 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->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); INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -95,7 +95,6 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) ...@@ -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); struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
if (jack) if (jack)
return jack; return jack;
snd_array_init(&codec->jacktbl, sizeof(*jack), 16);
jack = snd_array_new(&codec->jacktbl); jack = snd_array_new(&codec->jacktbl);
if (!jack) if (!jack)
return NULL; return NULL;
......
...@@ -1246,16 +1246,27 @@ static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) ...@@ -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; return get_defcfg_connect(conf) != AC_JACK_PORT_NONE;
} }
static int patch_ad1986a(struct hda_codec *codec) static int alloc_ad_spec(struct hda_codec *codec)
{ {
struct ad198x_spec *spec; struct ad198x_spec *spec;
int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL) if (!spec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; 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;
err = alloc_ad_spec(codec);
if (err < 0)
return err;
spec = codec->spec;
err = snd_hda_attach_beep_device(codec, 0x19); err = snd_hda_attach_beep_device(codec, 0x19);
if (err < 0) { if (err < 0) {
...@@ -1548,11 +1559,10 @@ static int patch_ad1983(struct hda_codec *codec) ...@@ -1548,11 +1559,10 @@ static int patch_ad1983(struct hda_codec *codec)
struct ad198x_spec *spec; struct ad198x_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_ad_spec(codec);
if (spec == NULL) if (err < 0)
return -ENOMEM; return err;
spec = codec->spec;
codec->spec = spec;
err = snd_hda_attach_beep_device(codec, 0x10); err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) { if (err < 0) {
...@@ -1954,11 +1964,10 @@ static int patch_ad1981(struct hda_codec *codec) ...@@ -1954,11 +1964,10 @@ static int patch_ad1981(struct hda_codec *codec)
struct ad198x_spec *spec; struct ad198x_spec *spec;
int err, board_config; int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_ad_spec(codec);
if (spec == NULL) if (err < 0)
return -ENOMEM; return -ENOMEM;
spec = codec->spec;
codec->spec = spec;
err = snd_hda_attach_beep_device(codec, 0x10); err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) { if (err < 0) {
...@@ -2836,7 +2845,6 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, ...@@ -2836,7 +2845,6 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
snd_array_init(&spec->kctls, sizeof(*knew), 32);
knew = snd_array_new(&spec->kctls); knew = snd_array_new(&spec->kctls);
if (!knew) if (!knew)
return -ENOMEM; return -ENOMEM;
...@@ -3254,11 +3262,10 @@ static int patch_ad1988(struct hda_codec *codec) ...@@ -3254,11 +3262,10 @@ static int patch_ad1988(struct hda_codec *codec)
struct ad198x_spec *spec; struct ad198x_spec *spec;
int err, board_config; int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_ad_spec(codec);
if (spec == NULL) if (err < 0)
return -ENOMEM; return err;
spec = codec->spec;
codec->spec = spec;
if (is_rev2(codec)) if (is_rev2(codec))
snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); 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) ...@@ -3574,11 +3581,10 @@ static int patch_ad1884(struct hda_codec *codec)
struct ad198x_spec *spec; struct ad198x_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_ad_spec(codec);
if (spec == NULL) if (err < 0)
return -ENOMEM; return err;
spec = codec->spec;
codec->spec = spec;
err = snd_hda_attach_beep_device(codec, 0x10); err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) { if (err < 0) {
...@@ -4574,11 +4580,10 @@ static int patch_ad1884a(struct hda_codec *codec) ...@@ -4574,11 +4580,10 @@ static int patch_ad1884a(struct hda_codec *codec)
struct ad198x_spec *spec; struct ad198x_spec *spec;
int err, board_config; int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_ad_spec(codec);
if (spec == NULL) if (err < 0)
return -ENOMEM; return err;
spec = codec->spec;
codec->spec = spec;
err = snd_hda_attach_beep_device(codec, 0x10); err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) { if (err < 0) {
...@@ -4987,11 +4992,10 @@ static int patch_ad1882(struct hda_codec *codec) ...@@ -4987,11 +4992,10 @@ static int patch_ad1882(struct hda_codec *codec)
struct ad198x_spec *spec; struct ad198x_spec *spec;
int err, board_config; int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_ad_spec(codec);
if (spec == NULL) if (err < 0)
return -ENOMEM; return err;
spec = codec->spec;
codec->spec = spec;
err = snd_hda_attach_beep_device(codec, 0x10); err = snd_hda_attach_beep_device(codec, 0x10);
if (err < 0) { if (err < 0) {
......
...@@ -905,7 +905,6 @@ static const struct snd_kcontrol_new alc_automute_mode_enum = { ...@@ -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) 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); return snd_array_new(&spec->kctls);
} }
...@@ -3605,7 +3604,6 @@ static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec, ...@@ -3605,7 +3604,6 @@ static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
struct hda_bind_ctls **ctlp, *ctl; struct hda_bind_ctls **ctlp, *ctl;
snd_array_init(&spec->bind_ctls, sizeof(ctl), 8);
ctlp = snd_array_new(&spec->bind_ctls); ctlp = snd_array_new(&spec->bind_ctls);
if (!ctlp) if (!ctlp)
return NULL; return NULL;
...@@ -4376,6 +4374,8 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) ...@@ -4376,6 +4374,8 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
codec->spec = spec; codec->spec = spec;
spec->mixer_nid = mixer_nid; spec->mixer_nid = mixer_nid;
snd_hda_gen_init(&spec->gen); 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); err = alc_codec_rename_from_preset(codec);
if (err < 0) { if (err < 0) {
......
...@@ -2811,7 +2811,6 @@ stac_control_new(struct sigmatel_spec *spec, ...@@ -2811,7 +2811,6 @@ stac_control_new(struct sigmatel_spec *spec,
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
snd_array_init(&spec->kctls, sizeof(*knew), 32);
knew = snd_array_new(&spec->kctls); knew = snd_array_new(&spec->kctls);
if (!knew) if (!knew)
return NULL; return NULL;
...@@ -5159,20 +5158,34 @@ static const struct hda_codec_ops stac92xx_patch_ops = { ...@@ -5159,20 +5158,34 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
.reboot_notify = stac92xx_shutup, .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) static int patch_stac9200(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, ARRAY_SIZE(stac9200_pin_nids),
if (spec == NULL) stac9200_pin_nids);
return -ENOMEM; if (err < 0)
return err;
codec->no_trigger_sense = 1; spec = codec->spec;
codec->spec = spec;
spec->linear_tone_beep = 1; 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, spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models, stac9200_models,
stac9200_cfg_tbl); stac9200_cfg_tbl);
...@@ -5228,15 +5241,13 @@ static int patch_stac925x(struct hda_codec *codec) ...@@ -5228,15 +5241,13 @@ static int patch_stac925x(struct hda_codec *codec)
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, ARRAY_SIZE(stac925x_pin_nids),
if (spec == NULL) stac925x_pin_nids);
return -ENOMEM; if (err < 0)
return err;
codec->no_trigger_sense = 1; spec = codec->spec;
codec->spec = spec;
spec->linear_tone_beep = 1; spec->linear_tone_beep = 1;
spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
spec->pin_nids = stac925x_pin_nids;
/* Check first for codec ID */ /* Check first for codec ID */
spec->board_config = snd_hda_check_board_codec_sid_config(codec, spec->board_config = snd_hda_check_board_codec_sid_config(codec,
...@@ -5311,19 +5322,17 @@ static int patch_stac92hd73xx(struct hda_codec *codec) ...@@ -5311,19 +5322,17 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; hda_nid_t conn[STAC92HD73_DAC_COUNT + 2];
int err = 0; int err;
int num_dacs; int num_dacs;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, ARRAY_SIZE(stac92hd73xx_pin_nids),
if (spec == NULL) stac92hd73xx_pin_nids);
return -ENOMEM; if (err < 0)
return err;
codec->no_trigger_sense = 1; spec = codec->spec;
codec->spec = spec;
spec->linear_tone_beep = 0; spec->linear_tone_beep = 0;
codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; 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, spec->board_config = snd_hda_check_board_config(codec,
STAC_92HD73XX_MODELS, STAC_92HD73XX_MODELS,
stac92hd73xx_models, stac92hd73xx_models,
...@@ -5600,9 +5609,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5600,9 +5609,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
int default_polarity = -1; /* no default cfg */ int default_polarity = -1; /* no default cfg */
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, 0, NULL); /* pins filled later */
if (spec == NULL) if (err < 0)
return -ENOMEM; return err;
if (hp_bnb2011_with_dock(codec)) { if (hp_bnb2011_with_dock(codec)) {
snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f); snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f);
...@@ -5610,11 +5619,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5610,11 +5619,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
} }
codec->epss = 0; /* longer delay needed for D3 */ codec->epss = 0; /* longer delay needed for D3 */
codec->no_trigger_sense = 1;
codec->spec = spec;
stac92hd8x_fill_auto_spec(codec); stac92hd8x_fill_auto_spec(codec);
spec = codec->spec;
spec->linear_tone_beep = 0; spec->linear_tone_beep = 0;
codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
spec->digbeep_nid = 0x21; spec->digbeep_nid = 0x21;
...@@ -5783,21 +5790,19 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5783,21 +5790,19 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
unsigned int pin_cfg; unsigned int pin_cfg;
int err = 0; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, STAC92HD71BXX_NUM_PINS,
if (spec == NULL) stac92hd71bxx_pin_nids_4port);
return -ENOMEM; if (err < 0)
return err;
codec->no_trigger_sense = 1; spec = codec->spec;
codec->spec = spec;
spec->linear_tone_beep = 0; spec->linear_tone_beep = 0;
codec->patch_ops = stac92xx_patch_ops; codec->patch_ops = stac92xx_patch_ops;
spec->num_pins = STAC92HD71BXX_NUM_PINS;
switch (codec->vendor_id) { switch (codec->vendor_id) {
case 0x111d76b6: case 0x111d76b6:
case 0x111d76b7: case 0x111d76b7:
spec->pin_nids = stac92hd71bxx_pin_nids_4port;
break; break;
case 0x111d7603: case 0x111d7603:
case 0x111d7608: case 0x111d7608:
...@@ -6028,15 +6033,13 @@ static int patch_stac922x(struct hda_codec *codec) ...@@ -6028,15 +6033,13 @@ static int patch_stac922x(struct hda_codec *codec)
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, ARRAY_SIZE(stac922x_pin_nids),
if (spec == NULL) stac922x_pin_nids);
return -ENOMEM; if (err < 0)
return err;
codec->no_trigger_sense = 1; spec = codec->spec;
codec->spec = spec;
spec->linear_tone_beep = 1; 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, spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
stac922x_models, stac922x_models,
stac922x_cfg_tbl); stac922x_cfg_tbl);
...@@ -6133,16 +6136,14 @@ static int patch_stac927x(struct hda_codec *codec) ...@@ -6133,16 +6136,14 @@ static int patch_stac927x(struct hda_codec *codec)
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, ARRAY_SIZE(stac927x_pin_nids),
if (spec == NULL) stac927x_pin_nids);
return -ENOMEM; if (err < 0)
return err;
codec->no_trigger_sense = 1; spec = codec->spec;
codec->spec = spec;
spec->linear_tone_beep = 1; spec->linear_tone_beep = 1;
codec->slave_dig_outs = stac927x_slave_dig_outs; 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, spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
stac927x_models, stac927x_models,
stac927x_cfg_tbl); stac927x_cfg_tbl);
...@@ -6269,15 +6270,13 @@ static int patch_stac9205(struct hda_codec *codec) ...@@ -6269,15 +6270,13 @@ static int patch_stac9205(struct hda_codec *codec)
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, ARRAY_SIZE(stac9205_pin_nids),
if (spec == NULL) stac9205_pin_nids);
return -ENOMEM; if (err < 0)
return err;
codec->no_trigger_sense = 1; spec = codec->spec;
codec->spec = spec;
spec->linear_tone_beep = 1; 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, spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
stac9205_models, stac9205_models,
stac9205_cfg_tbl); stac9205_cfg_tbl);
...@@ -6425,14 +6424,13 @@ static int patch_stac9872(struct hda_codec *codec) ...@@ -6425,14 +6424,13 @@ static int patch_stac9872(struct hda_codec *codec)
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
int err; int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); err = alloc_stac_spec(codec, ARRAY_SIZE(stac9872_pin_nids),
if (spec == NULL) stac9872_pin_nids);
return -ENOMEM; if (err < 0)
codec->no_trigger_sense = 1; return err;
codec->spec = spec;
spec = codec->spec;
spec->linear_tone_beep = 1; 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, spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
stac9872_models, stac9872_models,
......
...@@ -241,6 +241,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec) ...@@ -241,6 +241,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
if (spec == NULL) if (spec == NULL)
return NULL; return NULL;
snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
mutex_init(&spec->config_mutex); mutex_init(&spec->config_mutex);
codec->spec = spec; codec->spec = spec;
spec->codec = codec; spec->codec = codec;
...@@ -387,7 +388,6 @@ static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec, ...@@ -387,7 +388,6 @@ static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec,
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
snd_array_init(&spec->kctls, sizeof(*knew), 32);
knew = snd_array_new(&spec->kctls); knew = snd_array_new(&spec->kctls);
if (!knew) if (!knew)
return NULL; return NULL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册