This reverts commit 4eea30914facd2c99061cd70e5b05d3c76c743a2.
The commit causes an error with node ranges: In my case, connection list length is 3, with a connection list read of 0x1e9915: a total of 6 nids (0x15, 0x16, 0x17, 0x18, 0x19, 0x1e). Since the new code makes us allocate only 3 nids to the array sent to get_raw_connections, the function fails. --- sound/pci/hda/hda_codec.c | 62 +++++++++++++++----------------------------- sound/pci/hda/hda_codec.h | 4 ++- sound/pci/hda/hda_proc.c | 20 +++----------- sound/pci/hda/patch_hdmi.c | 3 --- 4 files changed, 28 insertions(+), 61 deletions(-)
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 97c68dd..e5e8549 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -382,23 +382,13 @@ static void remove_conn_list(struct hda_codec *codec) /* read the connection and add to the cache */ static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid) { - hda_nid_t list[32]; - hda_nid_t *result = list; + hda_nid_t list[HDA_MAX_CONNECTIONS]; int len;
len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list)); - if (len == -ENOSPC) { - len = snd_hda_get_num_raw_conns(codec, nid); - result = kmalloc(sizeof(hda_nid_t) * len, GFP_KERNEL); - if (!result) - return -ENOMEM; - len = snd_hda_get_raw_connections(codec, nid, result, len); - } - if (len >= 0) - len = snd_hda_override_conn_list(codec, nid, len, result); - if (result != list) - kfree(result); - return len; + if (len < 0) + return len; + return snd_hda_override_conn_list(codec, nid, len, list); }
/** @@ -476,27 +466,6 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, } EXPORT_SYMBOL_HDA(snd_hda_get_connections);
-/* return CONNLIST_LEN parameter of the given widget */ -static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int wcaps = get_wcaps(codec, nid); - unsigned int parm; - - if (!(wcaps & AC_WCAP_CONN_LIST) && - get_wcaps_type(wcaps) != AC_WID_VOL_KNB) - return 0; - - parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); - if (parm == -1) - parm = 0; - return parm; -} - -int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid) -{ - return get_num_conns(codec, nid) & AC_CLIST_LENGTH; -} - /** * snd_hda_get_raw_connections - copy connection list without cache * @codec: the HDA codec @@ -514,16 +483,19 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, unsigned int parm; int i, conn_len, conns; unsigned int shift, num_elems, mask; + unsigned int wcaps; hda_nid_t prev_nid; int null_count = 0;
if (snd_BUG_ON(!conn_list || max_conns <= 0)) return -EINVAL;
- parm = get_num_conns(codec, nid); - if (!parm) + wcaps = get_wcaps(codec, nid); + if (!(wcaps & AC_WCAP_CONN_LIST) && + get_wcaps_type(wcaps) != AC_WID_VOL_KNB) return 0;
+ parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); if (parm & AC_CLIST_LONG) { /* long form */ shift = 16; @@ -580,13 +552,21 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, continue; } for (n = prev_nid + 1; n <= val; n++) { - if (conns >= max_conns) - return -ENOSPC; + if (conns >= max_conns) { + snd_printk(KERN_ERR "hda_codec: " + "Too many connections %d for NID 0x%x\n", + conns, nid); + return -EINVAL; + } conn_list[conns++] = n; } } else { - if (conns >= max_conns) - return -ENOSPC; + if (conns >= max_conns) { + snd_printk(KERN_ERR "hda_codec: " + "Too many connections %d for NID 0x%x\n", + conns, nid); + return -EINVAL; + } conn_list[conns++] = val; } prev_nid = val; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 23ca172..246ed53 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -551,6 +551,9 @@ enum { AC_JACK_PORT_BOTH, };
+/* max. connections to a widget */ +#define HDA_MAX_CONNECTIONS 32 + /* max. codec address */ #define HDA_MAX_CODEC_ADDRESS 0x0f
@@ -957,7 +960,6 @@ snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid) { return snd_hda_get_connections(codec, nid, NULL, 0); } -int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid); int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns); int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 0fee8fa..5e02f26 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -22,7 +22,6 @@ */
#include <linux/init.h> -#include <linux/slab.h> #include <sound/core.h> #include "hda_codec.h" #include "hda_local.h" @@ -624,7 +623,7 @@ static void print_codec_info(struct snd_info_entry *entry, snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); unsigned int wid_type = get_wcaps_type(wid_caps); - hda_nid_t *conn = NULL; + hda_nid_t conn[HDA_MAX_CONNECTIONS]; int conn_len = 0;
snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, @@ -661,18 +660,9 @@ static void print_codec_info(struct snd_info_entry *entry, if (wid_type == AC_WID_VOL_KNB) wid_caps |= AC_WCAP_CONN_LIST;
- if (wid_caps & AC_WCAP_CONN_LIST) { - conn_len = snd_hda_get_num_raw_conns(codec, nid); - if (conn_len > 0) { - conn = kmalloc(sizeof(hda_nid_t) * conn_len, - GFP_KERNEL); - if (!conn) - return; - if (snd_hda_get_raw_connections(codec, nid, conn, - conn_len) < 0) - conn_len = 0; - } - } + if (wid_caps & AC_WCAP_CONN_LIST) + conn_len = snd_hda_get_raw_connections(codec, nid, conn, + HDA_MAX_CONNECTIONS);
if (wid_caps & AC_WCAP_IN_AMP) { snd_iprintf(buffer, " Amp-In caps: "); @@ -745,8 +735,6 @@ static void print_codec_info(struct snd_info_entry *entry,
if (codec->proc_widget_hook) codec->proc_widget_hook(buffer, codec, nid); - - kfree(conn); } snd_hda_power_down(codec); } diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 78e1827..d24af4a 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -64,9 +64,6 @@ struct hdmi_spec_per_cvt { unsigned int maxbps; };
-/* max. connections to a widget */ -#define HDA_MAX_CONNECTIONS 32 - struct hdmi_spec_per_pin { hda_nid_t pin_nid; int num_mux_nids;