diff options
| author | Wu Fengguang <fengguang.wu@intel.com> | 2011-11-16 03:29:46 -0500 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2011-11-16 04:44:21 -0500 |
| commit | b95d68b8179764e29558b75cec35ef4a6a98925b (patch) | |
| tree | 875fb72efe3cefea4df2bb37404dd32590666065 | |
| parent | e53de8f00c80fd1a312c95bc5157fdb98d46e070 (diff) | |
ALSA: hda - fix ELD memory leak
memset(eld) clears eld->proc_entry which will leak the struct
snd_info_entry when unloading module.
Fix it by
- memset only the fields before eld->eld_buffer
- set eld->eld_valid to true _after_ all eld fields have been filled
Cc: <stable@kernel.org>
Cc: Pierre-louis Bossart <pierre-louis.bossart@intel.com>
Acked-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | sound/pci/hda/hda_eld.c | 5 | ||||
| -rw-r--r-- | sound/pci/hda/hda_local.h | 3 | ||||
| -rw-r--r-- | sound/pci/hda/patch_hdmi.c | 11 |
3 files changed, 9 insertions, 10 deletions
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 1c8ddf547a2d..a065d6d2d6ff 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
| @@ -297,10 +297,10 @@ static int hdmi_update_eld(struct hdmi_eld *e, | |||
| 297 | buf + ELD_FIXED_BYTES + mnl + 3 * i); | 297 | buf + ELD_FIXED_BYTES + mnl + 3 * i); |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | e->eld_valid = true; | ||
| 300 | return 0; | 301 | return 0; |
| 301 | 302 | ||
| 302 | out_fail: | 303 | out_fail: |
| 303 | e->eld_ver = 0; | ||
| 304 | return -EINVAL; | 304 | return -EINVAL; |
| 305 | } | 305 | } |
| 306 | 306 | ||
| @@ -323,9 +323,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, | |||
| 323 | * ELD is valid, actual eld_size is assigned in hdmi_update_eld() | 323 | * ELD is valid, actual eld_size is assigned in hdmi_update_eld() |
| 324 | */ | 324 | */ |
| 325 | 325 | ||
| 326 | if (!eld->eld_valid) | ||
| 327 | return -ENOENT; | ||
| 328 | |||
| 329 | size = snd_hdmi_get_eld_size(codec, nid); | 326 | size = snd_hdmi_get_eld_size(codec, nid); |
| 330 | if (size == 0) { | 327 | if (size == 0) { |
| 331 | /* wfg: workaround for ASUS P5E-VM HDMI board */ | 328 | /* wfg: workaround for ASUS P5E-VM HDMI board */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 6579e0f2bb57..618ddad17236 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
| @@ -653,6 +653,9 @@ struct hdmi_eld { | |||
| 653 | int spk_alloc; | 653 | int spk_alloc; |
| 654 | int sad_count; | 654 | int sad_count; |
| 655 | struct cea_sad sad[ELD_MAX_SAD]; | 655 | struct cea_sad sad[ELD_MAX_SAD]; |
| 656 | /* | ||
| 657 | * all fields above eld_buffer will be cleared before updating ELD | ||
| 658 | */ | ||
| 656 | char eld_buffer[ELD_MAX_SIZE]; | 659 | char eld_buffer[ELD_MAX_SIZE]; |
| 657 | #ifdef CONFIG_PROC_FS | 660 | #ifdef CONFIG_PROC_FS |
| 658 | struct snd_info_entry *proc_entry; | 661 | struct snd_info_entry *proc_entry; |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 81b7b791b3c3..aebfee50bd88 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
| @@ -980,20 +980,19 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | |||
| 980 | * the unsolicited response to avoid custom WARs. | 980 | * the unsolicited response to avoid custom WARs. |
| 981 | */ | 981 | */ |
| 982 | int present = snd_hda_pin_sense(codec, pin_nid); | 982 | int present = snd_hda_pin_sense(codec, pin_nid); |
| 983 | bool eld_valid = false; | ||
| 983 | 984 | ||
| 984 | memset(eld, 0, sizeof(*eld)); | 985 | memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer)); |
| 985 | 986 | ||
| 986 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | 987 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); |
| 987 | if (eld->monitor_present) | 988 | if (eld->monitor_present) |
| 988 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | 989 | eld_valid = !!(present & AC_PINSENSE_ELDV); |
| 989 | else | ||
| 990 | eld->eld_valid = 0; | ||
| 991 | 990 | ||
| 992 | printk(KERN_INFO | 991 | printk(KERN_INFO |
| 993 | "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | 992 | "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", |
| 994 | codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); | 993 | codec->addr, pin_nid, eld->monitor_present, eld_valid); |
| 995 | 994 | ||
| 996 | if (eld->eld_valid) | 995 | if (eld_valid) |
| 997 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | 996 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) |
| 998 | snd_hdmi_show_eld(eld); | 997 | snd_hdmi_show_eld(eld); |
| 999 | 998 | ||
