[alsa-devel] [PATCH] Revert "ALSA: hda - Remove limit of widget connections"
David Henningsson
david.henningsson at canonical.com
Tue Mar 12 15:05:02 CET 2013
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;
--
1.7.9.5
More information about the Alsa-devel
mailing list