From ca9c1aaec4187fc9922cfb6b283fffef89286943 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Tue, 6 Jan 2009 20:11:51 +0000
Subject: ASoC: dapm: Allow explictly named mixer controls

This patch allows you to define the mixer paths as having the same name as the
paths they represent.

This is required to support codecs such as the wm9705 neatly without extra
controls in the alsa mixer.

Signed-off-by: Ian Molton <ian@mnementh.co.uk>
---
 Documentation/sound/alsa/soc/dapm.txt | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
index 46f9684d0b2..9e6763264a2 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -116,6 +116,9 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
 	ARRAY_SIZE(wm8731_output_mixer_controls)),
 
+If you dont want the mixer elements prefixed with the name of the mixer widget,
+you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
+as for SND_SOC_DAPM_MIXER.
 
 2.3 Platform/Machine domain Widgets
 -----------------------------------
-- 
cgit v1.2.3-70-g09d2


From fbd59a8d1f7cf325fdb6828659f1fb76631e87b3 Mon Sep 17 00:00:00 2001
From: Rusty Russell <rusty@rustcorp.com.au>
Date: Sat, 10 Jan 2009 21:58:08 -0800
Subject: cpumask: Use topology_core_cpumask()/topology_thread_cpumask()

Impact: reduce stack usage, use new cpumask API.

This actually uses topology_core_cpumask() and
topology_thread_cpumask(), removing the only users of
topology_core_siblings() and topology_thread_siblings()

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Mike Travis <travis@sgi.com>
Cc: linux-net-drivers@solarflare.com
---
 Documentation/cputopology.txt |  6 +++---
 drivers/base/topology.c       | 33 ++++++++++++++++-----------------
 drivers/net/sfc/efx.c         |  4 ++--
 include/linux/topology.h      |  6 ++++++
 4 files changed, 27 insertions(+), 22 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt
index 45932ec21ce..b41f3e58aef 100644
--- a/Documentation/cputopology.txt
+++ b/Documentation/cputopology.txt
@@ -18,11 +18,11 @@ For an architecture to support this feature, it must define some of
 these macros in include/asm-XXX/topology.h:
 #define topology_physical_package_id(cpu)
 #define topology_core_id(cpu)
-#define topology_thread_siblings(cpu)
-#define topology_core_siblings(cpu)
+#define topology_thread_cpumask(cpu)
+#define topology_core_cpumask(cpu)
 
 The type of **_id is int.
-The type of siblings is cpumask_t.
+The type of siblings is (const) struct cpumask *.
 
 To be consistent on all architectures, include/linux/topology.h
 provides default definitions for any of the above macros that are
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index a778fb52b11..bf6b13206d0 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -31,7 +31,10 @@
 #include <linux/hardirq.h>
 #include <linux/topology.h>
 
-#define define_one_ro(_name) 		\
+#define define_one_ro_named(_name, _func)				\
+static SYSDEV_ATTR(_name, 0444, _func, NULL)
+
+#define define_one_ro(_name)				\
 static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
 
 #define define_id_show_func(name)				\
@@ -42,8 +45,8 @@ static ssize_t show_##name(struct sys_device *dev,		\
 	return sprintf(buf, "%d\n", topology_##name(cpu));	\
 }
 
-#if defined(topology_thread_siblings) || defined(topology_core_siblings)
-static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
+#if defined(topology_thread_cpumask) || defined(topology_core_cpumask)
+static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
 {
 	ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
 	int n = 0;
@@ -65,7 +68,7 @@ static ssize_t show_##name(struct sys_device *dev,			\
 			   struct sysdev_attribute *attr, char *buf)	\
 {									\
 	unsigned int cpu = dev->id;					\
-	return show_cpumap(0, &(topology_##name(cpu)), buf);		\
+	return show_cpumap(0, topology_##name(cpu), buf);		\
 }
 
 #define define_siblings_show_list(name)					\
@@ -74,7 +77,7 @@ static ssize_t show_##name##_list(struct sys_device *dev,		\
 				  char *buf)				\
 {									\
 	unsigned int cpu = dev->id;					\
-	return show_cpumap(1, &(topology_##name(cpu)), buf);		\
+	return show_cpumap(1, topology_##name(cpu), buf);		\
 }
 
 #else
@@ -82,9 +85,7 @@ static ssize_t show_##name##_list(struct sys_device *dev,		\
 static ssize_t show_##name(struct sys_device *dev,			\
 			   struct sysdev_attribute *attr, char *buf)	\
 {									\
-	unsigned int cpu = dev->id;					\
-	cpumask_t mask = topology_##name(cpu);				\
-	return show_cpumap(0, &mask, buf);				\
+	return show_cpumap(0, topology_##name(dev->id), buf);		\
 }
 
 #define define_siblings_show_list(name)					\
@@ -92,9 +93,7 @@ static ssize_t show_##name##_list(struct sys_device *dev,		\
 				  struct sysdev_attribute *attr,	\
 				  char *buf)				\
 {									\
-	unsigned int cpu = dev->id;					\
-	cpumask_t mask = topology_##name(cpu);				\
-	return show_cpumap(1, &mask, buf);				\
+	return show_cpumap(1, topology_##name(dev->id), buf);		\
 }
 #endif
 
@@ -107,13 +106,13 @@ define_one_ro(physical_package_id);
 define_id_show_func(core_id);
 define_one_ro(core_id);
 
-define_siblings_show_func(thread_siblings);
-define_one_ro(thread_siblings);
-define_one_ro(thread_siblings_list);
+define_siblings_show_func(thread_cpumask);
+define_one_ro_named(thread_siblings, show_thread_cpumask);
+define_one_ro_named(thread_siblings_list, show_thread_cpumask_list);
 
-define_siblings_show_func(core_siblings);
-define_one_ro(core_siblings);
-define_one_ro(core_siblings_list);
+define_siblings_show_func(core_cpumask);
+define_one_ro_named(core_siblings, show_core_cpumask);
+define_one_ro_named(core_siblings_list, show_core_cpumask_list);
 
 static struct attribute *default_attrs[] = {
 	&attr_physical_package_id.attr,
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7673fd92eaf..f2e56ceee0e 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -863,8 +863,8 @@ static int efx_wanted_rx_queues(void)
 	for_each_online_cpu(cpu) {
 		if (!cpu_isset(cpu, core_mask)) {
 			++count;
-			cpus_or(core_mask, core_mask,
-				topology_core_siblings(cpu));
+			cpumask_or(&core_mask, &core_mask,
+				   topology_core_cpumask(cpu));
 		}
 	}
 
diff --git a/include/linux/topology.h b/include/linux/topology.h
index e632d29f054..a16b9e06f2e 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -193,5 +193,11 @@ int arch_update_cpu_topology(void);
 #ifndef topology_core_siblings
 #define topology_core_siblings(cpu)		cpumask_of_cpu(cpu)
 #endif
+#ifndef topology_thread_cpumask
+#define topology_thread_cpumask(cpu)		cpumask_of(cpu)
+#endif
+#ifndef topology_core_cpumask
+#define topology_core_cpumask(cpu)		cpumask_of(cpu)
+#endif
 
 #endif /* _LINUX_TOPOLOGY_H */
-- 
cgit v1.2.3-70-g09d2


From d453379bc5d34d7f55b55931245de5ac1896fd8d Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@alsa3.local>
Date: Sun, 28 Dec 2008 16:45:34 +0100
Subject: ALSA: Update description of snd_card_create() in documents

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 44 ++++++++++++----------
 1 file changed, 25 insertions(+), 19 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 87a7c07ab65..320384c1791 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -492,9 +492,9 @@
           }
 
           /* (2) */
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-          if (card == NULL)
-                  return -ENOMEM;
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+          if (err < 0)
+                  return err;
 
           /* (3) */
           err = snd_mychip_create(card, pci, &chip);
@@ -590,8 +590,9 @@
             <programlisting>
 <![CDATA[
   struct snd_card *card;
+  int err;
   ....
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
 ]]>
             </programlisting>
           </informalexample>
@@ -809,26 +810,28 @@
 
       <para>
         As mentioned above, to create a card instance, call
-      <function>snd_card_new()</function>.
+      <function>snd_card_create()</function>.
 
         <informalexample>
           <programlisting>
 <![CDATA[
   struct snd_card *card;
-  card = snd_card_new(index, id, module, extra_size);
+  int err;
+  err = snd_card_create(index, id, module, extra_size, &card);
 ]]>
           </programlisting>
         </informalexample>
       </para>
 
       <para>
-        The function takes four arguments, the card-index number, the
+        The function takes five arguments, the card-index number, the
         id string, the module pointer (usually
         <constant>THIS_MODULE</constant>),
-        and the size of extra-data space.  The last argument is used to
+        the size of extra-data space, and the pointer to return the
+        card instance.  The extra_size argument is used to
         allocate card-&gt;private_data for the
         chip-specific data.  Note that these data
-        are allocated by <function>snd_card_new()</function>.
+        are allocated by <function>snd_card_create()</function>.
       </para>
     </section>
 
@@ -915,15 +918,16 @@
       </para>
 
       <section id="card-management-chip-specific-snd-card-new">
-        <title>1. Allocating via <function>snd_card_new()</function>.</title>
+        <title>1. Allocating via <function>snd_card_create()</function>.</title>
         <para>
           As mentioned above, you can pass the extra-data-length
-	  to the 4th argument of <function>snd_card_new()</function>, i.e.
+	  to the 4th argument of <function>snd_card_create()</function>, i.e.
 
           <informalexample>
             <programlisting>
 <![CDATA[
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct mychip));
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                        sizeof(struct mychip), &card);
 ]]>
             </programlisting>
           </informalexample>
@@ -952,8 +956,8 @@
 
         <para>
           After allocating a card instance via
-          <function>snd_card_new()</function> (with
-          <constant>NULL</constant> on the 4th arg), call
+          <function>snd_card_create()</function> (with
+          <constant>0</constant> on the 4th arg), call
           <function>kzalloc()</function>. 
 
           <informalexample>
@@ -961,7 +965,7 @@
 <![CDATA[
   struct snd_card *card;
   struct mychip *chip;
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
   .....
   chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 ]]>
@@ -5750,8 +5754,9 @@ struct _snd_pcm_runtime {
           ....
           struct snd_card *card;
           struct mychip *chip;
+          int err;
           ....
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
           ....
           chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           ....
@@ -5763,7 +5768,7 @@ struct _snd_pcm_runtime {
       </informalexample>
 
 	When you created the chip data with
-	<function>snd_card_new()</function>, it's anyway accessible
+	<function>snd_card_create()</function>, it's anyway accessible
 	via <structfield>private_data</structfield> field.
 
       <informalexample>
@@ -5775,9 +5780,10 @@ struct _snd_pcm_runtime {
           ....
           struct snd_card *card;
           struct mychip *chip;
+          int err;
           ....
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-                              sizeof(struct mychip));
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                                sizeof(struct mychip), &card);
           ....
           chip = card->private_data;
           ....
-- 
cgit v1.2.3-70-g09d2


From ee287587dafd77fd211e50637561224605c214b4 Mon Sep 17 00:00:00 2001
From: "H. Peter Anvin" <hpa@linux.intel.com>
Date: Wed, 14 Jan 2009 16:07:38 -0800
Subject: bzip2/lzma: update boot protocol specification

Impact: documentation

Update the boot protocol specification to include the currently
supported file formats and their magic numbers.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
---
 Documentation/x86/boot.txt | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index fcdc62b3c3d..9ac70ffe2b7 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -542,7 +542,10 @@ Protocol:	2.08+
 
   The payload may be compressed. The format of both the compressed and
   uncompressed data should be determined using the standard magic
-  numbers. Currently only gzip compressed ELF is used.
+  numbers.  The currently supported compression formats are gzip
+  (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A) and LZMA
+  (magic number 5D 00).  The uncompressed payload is currently always ELF
+  (magic number 7F 45 4C 46).
   
 Field name:	payload_length
 Type:		read
-- 
cgit v1.2.3-70-g09d2


From e56d0cfe7790fd3218ae4f6aae1335547fea8763 Mon Sep 17 00:00:00 2001
From: Baodong Chen <chenbdchenbd@gmail.com>
Date: Thu, 8 Jan 2009 19:24:29 +0800
Subject: Documentation/x86/boot.txt: modify fieldname

Modify field names to the right ones:

 - start_sys was changed to start_sys_seg
 - iinitrd_addr_max was changed to ramdisk_max
 - pad2 was changed to pad2 and pad3
 - readmode_swtch was changed to realmode_swtch

Signed-off-by: Baodong Chen <[email]chenbdchenbd@gmail.com[email]>
Acked-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 Documentation/x86/boot.txt | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index 7b4596ac412..12299697b7c 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -158,7 +158,7 @@ Offset	Proto	Name		Meaning
 0202/4	2.00+	header		Magic signature "HdrS"
 0206/2	2.00+	version		Boot protocol version supported
 0208/4	2.00+	realmode_swtch	Boot loader hook (see below)
-020C/2	2.00+	start_sys	The load-low segment (0x1000) (obsolete)
+020C/2	2.00+	start_sys_seg	The load-low segment (0x1000) (obsolete)
 020E/2	2.00+	kernel_version	Pointer to kernel version string
 0210/1	2.00+	type_of_loader	Boot loader identifier
 0211/1	2.00+	loadflags	Boot protocol option flags
@@ -170,10 +170,11 @@ Offset	Proto	Name		Meaning
 0224/2	2.01+	heap_end_ptr	Free memory after setup end
 0226/2	N/A	pad1		Unused
 0228/4	2.02+	cmd_line_ptr	32-bit pointer to the kernel command line
-022C/4	2.03+	initrd_addr_max	Highest legal initrd address
+022C/4	2.03+	ramdisk_max	Highest legal initrd address
 0230/4	2.05+	kernel_alignment Physical addr alignment required for kernel
 0234/1	2.05+	relocatable_kernel Whether kernel is relocatable or not
-0235/3	N/A	pad2		Unused
+0235/1	N/A	pad2		Unused
+0236/2	N/A	pad3		Unused
 0238/4	2.06+	cmdline_size	Maximum size of the kernel command line
 023C/4	2.07+	hardware_subarch Hardware subarchitecture
 0240/8	2.07+	hardware_subarch_data Subarchitecture-specific data
@@ -299,14 +300,14 @@ Protocol:	2.00+
   e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
   10.17.
 
-Field name:	readmode_swtch
+Field name:	realmode_swtch
 Type:		modify (optional)
 Offset/size:	0x208/4
 Protocol:	2.00+
 
   Boot loader hook (see ADVANCED BOOT LOADER HOOKS below.)
 
-Field name:	start_sys
+Field name:	start_sys_seg
 Type:		read
 Offset/size:	0x20c/2
 Protocol:	2.00+
@@ -468,7 +469,7 @@ Protocol:	2.02+
   zero, the kernel will assume that your boot loader does not support
   the 2.02+ protocol.
 
-Field name:	initrd_addr_max
+Field name:	ramdisk_max
 Type:		read
 Offset/size:	0x22c/4
 Protocol:	2.03+
-- 
cgit v1.2.3-70-g09d2


From 08989930f91e4802b94e03eb54e5385bac112811 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 21 Jan 2009 07:43:23 +0100
Subject: ALSA: hda - Remove old models for STAC9872 from the document

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 64eb1100eec..75914bcdce7 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -352,5 +352,4 @@ STAC92HD83*
 
 STAC9872
 ========
-  vaio		Setup for VAIO FE550G/SZ110
-  vaio-ar Setup for VAIO AR
+  N/A
-- 
cgit v1.2.3-70-g09d2


From 792b48780e8b6435d017cef4b5c304876a48653e Mon Sep 17 00:00:00 2001
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Date: Fri, 16 Jan 2009 23:36:31 +0000
Subject: dccp: Implement both feature-local and feature-remote Sequence Window
 feature

This adds full support for local/remote Sequence Window feature, from which the
  * sequence-number-validity (W) and
  * acknowledgment-number-validity (W') windows
derive as specified in RFC 4340, 7.5.3.

Specifically, the following is contained in this patch:
  * integrated new socket fields into dccp_sk;
  * updated the update_gsr/gss routines with regard to these fields;
  * updated handler code: the Sequence Window feature is located at the TX side,
    so the local feature is meant if the handler-rx flag is false;
  * the initialisation of `rcv_wnd' in reqsk is removed, since
    - rcv_wnd is not used by the code anywhere;
    - sequence number checks are not done in the LISTEN state (cf. 7.5.3);
    - dccp_check_req checks the Ack number validity more rigorously;
  * the `struct dccp_minisock' became empty and is now removed.

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/dccp.txt |  3 ++-
 include/linux/dccp.h              | 24 ++++--------------------
 net/dccp/dccp.h                   | 16 +++++++---------
 net/dccp/feat.c                   | 13 +++++++++++--
 net/dccp/minisocks.c              | 11 -----------
 net/dccp/proto.c                  |  2 --
 6 files changed, 24 insertions(+), 45 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index 7a3bb1abb83..b132e4a3cf0 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -141,7 +141,8 @@ rx_ccid = 2
 	Default CCID for the receiver-sender half-connection; see tx_ccid.
 
 seq_window = 100
-	The initial sequence window (sec. 7.5.2).
+	The initial sequence window (sec. 7.5.2) of the sender. This influences
+	the local ackno validity and the remote seqno validity windows (7.5.1).
 
 tx_qlen = 5
 	The size of the transmit buffer in packets. A value of 0 corresponds
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 990e97fa1f0..7a0502ab383 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -363,19 +363,6 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
 /* FIXME: for now we're default to 1 but it should really be 0 */
 #define DCCPF_INITIAL_SEND_NDP_COUNT		1
 
-/**
-  * struct dccp_minisock - Minimal DCCP connection representation
-  *
-  * Will be used to pass the state from dccp_request_sock to dccp_sock.
-  *
-  * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2)
-  */
-struct dccp_minisock {
-	__u64			dccpms_sequence_window;
-};
-
-extern void dccp_minisock_init(struct dccp_minisock *dmsk);
-
 /**
  * struct dccp_request_sock  -  represent DCCP-specific connection request
  * @dreq_inet_rsk: structure inherited from
@@ -464,13 +451,14 @@ struct dccp_ackvec;
  * @dccps_timestamp_time - time of receiving latest @dccps_timestamp_echo
  * @dccps_l_ack_ratio - feature-local Ack Ratio
  * @dccps_r_ack_ratio - feature-remote Ack Ratio
+ * @dccps_l_seq_win - local Sequence Window (influences ack number validity)
+ * @dccps_r_seq_win - remote Sequence Window (influences seq number validity)
  * @dccps_pcslen - sender   partial checksum coverage (via sockopt)
  * @dccps_pcrlen - receiver partial checksum coverage (via sockopt)
  * @dccps_send_ndp_count - local Send NDP Count feature (7.7.2)
  * @dccps_ndp_count - number of Non Data Packets since last data packet
  * @dccps_mss_cache - current value of MSS (path MTU minus header sizes)
  * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4)
- * @dccps_minisock - associated minisock (accessed via dccp_msk)
  * @dccps_featneg - tracks feature-negotiation state (mostly during handshake)
  * @dccps_hc_rx_ackvec - rx half connection ack vector
  * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection)
@@ -504,12 +492,13 @@ struct dccp_sock {
 	__u32				dccps_timestamp_time;
 	__u16				dccps_l_ack_ratio;
 	__u16				dccps_r_ack_ratio;
+	__u64				dccps_l_seq_win:48;
+	__u64				dccps_r_seq_win:48;
 	__u8				dccps_pcslen:4;
 	__u8				dccps_pcrlen:4;
 	__u8				dccps_send_ndp_count:1;
 	__u64				dccps_ndp_count:48;
 	unsigned long			dccps_rate_last;
-	struct dccp_minisock		dccps_minisock;
 	struct list_head		dccps_featneg;
 	struct dccp_ackvec		*dccps_hc_rx_ackvec;
 	struct ccid			*dccps_hc_rx_ccid;
@@ -527,11 +516,6 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk)
 	return (struct dccp_sock *)sk;
 }
 
-static inline struct dccp_minisock *dccp_msk(const struct sock *sk)
-{
-	return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock;
-}
-
 static inline const char *dccp_role(const struct sock *sk)
 {
 	switch (dccp_sk(sk)->dccps_role) {
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index f2230fc168e..04ae91898a6 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -409,23 +409,21 @@ static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack,
 static inline void dccp_update_gsr(struct sock *sk, u64 seq)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
-	const struct dccp_minisock *dmsk = dccp_msk(sk);
 
 	dp->dccps_gsr = seq;
-	dccp_set_seqno(&dp->dccps_swl,
-		       dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4));
-	dccp_set_seqno(&dp->dccps_swh,
-		       dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4);
+	/* Sequence validity window depends on remote Sequence Window (7.5.1) */
+	dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4);
+	dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4);
 }
 
 static inline void dccp_update_gss(struct sock *sk, u64 seq)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 
-	dp->dccps_awh = dp->dccps_gss = seq;
-	dccp_set_seqno(&dp->dccps_awl,
-		       (dp->dccps_gss -
-			dccp_msk(sk)->dccpms_sequence_window + 1));
+	dp->dccps_gss = seq;
+	/* Ack validity window depends on local Sequence Window value (7.5.1) */
+	dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win);
+	dp->dccps_awh = dp->dccps_gss;
 }
 
 static inline int dccp_ack_pending(const struct sock *sk)
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 67ffac9905f..7303f79705d 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -51,8 +51,17 @@ static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx)
 
 static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx)
 {
-	if (!rx)
-		dccp_msk(sk)->dccpms_sequence_window = seq_win;
+	struct dccp_sock *dp = dccp_sk(sk);
+
+	if (rx) {
+		dp->dccps_r_seq_win = seq_win;
+		/* propagate changes to update SWL/SWH */
+		dccp_update_gsr(sk, dp->dccps_gsr);
+	} else {
+		dp->dccps_l_seq_win = seq_win;
+		/* propagate changes to update AWL */
+		dccp_update_gss(sk, dp->dccps_gss);
+	}
 	return 0;
 }
 
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 6821ae33dd3..5ca49cec95f 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -42,11 +42,6 @@ struct inet_timewait_death_row dccp_death_row = {
 
 EXPORT_SYMBOL_GPL(dccp_death_row);
 
-void dccp_minisock_init(struct dccp_minisock *dmsk)
-{
-	dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window;
-}
-
 void dccp_time_wait(struct sock *sk, int state, int timeo)
 {
 	struct inet_timewait_sock *tw = NULL;
@@ -110,7 +105,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
 		struct dccp_request_sock *dreq = dccp_rsk(req);
 		struct inet_connection_sock *newicsk = inet_csk(newsk);
 		struct dccp_sock *newdp = dccp_sk(newsk);
-		struct dccp_minisock *newdmsk = dccp_msk(newsk);
 
 		newdp->dccps_role	    = DCCP_ROLE_SERVER;
 		newdp->dccps_hc_rx_ackvec   = NULL;
@@ -128,10 +122,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
 		 *    Initialize S.GAR := S.ISS
 		 *    Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
 		 */
-
-		/* See dccp_v4_conn_request */
-		newdmsk->dccpms_sequence_window = req->rcv_wnd;
-
 		newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss;
 		dccp_update_gss(newsk, dreq->dreq_iss);
 
@@ -290,7 +280,6 @@ int dccp_reqsk_init(struct request_sock *req,
 	inet_rsk(req)->rmt_port	  = dccp_hdr(skb)->dccph_sport;
 	inet_rsk(req)->loc_port	  = dccp_hdr(skb)->dccph_dport;
 	inet_rsk(req)->acked	  = 0;
-	req->rcv_wnd		  = sysctl_dccp_feat_sequence_window;
 	dreq->dreq_timestamp_echo = 0;
 
 	/* inherit feature negotiation options from listening socket */
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 945b4d5d23b..314a1b5c033 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -174,8 +174,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
 
-	dccp_minisock_init(&dp->dccps_minisock);
-
 	icsk->icsk_rto		= DCCP_TIMEOUT_INIT;
 	icsk->icsk_syn_retries	= sysctl_dccp_request_retries;
 	sk->sk_state		= DCCP_CLOSED;
-- 
cgit v1.2.3-70-g09d2


From d9a4268ee92ba1a2355c892a3add1fa66856b510 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 22 Jan 2009 17:40:18 +0100
Subject: ALSA: hda - Add quirk for Gateway %1616 laptop

Gateway T1616 laptop needs EAPD always on while the current STAC9205
code turns off per HP plug.  Added a new model "eapd" to keep it on.

Reference: Novell bnc#467597
	https://bugzilla.novell.com/show_bug.cgi?id=467597

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt |  1 +
 sound/pci/hda/patch_sigmatel.c               | 10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 75914bcdce7..ef6b22e2541 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -285,6 +285,7 @@ STAC9205/9254
   dell-m42	Dell (unknown)
   dell-m43	Dell Precision
   dell-m44	Dell Inspiron
+  eapd		Keep EAPD on (e.g. Gateway T1616)
 
 STAC9220/9221
 =============
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3f85731055c..ed2fa431b03 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -66,6 +66,7 @@ enum {
 	STAC_9205_DELL_M42,
 	STAC_9205_DELL_M43,
 	STAC_9205_DELL_M44,
+	STAC_9205_EAPD,
 	STAC_9205_MODELS
 };
 
@@ -2240,6 +2241,7 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
 	[STAC_9205_DELL_M42] = dell_9205_m42_pin_configs,
 	[STAC_9205_DELL_M43] = dell_9205_m43_pin_configs,
 	[STAC_9205_DELL_M44] = dell_9205_m44_pin_configs,
+	[STAC_9205_EAPD] = NULL,
 };
 
 static const char *stac9205_models[STAC_9205_MODELS] = {
@@ -2247,12 +2249,14 @@ static const char *stac9205_models[STAC_9205_MODELS] = {
 	[STAC_9205_DELL_M42] = "dell-m42",
 	[STAC_9205_DELL_M43] = "dell-m43",
 	[STAC_9205_DELL_M44] = "dell-m44",
+	[STAC_9205_EAPD] = "eapd",
 };
 
 static struct snd_pci_quirk stac9205_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
 		      "DFI LanParty", STAC_9205_REF),
+	/* Dell */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
 		      "unknown Dell", STAC_9205_DELL_M42),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
@@ -2283,6 +2287,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
 		      "Dell Inspiron", STAC_9205_DELL_M44),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
 		      "Dell Vostro 1500", STAC_9205_DELL_M42),
+	/* Gateway */
+	SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
 	{} /* terminator */
 };
 
@@ -5320,7 +5326,9 @@ static int patch_stac9205(struct hda_codec *codec)
 
 	spec->aloopback_mask = 0x40;
 	spec->aloopback_shift = 0;
-	spec->eapd_switch = 1;
+	/* Turn on/off EAPD per HP plugging */
+	if (spec->board_config != STAC_9205_EAPD)
+		spec->eapd_switch = 1;
 	spec->multiout.dac_nids = spec->dac_nids;
 	
 	switch (spec->board_config){
-- 
cgit v1.2.3-70-g09d2


From c96330b083ce88b9fea428df99b4631f1b6410ef Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 28 Jan 2009 08:23:03 +0100
Subject: ALSA: Add description of new snd-msnd-* drivers

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt | 48 +++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 841a9365d5f..ba7b14a13ab 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1185,6 +1185,54 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     This module supports multiple devices and PnP.
     
+  Module snd-msnd-classic
+  -----------------------
+
+    Module for Turtle Beach MultiSound Classic, Tahiti or Monterey
+    soundcards.
+
+    io		- Port # for msnd-classic card
+    irq		- IRQ # for msnd-classic card
+    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
+		  0xe0000 or 0xe8000)
+    write_ndelay - enable write ndelay (default = 1)
+    calibrate_signal - calibrate signal (default = 0)
+    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
+    digital	- Digital daughterboard present (default = 0)
+    cfg		- Config port (0x250, 0x260 or 0x270) default = PnP
+    reset	- Reset all devices
+    mpu_io	- MPU401 I/O port
+    mpu_irq	- MPU401 irq#
+    ide_io0	- IDE port #0
+    ide_io1	- IDE port #1
+    ide_irq	- IDE irq#
+    joystick_io	- Joystick I/O port
+
+    The driver requires firmware files "turtlebeach/msndinit.bin" and
+    "turtlebeach/msndperm.bin" in the proper firmware directory.
+
+    See Documentation/sound/oss/MultiSound for important information
+    about this driver.  Note that it has been discontinued, but the 
+    Voyetra Turtle Beach knowledge base entry for it is still available
+    at
+	http://www.turtlebeach.com/site/kb_ftp/790.asp
+
+  Module snd-msnd-pinnacle
+  ------------------------
+
+    Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards.
+
+    io		- Port # for pinnacle/fiji card
+    irq		- IRQ # for pinnalce/fiji card
+    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
+		  0xe0000 or 0xe8000)
+    write_ndelay - enable write ndelay (default = 1)
+    calibrate_signal - calibrate signal (default = 0)
+    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
+
+    The driver requires firmware files "turtlebeach/pndspini.bin" and
+    "turtlebeach/pndsperm.bin" in the proper firmware directory.
+
   Module snd-mtpav
   ----------------
 
-- 
cgit v1.2.3-70-g09d2


From 9e128fddcc589db4e7d9e8328f656ae4a21a2808 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 29 Jan 2009 11:49:10 +0100
Subject: ALSA: Add missing description of snd-cmi8330 module parameters

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 841a9365d5f..7134a8f7044 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -346,6 +346,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     sbirq	- IRQ # for CMI8330 chip (SB16)
     sbdma8	- 8bit DMA # for CMI8330 chip (SB16)
     sbdma16	- 16bit DMA # for CMI8330 chip (SB16)
+    fmport	- (optional) OPL3 I/O port
+    mpuport	- (optional) MPU401 I/O port
+    mpuirq	- (optional) MPU401 irq #
 
     This module supports multiple cards and autoprobe.
 
-- 
cgit v1.2.3-70-g09d2


From c557289cb8ea063bd09db88f8a687a841556e291 Mon Sep 17 00:00:00 2001
From: Michael Buesch <mb@bu3sch.de>
Date: Sat, 27 Dec 2008 18:26:39 +0100
Subject: b43: Change schedule for old-fw support removal

The scheduled date for the removal of old fw support was in July 2008.
However, we're not going to remove the support unless it causes a major
headache. So change the schedule from "July 2008" to "when it causes headaches".

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 Documentation/feature-removal-schedule.txt |  4 +++-
 drivers/net/wireless/b43/main.c            | 10 +++++++---
 2 files changed, 10 insertions(+), 4 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 5ddbe350487..ac98851f7a0 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -229,7 +229,9 @@ Who:	Jan Engelhardt <jengelh@computergmbh.de>
 ---------------------------
 
 What:	b43 support for firmware revision < 410
-When:	July 2008
+When:	The schedule was July 2008, but it was decided that we are going to keep the
+        code as long as there are no major maintanance headaches.
+	So it _could_ be removed _any_ time now, if it conflicts with something new.
 Why:	The support code for the old firmware hurts code readability/maintainability
 	and slightly hurts runtime performance. Bugfixes for the old firmware
 	are not provided by Broadcom anymore.
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index c627bac87a4..5ca55dcd034 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1954,8 +1954,9 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
 	const char *text;
 
 	text = "You must go to "
-	       "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware "
-	       "and download the latest firmware (version 4).\n";
+	       "http://wireless.kernel.org/en/users/Drivers/b43#devicefirmware "
+	       "and download the correct firmware for this driver version. "
+	       "Please carefully read all instructions on this website.\n";
 	if (error)
 		b43err(wl, text);
 	else
@@ -2271,8 +2272,11 @@ static int b43_upload_microcode(struct b43_wldev *dev)
 	}
 
 	if (b43_is_old_txhdr_format(dev)) {
+		/* We're over the deadline, but we keep support for old fw
+		 * until it turns out to be in major conflict with something new. */
 		b43warn(dev->wl, "You are using an old firmware image. "
-			"Support for old firmware will be removed in July 2008.\n");
+			"Support for old firmware will be removed soon "
+			"(official deadline was July 2008).\n");
 		b43_print_fw_helptext(dev->wl, 0);
 	}
 
-- 
cgit v1.2.3-70-g09d2


From d1c3a37ceeb1a5ea02991a0476355f1a1d3b3e83 Mon Sep 17 00:00:00 2001
From: Johannes Berg <johannes@sipsolutions.net>
Date: Wed, 7 Jan 2009 00:26:10 +0100
Subject: mac80211: clarify alignment docs, fix up alignment

Not all drivers are capable of passing properly aligned frames,
in particular with mesh networking no hardware will support
completely aligning it correctly.

This patch adds code to align the data payload to a 4-byte
boundary in memory for those platforms that require this, or
when CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is set.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 Documentation/DocBook/mac80211.tmpl |   4 +-
 net/mac80211/rx.c                   | 110 +++++++++++++++++++++++++-----------
 2 files changed, 79 insertions(+), 35 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
index 77c3c202991..bdf908a6e54 100644
--- a/Documentation/DocBook/mac80211.tmpl
+++ b/Documentation/DocBook/mac80211.tmpl
@@ -165,8 +165,8 @@ usage should require reading the full document.
 !Pinclude/net/mac80211.h Frame format
       </sect1>
       <sect1>
-        <title>Alignment issues</title>
-        <para>TBD</para>
+        <title>Packet alignment</title>
+!Pnet/mac80211/rx.c Packet alignment
       </sect1>
       <sect1>
         <title>Calling into mac80211 from interrupts</title>
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ddb966f5888..b68e082e99c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -102,7 +102,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
 	return len;
 }
 
-/**
+/*
  * ieee80211_add_rx_radiotap_header - add radiotap header
  *
  * add a radiotap header containing all the fields which the hardware provided.
@@ -371,39 +371,50 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
 	rx->skb->priority = (tid > 7) ? 0 : tid;
 }
 
-static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
+/**
+ * DOC: Packet alignment
+ *
+ * Drivers always need to pass packets that are aligned to two-byte boundaries
+ * to the stack.
+ *
+ * Additionally, should, if possible, align the payload data in a way that
+ * guarantees that the contained IP header is aligned to a four-byte
+ * boundary. In the case of regular frames, this simply means aligning the
+ * payload to a four-byte boundary (because either the IP header is directly
+ * contained, or IV/RFC1042 headers that have a length divisible by four are
+ * in front of it).
+ *
+ * With A-MSDU frames, however, the payload data address must yield two modulo
+ * four because there are 14-byte 802.3 headers within the A-MSDU frames that
+ * push the IP header further back to a multiple of four again. Thankfully, the
+ * specs were sane enough this time around to require padding each A-MSDU
+ * subframe to a length that is a multiple of four.
+ *
+ * Padding like Atheros hardware adds which is inbetween the 802.11 header and
+ * the payload is not supported, the driver is required to move the 802.11
+ * header to be directly in front of the payload in that case.
+ */
+static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
 {
-#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 	int hdrlen;
 
+#ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+	return;
+#endif
+
+	if (WARN_ONCE((unsigned long)rx->skb->data & 1,
+		      "unaligned packet at 0x%p\n", rx->skb->data))
+		return;
+
 	if (!ieee80211_is_data_present(hdr->frame_control))
 		return;
 
-	/*
-	 * Drivers are required to align the payload data in a way that
-	 * guarantees that the contained IP header is aligned to a four-
-	 * byte boundary. In the case of regular frames, this simply means
-	 * aligning the payload to a four-byte boundary (because either
-	 * the IP header is directly contained, or IV/RFC1042 headers that
-	 * have a length divisible by four are in front of it.
-	 *
-	 * With A-MSDU frames, however, the payload data address must
-	 * yield two modulo four because there are 14-byte 802.3 headers
-	 * within the A-MSDU frames that push the IP header further back
-	 * to a multiple of four again. Thankfully, the specs were sane
-	 * enough this time around to require padding each A-MSDU subframe
-	 * to a length that is a multiple of four.
-	 *
-	 * Padding like atheros hardware adds which is inbetween the 802.11
-	 * header and the payload is not supported, the driver is required
-	 * to move the 802.11 header further back in that case.
-	 */
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 	if (rx->flags & IEEE80211_RX_AMSDU)
 		hdrlen += ETH_HLEN;
-	WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
-#endif
+	WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3,
+		  "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen);
 }
 
 
@@ -1267,10 +1278,37 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
 	}
 
 	if (skb) {
-		/* deliver to local stack */
-		skb->protocol = eth_type_trans(skb, dev);
-		memset(skb->cb, 0, sizeof(skb->cb));
-		netif_rx(skb);
+		int align __maybe_unused;
+
+#if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+		/*
+		 * 'align' will only take the values 0 or 2 here
+		 * since all frames are required to be aligned
+		 * to 2-byte boundaries when being passed to
+		 * mac80211. That also explains the __skb_push()
+		 * below.
+		 */
+		align = (unsigned long)skb->data & 4;
+		if (align) {
+			if (WARN_ON(skb_headroom(skb) < 3)) {
+				dev_kfree_skb(skb);
+				skb = NULL;
+			} else {
+				u8 *data = skb->data;
+				size_t len = skb->len;
+				u8 *new = __skb_push(skb, align);
+				memmove(new, data, len);
+				__skb_trim(skb, len);
+			}
+		}
+#endif
+
+		if (skb) {
+			/* deliver to local stack */
+			skb->protocol = eth_type_trans(skb, dev);
+			memset(skb->cb, 0, sizeof(skb->cb));
+			netif_rx(skb);
+		}
 	}
 
 	if (xmit_skb) {
@@ -1339,14 +1377,20 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 		if (remaining <= subframe_len + padding)
 			frame = skb;
 		else {
-			frame = dev_alloc_skb(local->hw.extra_tx_headroom +
-					      subframe_len);
+			/*
+			 * Allocate and reserve two bytes more for payload
+			 * alignment since sizeof(struct ethhdr) is 14.
+			 */
+			frame = dev_alloc_skb(
+				ALIGN(local->hw.extra_tx_headroom, 4) +
+				subframe_len + 2);
 
 			if (frame == NULL)
 				return RX_DROP_UNUSABLE;
 
-			skb_reserve(frame, local->hw.extra_tx_headroom +
-				    sizeof(struct ethhdr));
+			skb_reserve(frame,
+				    ALIGN(local->hw.extra_tx_headroom, 4) +
+				    sizeof(struct ethhdr) + 2);
 			memcpy(skb_put(frame, ntohs(len)), skb->data,
 				ntohs(len));
 
@@ -1976,7 +2020,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 		rx.flags |= IEEE80211_RX_IN_SCAN;
 
 	ieee80211_parse_qos(&rx);
-	ieee80211_verify_ip_alignment(&rx);
+	ieee80211_verify_alignment(&rx);
 
 	skb = rx.skb;
 
-- 
cgit v1.2.3-70-g09d2


From 4be8c3873e0b88397866d3ede578503e188f9ad2 Mon Sep 17 00:00:00 2001
From: Johannes Berg <johannes@sipsolutions.net>
Date: Wed, 7 Jan 2009 18:28:20 +0100
Subject: mac80211: extend/document powersave API

This modifies hardware flags for powersave to support three different
flags:
 * IEEE80211_HW_SUPPORTS_PS - indicates general PS support
 * IEEE80211_HW_PS_NULLFUNC_STACK - indicates nullfunc sending in software
 * IEEE80211_HW_SUPPORTS_DYNAMIC_PS - indicates dynamic PS on the device

It also adds documentation for all this which explains how to set the
various flags.

Additionally, it fixes a few things:
 * a spot where && was used to test flags
 * enable CONF_PS only when associated again

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 Documentation/DocBook/mac80211.tmpl     |  8 +++--
 drivers/net/wireless/iwlwifi/iwl-core.c |  3 +-
 drivers/net/wireless/rt2x00/rt2400pci.c |  4 ++-
 drivers/net/wireless/rt2x00/rt2500pci.c |  4 ++-
 drivers/net/wireless/rt2x00/rt2500usb.c |  4 ++-
 drivers/net/wireless/rt2x00/rt61pci.c   |  4 ++-
 drivers/net/wireless/rt2x00/rt73usb.c   |  4 ++-
 include/net/mac80211.h                  | 53 +++++++++++++++++++++++++++++----
 net/mac80211/mlme.c                     | 31 ++++++++++---------
 net/mac80211/tx.c                       |  2 +-
 net/mac80211/wext.c                     | 40 +++++++++++++++----------
 11 files changed, 111 insertions(+), 46 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
index bdf908a6e54..8af6d962687 100644
--- a/Documentation/DocBook/mac80211.tmpl
+++ b/Documentation/DocBook/mac80211.tmpl
@@ -17,8 +17,7 @@
     </authorgroup>
 
     <copyright>
-      <year>2007</year>
-      <year>2008</year>
+      <year>2007-2009</year>
       <holder>Johannes Berg</holder>
     </copyright>
 
@@ -223,6 +222,11 @@ usage should require reading the full document.
 !Finclude/net/mac80211.h ieee80211_key_flags
     </chapter>
 
+    <chapter id="powersave">
+      <title>Powersave support</title>
+!Pinclude/net/mac80211.h Powersave support
+    </chapter>
+
     <chapter id="qos">
       <title>Multiple queues and QoS support</title>
       <para>TBD</para>
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 76315c30e6f..07c3870365b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -805,7 +805,8 @@ int iwl_setup_mac(struct iwl_priv *priv)
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_NOISE_DBM |
-		    IEEE80211_HW_AMPDU_AGGREGATION;
+		    IEEE80211_HW_AMPDU_AGGREGATION |
+		    IEEE80211_HW_SUPPORTS_PS;
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_ADHOC);
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 9104113270d..ae8bfd6b59d 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1449,7 +1449,9 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	 * Initialize all hw fields.
 	 */
 	rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-			       IEEE80211_HW_SIGNAL_DBM;
+			       IEEE80211_HW_SIGNAL_DBM |
+			       IEEE80211_HW_SUPPORTS_PS |
+			       IEEE80211_HW_PS_NULLFUNC_STACK;
 	rt2x00dev->hw->extra_tx_headroom = 0;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index ebcc4977092..bca6798be15 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1749,7 +1749,9 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	 * Initialize all hw fields.
 	 */
 	rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-			       IEEE80211_HW_SIGNAL_DBM;
+			       IEEE80211_HW_SIGNAL_DBM |
+			       IEEE80211_HW_SUPPORTS_PS |
+			       IEEE80211_HW_PS_NULLFUNC_STACK;
 
 	rt2x00dev->hw->extra_tx_headroom = 0;
 
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index e992bad6464..27a6971df57 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1801,7 +1801,9 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	rt2x00dev->hw->flags =
 	    IEEE80211_HW_RX_INCLUDES_FCS |
 	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-	    IEEE80211_HW_SIGNAL_DBM;
+	    IEEE80211_HW_SIGNAL_DBM |
+	    IEEE80211_HW_SUPPORTS_PS |
+	    IEEE80211_HW_PS_NULLFUNC_STACK;
 
 	rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 82d35a5a4aa..549480a963e 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2556,7 +2556,9 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	 */
 	rt2x00dev->hw->flags =
 	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-	    IEEE80211_HW_SIGNAL_DBM;
+	    IEEE80211_HW_SIGNAL_DBM |
+	    IEEE80211_HW_SUPPORTS_PS |
+	    IEEE80211_HW_PS_NULLFUNC_STACK;
 	rt2x00dev->hw->extra_tx_headroom = 0;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 2b70c01b55e..849220236c7 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2077,7 +2077,9 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	 */
 	rt2x00dev->hw->flags =
 	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-	    IEEE80211_HW_SIGNAL_DBM;
+	    IEEE80211_HW_SIGNAL_DBM |
+	    IEEE80211_HW_SUPPORTS_PS |
+	    IEEE80211_HW_PS_NULLFUNC_STACK;
 	rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 83ee8a21229..8a305bfdb87 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -850,10 +850,15 @@ enum ieee80211_tkip_key_type {
  * @IEEE80211_HW_AMPDU_AGGREGATION:
  *	Hardware supports 11n A-MPDU aggregation.
  *
- * @IEEE80211_HW_NO_STACK_DYNAMIC_PS:
- *	Hardware which has dynamic power save support, meaning
- *	that power save is enabled in idle periods, and don't need support
- *	from stack.
+ * @IEEE80211_HW_SUPPORTS_PS:
+ *	Hardware has power save support (i.e. can go to sleep).
+ *
+ * @IEEE80211_HW_PS_NULLFUNC_STACK:
+ *	Hardware requires nullfunc frame handling in stack, implies
+ *	stack support for dynamic PS.
+ *
+ * @IEEE80211_HW_SUPPORTS_DYNAMIC_PS:
+ *	Hardware has support for dynamic PS.
  */
 enum ieee80211_hw_flags {
 	IEEE80211_HW_RX_INCLUDES_FCS			= 1<<1,
@@ -866,7 +871,9 @@ enum ieee80211_hw_flags {
 	IEEE80211_HW_NOISE_DBM				= 1<<8,
 	IEEE80211_HW_SPECTRUM_MGMT			= 1<<9,
 	IEEE80211_HW_AMPDU_AGGREGATION			= 1<<10,
-	IEEE80211_HW_NO_STACK_DYNAMIC_PS		= 1<<11,
+	IEEE80211_HW_SUPPORTS_PS			= 1<<11,
+	IEEE80211_HW_PS_NULLFUNC_STACK			= 1<<12,
+	IEEE80211_HW_SUPPORTS_DYNAMIC_PS		= 1<<13,
 };
 
 /**
@@ -1052,6 +1059,42 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  * handler is software decryption with wrap around of iv16.
  */
 
+/**
+ * DOC: Powersave support
+ *
+ * mac80211 has support for various powersave implementations.
+ *
+ * First, it can support hardware that handles all powersaving by
+ * itself, such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS
+ * hardware flag. In that case, it will be told about the desired
+ * powersave mode depending on the association status, and the driver
+ * must take care of sending nullfunc frames when necessary, i.e. when
+ * entering and leaving powersave mode. The driver is required to look at
+ * the AID in beacons and signal to the AP that it woke up when it finds
+ * traffic directed to it. This mode supports dynamic PS by simply
+ * enabling/disabling PS.
+ *
+ * Additionally, such hardware may set the %IEEE80211_HW_SUPPORTS_DYNAMIC_PS
+ * flag to indicate that it can support dynamic PS mode itself (see below).
+ *
+ * Other hardware designs cannot send nullfunc frames by themselves and also
+ * need software support for parsing the TIM bitmap. This is also supported
+ * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and
+ * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still
+ * required to pass up beacons. Additionally, in this case, mac80211 will
+ * wake up the hardware when multicast traffic is announced in the beacon.
+ *
+ * FIXME: I don't think we can be fast enough in software when we want to
+ *	  receive multicast traffic?
+ *
+ * Dynamic powersave mode is an extension to normal powersave mode in which
+ * the hardware stays awake for a user-specified period of time after sending
+ * a frame so that reply frames need not be buffered and therefore delayed
+ * to the next wakeup. This can either be supported by hardware, in which case
+ * the driver needs to look at the @dynamic_ps_timeout hardware configuration
+ * value, or by the stack if all nullfunc handling is in the stack.
+ */
+
 /**
  * DOC: Frame filtering
  *
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7709e764567..a1e683e305f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -775,17 +775,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
 	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
 
-	if (local->powersave &&
-			!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) {
-		if (local->hw.conf.dynamic_ps_timeout > 0)
+	if (local->powersave) {
+		if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) &&
+		    local->hw.conf.dynamic_ps_timeout > 0) {
 			mod_timer(&local->dynamic_ps_timer, jiffies +
 				  msecs_to_jiffies(
 					local->hw.conf.dynamic_ps_timeout));
-		else {
-			ieee80211_send_nullfunc(local, sdata, 1);
+		} else {
+			if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+				ieee80211_send_nullfunc(local, sdata, 1);
 			conf->flags |= IEEE80211_CONF_PS;
-			ieee80211_hw_config(local,
-					    IEEE80211_CONF_CHANGE_PS);
+			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 		}
 	}
 
@@ -1779,16 +1779,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 	ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
 				 elems.wmm_param_len);
 
-	if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) {
+	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK &&
+	    local->hw.conf.flags & IEEE80211_CONF_PS) {
 		directed_tim = check_tim(&elems, ifsta->aid, &is_mc);
 
 		if (directed_tim || is_mc) {
-			if (local->hw.conf.flags && IEEE80211_CONF_PS) {
-				local->hw.conf.flags &= ~IEEE80211_CONF_PS;
-				ieee80211_hw_config(local,
-						IEEE80211_CONF_CHANGE_PS);
-				ieee80211_send_nullfunc(local, sdata, 0);
-			}
+			local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+			ieee80211_send_nullfunc(local, sdata, 0);
 		}
 	}
 
@@ -2694,9 +2692,10 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 	if (local->hw.conf.flags & IEEE80211_CONF_PS)
 		return;
 
-	ieee80211_send_nullfunc(local, sdata, 1);
-	local->hw.conf.flags |= IEEE80211_CONF_PS;
+	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+		ieee80211_send_nullfunc(local, sdata, 1);
 
+	local->hw.conf.flags |= IEEE80211_CONF_PS;
 	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 }
 
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b18a7269011..cd6bc87eec7 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1295,7 +1295,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		return 0;
 	}
 
-	if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
+	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
 	    local->hw.conf.dynamic_ps_timeout > 0) {
 		if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 			ieee80211_stop_queues_by_reason(&local->hw,
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 3f2db0bda46..1e5b29bdb3a 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -837,6 +837,9 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
 	int ret = 0, timeout = 0;
 	bool ps;
 
+	if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
+		return -EOPNOTSUPP;
+
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return -EINVAL;
 
@@ -862,32 +865,37 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
 	if (wrq->flags & IW_POWER_TIMEOUT)
 		timeout = wrq->value / 1000;
 
-set:
+ set:
 	if (ps == local->powersave && timeout == conf->dynamic_ps_timeout)
 		return ret;
 
 	local->powersave = ps;
 	conf->dynamic_ps_timeout = timeout;
 
-	if (local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) {
+	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
 		ret = ieee80211_hw_config(local,
 					  IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT);
-	} else if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
-		if (conf->dynamic_ps_timeout > 0)
-			mod_timer(&local->dynamic_ps_timer, jiffies +
-				  msecs_to_jiffies(conf->dynamic_ps_timeout));
-		else {
-			if (local->powersave) {
+
+	if (!(sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
+		return ret;
+
+	if (conf->dynamic_ps_timeout > 0 &&
+	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
+		mod_timer(&local->dynamic_ps_timer, jiffies +
+			  msecs_to_jiffies(conf->dynamic_ps_timeout));
+	} else {
+		if (local->powersave) {
+			if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
 				ieee80211_send_nullfunc(local, sdata, 1);
-				conf->flags |= IEEE80211_CONF_PS;
-				ret = ieee80211_hw_config(local,
-						IEEE80211_CONF_CHANGE_PS);
-			} else {
-				conf->flags &= ~IEEE80211_CONF_PS;
-				ret = ieee80211_hw_config(local,
-						IEEE80211_CONF_CHANGE_PS);
+			conf->flags |= IEEE80211_CONF_PS;
+			ret = ieee80211_hw_config(local,
+					IEEE80211_CONF_CHANGE_PS);
+		} else {
+			conf->flags &= ~IEEE80211_CONF_PS;
+			ret = ieee80211_hw_config(local,
+					IEEE80211_CONF_CHANGE_PS);
+			if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
 				ieee80211_send_nullfunc(local, sdata, 0);
-			}
 		}
 	}
 
-- 
cgit v1.2.3-70-g09d2


From 504a06d8b05cb5b214c9b97752d8451e88d9ef81 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 30 Jan 2009 19:59:10 +0100
Subject: ALSA: Add description of new fm_port option for snd-es1688 driver

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt | 1 +
 1 file changed, 1 insertion(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 7134a8f7044..a763b76afe5 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -609,6 +609,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
 
     port	- port # for ES-1688 chip (0x220,0x240,0x260)
+    fm_port	- port # for OPL3 (option; share the same port as default)
     mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
     irq		- IRQ # for ES-1688 chip (5,7,9,10)
     mpu_irq	- IRQ # for MPU-401 port (5,7,9,10)
-- 
cgit v1.2.3-70-g09d2


From eefef1cf7653cd4e0aaf743c00ae8345086cdc01 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <shemminger@linux-foundation.org>
Date: Sun, 1 Feb 2009 01:04:33 -0800
Subject: net: add ARP notify option for devices

This adds another inet device option to enable gratuitous ARP
when device is brought up or address change. This is handy for
clusters or virtualization.

Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/ip-sysctl.txt | 6 ++++++
 include/linux/inetdevice.h             | 1 +
 include/linux/sysctl.h                 | 1 +
 kernel/sysctl_check.c                  | 1 +
 net/ipv4/devinet.c                     | 9 +++++++++
 5 files changed, 18 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index c7712787933..ff3f219ee4d 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -782,6 +782,12 @@ arp_ignore - INTEGER
 	The max value from conf/{all,interface}/arp_ignore is used
 	when ARP request is received on the {interface}
 
+arp_notify - BOOLEAN
+	Define mode for notification of address and device changes.
+	0 - (default): do nothing
+	1 - Generate gratuitous arp replies when device is brought up
+	    or hardware address changes.
+
 arp_accept - BOOLEAN
 	Define behavior when gratuitous arp replies are received:
 	0 - drop gratuitous arp frames
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 06fcdb45106..acef2a770b6 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -108,6 +108,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 #define IN_DEV_ARPFILTER(in_dev)	IN_DEV_ORCONF((in_dev), ARPFILTER)
 #define IN_DEV_ARP_ANNOUNCE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
 #define IN_DEV_ARP_IGNORE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
+#define IN_DEV_ARP_NOTIFY(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
 
 struct in_ifaddr
 {
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 39d471d1163..e76d3b22a46 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -490,6 +490,7 @@ enum
 	NET_IPV4_CONF_ARP_IGNORE=19,
 	NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
 	NET_IPV4_CONF_ARP_ACCEPT=21,
+	NET_IPV4_CONF_ARP_NOTIFY=22,
 	__NET_IPV4_CONF_MAX
 };
 
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index fafeb48f27c..b38423ca711 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -219,6 +219,7 @@ static const struct trans_ctl_table trans_net_ipv4_conf_vars_table[] = {
 	{ NET_IPV4_CONF_ARP_IGNORE,		"arp_ignore" },
 	{ NET_IPV4_CONF_PROMOTE_SECONDARIES,	"promote_secondaries" },
 	{ NET_IPV4_CONF_ARP_ACCEPT,		"arp_accept" },
+	{ NET_IPV4_CONF_ARP_NOTIFY,		"arp_notify" },
 	{}
 };
 
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 309997edc8a..d519a6a6672 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1075,6 +1075,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
 			}
 		}
 		ip_mc_up(in_dev);
+		/* fall through */
+	case NETDEV_CHANGEADDR:
+		if (IN_DEV_ARP_NOTIFY(in_dev))
+			arp_send(ARPOP_REQUEST, ETH_P_ARP,
+				 in_dev->ifa_list->ifa_address,
+				 dev,
+				 in_dev->ifa_list->ifa_address,
+				 NULL, dev->dev_addr, NULL);
 		break;
 	case NETDEV_DOWN:
 		ip_mc_down(in_dev);
@@ -1439,6 +1447,7 @@ static struct devinet_sysctl_table {
 		DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
 		DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
 		DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
+		DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"),
 
 		DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
 		DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
-- 
cgit v1.2.3-70-g09d2


From 123848e77623b9996288e85433985439c157fcd0 Mon Sep 17 00:00:00 2001
From: Tony Vroon <tony@linx.net>
Date: Tue, 3 Feb 2009 11:13:34 +0000
Subject: ALSA: Document tyan model for Realtek ALC262

As just pointed out to me, the new tyan model for ALC262 was
implemented but not documented. This adds the board to the
list, using both its marketing name (Thunder n6650W) and its
model number (S2915-E).

Signed-off-by: Tony Vroon <tony@linx.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt | 1 +
 1 file changed, 1 insertion(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index c9df9db5835..8f40999a456 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -56,6 +56,7 @@ ALC262
   sony-assamd	Sony ASSAMD
   toshiba-s06	Toshiba S06
   toshiba-rx1	Toshiba RX1
+  tyan		Tyan Thunder n6650W (S2915-E)
   ultra		Samsung Q1 Ultra Vista model
   lenovo-3000	Lenovo 3000 y410
   nec		NEC Versa S9100
-- 
cgit v1.2.3-70-g09d2


From 4d7902f22b0804730b80f7a4147f676430248a3a Mon Sep 17 00:00:00 2001
From: Andy Fleming <afleming@freescale.com>
Date: Wed, 4 Feb 2009 16:43:44 -0800
Subject: gianfar: Fix stashing support

Stashing is only supported on the 85xx (e500-based) SoCs.  The 83xx and 86xx
chips don't have a proper cache for this.  U-Boot has been updated to add
stashing properties to the device tree nodes of gianfar devices on 85xx.  So
now we modify Linux to keep stashing off unless those properties are there.

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/powerpc/dts-bindings/fsl/tsec.txt |  6 ++++++
 drivers/net/gianfar.c                           | 23 +++++++++++++++++++++++
 drivers/net/gianfar_sysfs.c                     | 12 +++++++++---
 3 files changed, 38 insertions(+), 3 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/powerpc/dts-bindings/fsl/tsec.txt b/Documentation/powerpc/dts-bindings/fsl/tsec.txt
index 7fa4b27574b..edb7ae19e86 100644
--- a/Documentation/powerpc/dts-bindings/fsl/tsec.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/tsec.txt
@@ -56,6 +56,12 @@ Properties:
     hardware.
   - fsl,magic-packet : If present, indicates that the hardware supports
     waking up via magic packet.
+  - bd-stash : If present, indicates that the hardware supports stashing
+    buffer descriptors in the L2.
+  - rx-stash-len : Denotes the number of bytes of a received buffer to stash
+    in the L2.
+  - rx-stash-idx : Denotes the index of the first byte from the received
+    buffer to stash in the L2.
 
 Example:
 	ethernet@24000 {
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 33de25602b3..dadd08cd801 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -164,6 +164,9 @@ static int gfar_of_init(struct net_device *dev)
 	struct gfar_private *priv = netdev_priv(dev);
 	struct device_node *np = priv->node;
 	char bus_name[MII_BUS_ID_SIZE];
+	const u32 *stash;
+	const u32 *stash_len;
+	const u32 *stash_idx;
 
 	if (!np || !of_device_is_available(np))
 		return -ENODEV;
@@ -193,6 +196,26 @@ static int gfar_of_init(struct net_device *dev)
 		}
 	}
 
+	stash = of_get_property(np, "bd-stash", NULL);
+
+	if(stash) {
+		priv->device_flags |= FSL_GIANFAR_DEV_HAS_BD_STASHING;
+		priv->bd_stash_en = 1;
+	}
+
+	stash_len = of_get_property(np, "rx-stash-len", NULL);
+
+	if (stash_len)
+		priv->rx_stash_size = *stash_len;
+
+	stash_idx = of_get_property(np, "rx-stash-idx", NULL);
+
+	if (stash_idx)
+		priv->rx_stash_index = *stash_idx;
+
+	if (stash_len || stash_idx)
+		priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING;
+
 	mac_addr = of_get_mac_address(np);
 	if (mac_addr)
 		memcpy(dev->dev_addr, mac_addr, MAC_ADDR_LEN);
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 74e0b4d4258..dd26da74f27 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -53,6 +53,9 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
 	u32 temp;
 	unsigned long flags;
 
+	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING))
+		return count;
+
 	/* Find out the new setting */
 	if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
 		new_setting = 1;
@@ -100,6 +103,9 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev,
 	u32 temp;
 	unsigned long flags;
 
+	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
+		return count;
+
 	spin_lock_irqsave(&priv->rxlock, flags);
 	if (length > priv->rx_buffer_size)
 		goto out;
@@ -152,6 +158,9 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev,
 	u32 temp;
 	unsigned long flags;
 
+	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
+		return count;
+
 	spin_lock_irqsave(&priv->rxlock, flags);
 	if (index > priv->rx_stash_size)
 		goto out;
@@ -294,12 +303,9 @@ void gfar_init_sysfs(struct net_device *dev)
 	int rc;
 
 	/* Initialize the default values */
-	priv->rx_stash_size = DEFAULT_STASH_LENGTH;
-	priv->rx_stash_index = DEFAULT_STASH_INDEX;
 	priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
 	priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
 	priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
-	priv->bd_stash_en = DEFAULT_BD_STASH;
 
 	/* Create our sysfs files */
 	rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
-- 
cgit v1.2.3-70-g09d2


From 6146f0d5e47ca4047ffded0fb79b6c25359b386c Mon Sep 17 00:00:00 2001
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date: Wed, 4 Feb 2009 09:06:57 -0500
Subject: integrity: IMA hooks

This patch replaces the generic integrity hooks, for which IMA registered
itself, with IMA integrity hooks in the appropriate places directly
in the fs directory.

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 Documentation/kernel-parameters.txt |  1 +
 fs/exec.c                           | 10 +++++++++
 fs/file_table.c                     |  2 ++
 fs/inode.c                          | 24 ++++++++++++++------
 fs/namei.c                          |  8 +++++++
 include/linux/ima.h                 | 44 +++++++++++++++++++++++++++++++++++++
 mm/mmap.c                           |  4 ++++
 7 files changed, 86 insertions(+), 7 deletions(-)
 create mode 100644 include/linux/ima.h

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index a2d8805c03d..7c67b94d182 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -44,6 +44,7 @@ parameter is applicable:
 	FB	The frame buffer device is enabled.
 	HW	Appropriate hardware is enabled.
 	IA-64	IA-64 architecture is enabled.
+	IMA     Integrity measurement architecture is enabled.
 	IOSCHED	More than one I/O scheduler is enabled.
 	IP_PNP	IP DHCP, BOOTP, or RARP is enabled.
 	ISAPNP	ISA PnP code is enabled.
diff --git a/fs/exec.c b/fs/exec.c
index 02d2e120542..9c789a525cc 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -45,6 +45,7 @@
 #include <linux/proc_fs.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/syscalls.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
@@ -128,6 +129,9 @@ asmlinkage long sys_uselib(const char __user * library)
 		goto exit;
 
 	error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN);
+	if (error)
+		goto exit;
+	error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN);
 	if (error)
 		goto exit;
 
@@ -681,6 +685,9 @@ struct file *open_exec(const char *name)
 		goto out_path_put;
 
 	err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN);
+	if (err)
+		goto out_path_put;
+	err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN);
 	if (err)
 		goto out_path_put;
 
@@ -1207,6 +1214,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 	}
 #endif
 	retval = security_bprm_check(bprm);
+	if (retval)
+		return retval;
+	retval = ima_bprm_check(bprm);
 	if (retval)
 		return retval;
 
diff --git a/fs/file_table.c b/fs/file_table.c
index 0fbcacc3ea7..55895ccc08c 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/eventpoll.h>
 #include <linux/rcupdate.h>
 #include <linux/mount.h>
@@ -276,6 +277,7 @@ void __fput(struct file *file)
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	security_file_free(file);
+	ima_file_free(file);
 	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
 		cdev_put(inode->i_cdev);
 	fops_put(file->f_op);
diff --git a/fs/inode.c b/fs/inode.c
index 098a2443196..ed22b14f220 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -17,6 +17,7 @@
 #include <linux/hash.h>
 #include <linux/swap.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/pagemap.h>
 #include <linux/cdev.h>
 #include <linux/bootmem.h>
@@ -144,13 +145,13 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
 	inode->i_cdev = NULL;
 	inode->i_rdev = 0;
 	inode->dirtied_when = 0;
-	if (security_inode_alloc(inode)) {
-		if (inode->i_sb->s_op->destroy_inode)
-			inode->i_sb->s_op->destroy_inode(inode);
-		else
-			kmem_cache_free(inode_cachep, (inode));
-		return NULL;
-	}
+
+	if (security_inode_alloc(inode))
+		goto out_free_inode;
+
+	/* allocate and initialize an i_integrity */
+	if (ima_inode_alloc(inode))
+		goto out_free_security;
 
 	spin_lock_init(&inode->i_lock);
 	lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);
@@ -186,6 +187,15 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
 	inode->i_mapping = mapping;
 
 	return inode;
+
+out_free_security:
+	security_inode_free(inode);
+out_free_inode:
+	if (inode->i_sb->s_op->destroy_inode)
+		inode->i_sb->s_op->destroy_inode(inode);
+	else
+		kmem_cache_free(inode_cachep, (inode));
+	return NULL;
 }
 EXPORT_SYMBOL(inode_init_always);
 
diff --git a/fs/namei.c b/fs/namei.c
index af3783fff1d..734f2b5591b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -24,6 +24,7 @@
 #include <linux/fsnotify.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/syscalls.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
@@ -860,6 +861,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
 		err = exec_permission_lite(inode);
 		if (err == -EAGAIN)
 			err = vfs_permission(nd, MAY_EXEC);
+		if (!err)
+			err = ima_path_check(&nd->path, MAY_EXEC);
  		if (err)
 			break;
 
@@ -1525,6 +1528,11 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
 	error = vfs_permission(nd, acc_mode);
 	if (error)
 		return error;
+
+	error = ima_path_check(&nd->path,
+			       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
+	if (error)
+		return error;
 	/*
 	 * An append-only file must be opened in append mode for writing.
 	 */
diff --git a/include/linux/ima.h b/include/linux/ima.h
new file mode 100644
index 00000000000..4ed1e4d962e
--- /dev/null
+++ b/include/linux/ima.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+
+#include <linux/fs.h>
+
+#ifndef _LINUX_IMA_H
+#define _LINUX_IMA_H
+
+static inline int ima_bprm_check(struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static inline int ima_inode_alloc(struct inode *inode)
+{
+	return 0;
+}
+
+static inline void ima_inode_free(struct inode *inode)
+{
+	return;
+}
+
+static inline int ima_path_check(struct path *path, int mask)
+{
+	return 0;
+}
+
+static inline void ima_file_free(struct file *file)
+{
+	return;
+}
+
+static inline int ima_file_mmap(struct file *file, unsigned long prot)
+{
+	return 0;
+}
+#endif /* _LINUX_IMA_H */
diff --git a/mm/mmap.c b/mm/mmap.c
index d4855a682ab..c3647f3b062 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/module.h>
@@ -1048,6 +1049,9 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 	}
 
 	error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
+	if (error)
+		return error;
+	error = ima_file_mmap(file, prot);
 	if (error)
 		return error;
 
-- 
cgit v1.2.3-70-g09d2


From 3323eec921efd815178a23107ab63588c605c0b2 Mon Sep 17 00:00:00 2001
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date: Wed, 4 Feb 2009 09:06:58 -0500
Subject: integrity: IMA as an integrity service provider

IMA provides hardware (TPM) based measurement and attestation for
file measurements. As the Trusted Computing (TPM) model requires,
IMA measures all files before they are accessed in any way (on the
integrity_bprm_check, integrity_path_check and integrity_file_mmap
hooks), and commits the measurements to the TPM. Once added to the
TPM, measurements can not be removed.

In addition, IMA maintains a list of these file measurements, which
can be used to validate the aggregate value stored in the TPM.  The
TPM can sign these measurements, and thus the system can prove, to
itself and to a third party, the system's integrity in a way that
cannot be circumvented by malicious or compromised software.

- alloc ima_template_entry before calling ima_store_template()
- log ima_add_boot_aggregate() failure
- removed unused IMA_TEMPLATE_NAME_LEN
- replaced hard coded string length with #define name

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 Documentation/kernel-parameters.txt |   9 ++
 include/linux/audit.h               |   5 +
 include/linux/ima.h                 |  10 ++
 security/Kconfig                    |   5 +-
 security/Makefile                   |   4 +
 security/integrity/ima/Kconfig      |  49 +++++++
 security/integrity/ima/Makefile     |   9 ++
 security/integrity/ima/ima.h        | 135 +++++++++++++++++
 security/integrity/ima/ima_api.c    | 190 ++++++++++++++++++++++++
 security/integrity/ima/ima_audit.c  |  78 ++++++++++
 security/integrity/ima/ima_crypto.c | 140 ++++++++++++++++++
 security/integrity/ima/ima_iint.c   | 185 ++++++++++++++++++++++++
 security/integrity/ima/ima_init.c   |  90 ++++++++++++
 security/integrity/ima/ima_main.c   | 280 ++++++++++++++++++++++++++++++++++++
 security/integrity/ima/ima_policy.c | 126 ++++++++++++++++
 security/integrity/ima/ima_queue.c  | 140 ++++++++++++++++++
 16 files changed, 1454 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/ima/Kconfig
 create mode 100644 security/integrity/ima/Makefile
 create mode 100644 security/integrity/ima/ima.h
 create mode 100644 security/integrity/ima/ima_api.c
 create mode 100644 security/integrity/ima/ima_audit.c
 create mode 100644 security/integrity/ima/ima_crypto.c
 create mode 100644 security/integrity/ima/ima_iint.c
 create mode 100644 security/integrity/ima/ima_init.c
 create mode 100644 security/integrity/ima/ima_main.c
 create mode 100644 security/integrity/ima/ima_policy.c
 create mode 100644 security/integrity/ima/ima_queue.c

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 7c67b94d182..31e0c2c3c6e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -895,6 +895,15 @@ and is between 256 and 4096 characters. It is defined in the file
 	ihash_entries=	[KNL]
 			Set number of hash buckets for inode cache.
 
+	ima_audit=	[IMA]
+			Format: { "0" | "1" }
+			0 -- integrity auditing messages. (Default)
+			1 -- enable informational integrity auditing messages.
+
+	ima_hash=	[IMA]
+			Formt: { "sha1" | "md5" }
+			default: "sha1"
+
 	in2000=		[HW,SCSI]
 			See header of drivers/scsi/in2000.c.
 
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 26c4f6f65a4..8d1f67789b5 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -125,6 +125,11 @@
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
 #define AUDIT_ANOM_ABEND            1701 /* Process ended abnormally */
+#define AUDIT_INTEGRITY_DATA	    1800 /* Data integrity verification */
+#define AUDIT_INTEGRITY_METADATA    1801 /* Metadata integrity verification */
+#define AUDIT_INTEGRITY_STATUS	    1802 /* Integrity enable status */
+#define AUDIT_INTEGRITY_HASH	    1803 /* Integrity HASH type */
+#define AUDIT_INTEGRITY_PCR	    1804 /* PCR invalidation msgs */
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 4ed1e4d962e..dcc3664feee 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -12,6 +12,15 @@
 #ifndef _LINUX_IMA_H
 #define _LINUX_IMA_H
 
+#ifdef CONFIG_IMA
+extern int ima_bprm_check(struct linux_binprm *bprm);
+extern int ima_inode_alloc(struct inode *inode);
+extern void ima_inode_free(struct inode *inode);
+extern int ima_path_check(struct path *path, int mask);
+extern void ima_file_free(struct file *file);
+extern int ima_file_mmap(struct file *file, unsigned long prot);
+
+#else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
 	return 0;
@@ -41,4 +50,5 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
 {
 	return 0;
 }
+#endif /* CONFIG_IMA_H */
 #endif /* _LINUX_IMA_H */
diff --git a/security/Kconfig b/security/Kconfig
index d9f47ce7e20..a79b23f73d0 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -55,7 +55,8 @@ config SECURITYFS
 	bool "Enable the securityfs filesystem"
 	help
 	  This will build the securityfs filesystem.  It is currently used by
-	  the TPM bios character driver.  It is not used by SELinux or SMACK.
+	  the TPM bios character driver and IMA, an integrity provider.  It is
+	  not used by SELinux or SMACK.
 
 	  If you are unsure how to answer this question, answer N.
 
@@ -126,5 +127,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
 source security/selinux/Kconfig
 source security/smack/Kconfig
 
+source security/integrity/ima/Kconfig
+
 endmenu
 
diff --git a/security/Makefile b/security/Makefile
index c05c127fff9..595536cbffb 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -17,3 +17,7 @@ obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_SMACK)		+= smack/built-in.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= root_plug.o
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
+
+# Object integrity file lists
+subdir-$(CONFIG_IMA)			+= integrity/ima
+obj-$(CONFIG_IMA)			+= integrity/ima/built-in.o
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
new file mode 100644
index 00000000000..2a761c8ac99
--- /dev/null
+++ b/security/integrity/ima/Kconfig
@@ -0,0 +1,49 @@
+# IBM Integrity Measurement Architecture
+#
+config IMA
+	bool "Integrity Measurement Architecture(IMA)"
+	depends on ACPI
+	select SECURITYFS
+	select CRYPTO
+	select CRYPTO_HMAC
+	select CRYPTO_MD5
+	select CRYPTO_SHA1
+	select TCG_TPM
+	select TCG_TIS
+	help
+	  The Trusted Computing Group(TCG) runtime Integrity
+	  Measurement Architecture(IMA) maintains a list of hash
+	  values of executables and other sensitive system files,
+	  as they are read or executed. If an attacker manages
+	  to change the contents of an important system file
+	  being measured, we can tell.
+
+	  If your system has a TPM chip, then IMA also maintains
+	  an aggregate integrity value over this list inside the
+	  TPM hardware, so that the TPM can prove to a third party
+	  whether or not critical system files have been modified.
+	  Read <http://www.usenix.org/events/sec04/tech/sailer.html>
+	  to learn more about IMA.
+	  If unsure, say N.
+
+config IMA_MEASURE_PCR_IDX
+	int
+	depends on IMA
+	range 8 14
+	default 10
+	help
+	  IMA_MEASURE_PCR_IDX determines the TPM PCR register index
+	  that IMA uses to maintain the integrity aggregate of the
+	  measurement list.  If unsure, use the default 10.
+
+config IMA_AUDIT
+	bool
+	depends on IMA
+	default y
+	help
+	  This option adds a kernel parameter 'ima_audit', which
+	  allows informational auditing messages to be enabled
+	  at boot.  If this option is selected, informational integrity
+	  auditing messages can be enabled with 'ima_audit=1' on
+	  the kernel command line.
+
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
new file mode 100644
index 00000000000..9d6bf973b9b
--- /dev/null
+++ b/security/integrity/ima/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for building Trusted Computing Group's(TCG) runtime Integrity
+# Measurement Architecture(IMA).
+#
+
+obj-$(CONFIG_IMA) += ima.o
+
+ima-y := ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
+	 ima_policy.o ima_iint.o ima_audit.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
new file mode 100644
index 00000000000..bfa72ed41b9
--- /dev/null
+++ b/security/integrity/ima/ima.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima.h
+ *	internal Integrity Measurement Architecture (IMA) definitions
+ */
+
+#ifndef __LINUX_IMA_H
+#define __LINUX_IMA_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/security.h>
+#include <linux/hash.h>
+#include <linux/tpm.h>
+#include <linux/audit.h>
+
+enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII };
+enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
+
+/* digest size for IMA, fits SHA1 or MD5 */
+#define IMA_DIGEST_SIZE		20
+#define IMA_EVENT_NAME_LEN_MAX	255
+
+#define IMA_HASH_BITS 9
+#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
+
+/* set during initialization */
+extern int ima_initialized;
+extern int ima_used_chip;
+extern char *ima_hash;
+
+/* IMA inode template definition */
+struct ima_template_data {
+	u8 digest[IMA_DIGEST_SIZE];	/* sha1/md5 measurement hash */
+	char file_name[IMA_EVENT_NAME_LEN_MAX + 1];	/* name + \0 */
+};
+
+struct ima_template_entry {
+	u8 digest[IMA_DIGEST_SIZE];	/* sha1 or md5 measurement hash */
+	char *template_name;
+	int template_len;
+	struct ima_template_data template;
+};
+
+struct ima_queue_entry {
+	struct hlist_node hnext;	/* place in hash collision list */
+	struct list_head later;		/* place in ima_measurements list */
+	struct ima_template_entry *entry;
+};
+extern struct list_head ima_measurements;	/* list of all measurements */
+
+/* declarations */
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			 const unsigned char *fname, const char *op,
+			 const char *cause, int result, int info);
+
+/* Internal IMA function definitions */
+void ima_iintcache_init(void);
+int ima_init(void);
+int ima_add_template_entry(struct ima_template_entry *entry, int violation,
+			   const char *op, struct inode *inode);
+int ima_calc_hash(struct file *file, char *digest);
+int ima_calc_template_hash(int template_len, void *template, char *digest);
+int ima_calc_boot_aggregate(char *digest);
+void ima_add_violation(struct inode *inode, const unsigned char *filename,
+		       const char *op, const char *cause);
+
+/*
+ * used to protect h_table and sha_table
+ */
+extern spinlock_t ima_queue_lock;
+
+struct ima_h_table {
+	atomic_long_t len;	/* number of stored measurements in the list */
+	atomic_long_t violations;
+	struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
+};
+extern struct ima_h_table ima_htable;
+
+static inline unsigned long ima_hash_key(u8 *digest)
+{
+	return hash_long(*digest, IMA_HASH_BITS);
+}
+
+/* iint cache flags */
+#define IMA_MEASURED		1
+
+/* integrity data associated with an inode */
+struct ima_iint_cache {
+	u64 version;		/* track inode changes */
+	unsigned long flags;
+	u8 digest[IMA_DIGEST_SIZE];
+	struct mutex mutex;	/* protects: version, flags, digest */
+	long readcount;		/* measured files readcount */
+	long writecount;	/* measured files writecount */
+	struct kref refcount;	/* ima_iint_cache reference count */
+	struct rcu_head rcu;
+};
+
+/* LIM API function definitions */
+int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
+		     int mask, int function);
+int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file);
+void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
+			   const unsigned char *filename);
+int ima_store_template(struct ima_template_entry *entry, int violation,
+		       struct inode *inode);
+
+/* radix tree calls to lookup, insert, delete
+ * integrity data associated with an inode.
+ */
+struct ima_iint_cache *ima_iint_insert(struct inode *inode);
+struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
+struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode);
+void ima_iint_delete(struct inode *inode);
+void iint_free(struct kref *kref);
+void iint_rcu_free(struct rcu_head *rcu);
+
+/* IMA policy related functions */
+enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK };
+
+int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
+void ima_init_policy(void);
+void ima_update_policy(void);
+#endif
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
new file mode 100644
index 00000000000..a148a25804f
--- /dev/null
+++ b/security/integrity/ima/ima_api.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ *
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_api.c
+ *	Implements must_measure, collect_measurement, store_measurement,
+ *	and store_template.
+ */
+#include <linux/module.h>
+
+#include "ima.h"
+static char *IMA_TEMPLATE_NAME = "ima";
+
+/*
+ * ima_store_template - store ima template measurements
+ *
+ * Calculate the hash of a template entry, add the template entry
+ * to an ordered list of measurement entries maintained inside the kernel,
+ * and also update the aggregate integrity value (maintained inside the
+ * configured TPM PCR) over the hashes of the current list of measurement
+ * entries.
+ *
+ * Applications retrieve the current kernel-held measurement list through
+ * the securityfs entries in /sys/kernel/security/ima. The signed aggregate
+ * TPM PCR (called quote) can be retrieved using a TPM user space library
+ * and is used to validate the measurement list.
+ *
+ * Returns 0 on success, error code otherwise
+ */
+int ima_store_template(struct ima_template_entry *entry,
+		       int violation, struct inode *inode)
+{
+	const char *op = "add_template_measure";
+	const char *audit_cause = "hashing_error";
+	int result;
+
+	memset(entry->digest, 0, sizeof(entry->digest));
+	entry->template_name = IMA_TEMPLATE_NAME;
+	entry->template_len = sizeof(entry->template);
+
+	if (!violation) {
+		result = ima_calc_template_hash(entry->template_len,
+						&entry->template,
+						entry->digest);
+		if (result < 0) {
+			integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
+					    entry->template_name, op,
+					    audit_cause, result, 0);
+			return result;
+		}
+	}
+	result = ima_add_template_entry(entry, violation, op, inode);
+	return result;
+}
+
+/*
+ * ima_add_violation - add violation to measurement list.
+ *
+ * Violations are flagged in the measurement list with zero hash values.
+ * By extending the PCR with 0xFF's instead of with zeroes, the PCR
+ * value is invalidated.
+ */
+void ima_add_violation(struct inode *inode, const unsigned char *filename,
+		       const char *op, const char *cause)
+{
+	struct ima_template_entry *entry;
+	int violation = 1;
+	int result;
+
+	/* can overflow, only indicator */
+	atomic_long_inc(&ima_htable.violations);
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		result = -ENOMEM;
+		goto err_out;
+	}
+	memset(&entry->template, 0, sizeof(entry->template));
+	strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+	result = ima_store_template(entry, violation, inode);
+	if (result < 0)
+		kfree(entry);
+err_out:
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
+			    op, cause, result, 0);
+}
+
+/**
+ * ima_must_measure - measure decision based on policy.
+ * @inode: pointer to inode to measure
+ * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
+ * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP)
+ *
+ * The policy is defined in terms of keypairs:
+ * 		subj=, obj=, type=, func=, mask=, fsmagic=
+ *	subj,obj, and type: are LSM specific.
+ * 	func: PATH_CHECK | BPRM_CHECK | FILE_MMAP
+ * 	mask: contains the permission mask
+ *	fsmagic: hex value
+ *
+ * Must be called with iint->mutex held.
+ *
+ * Return 0 to measure. Return 1 if already measured.
+ * For matching a DONT_MEASURE policy, no policy, or other
+ * error, return an error code.
+*/
+int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
+		     int mask, int function)
+{
+	int must_measure;
+
+	if (iint->flags & IMA_MEASURED)
+		return 1;
+
+	must_measure = ima_match_policy(inode, function, mask);
+	return must_measure ? 0 : -EACCES;
+}
+
+/*
+ * ima_collect_measurement - collect file measurement
+ *
+ * Calculate the file hash, if it doesn't already exist,
+ * storing the measurement and i_version in the iint.
+ *
+ * Must be called with iint->mutex held.
+ *
+ * Return 0 on success, error code otherwise
+ */
+int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file)
+{
+	int result = -EEXIST;
+
+	if (!(iint->flags & IMA_MEASURED)) {
+		u64 i_version = file->f_dentry->d_inode->i_version;
+
+		memset(iint->digest, 0, IMA_DIGEST_SIZE);
+		result = ima_calc_hash(file, iint->digest);
+		if (!result)
+			iint->version = i_version;
+	}
+	return result;
+}
+
+/*
+ * ima_store_measurement - store file measurement
+ *
+ * Create an "ima" template and then store the template by calling
+ * ima_store_template.
+ *
+ * We only get here if the inode has not already been measured,
+ * but the measurement could already exist:
+ * 	- multiple copies of the same file on either the same or
+ *	  different filesystems.
+ *	- the inode was previously flushed as well as the iint info,
+ *	  containing the hashing info.
+ *
+ * Must be called with iint->mutex held.
+ */
+void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
+			   const unsigned char *filename)
+{
+	const char *op = "add_template_measure";
+	const char *audit_cause = "ENOMEM";
+	int result = -ENOMEM;
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ima_template_entry *entry;
+	int violation = 0;
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
+				    op, audit_cause, result, 0);
+		return;
+	}
+	memset(&entry->template, 0, sizeof(entry->template));
+	memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
+	strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+
+	result = ima_store_template(entry, violation, inode);
+	if (!result)
+		iint->flags |= IMA_MEASURED;
+	else
+		kfree(entry);
+}
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
new file mode 100644
index 00000000000..8a0f1e23ccf
--- /dev/null
+++ b/security/integrity/ima/ima_audit.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * File: integrity_audit.c
+ * 	Audit calls for the integrity subsystem
+ */
+
+#include <linux/fs.h>
+#include <linux/audit.h>
+#include "ima.h"
+
+static int ima_audit;
+
+#ifdef CONFIG_IMA_AUDIT
+
+/* ima_audit_setup - enable informational auditing messages */
+static int __init ima_audit_setup(char *str)
+{
+	unsigned long audit;
+	int rc;
+	char *op;
+
+	rc = strict_strtoul(str, 0, &audit);
+	if (rc || audit > 1)
+		printk(KERN_INFO "ima: invalid ima_audit value\n");
+	else
+		ima_audit = audit;
+	op = ima_audit ? "ima_audit_enabled" : "ima_audit_not_enabled";
+	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, NULL, op, 0, 0);
+	return 1;
+}
+__setup("ima_audit=", ima_audit_setup);
+#endif
+
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			 const unsigned char *fname, const char *op,
+			 const char *cause, int result, int audit_info)
+{
+	struct audit_buffer *ab;
+
+	if (!ima_audit && audit_info == 1) /* Skip informational messages */
+		return;
+
+	ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
+	audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u",
+			 current->pid, current->cred->uid,
+			 audit_get_loginuid(current));
+	audit_log_task_context(ab);
+	switch (audit_msgno) {
+	case AUDIT_INTEGRITY_DATA:
+	case AUDIT_INTEGRITY_METADATA:
+	case AUDIT_INTEGRITY_PCR:
+		audit_log_format(ab, " op=%s cause=%s", op, cause);
+		break;
+	case AUDIT_INTEGRITY_HASH:
+		audit_log_format(ab, " op=%s hash=%s", op, cause);
+		break;
+	case AUDIT_INTEGRITY_STATUS:
+	default:
+		audit_log_format(ab, " op=%s", op);
+	}
+	audit_log_format(ab, " comm=");
+	audit_log_untrustedstring(ab, current->comm);
+	if (fname) {
+		audit_log_format(ab, " name=");
+		audit_log_untrustedstring(ab, fname);
+	}
+	if (inode)
+		audit_log_format(ab, " dev=%s ino=%lu",
+				 inode->i_sb->s_id, inode->i_ino);
+	audit_log_format(ab, " res=%d", result);
+	audit_log_end(ab);
+}
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
new file mode 100644
index 00000000000..c2a46e40999
--- /dev/null
+++ b/security/integrity/ima/ima_crypto.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Mimi Zohar <zohar@us.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * File: ima_crypto.c
+ * 	Calculates md5/sha1 file hash, template hash, boot-aggreate hash
+ */
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/err.h>
+#include "ima.h"
+
+static int init_desc(struct hash_desc *desc)
+{
+	int rc;
+
+	desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc->tfm)) {
+		pr_info("failed to load %s transform: %ld\n",
+			ima_hash, PTR_ERR(desc->tfm));
+		rc = PTR_ERR(desc->tfm);
+		return rc;
+	}
+	desc->flags = 0;
+	rc = crypto_hash_init(desc);
+	if (rc)
+		crypto_free_hash(desc->tfm);
+	return rc;
+}
+
+/*
+ * Calculate the MD5/SHA1 file digest
+ */
+int ima_calc_hash(struct file *file, char *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	loff_t i_size;
+	char *rbuf;
+	int rc, offset = 0;
+
+	rc = init_desc(&desc);
+	if (rc != 0)
+		return rc;
+
+	rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!rbuf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	i_size = i_size_read(file->f_dentry->d_inode);
+	while (offset < i_size) {
+		int rbuf_len;
+
+		rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
+		if (rbuf_len < 0) {
+			rc = rbuf_len;
+			break;
+		}
+		offset += rbuf_len;
+		sg_set_buf(sg, rbuf, rbuf_len);
+
+		rc = crypto_hash_update(&desc, sg, rbuf_len);
+		if (rc)
+			break;
+	}
+	kfree(rbuf);
+	if (!rc)
+		rc = crypto_hash_final(&desc, digest);
+out:
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
+
+/*
+ * Calculate the hash of a given template
+ */
+int ima_calc_template_hash(int template_len, void *template, char *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	int rc;
+
+	rc = init_desc(&desc);
+	if (rc != 0)
+		return rc;
+
+	sg_set_buf(sg, template, template_len);
+	rc = crypto_hash_update(&desc, sg, template_len);
+	if (!rc)
+		rc = crypto_hash_final(&desc, digest);
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
+
+static void ima_pcrread(int idx, u8 *pcr)
+{
+	if (!ima_used_chip)
+		return;
+
+	if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
+		pr_err("Error Communicating to TPM chip\n");
+}
+
+/*
+ * Calculate the boot aggregate hash
+ */
+int ima_calc_boot_aggregate(char *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg;
+	u8 pcr_i[IMA_DIGEST_SIZE];
+	int rc, i;
+
+	rc = init_desc(&desc);
+	if (rc != 0)
+		return rc;
+
+	/* cumulative sha1 over tpm registers 0-7 */
+	for (i = TPM_PCR0; i < TPM_PCR8; i++) {
+		ima_pcrread(i, pcr_i);
+		/* now accumulate with current aggregate */
+		sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE);
+		rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE);
+	}
+	if (!rc)
+		crypto_hash_final(&desc, digest);
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
new file mode 100644
index 00000000000..750db3c993a
--- /dev/null
+++ b/security/integrity/ima/ima_iint.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ *
+ * Authors:
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_iint.c
+ * 	- implements the IMA hooks: ima_inode_alloc, ima_inode_free
+ *	- cache integrity information associated with an inode
+ *	  using a radix tree.
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/radix-tree.h>
+#include "ima.h"
+
+#define ima_iint_delete ima_inode_free
+
+RADIX_TREE(ima_iint_store, GFP_ATOMIC);
+DEFINE_SPINLOCK(ima_iint_lock);
+
+static struct kmem_cache *iint_cache __read_mostly;
+
+/* ima_iint_find_get - return the iint associated with an inode
+ *
+ * ima_iint_find_get gets a reference to the iint. Caller must
+ * remember to put the iint reference.
+ */
+struct ima_iint_cache *ima_iint_find_get(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+
+	rcu_read_lock();
+	iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode);
+	if (!iint)
+		goto out;
+	kref_get(&iint->refcount);
+out:
+	rcu_read_unlock();
+	return iint;
+}
+
+/* Allocate memory for the iint associated with the inode
+ * from the iint_cache slab, initialize the iint, and
+ * insert it into the radix tree.
+ *
+ * On success return a pointer to the iint; on failure return NULL.
+ */
+struct ima_iint_cache *ima_iint_insert(struct inode *inode)
+{
+	struct ima_iint_cache *iint = NULL;
+	int rc = 0;
+
+	if (!ima_initialized)
+		return iint;
+	iint = kmem_cache_alloc(iint_cache, GFP_KERNEL);
+	if (!iint)
+		return iint;
+
+	rc = radix_tree_preload(GFP_KERNEL);
+	if (rc < 0)
+		goto out;
+
+	spin_lock(&ima_iint_lock);
+	rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
+	spin_unlock(&ima_iint_lock);
+out:
+	if (rc < 0) {
+		kmem_cache_free(iint_cache, iint);
+		if (rc == -EEXIST) {
+			iint = radix_tree_lookup(&ima_iint_store,
+						 (unsigned long)inode);
+		} else
+			iint = NULL;
+	}
+	radix_tree_preload_end();
+	return iint;
+}
+
+/**
+ * ima_inode_alloc - allocate an iint associated with an inode
+ * @inode: pointer to the inode
+ *
+ * Return 0 on success, 1 on failure.
+ */
+int ima_inode_alloc(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+
+	if (!ima_initialized)
+		return 0;
+
+	iint = ima_iint_insert(inode);
+	if (!iint)
+		return 1;
+	return 0;
+}
+
+/* ima_iint_find_insert_get - get the iint associated with an inode
+ *
+ * Most insertions are done at inode_alloc, except those allocated
+ * before late_initcall. When the iint does not exist, allocate it,
+ * initialize and insert it, and increment the iint refcount.
+ *
+ * (Can't initialize at security_initcall before any inodes are
+ * allocated, got to wait at least until proc_init.)
+ *
+ *  Return the iint.
+ */
+struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
+{
+	struct ima_iint_cache *iint = NULL;
+
+	iint = ima_iint_find_get(inode);
+	if (iint)
+		return iint;
+
+	iint = ima_iint_insert(inode);
+	if (iint)
+		kref_get(&iint->refcount);
+
+	return iint;
+}
+
+/* iint_free - called when the iint refcount goes to zero */
+void iint_free(struct kref *kref)
+{
+	struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
+						   refcount);
+	iint->version = 0;
+	iint->flags = 0UL;
+	kref_set(&iint->refcount, 1);
+	kmem_cache_free(iint_cache, iint);
+}
+
+void iint_rcu_free(struct rcu_head *rcu_head)
+{
+	struct ima_iint_cache *iint = container_of(rcu_head,
+						   struct ima_iint_cache, rcu);
+	kref_put(&iint->refcount, iint_free);
+}
+
+/**
+ * ima_iint_delete - called on integrity_inode_free
+ * @inode: pointer to the inode
+ *
+ * Free the integrity information(iint) associated with an inode.
+ */
+void ima_iint_delete(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+
+	if (!ima_initialized)
+		return;
+	spin_lock(&ima_iint_lock);
+	iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
+	spin_unlock(&ima_iint_lock);
+	if (iint)
+		call_rcu(&iint->rcu, iint_rcu_free);
+}
+
+static void init_once(void *foo)
+{
+	struct ima_iint_cache *iint = foo;
+
+	memset(iint, 0, sizeof *iint);
+	iint->version = 0;
+	iint->flags = 0UL;
+	mutex_init(&iint->mutex);
+	iint->readcount = 0;
+	iint->writecount = 0;
+	kref_set(&iint->refcount, 1);
+}
+
+void ima_iintcache_init(void)
+{
+	iint_cache =
+	    kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
+			      SLAB_PANIC, init_once);
+}
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
new file mode 100644
index 00000000000..e0f02e328d7
--- /dev/null
+++ b/security/integrity/ima/ima_init.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer      <sailer@watson.ibm.com>
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Mimi Zohar         <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_init.c
+ *             initialization and cleanup functions
+ */
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/err.h>
+#include "ima.h"
+
+/* name for boot aggregate entry */
+static char *boot_aggregate_name = "boot_aggregate";
+int ima_used_chip;
+
+/* Add the boot aggregate to the IMA measurement list and extend
+ * the PCR register.
+ *
+ * Calculate the boot aggregate, a SHA1 over tpm registers 0-7,
+ * assuming a TPM chip exists, and zeroes if the TPM chip does not
+ * exist.  Add the boot aggregate measurement to the measurement
+ * list and extend the PCR register.
+ *
+ * If a tpm chip does not exist, indicate the core root of trust is
+ * not hardware based by invalidating the aggregate PCR value.
+ * (The aggregate PCR value is invalidated by adding one value to
+ * the measurement list and extending the aggregate PCR value with
+ * a different value.) Violations add a zero entry to the measurement
+ * list and extend the aggregate PCR value with ff...ff's.
+ */
+static void ima_add_boot_aggregate(void)
+{
+	struct ima_template_entry *entry;
+	const char *op = "add_boot_aggregate";
+	const char *audit_cause = "ENOMEM";
+	int result = -ENOMEM;
+	int violation = 1;
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		goto err_out;
+
+	memset(&entry->template, 0, sizeof(entry->template));
+	strncpy(entry->template.file_name, boot_aggregate_name,
+		IMA_EVENT_NAME_LEN_MAX);
+	if (ima_used_chip) {
+		violation = 0;
+		result = ima_calc_boot_aggregate(entry->template.digest);
+		if (result < 0) {
+			audit_cause = "hashing_error";
+			kfree(entry);
+			goto err_out;
+		}
+	}
+	result = ima_store_template(entry, violation, NULL);
+	if (result < 0)
+		kfree(entry);
+	return;
+err_out:
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,
+			    audit_cause, result, 0);
+}
+
+int ima_init(void)
+{
+	u8 pcr_i[IMA_DIGEST_SIZE];
+	int rc;
+
+	ima_used_chip = 0;
+	rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i);
+	if (rc == 0)
+		ima_used_chip = 1;
+
+	if (!ima_used_chip)
+		pr_info("No TPM chip found, activating TPM-bypass!\n");
+
+	ima_add_boot_aggregate();	/* boot aggregate must be first entry */
+	ima_init_policy();
+	return 0;
+}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
new file mode 100644
index 00000000000..53cee4c512c
--- /dev/null
+++ b/security/integrity/ima/ima_main.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Serge Hallyn <serue@us.ibm.com>
+ * Kylene Hall <kylene@us.ibm.com>
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_main.c
+ *             implements the IMA hooks: ima_bprm_check, ima_file_mmap,
+ *             and ima_path_check.
+ */
+#include <linux/module.h>
+#include <linux/file.h>
+#include <linux/binfmts.h>
+#include <linux/mount.h>
+#include <linux/mman.h>
+
+#include "ima.h"
+
+int ima_initialized;
+
+char *ima_hash = "sha1";
+static int __init hash_setup(char *str)
+{
+	const char *op = "hash_setup";
+	const char *hash = "sha1";
+	int result = 0;
+	int audit_info = 0;
+
+	if (strncmp(str, "md5", 3) == 0) {
+		hash = "md5";
+		ima_hash = str;
+	} else if (strncmp(str, "sha1", 4) != 0) {
+		hash = "invalid_hash_type";
+		result = 1;
+	}
+	integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash,
+			    result, audit_info);
+	return 1;
+}
+__setup("ima_hash=", hash_setup);
+
+/**
+ * ima_file_free - called on __fput()
+ * @file: pointer to file structure being freed
+ *
+ * Flag files that changed, based on i_version;
+ * and decrement the iint readcount/writecount.
+ */
+void ima_file_free(struct file *file)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ima_iint_cache *iint;
+
+	if (!ima_initialized || !S_ISREG(inode->i_mode))
+		return;
+	iint = ima_iint_find_get(inode);
+	if (!iint)
+		return;
+
+	mutex_lock(&iint->mutex);
+	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		iint->readcount--;
+
+	if (file->f_mode & FMODE_WRITE) {
+		iint->writecount--;
+		if (iint->writecount == 0) {
+			if (iint->version != inode->i_version)
+				iint->flags &= ~IMA_MEASURED;
+		}
+	}
+	mutex_unlock(&iint->mutex);
+	kref_put(&iint->refcount, iint_free);
+}
+
+/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
+ *
+ * When opening a file for read, if the file is already open for write,
+ * the file could change, resulting in a file measurement error.
+ *
+ * Opening a file for write, if the file is already open for read, results
+ * in a time of measure, time of use (ToMToU) error.
+ *
+ * In either case invalidate the PCR.
+ */
+enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
+static void ima_read_write_check(enum iint_pcr_error error,
+				 struct ima_iint_cache *iint,
+				 struct inode *inode,
+				 const unsigned char *filename)
+{
+	switch (error) {
+	case TOMTOU:
+		if (iint->readcount > 0)
+			ima_add_violation(inode, filename, "invalid_pcr",
+					  "ToMToU");
+		break;
+	case OPEN_WRITERS:
+		if (iint->writecount > 0)
+			ima_add_violation(inode, filename, "invalid_pcr",
+					  "open_writers");
+		break;
+	}
+}
+
+static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
+				const unsigned char *filename)
+{
+	int rc = 0;
+
+	if (IS_ERR(file)) {
+		pr_info("%s dentry_open failed\n", filename);
+		return rc;
+	}
+	iint->readcount++;
+
+	rc = ima_collect_measurement(iint, file);
+	if (!rc)
+		ima_store_measurement(iint, file, filename);
+	return rc;
+}
+
+/**
+ * ima_path_check - based on policy, collect/store measurement.
+ * @path: contains a pointer to the path to be measured
+ * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
+ *
+ * Measure the file being open for readonly, based on the
+ * ima_must_measure() policy decision.
+ *
+ * Keep read/write counters for all files, but only
+ * invalidate the PCR for measured files:
+ * 	- Opening a file for write when already open for read,
+ *	  results in a time of measure, time of use (ToMToU) error.
+ *	- Opening a file for read when already open for write,
+ * 	  could result in a file measurement error.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+int ima_path_check(struct path *path, int mask)
+{
+	struct inode *inode = path->dentry->d_inode;
+	struct ima_iint_cache *iint;
+	struct file *file = NULL;
+	int rc;
+
+	if (!ima_initialized || !S_ISREG(inode->i_mode))
+		return 0;
+	iint = ima_iint_find_insert_get(inode);
+	if (!iint)
+		return 0;
+
+	mutex_lock(&iint->mutex);
+	if ((mask & MAY_WRITE) || (mask == 0))
+		iint->writecount++;
+	else if (mask & (MAY_READ | MAY_EXEC))
+		iint->readcount++;
+
+	rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
+	if (rc < 0)
+		goto out;
+
+	if ((mask & MAY_WRITE) || (mask == 0))
+		ima_read_write_check(TOMTOU, iint, inode,
+				     path->dentry->d_name.name);
+
+	if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
+		goto out;
+
+	ima_read_write_check(OPEN_WRITERS, iint, inode,
+			     path->dentry->d_name.name);
+	if (!(iint->flags & IMA_MEASURED)) {
+		struct dentry *dentry = dget(path->dentry);
+		struct vfsmount *mnt = mntget(path->mnt);
+
+		file = dentry_open(dentry, mnt, O_RDONLY, current->cred);
+		rc = get_path_measurement(iint, file, dentry->d_name.name);
+	}
+out:
+	mutex_unlock(&iint->mutex);
+	if (file)
+		fput(file);
+	kref_put(&iint->refcount, iint_free);
+	return 0;
+}
+
+static int process_measurement(struct file *file, const unsigned char *filename,
+			       int mask, int function)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ima_iint_cache *iint;
+	int rc;
+
+	if (!ima_initialized || !S_ISREG(inode->i_mode))
+		return 0;
+	iint = ima_iint_find_insert_get(inode);
+	if (!iint)
+		return -ENOMEM;
+
+	mutex_lock(&iint->mutex);
+	rc = ima_must_measure(iint, inode, mask, function);
+	if (rc != 0)
+		goto out;
+
+	rc = ima_collect_measurement(iint, file);
+	if (!rc)
+		ima_store_measurement(iint, file, filename);
+out:
+	mutex_unlock(&iint->mutex);
+	kref_put(&iint->refcount, iint_free);
+	return rc;
+}
+
+/**
+ * ima_file_mmap - based on policy, collect/store measurement.
+ * @file: pointer to the file to be measured (May be NULL)
+ * @prot: contains the protection that will be applied by the kernel.
+ *
+ * Measure files being mmapped executable based on the ima_must_measure()
+ * policy decision.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+int ima_file_mmap(struct file *file, unsigned long prot)
+{
+	int rc;
+
+	if (!file)
+		return 0;
+	if (prot & PROT_EXEC)
+		rc = process_measurement(file, file->f_dentry->d_name.name,
+					 MAY_EXEC, FILE_MMAP);
+	return 0;
+}
+
+/**
+ * ima_bprm_check - based on policy, collect/store measurement.
+ * @bprm: contains the linux_binprm structure
+ *
+ * The OS protects against an executable file, already open for write,
+ * from being executed in deny_write_access() and an executable file,
+ * already open for execute, from being modified in get_write_access().
+ * So we can be certain that what we verify and measure here is actually
+ * what is being executed.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+int ima_bprm_check(struct linux_binprm *bprm)
+{
+	int rc;
+
+	rc = process_measurement(bprm->file, bprm->filename,
+				 MAY_EXEC, BPRM_CHECK);
+	return 0;
+}
+
+static int __init init_ima(void)
+{
+	int error;
+
+	ima_iintcache_init();
+	error = ima_init();
+	ima_initialized = 1;
+	return error;
+}
+
+late_initcall(init_ima);	/* Start IMA after the TPM is available */
+
+MODULE_DESCRIPTION("Integrity Measurement Architecture");
+MODULE_LICENSE("GPL");
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
new file mode 100644
index 00000000000..7c3d1ffb147
--- /dev/null
+++ b/security/integrity/ima/ima_policy.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 IBM Corporation
+ * Author: Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * ima_policy.c
+ * 	- initialize default measure policy rules
+ *
+ */
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/audit.h>
+#include <linux/security.h>
+#include <linux/magic.h>
+
+#include "ima.h"
+
+/* flags definitions */
+#define IMA_FUNC 	0x0001
+#define IMA_MASK 	0x0002
+#define IMA_FSMAGIC	0x0004
+#define IMA_UID		0x0008
+
+enum ima_action { DONT_MEASURE, MEASURE };
+
+struct ima_measure_rule_entry {
+	struct list_head list;
+	enum ima_action action;
+	unsigned int flags;
+	enum ima_hooks func;
+	int mask;
+	unsigned long fsmagic;
+	uid_t uid;
+};
+
+static struct ima_measure_rule_entry default_rules[] = {
+	{.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,
+	 .flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,
+	 .flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC},
+	{.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
+	 .flags = IMA_FUNC | IMA_MASK},
+	{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
+	 .flags = IMA_FUNC | IMA_MASK},
+	{.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0,
+	 .flags = IMA_FUNC | IMA_MASK | IMA_UID}
+};
+
+static LIST_HEAD(measure_default_rules);
+static struct list_head *ima_measure;
+
+/**
+ * ima_match_rules - determine whether an inode matches the measure rule.
+ * @rule: a pointer to a rule
+ * @inode: a pointer to an inode
+ * @func: LIM hook identifier
+ * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
+ *
+ * Returns true on rule match, false on failure.
+ */
+static bool ima_match_rules(struct ima_measure_rule_entry *rule,
+			    struct inode *inode, enum ima_hooks func, int mask)
+{
+	struct task_struct *tsk = current;
+
+	if ((rule->flags & IMA_FUNC) && rule->func != func)
+		return false;
+	if ((rule->flags & IMA_MASK) && rule->mask != mask)
+		return false;
+	if ((rule->flags & IMA_FSMAGIC)
+	    && rule->fsmagic != inode->i_sb->s_magic)
+		return false;
+	if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
+		return false;
+	return true;
+}
+
+/**
+ * ima_match_policy - decision based on LSM and other conditions
+ * @inode: pointer to an inode for which the policy decision is being made
+ * @func: IMA hook identifier
+ * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
+ *
+ * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
+ * conditions.
+ *
+ * (There is no need for locking when walking the policy list,
+ * as elements in the list are never deleted, nor does the list
+ * change.)
+ */
+int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
+{
+	struct ima_measure_rule_entry *entry;
+
+	list_for_each_entry(entry, ima_measure, list) {
+		bool rc;
+
+		rc = ima_match_rules(entry, inode, func, mask);
+		if (rc)
+			return entry->action;
+	}
+	return 0;
+}
+
+/**
+ * ima_init_policy - initialize the default measure rules.
+ *
+ * (Could use the default_rules directly, but in policy patch
+ * ima_measure points to either the measure_default_rules or the
+ * the new measure_policy_rules.)
+ */
+void ima_init_policy(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(default_rules); i++)
+		list_add_tail(&default_rules[i].list, &measure_default_rules);
+	ima_measure = &measure_default_rules;
+}
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
new file mode 100644
index 00000000000..7ec94314ac0
--- /dev/null
+++ b/security/integrity/ima/ima_queue.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Serge Hallyn <serue@us.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * File: ima_queue.c
+ *       Implements queues that store template measurements and
+ *       maintains aggregate over the stored measurements
+ *       in the pre-configured TPM PCR (if available).
+ *       The measurement list is append-only. No entry is
+ *       ever removed or changed during the boot-cycle.
+ */
+#include <linux/module.h>
+#include <linux/rculist.h>
+#include "ima.h"
+
+LIST_HEAD(ima_measurements);	/* list of all measurements */
+
+/* key: inode (before secure-hashing a file) */
+struct ima_h_table ima_htable = {
+	.len = ATOMIC_LONG_INIT(0),
+	.violations = ATOMIC_LONG_INIT(0),
+	.queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT
+};
+
+/* mutex protects atomicity of extending measurement list
+ * and extending the TPM PCR aggregate. Since tpm_extend can take
+ * long (and the tpm driver uses a mutex), we can't use the spinlock.
+ */
+static DEFINE_MUTEX(ima_extend_list_mutex);
+
+/* lookup up the digest value in the hash table, and return the entry */
+static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value)
+{
+	struct ima_queue_entry *qe, *ret = NULL;
+	unsigned int key;
+	struct hlist_node *pos;
+	int rc;
+
+	key = ima_hash_key(digest_value);
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(qe, pos, &ima_htable.queue[key], hnext) {
+		rc = memcmp(qe->entry->digest, digest_value, IMA_DIGEST_SIZE);
+		if (rc == 0) {
+			ret = qe;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	return ret;
+}
+
+/* ima_add_template_entry helper function:
+ * - Add template entry to measurement list and hash table.
+ *
+ * (Called with ima_extend_list_mutex held.)
+ */
+static int ima_add_digest_entry(struct ima_template_entry *entry)
+{
+	struct ima_queue_entry *qe;
+	unsigned int key;
+
+	qe = kmalloc(sizeof(*qe), GFP_KERNEL);
+	if (qe == NULL) {
+		pr_err("OUT OF MEMORY ERROR creating queue entry.\n");
+		return -ENOMEM;
+	}
+	qe->entry = entry;
+
+	INIT_LIST_HEAD(&qe->later);
+	list_add_tail_rcu(&qe->later, &ima_measurements);
+
+	atomic_long_inc(&ima_htable.len);
+	key = ima_hash_key(entry->digest);
+	hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+	return 0;
+}
+
+static int ima_pcr_extend(const u8 *hash)
+{
+	int result = 0;
+
+	if (!ima_used_chip)
+		return result;
+
+	result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
+	if (result != 0)
+		pr_err("Error Communicating to TPM chip\n");
+	return result;
+}
+
+/* Add template entry to the measurement list and hash table,
+ * and extend the pcr.
+ */
+int ima_add_template_entry(struct ima_template_entry *entry, int violation,
+			   const char *op, struct inode *inode)
+{
+	u8 digest[IMA_DIGEST_SIZE];
+	const char *audit_cause = "hash_added";
+	int audit_info = 1;
+	int result = 0;
+
+	mutex_lock(&ima_extend_list_mutex);
+	if (!violation) {
+		memcpy(digest, entry->digest, sizeof digest);
+		if (ima_lookup_digest_entry(digest)) {
+			audit_cause = "hash_exists";
+			goto out;
+		}
+	}
+
+	result = ima_add_digest_entry(entry);
+	if (result < 0) {
+		audit_cause = "ENOMEM";
+		audit_info = 0;
+		goto out;
+	}
+
+	if (violation)		/* invalidate pcr */
+		memset(digest, 0xff, sizeof digest);
+
+	result = ima_pcr_extend(digest);
+	if (result != 0) {
+		audit_cause = "TPM error";
+		audit_info = 0;
+	}
+out:
+	mutex_unlock(&ima_extend_list_mutex);
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, entry->template_name,
+			    op, audit_cause, result, audit_info);
+	return result;
+}
-- 
cgit v1.2.3-70-g09d2


From 4af4662fa4a9dc62289c580337ae2506339c4729 Mon Sep 17 00:00:00 2001
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date: Wed, 4 Feb 2009 09:07:00 -0500
Subject: integrity: IMA policy

Support for a user loadable policy through securityfs
with support for LSM specific policy data.
- free invalid rule in ima_parse_add_rule()

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 Documentation/ABI/testing/ima_policy |  61 ++++++++
 security/integrity/ima/Kconfig       |   6 +
 security/integrity/ima/ima.h         |  24 +++
 security/integrity/ima/ima_fs.c      |  67 +++++++-
 security/integrity/ima/ima_policy.c  | 293 ++++++++++++++++++++++++++++++++++-
 5 files changed, 447 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/ABI/testing/ima_policy

(limited to 'Documentation')

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
new file mode 100644
index 00000000000..6434f0df012
--- /dev/null
+++ b/Documentation/ABI/testing/ima_policy
@@ -0,0 +1,61 @@
+What:		security/ima/policy
+Date:		May 2008
+Contact:	Mimi Zohar <zohar@us.ibm.com>
+Description:
+		The Trusted Computing Group(TCG) runtime Integrity
+		Measurement Architecture(IMA) maintains a list of hash
+		values of executables and other sensitive system files
+		loaded into the run-time of this system.  At runtime,
+		the policy can be constrained based on LSM specific data.
+		Policies are loaded into the securityfs file ima/policy
+		by opening the file, writing the rules one at a time and
+		then closing the file.  The new policy takes effect after
+		the file ima/policy is closed.
+
+		rule format: action [condition ...]
+
+		action: measure | dont_measure
+		condition:= base | lsm
+			base:	[[func=] [mask=] [fsmagic=] [uid=]]
+			lsm:	[[subj_user=] [subj_role=] [subj_type=]
+				 [obj_user=] [obj_role=] [obj_type=]]
+
+		base: 	func:= [BPRM_CHECK][FILE_MMAP][INODE_PERMISSION]
+			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
+			fsmagic:= hex value
+			uid:= decimal value
+		lsm:  	are LSM specific
+
+		default policy:
+			# PROC_SUPER_MAGIC
+			dont_measure fsmagic=0x9fa0
+			# SYSFS_MAGIC
+			dont_measure fsmagic=0x62656572
+			# DEBUGFS_MAGIC
+			dont_measure fsmagic=0x64626720
+			# TMPFS_MAGIC
+			dont_measure fsmagic=0x01021994
+			# SECURITYFS_MAGIC
+			dont_measure fsmagic=0x73636673
+
+			measure func=BPRM_CHECK
+			measure func=FILE_MMAP mask=MAY_EXEC
+			measure func=INODE_PERM mask=MAY_READ uid=0
+
+		The default policy measures all executables in bprm_check,
+		all files mmapped executable in file_mmap, and all files
+		open for read by root in inode_permission.
+
+		Examples of LSM specific definitions:
+
+		SELinux:
+			# SELINUX_MAGIC
+			dont_measure fsmagic=0xF97CFF8C
+
+			dont_measure obj_type=var_log_t
+			dont_measure obj_type=auditd_log_t
+			measure subj_user=system_u func=INODE_PERM mask=MAY_READ
+			measure subj_role=system_r func=INODE_PERM mask=MAY_READ
+
+		Smack:
+			measure subj_user=_ func=INODE_PERM mask=MAY_READ
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 2a761c8ac99..3d2b6ee778a 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -47,3 +47,9 @@ config IMA_AUDIT
 	  auditing messages can be enabled with 'ima_audit=1' on
 	  the kernel command line.
 
+config IMA_LSM_RULES
+	bool
+	depends on IMA && (SECURITY_SELINUX || SECURITY_SMACK)
+	default y
+	help
+	  Disabling this option will disregard LSM based policy rules
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 9c280cc7300..42706b55492 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -137,4 +137,28 @@ enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK };
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
 void ima_init_policy(void);
 void ima_update_policy(void);
+int ima_parse_add_rule(char *);
+void ima_delete_rules(void);
+
+/* LSM based policy rules require audit */
+#ifdef CONFIG_IMA_LSM_RULES
+
+#define security_filter_rule_init security_audit_rule_init
+#define security_filter_rule_match security_audit_rule_match
+
+#else
+
+static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
+					    void **lsmrule)
+{
+	return -EINVAL;
+}
+
+static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
+					     void *lsmrule,
+					     struct audit_context *actx)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_IMA_LSM_RULES */
 #endif
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 4f25be768b5..95ef1caa64b 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -19,9 +19,11 @@
 #include <linux/seq_file.h>
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
+#include <linux/parser.h>
 
 #include "ima.h"
 
+static int valid_policy = 1;
 #define TMPBUFLEN 12
 static ssize_t ima_show_htable_value(char __user *buf, size_t count,
 				     loff_t *ppos, atomic_long_t *val)
@@ -237,11 +239,66 @@ static struct file_operations ima_ascii_measurements_ops = {
 	.release = seq_release,
 };
 
+static ssize_t ima_write_policy(struct file *file, const char __user *buf,
+				size_t datalen, loff_t *ppos)
+{
+	char *data;
+	int rc;
+
+	if (datalen >= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	data = kmalloc(datalen + 1, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	if (copy_from_user(data, buf, datalen)) {
+		kfree(data);
+		return -EFAULT;
+	}
+	*(data + datalen) = '\0';
+	rc = ima_parse_add_rule(data);
+	if (rc < 0) {
+		datalen = -EINVAL;
+		valid_policy = 0;
+	}
+
+	kfree(data);
+	return datalen;
+}
+
 static struct dentry *ima_dir;
 static struct dentry *binary_runtime_measurements;
 static struct dentry *ascii_runtime_measurements;
 static struct dentry *runtime_measurements_count;
 static struct dentry *violations;
+static struct dentry *ima_policy;
+
+/*
+ * ima_release_policy - start using the new measure policy rules.
+ *
+ * Initially, ima_measure points to the default policy rules, now
+ * point to the new policy rules, and remove the securityfs policy file.
+ */
+static int ima_release_policy(struct inode *inode, struct file *file)
+{
+	if (!valid_policy) {
+		ima_delete_rules();
+		return 0;
+	}
+	ima_update_policy();
+	securityfs_remove(ima_policy);
+	ima_policy = NULL;
+	return 0;
+}
+
+static struct file_operations ima_measure_policy_ops = {
+	.write = ima_write_policy,
+	.release = ima_release_policy
+};
 
 int ima_fs_init(void)
 {
@@ -276,13 +333,20 @@ int ima_fs_init(void)
 	if (IS_ERR(violations))
 		goto out;
 
-	return 0;
+	ima_policy = securityfs_create_file("policy",
+					    S_IRUSR | S_IRGRP | S_IWUSR,
+					    ima_dir, NULL,
+					    &ima_measure_policy_ops);
+	if (IS_ERR(ima_policy))
+		goto out;
 
+	return 0;
 out:
 	securityfs_remove(runtime_measurements_count);
 	securityfs_remove(ascii_runtime_measurements);
 	securityfs_remove(binary_runtime_measurements);
 	securityfs_remove(ima_dir);
+	securityfs_remove(ima_policy);
 	return -1;
 }
 
@@ -293,4 +357,5 @@ void __exit ima_fs_cleanup(void)
 	securityfs_remove(ascii_runtime_measurements);
 	securityfs_remove(binary_runtime_measurements);
 	securityfs_remove(ima_dir);
+	securityfs_remove(ima_policy);
 }
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 7c3d1ffb147..bd453603e2c 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -15,6 +15,7 @@
 #include <linux/audit.h>
 #include <linux/security.h>
 #include <linux/magic.h>
+#include <linux/parser.h>
 
 #include "ima.h"
 
@@ -24,7 +25,12 @@
 #define IMA_FSMAGIC	0x0004
 #define IMA_UID		0x0008
 
-enum ima_action { DONT_MEASURE, MEASURE };
+enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE };
+
+#define MAX_LSM_RULES 6
+enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
+	LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
+};
 
 struct ima_measure_rule_entry {
 	struct list_head list;
@@ -34,8 +40,15 @@ struct ima_measure_rule_entry {
 	int mask;
 	unsigned long fsmagic;
 	uid_t uid;
+	struct {
+		void *rule;	/* LSM file metadata specific */
+		int type;	/* audit type */
+	} lsm[MAX_LSM_RULES];
 };
 
+/* Without LSM specific knowledge, the default policy can only be
+ * written in terms of .action, .func, .mask, .fsmagic, and .uid
+ */
 static struct ima_measure_rule_entry default_rules[] = {
 	{.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,
 	 .flags = IMA_FSMAGIC},
@@ -54,8 +67,11 @@ static struct ima_measure_rule_entry default_rules[] = {
 };
 
 static LIST_HEAD(measure_default_rules);
+static LIST_HEAD(measure_policy_rules);
 static struct list_head *ima_measure;
 
+static DEFINE_MUTEX(ima_measure_mutex);
+
 /**
  * ima_match_rules - determine whether an inode matches the measure rule.
  * @rule: a pointer to a rule
@@ -69,6 +85,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
 			    struct inode *inode, enum ima_hooks func, int mask)
 {
 	struct task_struct *tsk = current;
+	int i;
 
 	if ((rule->flags & IMA_FUNC) && rule->func != func)
 		return false;
@@ -79,6 +96,39 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
 		return false;
 	if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
 		return false;
+	for (i = 0; i < MAX_LSM_RULES; i++) {
+		int rc;
+		u32 osid, sid;
+
+		if (!rule->lsm[i].rule)
+			continue;
+
+		switch (i) {
+		case LSM_OBJ_USER:
+		case LSM_OBJ_ROLE:
+		case LSM_OBJ_TYPE:
+			security_inode_getsecid(inode, &osid);
+			rc = security_filter_rule_match(osid,
+							rule->lsm[i].type,
+							AUDIT_EQUAL,
+							rule->lsm[i].rule,
+							NULL);
+			break;
+		case LSM_SUBJ_USER:
+		case LSM_SUBJ_ROLE:
+		case LSM_SUBJ_TYPE:
+			security_task_getsecid(tsk, &sid);
+			rc = security_filter_rule_match(sid,
+							rule->lsm[i].type,
+							AUDIT_EQUAL,
+							rule->lsm[i].rule,
+							NULL);
+		default:
+			break;
+		}
+		if (!rc)
+			return false;
+	}
 	return true;
 }
 
@@ -112,9 +162,8 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
 /**
  * ima_init_policy - initialize the default measure rules.
  *
- * (Could use the default_rules directly, but in policy patch
  * ima_measure points to either the measure_default_rules or the
- * the new measure_policy_rules.)
+ * the new measure_policy_rules.
  */
 void ima_init_policy(void)
 {
@@ -124,3 +173,241 @@ void ima_init_policy(void)
 		list_add_tail(&default_rules[i].list, &measure_default_rules);
 	ima_measure = &measure_default_rules;
 }
+
+/**
+ * ima_update_policy - update default_rules with new measure rules
+ *
+ * Called on file .release to update the default rules with a complete new
+ * policy.  Once updated, the policy is locked, no additional rules can be
+ * added to the policy.
+ */
+void ima_update_policy(void)
+{
+	const char *op = "policy_update";
+	const char *cause = "already exists";
+	int result = 1;
+	int audit_info = 0;
+
+	if (ima_measure == &measure_default_rules) {
+		ima_measure = &measure_policy_rules;
+		cause = "complete";
+		result = 0;
+	}
+	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+			    NULL, op, cause, result, audit_info);
+}
+
+enum {
+	Opt_err = -1,
+	Opt_measure = 1, Opt_dont_measure,
+	Opt_obj_user, Opt_obj_role, Opt_obj_type,
+	Opt_subj_user, Opt_subj_role, Opt_subj_type,
+	Opt_func, Opt_mask, Opt_fsmagic, Opt_uid
+};
+
+static match_table_t policy_tokens = {
+	{Opt_measure, "measure"},
+	{Opt_dont_measure, "dont_measure"},
+	{Opt_obj_user, "obj_user=%s"},
+	{Opt_obj_role, "obj_role=%s"},
+	{Opt_obj_type, "obj_type=%s"},
+	{Opt_subj_user, "subj_user=%s"},
+	{Opt_subj_role, "subj_role=%s"},
+	{Opt_subj_type, "subj_type=%s"},
+	{Opt_func, "func=%s"},
+	{Opt_mask, "mask=%s"},
+	{Opt_fsmagic, "fsmagic=%s"},
+	{Opt_uid, "uid=%s"},
+	{Opt_err, NULL}
+};
+
+static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
+			     char *args, int lsm_rule, int audit_type)
+{
+	int result;
+
+	entry->lsm[lsm_rule].type = audit_type;
+	result = security_filter_rule_init(entry->lsm[lsm_rule].type,
+					   AUDIT_EQUAL, args,
+					   &entry->lsm[lsm_rule].rule);
+	return result;
+}
+
+static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
+{
+	struct audit_buffer *ab;
+	char *p;
+	int result = 0;
+
+	ab = audit_log_start(current->audit_context, GFP_KERNEL,
+			     AUDIT_INTEGRITY_STATUS);
+
+	entry->action = -1;
+	while ((p = strsep(&rule, " \n")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+		unsigned long lnum;
+
+		if (result < 0)
+			break;
+		if (!*p)
+			continue;
+		token = match_token(p, policy_tokens, args);
+		switch (token) {
+		case Opt_measure:
+			audit_log_format(ab, "%s ", "measure");
+			entry->action = MEASURE;
+			break;
+		case Opt_dont_measure:
+			audit_log_format(ab, "%s ", "dont_measure");
+			entry->action = DONT_MEASURE;
+			break;
+		case Opt_func:
+			audit_log_format(ab, "func=%s ", args[0].from);
+			if (strcmp(args[0].from, "PATH_CHECK") == 0)
+				entry->func = PATH_CHECK;
+			else if (strcmp(args[0].from, "FILE_MMAP") == 0)
+				entry->func = FILE_MMAP;
+			else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
+				entry->func = BPRM_CHECK;
+			else
+				result = -EINVAL;
+			if (!result)
+				entry->flags |= IMA_FUNC;
+			break;
+		case Opt_mask:
+			audit_log_format(ab, "mask=%s ", args[0].from);
+			if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
+				entry->mask = MAY_EXEC;
+			else if (strcmp(args[0].from, "MAY_WRITE") == 0)
+				entry->mask = MAY_WRITE;
+			else if (strcmp(args[0].from, "MAY_READ") == 0)
+				entry->mask = MAY_READ;
+			else if (strcmp(args[0].from, "MAY_APPEND") == 0)
+				entry->mask = MAY_APPEND;
+			else
+				result = -EINVAL;
+			if (!result)
+				entry->flags |= IMA_MASK;
+			break;
+		case Opt_fsmagic:
+			audit_log_format(ab, "fsmagic=%s ", args[0].from);
+			result = strict_strtoul(args[0].from, 16,
+						&entry->fsmagic);
+			if (!result)
+				entry->flags |= IMA_FSMAGIC;
+			break;
+		case Opt_uid:
+			audit_log_format(ab, "uid=%s ", args[0].from);
+			result = strict_strtoul(args[0].from, 10, &lnum);
+			if (!result) {
+				entry->uid = (uid_t) lnum;
+				if (entry->uid != lnum)
+					result = -EINVAL;
+				else
+					entry->flags |= IMA_UID;
+			}
+			break;
+		case Opt_obj_user:
+			audit_log_format(ab, "obj_user=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_OBJ_USER,
+						   AUDIT_OBJ_USER);
+			break;
+		case Opt_obj_role:
+			audit_log_format(ab, "obj_role=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_OBJ_ROLE,
+						   AUDIT_OBJ_ROLE);
+			break;
+		case Opt_obj_type:
+			audit_log_format(ab, "obj_type=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_OBJ_TYPE,
+						   AUDIT_OBJ_TYPE);
+			break;
+		case Opt_subj_user:
+			audit_log_format(ab, "subj_user=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_SUBJ_USER,
+						   AUDIT_SUBJ_USER);
+			break;
+		case Opt_subj_role:
+			audit_log_format(ab, "subj_role=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_SUBJ_ROLE,
+						   AUDIT_SUBJ_ROLE);
+			break;
+		case Opt_subj_type:
+			audit_log_format(ab, "subj_type=%s ", args[0].from);
+			result = ima_lsm_rule_init(entry, args[0].from,
+						   LSM_SUBJ_TYPE,
+						   AUDIT_SUBJ_TYPE);
+			break;
+		case Opt_err:
+			printk(KERN_INFO "%s: unknown token: %s\n",
+			       __FUNCTION__, p);
+			break;
+		}
+	}
+	if (entry->action == UNKNOWN)
+		result = -EINVAL;
+
+	audit_log_format(ab, "res=%d", result);
+	audit_log_end(ab);
+	return result;
+}
+
+/**
+ * ima_parse_add_rule - add a rule to measure_policy_rules
+ * @rule - ima measurement policy rule
+ *
+ * Uses a mutex to protect the policy list from multiple concurrent writers.
+ * Returns 0 on success, an error code on failure.
+ */
+int ima_parse_add_rule(char *rule)
+{
+	const char *op = "add_rule";
+	struct ima_measure_rule_entry *entry;
+	int result = 0;
+	int audit_info = 0;
+
+	/* Prevent installed policy from changing */
+	if (ima_measure != &measure_default_rules) {
+		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+				    NULL, op, "already exists",
+				    -EACCES, audit_info);
+		return -EACCES;
+	}
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+				    NULL, op, "-ENOMEM", -ENOMEM, audit_info);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&entry->list);
+
+	result = ima_parse_rule(rule, entry);
+	if (!result) {
+		mutex_lock(&ima_measure_mutex);
+		list_add_tail(&entry->list, &measure_policy_rules);
+		mutex_unlock(&ima_measure_mutex);
+	} else
+		kfree(entry);
+	return result;
+}
+
+/* ima_delete_rules called to cleanup invalid policy */
+void ima_delete_rules()
+{
+	struct ima_measure_rule_entry *entry, *tmp;
+
+	mutex_lock(&ima_measure_mutex);
+	list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+	mutex_unlock(&ima_measure_mutex);
+}
-- 
cgit v1.2.3-70-g09d2


From ae374d667a54fb5e2c9c0c4e87b206bd665f3ad6 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 13 Feb 2009 08:33:55 +0100
Subject: ALSA: hda - Update documentation

Update documentation regarding codec probing; the new probe_only option
and the new probe_mask usage.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |  3 +++
 Documentation/sound/alsa/HD-Audio.txt           | 17 +++++++++++++++++
 2 files changed, 20 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 841a9365d5f..012afd7afb1 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -757,6 +757,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     model	- force the model name
     position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
+    		  When the bit 8 (0x100) is set, the lower 8 bits are used
+		  as the "fixed" codec slots; i.e. the driver probes the
+		  slots regardless what hardware reports back
     probe_only	- Only probing and no codec initialization (default=off);
 		  Useful to check the initial codec status for debugging
     bdl_pos_adj	- Specifies the DMA IRQ timing delay in samples.
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 8d68fff7183..99f7fbbe3e6 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -109,6 +109,13 @@ slot, pass `probe_mask=1`.  For the first and the third slots, pass
 Since 2.6.29 kernel, the driver has a more robust probing method, so
 this error might happen rarely, though.
 
+On a machine with a broken BIOS, sometimes you need to force the
+driver to probe the codec slots the hardware doesn't report for use.
+In such a case, turn the bit 8 (0x100) of `probe_mask` option on.
+Then the rest 8 bits are passed as the codec slots to probe
+unconditionally.  For example, `probe_mask=0x103` will force to probe
+the codec slots 0 and 1 no matter what the hardware reports.
+
 
 Interrupt Handling
 ~~~~~~~~~~~~~~~~~~
@@ -461,6 +468,16 @@ run with `--no-upload` option, and attach the generated file.
 There are some other useful options.  See `--help` option output for
 details.
 
+When a probe error occurs or when the driver obviously assigns a
+mismatched model, it'd be helpful to load the driver with
+`probe_only=1` option (at best after the cold reboot) and run
+alsa-info at this state.  With this option, the driver won't configure
+the mixer and PCM but just tries to probe the codec slot.  After
+probing, the proc file is available, so you can get the raw codec
+information before modified by the driver.  Of course, the driver
+isn't usable with `probe_only=1`.  But you can continue the
+configuration via hwdep sysfs file if hda-reconfig option is enabled.
+
 
 hda-verb
 ~~~~~~~~
-- 
cgit v1.2.3-70-g09d2


From 27e089888fb1a3d1d13892262f9d522b03985044 Mon Sep 17 00:00:00 2001
From: Aristeu Sergio Rozanski Filho <aris@ruivo.org>
Date: Thu, 12 Feb 2009 17:50:37 -0500
Subject: ALSA: hda: add quirk for Lenovo X200 laptop dock

Currently the HP connector on X200 dock doesn't detect when a HP is connected
nor allows sound to be played using it. This patch fixes the problem by adding
a quirk for this specific model. It's possible that others have the same NID
(0x19) to report when dock HP is connected, but I don't have access to any.
Please Cc me in the reply since I'm not subscribed to alsa-devel@.

Signed-off-by: Aristeu Rozanski <aris@redhat.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt |  1 +
 sound/pci/hda/patch_conexant.c               | 40 ++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 8f40999a456..0e52d273ce9 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -262,6 +262,7 @@ Conexant 5051
 =============
   laptop	Basic Laptop config (default)
   hp		HP Spartan laptop
+  lenovo-x200	Lenovo X200 laptop
 
 STAC9200
 ========
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index fdf876be712..b8de73ecfde 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -1798,6 +1798,40 @@ static struct hda_verb cxt5051_init_verbs[] = {
 	{ } /* end */
 };
 
+static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
+	/* Line in, Mic */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	/* SPK  */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP, Amp  */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Docking HP */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* DAC1 */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Record selector: Int mic */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
+	/* SPDIF route: PCM */
+	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* EAPD */
+	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
+	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
+	{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
+	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
+	{ } /* end */
+};
+
 /* initialize jack-sensing, too */
 static int cxt5051_init(struct hda_codec *codec)
 {
@@ -1815,18 +1849,21 @@ static int cxt5051_init(struct hda_codec *codec)
 enum {
 	CXT5051_LAPTOP,	 /* Laptops w/ EAPD support */
 	CXT5051_HP,	/* no docking */
+	CXT5051_LENOVO_X200,	/* Lenovo X200 laptop */
 	CXT5051_MODELS
 };
 
 static const char *cxt5051_models[CXT5051_MODELS] = {
 	[CXT5051_LAPTOP]	= "laptop",
 	[CXT5051_HP]		= "hp",
+	[CXT5051_LENOVO_X200]	= "lenovo-x200",
 };
 
 static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
 		      CXT5051_LAPTOP),
 	SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
+	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
 	{}
 };
 
@@ -1867,6 +1904,9 @@ static int patch_cxt5051(struct hda_codec *codec)
 		codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
 		spec->mixers[0] = cxt5051_hp_mixers;
 		break;
+	case CXT5051_LENOVO_X200:
+		spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
+		/* fallthru */
 	default:
 	case CXT5051_LAPTOP:
 		codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
-- 
cgit v1.2.3-70-g09d2


From cb9eff097831007afb30d64373f29d99825d0068 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Thu, 12 Feb 2009 05:03:36 +0000
Subject: net: new user space API for time stamping of incoming and outgoing
 packets

User space can request hardware and/or software time stamping.
Reporting of the result(s) via a new control message is enabled
separately for each field in the message because some of the
fields may require additional computation and thus cause overhead.
User space can tell the different kinds of time stamps apart
and choose what suits its needs.

When a TX timestamp operation is requested, the TX skb will be cloned
and the clone will be time stamped (in hardware or software) and added
to the socket error queue of the skb, if the skb has a socket
associated with it.

The actual TX timestamp will reach userspace as a RX timestamp on the
cloned packet. If timestamping is requested and no timestamping is
done in the device driver (potentially this may use hardware
timestamping), it will be done in software after the device's
start_hard_xmit routine.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/timestamping.txt          | 178 +++++++
 Documentation/networking/timestamping/.gitignore   |   1 +
 Documentation/networking/timestamping/Makefile     |   6 +
 .../networking/timestamping/timestamping.c         | 533 +++++++++++++++++++++
 arch/alpha/include/asm/socket.h                    |   3 +
 arch/arm/include/asm/socket.h                      |   3 +
 arch/avr32/include/asm/socket.h                    |   3 +
 arch/blackfin/include/asm/socket.h                 |   3 +
 arch/cris/include/asm/socket.h                     |   3 +
 arch/h8300/include/asm/socket.h                    |   3 +
 arch/ia64/include/asm/socket.h                     |   3 +
 arch/m68k/include/asm/socket.h                     |   3 +
 arch/mips/include/asm/socket.h                     |   3 +
 arch/parisc/include/asm/socket.h                   |   3 +
 arch/powerpc/include/asm/socket.h                  |   3 +
 arch/s390/include/asm/socket.h                     |   3 +
 arch/sh/include/asm/socket.h                       |   3 +
 arch/sparc/include/asm/socket.h                    |   3 +
 arch/x86/include/asm/socket.h                      |   3 +
 arch/xtensa/include/asm/socket.h                   |   3 +
 include/asm-frv/socket.h                           |   3 +
 include/asm-m32r/socket.h                          |   3 +
 include/asm-mn10300/socket.h                       |   3 +
 include/linux/errqueue.h                           |   1 +
 include/linux/net_tstamp.h                         | 104 ++++
 include/linux/sockios.h                            |   3 +
 26 files changed, 883 insertions(+)
 create mode 100644 Documentation/networking/timestamping.txt
 create mode 100644 Documentation/networking/timestamping/.gitignore
 create mode 100644 Documentation/networking/timestamping/Makefile
 create mode 100644 Documentation/networking/timestamping/timestamping.c
 create mode 100644 include/linux/net_tstamp.h

(limited to 'Documentation')

diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
new file mode 100644
index 00000000000..a681a65b5bc
--- /dev/null
+++ b/Documentation/networking/timestamping.txt
@@ -0,0 +1,178 @@
+The existing interfaces for getting network packages time stamped are:
+
+* SO_TIMESTAMP
+  Generate time stamp for each incoming packet using the (not necessarily
+  monotonous!) system time. Result is returned via recv_msg() in a
+  control message as timeval (usec resolution).
+
+* SO_TIMESTAMPNS
+  Same time stamping mechanism as SO_TIMESTAMP, but returns result as
+  timespec (nsec resolution).
+
+* IP_MULTICAST_LOOP + SO_TIMESTAMP[NS]
+  Only for multicasts: approximate send time stamp by receiving the looped
+  packet and using its receive time stamp.
+
+The following interface complements the existing ones: receive time
+stamps can be generated and returned for arbitrary packets and much
+closer to the point where the packet is really sent. Time stamps can
+be generated in software (as before) or in hardware (if the hardware
+has such a feature).
+
+SO_TIMESTAMPING:
+
+Instructs the socket layer which kind of information is wanted. The
+parameter is an integer with some of the following bits set. Setting
+other bits is an error and doesn't change the current state.
+
+SOF_TIMESTAMPING_TX_HARDWARE:  try to obtain send time stamp in hardware
+SOF_TIMESTAMPING_TX_SOFTWARE:  if SOF_TIMESTAMPING_TX_HARDWARE is off or
+                               fails, then do it in software
+SOF_TIMESTAMPING_RX_HARDWARE:  return the original, unmodified time stamp
+                               as generated by the hardware
+SOF_TIMESTAMPING_RX_SOFTWARE:  if SOF_TIMESTAMPING_RX_HARDWARE is off or
+                               fails, then do it in software
+SOF_TIMESTAMPING_RAW_HARDWARE: return original raw hardware time stamp
+SOF_TIMESTAMPING_SYS_HARDWARE: return hardware time stamp transformed to
+                               the system time base
+SOF_TIMESTAMPING_SOFTWARE:     return system time stamp generated in
+                               software
+
+SOF_TIMESTAMPING_TX/RX determine how time stamps are generated.
+SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the
+following control message:
+    struct scm_timestamping {
+           struct timespec systime;
+           struct timespec hwtimetrans;
+           struct timespec hwtimeraw;
+    };
+
+recvmsg() can be used to get this control message for regular incoming
+packets. For send time stamps the outgoing packet is looped back to
+the socket's error queue with the send time stamp(s) attached. It can
+be received with recvmsg(flags=MSG_ERRQUEUE). The call returns the
+original outgoing packet data including all headers preprended down to
+and including the link layer, the scm_timestamping control message and
+a sock_extended_err control message with ee_errno==ENOMSG and
+ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending
+bounced packet is ready for reading as far as select() is concerned.
+
+All three values correspond to the same event in time, but were
+generated in different ways. Each of these values may be empty (= all
+zero), in which case no such value was available. If the application
+is not interested in some of these values, they can be left blank to
+avoid the potential overhead of calculating them.
+
+systime is the value of the system time at that moment. This
+corresponds to the value also returned via SO_TIMESTAMP[NS]. If the
+time stamp was generated by hardware, then this field is
+empty. Otherwise it is filled in if SOF_TIMESTAMPING_SOFTWARE is
+set.
+
+hwtimeraw is the original hardware time stamp. Filled in if
+SOF_TIMESTAMPING_RAW_HARDWARE is set. No assumptions about its
+relation to system time should be made.
+
+hwtimetrans is the hardware time stamp transformed so that it
+corresponds as good as possible to system time. This correlation is
+not perfect; as a consequence, sorting packets received via different
+NICs by their hwtimetrans may differ from the order in which they were
+received. hwtimetrans may be non-monotonic even for the same NIC.
+Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
+by the network device and will be empty without that support.
+
+
+SIOCSHWTSTAMP:
+
+Hardware time stamping must also be initialized for each device driver
+that is expected to do hardware time stamping. The parameter is:
+
+struct hwtstamp_config {
+    int flags;           /* no flags defined right now, must be zero */
+    int tx_type;         /* HWTSTAMP_TX_* */
+    int rx_filter;       /* HWTSTAMP_FILTER_* */
+};
+
+Desired behavior is passed into the kernel and to a specific device by
+calling ioctl(SIOCSHWTSTAMP) with a pointer to a struct ifreq whose
+ifr_data points to a struct hwtstamp_config. The tx_type and
+rx_filter are hints to the driver what it is expected to do. If
+the requested fine-grained filtering for incoming packets is not
+supported, the driver may time stamp more than just the requested types
+of packets.
+
+A driver which supports hardware time stamping shall update the struct
+with the actual, possibly more permissive configuration. If the
+requested packets cannot be time stamped, then nothing should be
+changed and ERANGE shall be returned (in contrast to EINVAL, which
+indicates that SIOCSHWTSTAMP is not supported at all).
+
+Only a processes with admin rights may change the configuration. User
+space is responsible to ensure that multiple processes don't interfere
+with each other and that the settings are reset.
+
+/* possible values for hwtstamp_config->tx_type */
+enum {
+	/*
+	 * no outgoing packet will need hardware time stamping;
+	 * should a packet arrive which asks for it, no hardware
+	 * time stamping will be done
+	 */
+	HWTSTAMP_TX_OFF,
+
+	/*
+	 * enables hardware time stamping for outgoing packets;
+	 * the sender of the packet decides which are to be
+	 * time stamped by setting SOF_TIMESTAMPING_TX_SOFTWARE
+	 * before sending the packet
+	 */
+	HWTSTAMP_TX_ON,
+};
+
+/* possible values for hwtstamp_config->rx_filter */
+enum {
+	/* time stamp no incoming packet at all */
+	HWTSTAMP_FILTER_NONE,
+
+	/* time stamp any incoming packet */
+	HWTSTAMP_FILTER_ALL,
+
+        /* return value: time stamp all packets requested plus some others */
+        HWTSTAMP_FILTER_SOME,
+
+	/* PTP v1, UDP, any kind of event packet */
+	HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
+
+        ...
+};
+
+
+DEVICE IMPLEMENTATION
+
+A driver which supports hardware time stamping must support the
+SIOCSHWTSTAMP ioctl. Time stamps for received packets must be stored
+in the skb with skb_hwtstamp_set().
+
+Time stamps for outgoing packets are to be generated as follows:
+- In hard_start_xmit(), check if skb_hwtstamp_check_tx_hardware()
+  returns non-zero. If yes, then the driver is expected
+  to do hardware time stamping.
+- If this is possible for the skb and requested, then declare
+  that the driver is doing the time stamping by calling
+  skb_hwtstamp_tx_in_progress(). A driver not supporting
+  hardware time stamping doesn't do that. A driver must never
+  touch sk_buff::tstamp! It is used to store how time stamping
+  for an outgoing packets is to be done.
+- As soon as the driver has sent the packet and/or obtained a
+  hardware time stamp for it, it passes the time stamp back by
+  calling skb_hwtstamp_tx() with the original skb, the raw
+  hardware time stamp and a handle to the device (necessary
+  to convert the hardware time stamp to system time). If obtaining
+  the hardware time stamp somehow fails, then the driver should
+  not fall back to software time stamping. The rationale is that
+  this would occur at a later time in the processing pipeline
+  than other software time stamping and therefore could lead
+  to unexpected deltas between time stamps.
+- If the driver did not call skb_hwtstamp_tx_in_progress(), then
+  dev_hard_start_xmit() checks whether software time stamping
+  is wanted as fallback and potentially generates the time stamp.
diff --git a/Documentation/networking/timestamping/.gitignore b/Documentation/networking/timestamping/.gitignore
new file mode 100644
index 00000000000..71e81eb2e22
--- /dev/null
+++ b/Documentation/networking/timestamping/.gitignore
@@ -0,0 +1 @@
+timestamping
diff --git a/Documentation/networking/timestamping/Makefile b/Documentation/networking/timestamping/Makefile
new file mode 100644
index 00000000000..2a1489fdc03
--- /dev/null
+++ b/Documentation/networking/timestamping/Makefile
@@ -0,0 +1,6 @@
+CPPFLAGS = -I../../../include
+
+timestamping: timestamping.c
+
+clean:
+	rm -f timestamping
diff --git a/Documentation/networking/timestamping/timestamping.c b/Documentation/networking/timestamping/timestamping.c
new file mode 100644
index 00000000000..43d14310421
--- /dev/null
+++ b/Documentation/networking/timestamping/timestamping.c
@@ -0,0 +1,533 @@
+/*
+ * This program demonstrates how the various time stamping features in
+ * the Linux kernel work. It emulates the behavior of a PTP
+ * implementation in stand-alone master mode by sending PTPv1 Sync
+ * multicasts once every second. It looks for similar packets, but
+ * beyond that doesn't actually implement PTP.
+ *
+ * Outgoing packets are time stamped with SO_TIMESTAMPING with or
+ * without hardware support.
+ *
+ * Incoming packets are time stamped with SO_TIMESTAMPING with or
+ * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
+ * SO_TIMESTAMP[NS].
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ * Author: Patrick Ohly <patrick.ohly@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "asm/types.h"
+#include "linux/net_tstamp.h"
+#include "linux/errqueue.h"
+
+#ifndef SO_TIMESTAMPING
+# define SO_TIMESTAMPING         37
+# define SCM_TIMESTAMPING        SO_TIMESTAMPING
+#endif
+
+#ifndef SO_TIMESTAMPNS
+# define SO_TIMESTAMPNS 35
+#endif
+
+#ifndef SIOCGSTAMPNS
+# define SIOCGSTAMPNS 0x8907
+#endif
+
+#ifndef SIOCSHWTSTAMP
+# define SIOCSHWTSTAMP 0x89b0
+#endif
+
+static void usage(const char *error)
+{
+	if (error)
+		printf("invalid option: %s\n", error);
+	printf("timestamping interface option*\n\n"
+	       "Options:\n"
+	       "  IP_MULTICAST_LOOP - looping outgoing multicasts\n"
+	       "  SO_TIMESTAMP - normal software time stamping, ms resolution\n"
+	       "  SO_TIMESTAMPNS - more accurate software time stamping\n"
+	       "  SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
+	       "  SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
+	       "  SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
+	       "  SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
+	       "  SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
+	       "  SOF_TIMESTAMPING_SYS_HARDWARE - request reporting of transformed HW time stamps\n"
+	       "  SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
+	       "  SIOCGSTAMP - check last socket time stamp\n"
+	       "  SIOCGSTAMPNS - more accurate socket time stamp\n");
+	exit(1);
+}
+
+static void bail(const char *error)
+{
+	printf("%s: %s\n", error, strerror(errno));
+	exit(1);
+}
+
+static const unsigned char sync[] = {
+	0x00, 0x01, 0x00, 0x01,
+	0x5f, 0x44, 0x46, 0x4c,
+	0x54, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x01, 0x01,
+
+	/* fake uuid */
+	0x00, 0x01,
+	0x02, 0x03, 0x04, 0x05,
+
+	0x00, 0x01, 0x00, 0x37,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x49, 0x05, 0xcd, 0x01,
+	0x29, 0xb1, 0x8d, 0xb0,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01,
+
+	/* fake uuid */
+	0x00, 0x01,
+	0x02, 0x03, 0x04, 0x05,
+
+	0x00, 0x00, 0x00, 0x37,
+	0x00, 0x00, 0x00, 0x04,
+	0x44, 0x46, 0x4c, 0x54,
+	0x00, 0x00, 0xf0, 0x60,
+	0x00, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0xf0, 0x60,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x04,
+	0x44, 0x46, 0x4c, 0x54,
+	0x00, 0x01,
+
+	/* fake uuid */
+	0x00, 0x01,
+	0x02, 0x03, 0x04, 0x05,
+
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00
+};
+
+static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
+{
+	struct timeval now;
+	int res;
+
+	res = sendto(sock, sync, sizeof(sync), 0,
+		addr, addr_len);
+	gettimeofday(&now, 0);
+	if (res < 0)
+		printf("%s: %s\n", "send", strerror(errno));
+	else
+		printf("%ld.%06ld: sent %d bytes\n",
+		       (long)now.tv_sec, (long)now.tv_usec,
+		       res);
+}
+
+static void printpacket(struct msghdr *msg, int res,
+			char *data,
+			int sock, int recvmsg_flags,
+			int siocgstamp, int siocgstampns)
+{
+	struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
+	struct cmsghdr *cmsg;
+	struct timeval tv;
+	struct timespec ts;
+	struct timeval now;
+
+	gettimeofday(&now, 0);
+
+	printf("%ld.%06ld: received %s data, %d bytes from %s, %d bytes control messages\n",
+	       (long)now.tv_sec, (long)now.tv_usec,
+	       (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
+	       res,
+	       inet_ntoa(from_addr->sin_addr),
+	       msg->msg_controllen);
+	for (cmsg = CMSG_FIRSTHDR(msg);
+	     cmsg;
+	     cmsg = CMSG_NXTHDR(msg, cmsg)) {
+		printf("   cmsg len %d: ", cmsg->cmsg_len);
+		switch (cmsg->cmsg_level) {
+		case SOL_SOCKET:
+			printf("SOL_SOCKET ");
+			switch (cmsg->cmsg_type) {
+			case SO_TIMESTAMP: {
+				struct timeval *stamp =
+					(struct timeval *)CMSG_DATA(cmsg);
+				printf("SO_TIMESTAMP %ld.%06ld",
+				       (long)stamp->tv_sec,
+				       (long)stamp->tv_usec);
+				break;
+			}
+			case SO_TIMESTAMPNS: {
+				struct timespec *stamp =
+					(struct timespec *)CMSG_DATA(cmsg);
+				printf("SO_TIMESTAMPNS %ld.%09ld",
+				       (long)stamp->tv_sec,
+				       (long)stamp->tv_nsec);
+				break;
+			}
+			case SO_TIMESTAMPING: {
+				struct timespec *stamp =
+					(struct timespec *)CMSG_DATA(cmsg);
+				printf("SO_TIMESTAMPING ");
+				printf("SW %ld.%09ld ",
+				       (long)stamp->tv_sec,
+				       (long)stamp->tv_nsec);
+				stamp++;
+				printf("HW transformed %ld.%09ld ",
+				       (long)stamp->tv_sec,
+				       (long)stamp->tv_nsec);
+				stamp++;
+				printf("HW raw %ld.%09ld",
+				       (long)stamp->tv_sec,
+				       (long)stamp->tv_nsec);
+				break;
+			}
+			default:
+				printf("type %d", cmsg->cmsg_type);
+				break;
+			}
+			break;
+		case IPPROTO_IP:
+			printf("IPPROTO_IP ");
+			switch (cmsg->cmsg_type) {
+			case IP_RECVERR: {
+				struct sock_extended_err *err =
+					(struct sock_extended_err *)CMSG_DATA(cmsg);
+				printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
+					strerror(err->ee_errno),
+					err->ee_origin,
+#ifdef SO_EE_ORIGIN_TIMESTAMPING
+					err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
+					"bounced packet" : "unexpected origin"
+#else
+					"probably SO_EE_ORIGIN_TIMESTAMPING"
+#endif
+					);
+				if (res < sizeof(sync))
+					printf(" => truncated data?!");
+				else if (!memcmp(sync, data + res - sizeof(sync),
+							sizeof(sync)))
+					printf(" => GOT OUR DATA BACK (HURRAY!)");
+				break;
+			}
+			case IP_PKTINFO: {
+				struct in_pktinfo *pktinfo =
+					(struct in_pktinfo *)CMSG_DATA(cmsg);
+				printf("IP_PKTINFO interface index %u",
+					pktinfo->ipi_ifindex);
+				break;
+			}
+			default:
+				printf("type %d", cmsg->cmsg_type);
+				break;
+			}
+			break;
+		default:
+			printf("level %d type %d",
+				cmsg->cmsg_level,
+				cmsg->cmsg_type);
+			break;
+		}
+		printf("\n");
+	}
+
+	if (siocgstamp) {
+		if (ioctl(sock, SIOCGSTAMP, &tv))
+			printf("   %s: %s\n", "SIOCGSTAMP", strerror(errno));
+		else
+			printf("SIOCGSTAMP %ld.%06ld\n",
+			       (long)tv.tv_sec,
+			       (long)tv.tv_usec);
+	}
+	if (siocgstampns) {
+		if (ioctl(sock, SIOCGSTAMPNS, &ts))
+			printf("   %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
+		else
+			printf("SIOCGSTAMPNS %ld.%09ld\n",
+			       (long)ts.tv_sec,
+			       (long)ts.tv_nsec);
+	}
+}
+
+static void recvpacket(int sock, int recvmsg_flags,
+		       int siocgstamp, int siocgstampns)
+{
+	char data[256];
+	struct msghdr msg;
+	struct iovec entry;
+	struct sockaddr_in from_addr;
+	struct {
+		struct cmsghdr cm;
+		char control[512];
+	} control;
+	int res;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = &entry;
+	msg.msg_iovlen = 1;
+	entry.iov_base = data;
+	entry.iov_len = sizeof(data);
+	msg.msg_name = (caddr_t)&from_addr;
+	msg.msg_namelen = sizeof(from_addr);
+	msg.msg_control = &control;
+	msg.msg_controllen = sizeof(control);
+
+	res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
+	if (res < 0) {
+		printf("%s %s: %s\n",
+		       "recvmsg",
+		       (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
+		       strerror(errno));
+	} else {
+		printpacket(&msg, res, data,
+			    sock, recvmsg_flags,
+			    siocgstamp, siocgstampns);
+	}
+}
+
+int main(int argc, char **argv)
+{
+	int so_timestamping_flags = 0;
+	int so_timestamp = 0;
+	int so_timestampns = 0;
+	int siocgstamp = 0;
+	int siocgstampns = 0;
+	int ip_multicast_loop = 0;
+	char *interface;
+	int i;
+	int enabled = 1;
+	int sock;
+	struct ifreq device;
+	struct ifreq hwtstamp;
+	struct hwtstamp_config hwconfig, hwconfig_requested;
+	struct sockaddr_in addr;
+	struct ip_mreq imr;
+	struct in_addr iaddr;
+	int val;
+	socklen_t len;
+	struct timeval next;
+
+	if (argc < 2)
+		usage(0);
+	interface = argv[1];
+
+	for (i = 2; i < argc; i++) {
+		if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
+			so_timestamp = 1;
+		else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
+			so_timestampns = 1;
+		else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
+			siocgstamp = 1;
+		else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
+			siocgstampns = 1;
+		else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
+			ip_multicast_loop = 1;
+		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
+			so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
+		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
+			so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
+		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
+			so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
+		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
+			so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
+		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
+			so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
+		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SYS_HARDWARE"))
+			so_timestamping_flags |= SOF_TIMESTAMPING_SYS_HARDWARE;
+		else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
+			so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
+		else
+			usage(argv[i]);
+	}
+
+	sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (socket < 0)
+		bail("socket");
+
+	memset(&device, 0, sizeof(device));
+	strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
+	if (ioctl(sock, SIOCGIFADDR, &device) < 0)
+		bail("getting interface IP address");
+
+	memset(&hwtstamp, 0, sizeof(hwtstamp));
+	strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
+	hwtstamp.ifr_data = (void *)&hwconfig;
+	memset(&hwconfig, 0, sizeof(&hwconfig));
+	hwconfig.tx_type =
+		(so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
+		HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+	hwconfig.rx_filter =
+		(so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
+		HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
+	hwconfig_requested = hwconfig;
+	if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
+		if ((errno == EINVAL || errno == ENOTSUP) &&
+		    hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
+		    hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
+			printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
+		else
+			bail("SIOCSHWTSTAMP");
+	}
+	printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
+	       hwconfig_requested.tx_type, hwconfig.tx_type,
+	       hwconfig_requested.rx_filter, hwconfig.rx_filter);
+
+	/* bind to PTP port */
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = htonl(INADDR_ANY);
+	addr.sin_port = htons(319 /* PTP event port */);
+	if (bind(sock,
+		 (struct sockaddr *)&addr,
+		 sizeof(struct sockaddr_in)) < 0)
+		bail("bind");
+
+	/* set multicast group for outgoing packets */
+	inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
+	addr.sin_addr = iaddr;
+	imr.imr_multiaddr.s_addr = iaddr.s_addr;
+	imr.imr_interface.s_addr =
+		((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
+	if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
+		       &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
+		bail("set multicast");
+
+	/* join multicast group, loop our own packet */
+	if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+		       &imr, sizeof(struct ip_mreq)) < 0)
+		bail("join multicast group");
+
+	if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
+		       &ip_multicast_loop, sizeof(enabled)) < 0) {
+		bail("loop multicast");
+	}
+
+	/* set socket options for time stamping */
+	if (so_timestamp &&
+		setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
+			   &enabled, sizeof(enabled)) < 0)
+		bail("setsockopt SO_TIMESTAMP");
+
+	if (so_timestampns &&
+		setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
+			   &enabled, sizeof(enabled)) < 0)
+		bail("setsockopt SO_TIMESTAMPNS");
+
+	if (so_timestamping_flags &&
+		setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
+			   &so_timestamping_flags,
+			   sizeof(so_timestamping_flags)) < 0)
+		bail("setsockopt SO_TIMESTAMPING");
+
+	/* request IP_PKTINFO for debugging purposes */
+	if (setsockopt(sock, SOL_IP, IP_PKTINFO,
+		       &enabled, sizeof(enabled)) < 0)
+		printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
+
+	/* verify socket options */
+	len = sizeof(val);
+	if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
+		printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
+	else
+		printf("SO_TIMESTAMP %d\n", val);
+
+	if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
+		printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
+		       strerror(errno));
+	else
+		printf("SO_TIMESTAMPNS %d\n", val);
+
+	if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
+		printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
+		       strerror(errno));
+	} else {
+		printf("SO_TIMESTAMPING %d\n", val);
+		if (val != so_timestamping_flags)
+			printf("   not the expected value %d\n",
+			       so_timestamping_flags);
+	}
+
+	/* send packets forever every five seconds */
+	gettimeofday(&next, 0);
+	next.tv_sec = (next.tv_sec + 1) / 5 * 5;
+	next.tv_usec = 0;
+	while (1) {
+		struct timeval now;
+		struct timeval delta;
+		long delta_us;
+		int res;
+		fd_set readfs, errorfs;
+
+		gettimeofday(&now, 0);
+		delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
+			(long)(next.tv_usec - now.tv_usec);
+		if (delta_us > 0) {
+			/* continue waiting for timeout or data */
+			delta.tv_sec = delta_us / 1000000;
+			delta.tv_usec = delta_us % 1000000;
+
+			FD_ZERO(&readfs);
+			FD_ZERO(&errorfs);
+			FD_SET(sock, &readfs);
+			FD_SET(sock, &errorfs);
+			printf("%ld.%06ld: select %ldus\n",
+			       (long)now.tv_sec, (long)now.tv_usec,
+			       delta_us);
+			res = select(sock + 1, &readfs, 0, &errorfs, &delta);
+			gettimeofday(&now, 0);
+			printf("%ld.%06ld: select returned: %d, %s\n",
+			       (long)now.tv_sec, (long)now.tv_usec,
+			       res,
+			       res < 0 ? strerror(errno) : "success");
+			if (res > 0) {
+				if (FD_ISSET(sock, &readfs))
+					printf("ready for reading\n");
+				if (FD_ISSET(sock, &errorfs))
+					printf("has error\n");
+				recvpacket(sock, 0,
+					   siocgstamp,
+					   siocgstampns);
+				recvpacket(sock, MSG_ERRQUEUE,
+					   siocgstamp,
+					   siocgstampns);
+			}
+		} else {
+			/* write one packet */
+			sendpacket(sock,
+				   (struct sockaddr *)&addr,
+				   sizeof(addr));
+			next.tv_sec += 5;
+			continue;
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index a1057c2d95e..3641ec1452f 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -62,6 +62,9 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h
index 6817be9573a..537de4e0ef5 100644
--- a/arch/arm/include/asm/socket.h
+++ b/arch/arm/include/asm/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_SOCKET_H */
diff --git a/arch/avr32/include/asm/socket.h b/arch/avr32/include/asm/socket.h
index 35863f26092..04c86061970 100644
--- a/arch/avr32/include/asm/socket.h
+++ b/arch/avr32/include/asm/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/blackfin/include/asm/socket.h b/arch/blackfin/include/asm/socket.h
index 2ca702e44d4..fac7fe9e1f8 100644
--- a/arch/blackfin/include/asm/socket.h
+++ b/arch/blackfin/include/asm/socket.h
@@ -53,4 +53,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif				/* _ASM_SOCKET_H */
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h
index 9df0ca82f5d..d5cf7400540 100644
--- a/arch/cris/include/asm/socket.h
+++ b/arch/cris/include/asm/socket.h
@@ -56,6 +56,9 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_SOCKET_H */
 
 
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index da2520dbf25..602518a70a1 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/include/asm/socket.h b/arch/ia64/include/asm/socket.h
index d5ef0aa3e31..745421225ec 100644
--- a/arch/ia64/include/asm/socket.h
+++ b/arch/ia64/include/asm/socket.h
@@ -63,4 +63,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
index dbc64e92c41..ca87f938b03 100644
--- a/arch/m68k/include/asm/socket.h
+++ b/arch/m68k/include/asm/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_SOCKET_H */
diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h
index facc2d7a87c..2abca178016 100644
--- a/arch/mips/include/asm/socket.h
+++ b/arch/mips/include/asm/socket.h
@@ -75,6 +75,9 @@ To add: #define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h
index fba402c95ac..885472bf7b7 100644
--- a/arch/parisc/include/asm/socket.h
+++ b/arch/parisc/include/asm/socket.h
@@ -54,6 +54,9 @@
 
 #define SO_MARK			0x401f
 
+#define SO_TIMESTAMPING		0x4020
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
diff --git a/arch/powerpc/include/asm/socket.h b/arch/powerpc/include/asm/socket.h
index f5a4e168e49..1e5cfad0e3f 100644
--- a/arch/powerpc/include/asm/socket.h
+++ b/arch/powerpc/include/asm/socket.h
@@ -61,4 +61,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif	/* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h
index c786ab623b2..02330c50241 100644
--- a/arch/s390/include/asm/socket.h
+++ b/arch/s390/include/asm/socket.h
@@ -62,4 +62,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_SOCKET_H */
diff --git a/arch/sh/include/asm/socket.h b/arch/sh/include/asm/socket.h
index 6d4bf651295..345653b9682 100644
--- a/arch/sh/include/asm/socket.h
+++ b/arch/sh/include/asm/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* __ASM_SH_SOCKET_H */
diff --git a/arch/sparc/include/asm/socket.h b/arch/sparc/include/asm/socket.h
index bf50d0c2d58..982a12f959f 100644
--- a/arch/sparc/include/asm/socket.h
+++ b/arch/sparc/include/asm/socket.h
@@ -50,6 +50,9 @@
 
 #define SO_MARK			0x0022
 
+#define SO_TIMESTAMPING		0x0023
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
diff --git a/arch/x86/include/asm/socket.h b/arch/x86/include/asm/socket.h
index 8ab9cc8b2ec..ca8bf2cd0ba 100644
--- a/arch/x86/include/asm/socket.h
+++ b/arch/x86/include/asm/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_X86_SOCKET_H */
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h
index 6100682b1da..dd1a7a4a1ce 100644
--- a/arch/xtensa/include/asm/socket.h
+++ b/arch/xtensa/include/asm/socket.h
@@ -65,4 +65,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif	/* _XTENSA_SOCKET_H */
diff --git a/include/asm-frv/socket.h b/include/asm-frv/socket.h
index e51ca67b935..57c3d4054e8 100644
--- a/include/asm-frv/socket.h
+++ b/include/asm-frv/socket.h
@@ -54,5 +54,8 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_SOCKET_H */
 
diff --git a/include/asm-m32r/socket.h b/include/asm-m32r/socket.h
index 9a0e2001222..be7ed589af5 100644
--- a/include/asm-m32r/socket.h
+++ b/include/asm-m32r/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_M32R_SOCKET_H */
diff --git a/include/asm-mn10300/socket.h b/include/asm-mn10300/socket.h
index 80af9c4ccad..fb5daf438ec 100644
--- a/include/asm-mn10300/socket.h
+++ b/include/asm-mn10300/socket.h
@@ -54,4 +54,7 @@
 
 #define SO_MARK			36
 
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
 #endif /* _ASM_SOCKET_H */
diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h
index ceb1454b697..ec12cc74366 100644
--- a/include/linux/errqueue.h
+++ b/include/linux/errqueue.h
@@ -18,6 +18,7 @@ struct sock_extended_err
 #define SO_EE_ORIGIN_LOCAL	1
 #define SO_EE_ORIGIN_ICMP	2
 #define SO_EE_ORIGIN_ICMP6	3
+#define SO_EE_ORIGIN_TIMESTAMPING 4
 
 #define SO_EE_OFFENDER(ee)	((struct sockaddr*)((ee)+1))
 
diff --git a/include/linux/net_tstamp.h b/include/linux/net_tstamp.h
new file mode 100644
index 00000000000..a3b8546354a
--- /dev/null
+++ b/include/linux/net_tstamp.h
@@ -0,0 +1,104 @@
+/*
+ * Userspace API for hardware time stamping of network packets
+ *
+ * Copyright (C) 2008,2009 Intel Corporation
+ * Author: Patrick Ohly <patrick.ohly@intel.com>
+ *
+ */
+
+#ifndef _NET_TIMESTAMPING_H
+#define _NET_TIMESTAMPING_H
+
+#include <linux/socket.h>   /* for SO_TIMESTAMPING */
+
+/* SO_TIMESTAMPING gets an integer bit field comprised of these values */
+enum {
+	SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),
+	SOF_TIMESTAMPING_TX_SOFTWARE = (1<<1),
+	SOF_TIMESTAMPING_RX_HARDWARE = (1<<2),
+	SOF_TIMESTAMPING_RX_SOFTWARE = (1<<3),
+	SOF_TIMESTAMPING_SOFTWARE = (1<<4),
+	SOF_TIMESTAMPING_SYS_HARDWARE = (1<<5),
+	SOF_TIMESTAMPING_RAW_HARDWARE = (1<<6),
+	SOF_TIMESTAMPING_MASK =
+	(SOF_TIMESTAMPING_RAW_HARDWARE - 1) |
+	SOF_TIMESTAMPING_RAW_HARDWARE
+};
+
+/**
+ * struct hwtstamp_config - %SIOCSHWTSTAMP parameter
+ *
+ * @flags:	no flags defined right now, must be zero
+ * @tx_type:	one of HWTSTAMP_TX_*
+ * @rx_type:	one of one of HWTSTAMP_FILTER_*
+ *
+ * %SIOCSHWTSTAMP expects a &struct ifreq with a ifr_data pointer to
+ * this structure. dev_ifsioc() in the kernel takes care of the
+ * translation between 32 bit userspace and 64 bit kernel. The
+ * structure is intentionally chosen so that it has the same layout on
+ * 32 and 64 bit systems, don't break this!
+ */
+struct hwtstamp_config {
+	int flags;
+	int tx_type;
+	int rx_filter;
+};
+
+/* possible values for hwtstamp_config->tx_type */
+enum {
+	/*
+	 * No outgoing packet will need hardware time stamping;
+	 * should a packet arrive which asks for it, no hardware
+	 * time stamping will be done.
+	 */
+	HWTSTAMP_TX_OFF,
+
+	/*
+	 * Enables hardware time stamping for outgoing packets;
+	 * the sender of the packet decides which are to be
+	 * time stamped by setting %SOF_TIMESTAMPING_TX_SOFTWARE
+	 * before sending the packet.
+	 */
+	HWTSTAMP_TX_ON,
+};
+
+/* possible values for hwtstamp_config->rx_filter */
+enum {
+	/* time stamp no incoming packet at all */
+	HWTSTAMP_FILTER_NONE,
+
+	/* time stamp any incoming packet */
+	HWTSTAMP_FILTER_ALL,
+
+	/* return value: time stamp all packets requested plus some others */
+	HWTSTAMP_FILTER_SOME,
+
+	/* PTP v1, UDP, any kind of event packet */
+	HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
+	/* PTP v1, UDP, Sync packet */
+	HWTSTAMP_FILTER_PTP_V1_L4_SYNC,
+	/* PTP v1, UDP, Delay_req packet */
+	HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ,
+	/* PTP v2, UDP, any kind of event packet */
+	HWTSTAMP_FILTER_PTP_V2_L4_EVENT,
+	/* PTP v2, UDP, Sync packet */
+	HWTSTAMP_FILTER_PTP_V2_L4_SYNC,
+	/* PTP v2, UDP, Delay_req packet */
+	HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ,
+
+	/* 802.AS1, Ethernet, any kind of event packet */
+	HWTSTAMP_FILTER_PTP_V2_L2_EVENT,
+	/* 802.AS1, Ethernet, Sync packet */
+	HWTSTAMP_FILTER_PTP_V2_L2_SYNC,
+	/* 802.AS1, Ethernet, Delay_req packet */
+	HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ,
+
+	/* PTP v2/802.AS1, any layer, any kind of event packet */
+	HWTSTAMP_FILTER_PTP_V2_EVENT,
+	/* PTP v2/802.AS1, any layer, Sync packet */
+	HWTSTAMP_FILTER_PTP_V2_SYNC,
+	/* PTP v2/802.AS1, any layer, Delay_req packet */
+	HWTSTAMP_FILTER_PTP_V2_DELAY_REQ,
+};
+
+#endif /* _NET_TIMESTAMPING_H */
diff --git a/include/linux/sockios.h b/include/linux/sockios.h
index abef7596655..241f179347d 100644
--- a/include/linux/sockios.h
+++ b/include/linux/sockios.h
@@ -122,6 +122,9 @@
 #define SIOCBRADDIF	0x89a2		/* add interface to bridge      */
 #define SIOCBRDELIF	0x89a3		/* remove interface from bridge */
 
+/* hardware time stamping: parameters in linux/net_tstamp.h */
+#define SIOCSHWTSTAMP   0x89b0
+
 /* Device private ioctl calls */
 
 /*
-- 
cgit v1.2.3-70-g09d2


From 51f31cabe3ce5345b51e4a4f82138b38c4d5dc91 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Thu, 12 Feb 2009 05:03:39 +0000
Subject: ip: support for TX timestamps on UDP and RAW sockets

Instructions for time stamping outgoing packets are take from the
socket layer and later copied into the new skb.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/timestamping.txt | 2 ++
 include/net/ip.h                          | 1 +
 net/can/raw.c                             | 3 +++
 net/ipv4/icmp.c                           | 2 ++
 net/ipv4/ip_output.c                      | 6 ++++++
 net/ipv4/raw.c                            | 1 +
 net/ipv4/udp.c                            | 4 ++++
 7 files changed, 19 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
index a681a65b5bc..0e58b453917 100644
--- a/Documentation/networking/timestamping.txt
+++ b/Documentation/networking/timestamping.txt
@@ -56,6 +56,8 @@ and including the link layer, the scm_timestamping control message and
 a sock_extended_err control message with ee_errno==ENOMSG and
 ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending
 bounced packet is ready for reading as far as select() is concerned.
+If the outgoing packet has to be fragmented, then only the first
+fragment is time stamped and returned to the sending socket.
 
 All three values correspond to the same event in time, but were
 generated in different ways. Each of these values may be empty (= all
diff --git a/include/net/ip.h b/include/net/ip.h
index 10868139e65..4ac7577f98d 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -55,6 +55,7 @@ struct ipcm_cookie
 	__be32			addr;
 	int			oif;
 	struct ip_options	*opt;
+	union skb_shared_tx	shtx;
 };
 
 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
diff --git a/net/can/raw.c b/net/can/raw.c
index 0703cba4bf9..6aa154e806a 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -646,6 +646,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
 		goto put_dev;
 
 	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
+	if (err < 0)
+		goto free_skb;
+	err = sock_tx_timestamp(msg, sk, skb_tx(skb));
 	if (err < 0)
 		goto free_skb;
 	skb->dev = dev;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 705b33b184a..382800a62b3 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -375,6 +375,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 	inet->tos = ip_hdr(skb)->tos;
 	daddr = ipc.addr = rt->rt_src;
 	ipc.opt = NULL;
+	ipc.shtx.flags = 0;
 	if (icmp_param->replyopts.optlen) {
 		ipc.opt = &icmp_param->replyopts;
 		if (ipc.opt->srr)
@@ -532,6 +533,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 	inet_sk(sk)->tos = tos;
 	ipc.addr = iph->saddr;
 	ipc.opt = &icmp_param.replyopts;
+	ipc.shtx.flags = 0;
 
 	{
 		struct flowi fl = {
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 8ebe86dd72a..3e7e910c7c0 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -935,6 +935,10 @@ alloc_new_skb:
 							   sk->sk_allocation);
 				if (unlikely(skb == NULL))
 					err = -ENOBUFS;
+				else
+					/* only the initial fragment is
+					   time stamped */
+					ipc->shtx.flags = 0;
 			}
 			if (skb == NULL)
 				goto error;
@@ -945,6 +949,7 @@ alloc_new_skb:
 			skb->ip_summed = csummode;
 			skb->csum = 0;
 			skb_reserve(skb, hh_len);
+			*skb_tx(skb) = ipc->shtx;
 
 			/*
 			 *	Find where to start putting bytes.
@@ -1364,6 +1369,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
 
 	daddr = ipc.addr = rt->rt_src;
 	ipc.opt = NULL;
+	ipc.shtx.flags = 0;
 
 	if (replyopts.opt.optlen) {
 		ipc.opt = &replyopts.opt;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index dff8bc4e0fa..f774651f0a4 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -493,6 +493,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
 	ipc.addr = inet->saddr;
 	ipc.opt = NULL;
+	ipc.shtx.flags = 0;
 	ipc.oif = sk->sk_bound_dev_if;
 
 	if (msg->msg_controllen) {
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index c47c989cb1f..4bd178a111d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		return -EOPNOTSUPP;
 
 	ipc.opt = NULL;
+	ipc.shtx.flags = 0;
 
 	if (up->pending) {
 		/*
@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	ipc.addr = inet->saddr;
 
 	ipc.oif = sk->sk_bound_dev_if;
+	err = sock_tx_timestamp(msg, sk, &ipc.shtx);
+	if (err)
+		return err;
 	if (msg->msg_controllen) {
 		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
 		if (err)
-- 
cgit v1.2.3-70-g09d2


From c844a5d38e4247fc71e371221cf762a2a44d565b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 16 Feb 2009 23:17:33 +0100
Subject: ALSA: Fix documentation for snd-cs4236 driver

Updated; removal of snd-cs4232 entry.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt | 30 +++++--------------------
 1 file changed, 5 insertions(+), 25 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index a763b76afe5..57fe4f3ca2c 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -391,34 +391,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     The power-management is supported.
     
-  Module snd-cs4232
-  -----------------
-
-    Module for sound cards based on CS4232/CS4232A ISA chips.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for CS4232 chip (PnP setup - 0x534)
-    cport	- control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00)
-    mpu_port	- port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
-    fm_port	- FM port # for CS4232 chip (PnP setup - 0x388), -1 = disable
-    irq		- IRQ # for CS4232 chip (5,7,9,11,12,15)
-    mpu_irq	- IRQ # for MPU-401 UART (9,11,12,15)
-    dma1	- first DMA # for CS4232 chip (0,1,3)
-    dma2	- second DMA # for Yamaha CS4232 chip (0,1,3), -1 = disable
-    
-    This module supports multiple cards. This module does not support autoprobe
-    (if ISA PnP is not used) thus main port must be specified!!! Other ports are
-    optional.
-
-    The power-management is supported.
-    
   Module snd-cs4236
   -----------------
 
-    Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/
+    Module for sound cards based on CS4232/CS4232A,
+    	       	     	   	   CS4235/CS4236/CS4236B/CS4237B/
                                    CS4238B/CS4239 ISA chips.
 
     isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
@@ -440,6 +417,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     The power-management is supported.
 
+    This module is aliased as snd-cs4232 since it provides the old
+    snd-cs4232 functionality, too.
+
   Module snd-cs4281
   -----------------
 
-- 
cgit v1.2.3-70-g09d2


From 4dd3a29f295799295eac819bbf540690fbe30c16 Mon Sep 17 00:00:00 2001
From: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
Date: Wed, 18 Feb 2009 19:09:23 +0900
Subject: sound: fix opensound URL in oss Introduction

Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/oss/Introduction | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/oss/Introduction b/Documentation/sound/oss/Introduction
index f04ba6bb739..75d967ff926 100644
--- a/Documentation/sound/oss/Introduction
+++ b/Documentation/sound/oss/Introduction
@@ -80,7 +80,7 @@ Notes:
     additional features.
 
 2.  The commercial OSS driver may be obtained from the site:
-    http://www/opensound.com.  This may be used for cards that
+    http://www.opensound.com.  This may be used for cards that
     are unsupported by the kernel driver, or may be used
     by other operating systems.  
 
-- 
cgit v1.2.3-70-g09d2


From eca985d28e1a8092ba2686ec5485fd688df5cfb3 Mon Sep 17 00:00:00 2001
From: Krzysztof Helt <krzysztof.h1@wp.pl>
Date: Wed, 18 Feb 2009 19:07:18 +0100
Subject: sound: Remove documentation for OSS CS4232 driver

There is no OSS cs4232 driver in the kernel
any more and this documentation does not
contain any info useful for ALSA driver.

Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/oss/CS4232 | 23 -----------------------
 1 file changed, 23 deletions(-)
 delete mode 100644 Documentation/sound/oss/CS4232

(limited to 'Documentation')

diff --git a/Documentation/sound/oss/CS4232 b/Documentation/sound/oss/CS4232
deleted file mode 100644
index 7d6af7a5c1c..00000000000
--- a/Documentation/sound/oss/CS4232
+++ /dev/null
@@ -1,23 +0,0 @@
-To configure the Crystal CS423x sound chip and activate its DSP functions,
-modules may be loaded in this order:
-  
-	modprobe sound
-	insmod ad1848
-	insmod uart401
-	insmod cs4232 io=* irq=* dma=* dma2=*
-  
-This is the meaning of the parameters:
-  
-	io--I/O address of the Windows Sound System (normally 0x534)
-	irq--IRQ of this device
-	dma and dma2--DMA channels (DMA2 may be 0)
-  
-On some cards, the board attempts to do non-PnP setup, and fails.  If you
-have problems, use Linux' PnP facilities. 
-  
-To get MIDI facilities add
-  
-	insmod opl3 io=*
-  
-where "io" is the I/O address of the OPL3 synthesizer. This will be shown
-in /proc/sys/pnp and is normally 0x388.
-- 
cgit v1.2.3-70-g09d2


From f1085c4f319f1e43c95718045a235f276cc4b615 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 20 Feb 2009 14:50:35 +0100
Subject: ALSA: hda - Update documentation for pincfg sysfs entries

Added the brief descriptions of new sysfs entries for pint default
config values.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio.txt | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 99f7fbbe3e6..9c51e104546 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -365,10 +365,22 @@ modelname::
   to this file.
 init_verbs::
   The extra verbs to execute at initialization.  You can add a verb by
-  writing to this file.  Pass tree numbers, nid, verb and parameter.
+  writing to this file.  Pass three numbers: nid, verb and parameter.
 hints::
   Shows hint strings for codec parsers for any use.  Right now it's
   not used.
+init_pin_configs::
+  Shows the initial pin default config values set by BIOS.
+override_pin_configs::
+  Shows the pin default config values to override the BIOS setup.
+  Writing this (with two numbers, NID and value) appends the new
+  value.  The given will be used instead of the initial BIOS value at
+  the next reconfiguration time.
+cur_pin_configs::
+  Shows the pin default values set by the codec parser explicitly.
+  This doesn't show all pin values but only the changed values by
+  the parser.  That is, if the parser doesn't change the pin default
+  config values by itself, this will contain nothing.
 reconfig::
   Triggers the codec re-configuration.  When any value is written to
   this file, the driver re-initialize and parses the codec tree
-- 
cgit v1.2.3-70-g09d2


From b98103a5597b87211a1c74077b06faeac554bedc Mon Sep 17 00:00:00 2001
From: Andreas Herrmann <andreas.herrmann3@amd.com>
Date: Sat, 21 Feb 2009 00:09:47 +0100
Subject: x86: hpet: print HPET registers during setup (if hpet=verbose is
 used)

Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
Cc: Mark Hounschell <markh@compro.net>
Cc: Borislav Petkov <borislav.petkov@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 Documentation/kernel-parameters.txt |  4 +++-
 arch/x86/kernel/hpet.c              | 45 +++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b182626739e..01379a82264 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -492,10 +492,12 @@ and is between 256 and 4096 characters. It is defined in the file
 			Default: 64
 
 	hpet=		[X86-32,HPET] option to control HPET usage
-			Format: { enable (default) | disable | force }
+			Format: { enable (default) | disable | force |
+				verbose }
 			disable: disable HPET and use PIT instead
 			force: allow force enabled of undocumented chips (ICH4,
 			VIA, nVidia)
+			verbose: show contents of HPET registers during setup
 
 	com20020=	[HW,NET] ARCnet - COM20020 chipset
 			Format:
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index a00545fe5cd..1d86ca3c1f9 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -80,6 +80,7 @@ static inline void hpet_clear_mapping(void)
  */
 static int boot_hpet_disable;
 int hpet_force_user;
+static int hpet_verbose;
 
 static int __init hpet_setup(char *str)
 {
@@ -88,6 +89,8 @@ static int __init hpet_setup(char *str)
 			boot_hpet_disable = 1;
 		if (!strncmp("force", str, 5))
 			hpet_force_user = 1;
+		if (!strncmp("verbose", str, 7))
+			hpet_verbose = 1;
 	}
 	return 1;
 }
@@ -119,6 +122,43 @@ int is_hpet_enabled(void)
 }
 EXPORT_SYMBOL_GPL(is_hpet_enabled);
 
+static void _hpet_print_config(const char *function, int line)
+{
+	u32 i, timers, l, h;
+	printk(KERN_INFO "hpet: %s(%d):\n", function, line);
+	l = hpet_readl(HPET_ID);
+	h = hpet_readl(HPET_PERIOD);
+	timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+	printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h);
+	l = hpet_readl(HPET_CFG);
+	h = hpet_readl(HPET_STATUS);
+	printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h);
+	l = hpet_readl(HPET_COUNTER);
+	h = hpet_readl(HPET_COUNTER+4);
+	printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
+
+	for (i = 0; i < timers; i++) {
+		l = hpet_readl(HPET_Tn_CFG(i));
+		h = hpet_readl(HPET_Tn_CFG(i)+4);
+		printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n",
+		       i, l, h);
+		l = hpet_readl(HPET_Tn_CMP(i));
+		h = hpet_readl(HPET_Tn_CMP(i)+4);
+		printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n",
+		       i, l, h);
+		l = hpet_readl(HPET_Tn_ROUTE(i));
+		h = hpet_readl(HPET_Tn_ROUTE(i)+4);
+		printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n",
+		       i, l, h);
+	}
+}
+
+#define hpet_print_config()					\
+do {								\
+	if (hpet_verbose)					\
+		_hpet_print_config(__FUNCTION__, __LINE__);	\
+} while (0)
+
 /*
  * When the hpet driver (/dev/hpet) is enabled, we need to reserve
  * timer 0 and timer 1 in case of RTC emulation.
@@ -282,6 +322,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
 		hpet_writel(cmp, HPET_Tn_CMP(timer));
 		udelay(1);
 		hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+		hpet_print_config();
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -308,6 +349,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
 			irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
 			enable_irq(hdev->irq);
 		}
+		hpet_print_config();
 		break;
 	}
 }
@@ -526,6 +568,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
 
 	num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
 	num_timers++; /* Value read out starts from 0 */
+	hpet_print_config();
 
 	hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL);
 	if (!hpet_devs)
@@ -793,6 +836,7 @@ int __init hpet_enable(void)
 	 * information and the number of channels
 	 */
 	id = hpet_readl(HPET_ID);
+	hpet_print_config();
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 	/*
@@ -845,6 +889,7 @@ static __init int hpet_late_init(void)
 		return -ENODEV;
 
 	hpet_reserve_platform_timers(hpet_readl(HPET_ID));
+	hpet_print_config();
 
 	for_each_online_cpu(cpu) {
 		hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu);
-- 
cgit v1.2.3-70-g09d2


From c1cf8422f0512c2b14f0d66bce34abb0645c888a Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 20 Feb 2009 08:25:36 +0000
Subject: ip: add loose reverse path filtering

Extend existing reverse path filter option to allow strict or loose
filtering. (See http://en.wikipedia.org/wiki/Reverse_path_filtering).

For compatibility with existing usage, the value 1 is chosen for strict mode
and 2 for loose mode.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/ip-sysctl.txt | 24 +++++++++++++++---------
 net/ipv4/fib_frontend.c                |  2 +-
 2 files changed, 16 insertions(+), 10 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ff3f219ee4d..71041c21af9 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -699,16 +699,22 @@ accept_source_route - BOOLEAN
 	default TRUE (router)
 		FALSE (host)
 
-rp_filter - BOOLEAN
-	1 - do source validation by reversed path, as specified in RFC1812
-	    Recommended option for single homed hosts and stub network
-	    routers. Could cause troubles for complicated (not loop free)
-	    networks running a slow unreliable protocol (sort of RIP),
-	    or using static routes.
-
+rp_filter - INTEGER
 	0 - No source validation.
-
-	conf/all/rp_filter must also be set to TRUE to do source validation
+	1 - Strict mode as defined in RFC3704 Strict Reverse Path
+	    Each incoming packet is tested against the FIB and if the interface
+	    is not the best reverse path the packet check will fail.
+	    By default failed packets are discarded.
+	2 - Loose mode as defined in RFC3704 Loose Reverse Path
+	    Each incoming packet's source address is also tested against the FIB
+	    and if the source address is not reachable via any interface
+	    the packet check will fail.
+
+        Current recommended practice in RFC3704 is to enable strict mode
+	to prevent IP spoofin from DDos attacks. If using asymmetric routing
+        or other complicated routing,t hen loose mode is recommended.
+
+	conf/all/rp_filter must also be set to non-zero to do source validation
 	on the interface
 
 	Default value is 0. Note that some distributions enable it
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 741e4fa3e47..cafcc49d099 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -275,7 +275,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 	fib_res_put(&res);
 	if (no_addr)
 		goto last_resort;
-	if (rpf)
+	if (rpf == 1)
 		goto e_inval;
 	fl.oif = dev->ifindex;
 
-- 
cgit v1.2.3-70-g09d2


From 346ff70fdbe9093947b9494fe714c89cafcceade Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 23 Feb 2009 09:42:57 +0100
Subject: ALSA: hda - Rename {override,cur}_pin with {user,driver}_pin

Rename from override_pin and cur_pin with user_pin and driver_pin,
respectively, to be a bit more intuitive.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio.txt | 12 ++++++------
 sound/pci/hda/hda_codec.c             | 18 +++++++++---------
 sound/pci/hda/hda_codec.h             |  4 ++--
 sound/pci/hda/hda_hwdep.c             | 32 ++++++++++++++++----------------
 4 files changed, 33 insertions(+), 33 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 9c51e104546..f590850c149 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -371,16 +371,16 @@ hints::
   not used.
 init_pin_configs::
   Shows the initial pin default config values set by BIOS.
-override_pin_configs::
-  Shows the pin default config values to override the BIOS setup.
-  Writing this (with two numbers, NID and value) appends the new
-  value.  The given will be used instead of the initial BIOS value at
-  the next reconfiguration time.
-cur_pin_configs::
+driver_pin_configs::
   Shows the pin default values set by the codec parser explicitly.
   This doesn't show all pin values but only the changed values by
   the parser.  That is, if the parser doesn't change the pin default
   config values by itself, this will contain nothing.
+user_pin_configs::
+  Shows the pin default config values to override the BIOS setup.
+  Writing this (with two numbers, NID and value) appends the new
+  value.  The given will be used instead of the initial BIOS value at
+  the next reconfiguration time.
 reconfig::
   Triggers the codec re-configuration.  When any value is written to
   this file, the driver re-initialize and parses the codec tree
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 8ec2dfca9a6..df9453d0122 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -755,7 +755,7 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
 int snd_hda_codec_set_pincfg(struct hda_codec *codec,
 			     hda_nid_t nid, unsigned int cfg)
 {
-	return snd_hda_add_pincfg(codec, &codec->cur_pins, nid, cfg);
+	return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
 
@@ -764,11 +764,11 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
 {
 	struct hda_pincfg *pin;
 
-	pin = look_up_pincfg(codec, &codec->cur_pins, nid);
+	pin = look_up_pincfg(codec, &codec->driver_pins, nid);
 	if (pin)
 		return pin->cfg;
 #ifdef CONFIG_SND_HDA_HWDEP
-	pin = look_up_pincfg(codec, &codec->override_pins, nid);
+	pin = look_up_pincfg(codec, &codec->user_pins, nid);
 	if (pin)
 		return pin->cfg;
 #endif
@@ -797,12 +797,12 @@ static void free_hda_cache(struct hda_cache_rec *cache);
 /* restore the initial pin cfgs and release all pincfg lists */
 static void restore_init_pincfgs(struct hda_codec *codec)
 {
-	/* first free cur_pins and override_pins, then call restore_pincfg
+	/* first free driver_pins and user_pins, then call restore_pincfg
 	 * so that only the values in init_pins are restored
 	 */
-	snd_array_free(&codec->cur_pins);
+	snd_array_free(&codec->driver_pins);
 #ifdef CONFIG_SND_HDA_HWDEP
-	snd_array_free(&codec->override_pins);
+	snd_array_free(&codec->user_pins);
 #endif
 	restore_pincfgs(codec);
 	snd_array_free(&codec->init_pins);
@@ -874,7 +874,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
 	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
 	snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
 	snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
-	snd_array_init(&codec->cur_pins, sizeof(struct hda_pincfg), 16);
+	snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
 	if (codec->bus->modelname) {
 		codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
 		if (!codec->modelname) {
@@ -1463,8 +1463,8 @@ void snd_hda_codec_reset(struct hda_codec *codec)
 	free_hda_cache(&codec->cmd_cache);
 	init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
 	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
-	/* free only cur_pins so that init_pins + override_pins are restored */
-	snd_array_free(&codec->cur_pins);
+	/* free only driver_pins so that init_pins + user_pins are restored */
+	snd_array_free(&codec->driver_pins);
 	restore_pincfgs(codec);
 	codec->num_pcms = 0;
 	codec->pcm_info = NULL;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 6d01a8058f0..2ea628478a9 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -779,13 +779,13 @@ struct hda_codec {
 	unsigned int spdif_in_enable;	/* SPDIF input enable? */
 	hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
 	struct snd_array init_pins;	/* initial (BIOS) pin configurations */
-	struct snd_array cur_pins;	/* current pin configurations */
+	struct snd_array driver_pins;	/* pin configs set by codec parser */
 
 #ifdef CONFIG_SND_HDA_HWDEP
 	struct snd_hwdep *hwdep;	/* assigned hwdep device */
 	struct snd_array init_verbs;	/* additional init verbs */
 	struct snd_array hints;		/* additional hints */
-	struct snd_array override_pins;	/* default pin configs to override */
+	struct snd_array user_pins;	/* default pin configs to override */
 #endif
 
 	/* misc flags */
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 71039a6dec2..c660383ef38 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -109,7 +109,7 @@ static void clear_hwdep_elements(struct hda_codec *codec)
 	for (i = 0; i < codec->hints.used; i++, head++)
 		kfree(*head);
 	snd_array_free(&codec->hints);
-	snd_array_free(&codec->override_pins);
+	snd_array_free(&codec->user_pins);
 }
 
 static void hwdep_free(struct snd_hwdep *hwdep)
@@ -142,7 +142,7 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
 
 	snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
 	snd_array_init(&codec->hints, sizeof(char *), 32);
-	snd_array_init(&codec->override_pins, sizeof(struct hda_pincfg), 16);
+	snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
 
 	return 0;
 }
@@ -340,29 +340,29 @@ static ssize_t init_pin_configs_show(struct device *dev,
 	return pin_configs_show(codec, &codec->init_pins, buf);
 }
 
-static ssize_t override_pin_configs_show(struct device *dev,
-					 struct device_attribute *attr,
-					 char *buf)
+static ssize_t user_pin_configs_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
 {
 	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
 	struct hda_codec *codec = hwdep->private_data;
-	return pin_configs_show(codec, &codec->override_pins, buf);
+	return pin_configs_show(codec, &codec->user_pins, buf);
 }
 
-static ssize_t cur_pin_configs_show(struct device *dev,
-				    struct device_attribute *attr,
-				    char *buf)
+static ssize_t driver_pin_configs_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
 {
 	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
 	struct hda_codec *codec = hwdep->private_data;
-	return pin_configs_show(codec, &codec->cur_pins, buf);
+	return pin_configs_show(codec, &codec->driver_pins, buf);
 }
 
 #define MAX_PIN_CONFIGS		32
 
-static ssize_t override_pin_configs_store(struct device *dev,
-					  struct device_attribute *attr,
-					  const char *buf, size_t count)
+static ssize_t user_pin_configs_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
 {
 	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
 	struct hda_codec *codec = hwdep->private_data;
@@ -373,7 +373,7 @@ static ssize_t override_pin_configs_store(struct device *dev,
 		return -EINVAL;
 	if (!nid)
 		return -EINVAL;
-	err = snd_hda_add_pincfg(codec, &codec->override_pins, nid, cfg);
+	err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg);
 	if (err < 0)
 		return err;
 	return count;
@@ -397,8 +397,8 @@ static struct device_attribute codec_attrs[] = {
 	CODEC_ATTR_WO(init_verbs),
 	CODEC_ATTR_WO(hints),
 	CODEC_ATTR_RO(init_pin_configs),
-	CODEC_ATTR_RW(override_pin_configs),
-	CODEC_ATTR_RO(cur_pin_configs),
+	CODEC_ATTR_RW(user_pin_configs),
+	CODEC_ATTR_RO(driver_pin_configs),
 	CODEC_ATTR_WO(reconfig),
 	CODEC_ATTR_WO(clear),
 };
-- 
cgit v1.2.3-70-g09d2


From 5e7b8e0d87091ae21b291588817b5359a5e00795 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 23 Feb 2009 09:45:59 +0100
Subject: ALSA: hda - Make user_pin overriding the driver setup

Make user_pin overriding even the driver pincfg, e.g. the static / fixed
pin config table in patch_sigmatel.c.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio.txt |  3 ++-
 sound/pci/hda/hda_codec.c             | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 5 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index f590850c149..a4e5ef87af6 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -380,7 +380,8 @@ user_pin_configs::
   Shows the pin default config values to override the BIOS setup.
   Writing this (with two numbers, NID and value) appends the new
   value.  The given will be used instead of the initial BIOS value at
-  the next reconfiguration time.
+  the next reconfiguration time.  Note that this config will override
+  even the driver pin configs, too.
 reconfig::
   Triggers the codec re-configuration.  When any value is written to
   this file, the driver re-initialize and parses the codec tree
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index df9453d0122..a13480fa8e7 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -739,7 +739,9 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
 		       hda_nid_t nid, unsigned int cfg)
 {
 	struct hda_pincfg *pin;
+	unsigned int oldcfg;
 
+	oldcfg = snd_hda_codec_get_pincfg(codec, nid);
 	pin = look_up_pincfg(codec, list, nid);
 	if (!pin) {
 		pin = snd_array_new(list);
@@ -748,7 +750,13 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
 		pin->nid = nid;
 	}
 	pin->cfg = cfg;
-	set_pincfg(codec, nid, cfg);
+
+	/* change only when needed; e.g. if the pincfg is already present
+	 * in user_pins[], don't write it
+	 */
+	cfg = snd_hda_codec_get_pincfg(codec, nid);
+	if (oldcfg != cfg)
+		set_pincfg(codec, nid, cfg);
 	return 0;
 }
 
@@ -764,14 +772,14 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
 {
 	struct hda_pincfg *pin;
 
-	pin = look_up_pincfg(codec, &codec->driver_pins, nid);
-	if (pin)
-		return pin->cfg;
 #ifdef CONFIG_SND_HDA_HWDEP
 	pin = look_up_pincfg(codec, &codec->user_pins, nid);
 	if (pin)
 		return pin->cfg;
 #endif
+	pin = look_up_pincfg(codec, &codec->driver_pins, nid);
+	if (pin)
+		return pin->cfg;
 	pin = look_up_pincfg(codec, &codec->init_pins, nid);
 	if (pin)
 		return pin->cfg;
-- 
cgit v1.2.3-70-g09d2


From 39c2871eeaeeddcbecee29ec905ec528a057ca52 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 23 Feb 2009 14:14:51 +0100
Subject: ALSA: hda - Add an example about pin reconfiguration

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio.txt | 8 ++++++++
 1 file changed, 8 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index a4e5ef87af6..99958be7b45 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -391,6 +391,14 @@ clear::
   Resets the codec, removes the mixer elements and PCM stuff of the
   specified codec, and clear all init verbs and hints.
 
+For example, when you want to change the pin default configuration
+value of the pin widget 0x14 to 0x9993013f, and let the driver
+re-configure based on that state, run like below:
+------------------------------------------------------------------------
+  # echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
+  # echo 1 > /sys/class/sound/hwC0D0/reconfig  
+------------------------------------------------------------------------
+
 
 Power-Saving
 ~~~~~~~~~~~~
-- 
cgit v1.2.3-70-g09d2


From bf869c30628cc02295fb919f0d0074f296d5f129 Mon Sep 17 00:00:00 2001
From: Jesper Dangaard Brouer <jdb@comx.dk>
Date: Mon, 23 Feb 2009 04:37:55 +0000
Subject: Doc: Fix typos in ip-sysctl.txt about rp_filter.

First fix a typo in Stephens patch ;-)

Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/ip-sysctl.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 71041c21af9..e0b8c2c6171 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -711,8 +711,8 @@ rp_filter - INTEGER
 	    the packet check will fail.
 
         Current recommended practice in RFC3704 is to enable strict mode
-	to prevent IP spoofin from DDos attacks. If using asymmetric routing
-        or other complicated routing,t hen loose mode is recommended.
+	to prevent IP spoofing from DDos attacks. If using asymmetric routing
+        or other complicated routing, then loose mode is recommended.
 
 	conf/all/rp_filter must also be set to non-zero to do source validation
 	on the interface
-- 
cgit v1.2.3-70-g09d2


From e18f5feb0c851a0e77e315b3d9ef1c432b1a50ec Mon Sep 17 00:00:00 2001
From: Jesper Dangaard Brouer <jdb@comx.dk>
Date: Mon, 23 Feb 2009 04:39:04 +0000
Subject: Doc: Cleanup whitespaces in ip-sysctl.txt

Fix up whitespaces while going though ip-sysctl.txt anyway.

Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/ip-sysctl.txt | 118 ++++++++++++++++-----------------
 1 file changed, 59 insertions(+), 59 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index e0b8c2c6171..7185e4c41e5 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -2,7 +2,7 @@
 
 ip_forward - BOOLEAN
 	0 - disabled (default)
-	not 0 - enabled 
+	not 0 - enabled
 
 	Forward Packets between interfaces.
 
@@ -36,49 +36,49 @@ rt_cache_rebuild_count - INTEGER
 IP Fragmentation:
 
 ipfrag_high_thresh - INTEGER
-	Maximum memory used to reassemble IP fragments. When 
+	Maximum memory used to reassemble IP fragments. When
 	ipfrag_high_thresh bytes of memory is allocated for this purpose,
 	the fragment handler will toss packets until ipfrag_low_thresh
 	is reached.
-	
+
 ipfrag_low_thresh - INTEGER
-	See ipfrag_high_thresh	
+	See ipfrag_high_thresh
 
 ipfrag_time - INTEGER
-	Time in seconds to keep an IP fragment in memory.	
+	Time in seconds to keep an IP fragment in memory.
 
 ipfrag_secret_interval - INTEGER
-	Regeneration interval (in seconds) of the hash secret (or lifetime 
+	Regeneration interval (in seconds) of the hash secret (or lifetime
 	for the hash secret) for IP fragments.
 	Default: 600
 
 ipfrag_max_dist - INTEGER
-	ipfrag_max_dist is a non-negative integer value which defines the 
-	maximum "disorder" which is allowed among fragments which share a 
-	common IP source address. Note that reordering of packets is 
-	not unusual, but if a large number of fragments arrive from a source 
-	IP address while a particular fragment queue remains incomplete, it 
-	probably indicates that one or more fragments belonging to that queue 
-	have been lost. When ipfrag_max_dist is positive, an additional check 
-	is done on fragments before they are added to a reassembly queue - if 
-	ipfrag_max_dist (or more) fragments have arrived from a particular IP 
-	address between additions to any IP fragment queue using that source 
-	address, it's presumed that one or more fragments in the queue are 
-	lost. The existing fragment queue will be dropped, and a new one 
+	ipfrag_max_dist is a non-negative integer value which defines the
+	maximum "disorder" which is allowed among fragments which share a
+	common IP source address. Note that reordering of packets is
+	not unusual, but if a large number of fragments arrive from a source
+	IP address while a particular fragment queue remains incomplete, it
+	probably indicates that one or more fragments belonging to that queue
+	have been lost. When ipfrag_max_dist is positive, an additional check
+	is done on fragments before they are added to a reassembly queue - if
+	ipfrag_max_dist (or more) fragments have arrived from a particular IP
+	address between additions to any IP fragment queue using that source
+	address, it's presumed that one or more fragments in the queue are
+	lost. The existing fragment queue will be dropped, and a new one
 	started. An ipfrag_max_dist value of zero disables this check.
 
 	Using a very small value, e.g. 1 or 2, for ipfrag_max_dist can
 	result in unnecessarily dropping fragment queues when normal
-	reordering of packets occurs, which could lead to poor application 
-	performance. Using a very large value, e.g. 50000, increases the 
-	likelihood of incorrectly reassembling IP fragments that originate 
+	reordering of packets occurs, which could lead to poor application
+	performance. Using a very large value, e.g. 50000, increases the
+	likelihood of incorrectly reassembling IP fragments that originate
 	from different IP datagrams, which could result in data corruption.
 	Default: 64
 
 INET peer storage:
 
 inet_peer_threshold - INTEGER
-	The approximate size of the storage.  Starting from this threshold	
+	The approximate size of the storage.  Starting from this threshold
 	entries will be thrown aggressively.  This threshold also determines
 	entries' time-to-live and time intervals between garbage collection
 	passes.  More entries, less time-to-live, less GC interval.
@@ -105,7 +105,7 @@ inet_peer_gc_maxtime - INTEGER
 	in effect under low (or absent) memory pressure on the pool.
 	Measured in seconds.
 
-TCP variables: 
+TCP variables:
 
 somaxconn - INTEGER
 	Limit of socket listen() backlog, known in userspace as SOMAXCONN.
@@ -310,7 +310,7 @@ tcp_orphan_retries - INTEGER
 
 tcp_reordering - INTEGER
 	Maximal reordering of packets in a TCP stream.
-	Default: 3	
+	Default: 3
 
 tcp_retrans_collapse - BOOLEAN
 	Bug-to-bug compatibility with some broken printers.
@@ -521,7 +521,7 @@ IP Variables:
 
 ip_local_port_range - 2 INTEGERS
 	Defines the local port range that is used by TCP and UDP to
-	choose the local port. The first number is the first, the 
+	choose the local port. The first number is the first, the
 	second the last local port number. Default value depends on
 	amount of memory available on the system:
 	> 128Mb 32768-61000
@@ -594,12 +594,12 @@ icmp_errors_use_inbound_ifaddr - BOOLEAN
 
 	If zero, icmp error messages are sent with the primary address of
 	the exiting interface.
- 
+
 	If non-zero, the message will be sent with the primary address of
 	the interface that received the packet that caused the icmp error.
 	This is the behaviour network many administrators will expect from
 	a router. And it can make debugging complicated network layouts
-	much easier. 
+	much easier.
 
 	Note that if no primary address exists for the interface selected,
 	then the primary address of the first non-loopback interface that
@@ -611,7 +611,7 @@ igmp_max_memberships - INTEGER
 	Change the maximum number of multicast groups we can subscribe to.
 	Default: 20
 
-conf/interface/*  changes special settings per interface (where "interface" is 
+conf/interface/*  changes special settings per interface (where "interface" is
 		  the name of your network interface)
 conf/all/*	  is special, changes the settings for all interfaces
 
@@ -625,11 +625,11 @@ log_martians - BOOLEAN
 accept_redirects - BOOLEAN
 	Accept ICMP redirect messages.
 	accept_redirects for the interface will be enabled if:
-	- both conf/{all,interface}/accept_redirects are TRUE in the case forwarding
-	  for the interface is enabled
+	- both conf/{all,interface}/accept_redirects are TRUE in the case
+	  forwarding for the interface is enabled
 	or
-	- at least one of conf/{all,interface}/accept_redirects is TRUE in the case
-	  forwarding for the interface is disabled
+	- at least one of conf/{all,interface}/accept_redirects is TRUE in the
+	  case forwarding for the interface is disabled
 	accept_redirects for the interface will be disabled otherwise
 	default TRUE (host)
 		FALSE (router)
@@ -640,8 +640,8 @@ forwarding - BOOLEAN
 mc_forwarding - BOOLEAN
 	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
 	and a multicast routing daemon is required.
-	conf/all/mc_forwarding must also be set to TRUE to enable multicast routing
-	for the interface
+	conf/all/mc_forwarding must also be set to TRUE to enable multicast
+	routing	for the interface
 
 medium_id - INTEGER
 	Integer value used to differentiate the devices by the medium they
@@ -649,7 +649,7 @@ medium_id - INTEGER
 	the broadcast packets are received only on one of them.
 	The default value 0 means that the device is the only interface
 	to its medium, value of -1 means that medium is not known.
-	
+
 	Currently, it is used to change the proxy_arp behavior:
 	the proxy_arp feature is enabled for packets forwarded between
 	two devices attached to different media.
@@ -710,9 +710,9 @@ rp_filter - INTEGER
 	    and if the source address is not reachable via any interface
 	    the packet check will fail.
 
-        Current recommended practice in RFC3704 is to enable strict mode
+	Current recommended practice in RFC3704 is to enable strict mode
 	to prevent IP spoofing from DDos attacks. If using asymmetric routing
-        or other complicated routing, then loose mode is recommended.
+	or other complicated routing, then loose mode is recommended.
 
 	conf/all/rp_filter must also be set to non-zero to do source validation
 	on the interface
@@ -835,7 +835,7 @@ apply to IPv6 [XXX?].
 
 bindv6only - BOOLEAN
 	Default value for IPV6_V6ONLY socket option,
-	which restricts use of the IPv6 socket to IPv6 communication 
+	which restricts use of the IPv6 socket to IPv6 communication
 	only.
 		TRUE: disable IPv4-mapped address feature
 		FALSE: enable IPv4-mapped address feature
@@ -845,19 +845,19 @@ bindv6only - BOOLEAN
 IPv6 Fragmentation:
 
 ip6frag_high_thresh - INTEGER
-	Maximum memory used to reassemble IPv6 fragments. When 
+	Maximum memory used to reassemble IPv6 fragments. When
 	ip6frag_high_thresh bytes of memory is allocated for this purpose,
 	the fragment handler will toss packets until ip6frag_low_thresh
 	is reached.
-	
+
 ip6frag_low_thresh - INTEGER
-	See ip6frag_high_thresh	
+	See ip6frag_high_thresh
 
 ip6frag_time - INTEGER
 	Time in seconds to keep an IPv6 fragment in memory.
 
 ip6frag_secret_interval - INTEGER
-	Regeneration interval (in seconds) of the hash secret (or lifetime 
+	Regeneration interval (in seconds) of the hash secret (or lifetime
 	for the hash secret) for IPv6 fragments.
 	Default: 600
 
@@ -866,17 +866,17 @@ conf/default/*:
 
 
 conf/all/*:
-	Change all the interface-specific settings.  
+	Change all the interface-specific settings.
 
 	[XXX:  Other special features than forwarding?]
 
 conf/all/forwarding - BOOLEAN
-	Enable global IPv6 forwarding between all interfaces.  
+	Enable global IPv6 forwarding between all interfaces.
 
-	IPv4 and IPv6 work differently here; e.g. netfilter must be used 
+	IPv4 and IPv6 work differently here; e.g. netfilter must be used
 	to control which interfaces may forward packets and which not.
 
-	This also sets all interfaces' Host/Router setting 
+	This also sets all interfaces' Host/Router setting
 	'forwarding' to the specified value.  See below for details.
 
 	This referred to as global forwarding.
@@ -887,12 +887,12 @@ proxy_ndp - BOOLEAN
 conf/interface/*:
 	Change special settings per interface.
 
-	The functional behaviour for certain settings is different 
+	The functional behaviour for certain settings is different
 	depending on whether local forwarding is enabled or not.
 
 accept_ra - BOOLEAN
 	Accept Router Advertisements; autoconfigure using them.
-	
+
 	Functional default: enabled if local forwarding is disabled.
 			    disabled if local forwarding is enabled.
 
@@ -938,7 +938,7 @@ accept_source_route - INTEGER
 	Default: 0
 
 autoconf - BOOLEAN
-	Autoconfigure addresses using Prefix Information in Router 
+	Autoconfigure addresses using Prefix Information in Router
 	Advertisements.
 
 	Functional default: enabled if accept_ra_pinfo is enabled.
@@ -947,11 +947,11 @@ autoconf - BOOLEAN
 dad_transmits - INTEGER
 	The amount of Duplicate Address Detection probes to send.
 	Default: 1
-	
+
 forwarding - BOOLEAN
-	Configure interface-specific Host/Router behaviour.  
+	Configure interface-specific Host/Router behaviour.
 
-	Note: It is recommended to have the same setting on all 
+	Note: It is recommended to have the same setting on all
 	interfaces; mixed router/host scenarios are rather uncommon.
 
 	FALSE:
@@ -960,13 +960,13 @@ forwarding - BOOLEAN
 
 	1. IsRouter flag is not set in Neighbour Advertisements.
 	2. Router Solicitations are being sent when necessary.
-	3. If accept_ra is TRUE (default), accept Router 
+	3. If accept_ra is TRUE (default), accept Router
 	   Advertisements (and do autoconfiguration).
 	4. If accept_redirects is TRUE (default), accept Redirects.
 
 	TRUE:
 
-	If local forwarding is enabled, Router behaviour is assumed. 
+	If local forwarding is enabled, Router behaviour is assumed.
 	This means exactly the reverse from the above:
 
 	1. IsRouter flag is set in Neighbour Advertisements.
@@ -1001,7 +1001,7 @@ router_solicitation_interval - INTEGER
 	Default: 4
 
 router_solicitations - INTEGER
-	Number of Router Solicitations to send until assuming no 
+	Number of Router Solicitations to send until assuming no
 	routers are present.
 	Default: 3
 
@@ -1025,11 +1025,11 @@ temp_prefered_lft - INTEGER
 
 max_desync_factor - INTEGER
 	Maximum value for DESYNC_FACTOR, which is a random value
-	that ensures that clients don't synchronize with each 
+	that ensures that clients don't synchronize with each
 	other and generate new addresses at exactly the same time.
 	value is in seconds.
 	Default: 600
-	
+
 regen_max_retry - INTEGER
 	Number of attempts before give up attempting to generate
 	valid temporary addresses.
@@ -1037,8 +1037,8 @@ regen_max_retry - INTEGER
 
 max_addresses - INTEGER
 	Number of maximum addresses per interface.  0 disables limitation.
-	It is recommended not set too large value (or 0) because it would 
-	be too easy way to crash kernel to allow to create too much of 
+	It is recommended not set too large value (or 0) because it would
+	be too easy way to crash kernel to allow to create too much of
 	autoconfigured addresses.
 	Default: 16
 
-- 
cgit v1.2.3-70-g09d2


From ed12978453a3845c947695e7ad32bb3ede444813 Mon Sep 17 00:00:00 2001
From: Thomas Renninger <trenn@suse.de>
Date: Wed, 4 Feb 2009 01:17:41 +0100
Subject: [CPUFREQ] Introduce
 /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_transition_latency

It's not only useful for the ondemand and conservative governors, but
also for userspace daemons to know about the HW transition latency of
the CPU.
It is especially useful for userspace to know about this value when
the ondemand or conservative governors are run. The sampling rate
control value depends on it and for userspace being able to set sane
tuning values there it has to know about the transition latency.

Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 Documentation/cpu-freq/user-guide.txt | 12 ++++++++++++
 drivers/cpufreq/cpufreq.c             |  3 +++
 2 files changed, 15 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
index 917918f84fc..75f41193f3e 100644
--- a/Documentation/cpu-freq/user-guide.txt
+++ b/Documentation/cpu-freq/user-guide.txt
@@ -152,6 +152,18 @@ cpuinfo_min_freq :		this file shows the minimum operating
 				frequency the processor can run at(in kHz) 
 cpuinfo_max_freq :		this file shows the maximum operating
 				frequency the processor can run at(in kHz) 
+cpuinfo_transition_latency	The time it takes on this CPU to
+				switch between two frequencies in nano
+				seconds. If unknown or known to be
+				that high that the driver does not
+				work with the ondemand governor, -1
+				(CPUFREQ_ETERNAL) will be returned.
+				Using this information can be useful
+				to choose an appropriate polling
+				frequency for a kernel governor or
+				userspace daemon. Make sure to not
+				switch the frequency too often
+				resulting in performance loss.
 scaling_driver :		this file shows what cpufreq driver is
 				used to set the frequency on this CPU
 
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 1867dac35af..6fe466efb0b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -452,6 +452,7 @@ static ssize_t show_##file_name				\
 
 show_one(cpuinfo_min_freq, cpuinfo.min_freq);
 show_one(cpuinfo_max_freq, cpuinfo.max_freq);
+show_one(cpuinfo_transition_latency, cpuinfo.transition_latency);
 show_one(scaling_min_freq, min);
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
@@ -659,6 +660,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
 define_one_ro0400(cpuinfo_cur_freq);
 define_one_ro(cpuinfo_min_freq);
 define_one_ro(cpuinfo_max_freq);
+define_one_ro(cpuinfo_transition_latency);
 define_one_ro(scaling_available_governors);
 define_one_ro(scaling_driver);
 define_one_ro(scaling_cur_freq);
@@ -672,6 +674,7 @@ define_one_rw(scaling_setspeed);
 static struct attribute *default_attrs[] = {
 	&cpuinfo_min_freq.attr,
 	&cpuinfo_max_freq.attr,
+	&cpuinfo_transition_latency.attr,
 	&scaling_min_freq.attr,
 	&scaling_max_freq.attr,
 	&affected_cpus.attr,
-- 
cgit v1.2.3-70-g09d2


From 9411b4ef7fcb534fe1582fe02738254e398dd931 Mon Sep 17 00:00:00 2001
From: Thomas Renninger <trenn@suse.de>
Date: Wed, 4 Feb 2009 11:54:04 +0100
Subject: [CPUFREQ] ondemand/conservative: deprecate sampling_rate{min,max}

The same info can be obtained via the transition_latency sysfs file

Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 Documentation/cpu-freq/governors.txt   | 10 ++++++++--
 drivers/cpufreq/cpufreq_conservative.c | 15 +++++++++++++++
 drivers/cpufreq/cpufreq_ondemand.c     | 17 +++++++++++++++++
 3 files changed, 40 insertions(+), 2 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 5b0cfa67aff..9b1851297d4 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -119,8 +119,14 @@ want the kernel to look at the CPU usage and to make decisions on
 what to do about the frequency.  Typically this is set to values of
 around '10000' or more.
 
-show_sampling_rate_(min|max): the minimum and maximum sampling rates
-available that you may set 'sampling_rate' to.
+show_sampling_rate_(min|max): THIS INTERFACE IS DEPRECATED, DON'T USE IT.
+You can use wider ranges now and the general
+cpuinfo_transition_latency variable (cmp. with user-guide.txt) can be
+used to obtain exactly the same info:
+show_sampling_rate_min = transtition_latency * 500    / 1000
+show_sampling_rate_max = transtition_latency * 500000 / 1000
+(divided by 1000 is to illustrate that sampling rate is in us and
+transition latency is exported ns).
 
 up_threshold: defines what the average CPU usage between the samplings
 of 'sampling_rate' needs to be for the kernel to make a decision on
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index c6b3c6a02fc..0912d7ca8cd 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -140,11 +140,26 @@ static struct notifier_block dbs_cpufreq_notifier_block = {
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
 {
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
+		       "sysfs file is deprecated - used by: %s\n",
+		       current->comm);
+		print_once = 1;
+	}
 	return sprintf(buf, "%u\n", MAX_SAMPLING_RATE);
 }
 
 static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
 {
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
+		       "sysfs file is deprecated - used by: %s\n", current->comm);
+		print_once = 1;
+	}
 	return sprintf(buf, "%u\n", MIN_SAMPLING_RATE);
 }
 
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 1fa4420eb33..32ddeaa4224 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -21,6 +21,7 @@
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 #include <linux/ktime.h>
+#include <linux/sched.h>
 
 /*
  * dbs is used in this file as a shortform for demandbased switching
@@ -203,11 +204,27 @@ static void ondemand_powersave_bias_init(void)
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
 {
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_max "
+		       "sysfs file is deprecated - used by: %s\n",
+		       current->comm);
+		print_once = 1;
+	}
 	return sprintf(buf, "%u\n", MAX_SAMPLING_RATE);
 }
 
 static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
 {
+	static int print_once;
+
+	if (!print_once) {
+		printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_min "
+		       "sysfs file is deprecated - used by: %s\n",
+		       current->comm);
+		print_once = 1;
+	}
 	return sprintf(buf, "%u\n", MIN_SAMPLING_RATE);
 }
 
-- 
cgit v1.2.3-70-g09d2


From 112124ab0a9f507a0d7fdbb1e1ed2b9a24f8c4ea Mon Sep 17 00:00:00 2001
From: Thomas Renninger <trenn@suse.de>
Date: Wed, 4 Feb 2009 11:55:12 +0100
Subject: [CPUFREQ] ondemand/conservative: sanitize sampling_rate restrictions

Limit sampling rate to transition_latency * 100 or kernel limits.
If sampling_rate is tried to be set too low, set the lowest allowed value.

Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 Documentation/cpu-freq/governors.txt   | 14 +++++++++++++-
 drivers/cpufreq/cpufreq_conservative.c | 28 ++++++++++++++++++----------
 drivers/cpufreq/cpufreq_ondemand.c     | 28 ++++++++++++++++++----------
 3 files changed, 49 insertions(+), 21 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 9b1851297d4..ce73f3eb5dd 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -117,7 +117,19 @@ accessible parameters:
 sampling_rate: measured in uS (10^-6 seconds), this is how often you
 want the kernel to look at the CPU usage and to make decisions on
 what to do about the frequency.  Typically this is set to values of
-around '10000' or more.
+around '10000' or more. It's default value is (cmp. with users-guide.txt):
+transition_latency * 1000
+The lowest value you can set is:
+transition_latency * 100 or it may get restricted to a value where it
+makes not sense for the kernel anymore to poll that often which depends
+on your HZ config variable (HZ=1000: max=20000us, HZ=250: max=5000).
+Be aware that transition latency is in ns and sampling_rate is in us, so you
+get the same sysfs value by default.
+Sampling rate should always get adjusted considering the transition latency
+To set the sampling rate 750 times as high as the transition latency
+in the bash (as said, 1000 is default), do:
+echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) \
+    >ondemand/sampling_rate
 
 show_sampling_rate_(min|max): THIS INTERFACE IS DEPRECATED, DON'T USE IT.
 You can use wider ranges now and the general
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 0912d7ca8cd..8d541c69aec 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -54,8 +54,20 @@ static unsigned int def_sampling_rate;
 			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
 #define MIN_SAMPLING_RATE			\
 			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon
+ * Define the minimal settable sampling rate to the greater of:
+ *   - "HW transition latency" * 100 (same as default sampling / 10)
+ *   - MIN_STAT_SAMPLING_RATE
+ * To avoid that userspace shoots itself.
+*/
+static unsigned int minimum_sampling_rate(void)
+{
+	return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE);
+}
+
+/* This will also vanish soon with removing sampling_rate_max */
 #define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
-#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER	(1000)
+#define LATENCY_MULTIPLIER			(1000)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(10)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
@@ -208,13 +220,11 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
 	ret = sscanf(buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > MAX_SAMPLING_RATE ||
-	    input < MIN_SAMPLING_RATE) {
+	if (ret != 1) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
-
-	dbs_tuners_ins.sampling_rate = input;
+	dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate());
 	mutex_unlock(&dbs_mutex);
 
 	return count;
@@ -540,11 +550,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 			if (latency == 0)
 				latency = 1;
 
-			def_sampling_rate = 10 * latency *
-					DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
-
-			if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
-				def_sampling_rate = MIN_STAT_SAMPLING_RATE;
+			def_sampling_rate =
+				max(10 * latency * LATENCY_MULTIPLIER,
+				    MIN_STAT_SAMPLING_RATE);
 
 			dbs_tuners_ins.sampling_rate = def_sampling_rate;
 
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 32ddeaa4224..338f428a15b 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -52,8 +52,20 @@ static unsigned int def_sampling_rate;
 			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
 #define MIN_SAMPLING_RATE			\
 			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon
+ * Define the minimal settable sampling rate to the greater of:
+ *   - "HW transition latency" * 100 (same as default sampling / 10)
+ *   - MIN_STAT_SAMPLING_RATE
+ * To avoid that userspace shoots itself.
+*/
+static unsigned int minimum_sampling_rate(void)
+{
+	return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE);
+}
+
+/* This will also vanish soon with removing sampling_rate_max */
 #define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
-#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER	(1000)
+#define LATENCY_MULTIPLIER			(1000)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
 
 static void do_dbs_timer(struct work_struct *work);
@@ -255,13 +267,11 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
 	ret = sscanf(buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > MAX_SAMPLING_RATE
-		     || input < MIN_SAMPLING_RATE) {
+	if (ret != 1) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
-
-	dbs_tuners_ins.sampling_rate = input;
+	dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate());
 	mutex_unlock(&dbs_mutex);
 
 	return count;
@@ -607,11 +617,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 			if (latency == 0)
 				latency = 1;
 
-			def_sampling_rate = latency *
-					DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
-
-			if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
-				def_sampling_rate = MIN_STAT_SAMPLING_RATE;
+			def_sampling_rate =
+				max(latency * LATENCY_MULTIPLIER,
+				    MIN_STAT_SAMPLING_RATE);
 
 			dbs_tuners_ins.sampling_rate = def_sampling_rate;
 		}
-- 
cgit v1.2.3-70-g09d2


From 9e5f6cf5f755ca5c52071c317421fae19966a658 Mon Sep 17 00:00:00 2001
From: Andreas Herrmann <andreas.herrmann3@amd.com>
Date: Wed, 25 Feb 2009 11:30:45 +0100
Subject: x86: update description for memtest boot parameter

Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 Documentation/kernel-parameters.txt | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f6d5d5b9b2b..10c4b8b75c9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1308,8 +1308,13 @@ and is between 256 and 4096 characters. It is defined in the file
 
 	memtest=	[KNL,X86] Enable memtest
 			Format: <integer>
-			range: 0,4 : pattern number
 			default : 0 <disable>
+			Specifies the number of memtest passes to be
+			performed. Each pass selects another test
+			pattern from a given set of patterns. Memtest
+			fills the memory with this pattern, validates
+			memory contents and reserves bad memory
+			regions that are detected.
 
 	meye.*=		[HW] Set MotionEye Camera parameters
 			See Documentation/video4linux/meye.txt.
-- 
cgit v1.2.3-70-g09d2


From 930738de602d2ceb0d1c1b368fe2a8d2a974ab72 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Thu, 26 Feb 2009 09:27:20 +0100
Subject: sound: virtuoso: add Xonar Essence STX support

Add support for the Asus Xonar Essence STX sound card.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/ALSA-Configuration.txt |   2 +-
 sound/pci/Kconfig                               |   3 +-
 sound/pci/oxygen/virtuoso.c                     | 192 ++++++++++++++++++++++++
 3 files changed, 195 insertions(+), 2 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 841a9365d5f..1356d2a6772 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1824,7 +1824,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   -------------------
 
     Module for sound cards based on the Asus AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe).
+    i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX.
 
     This module supports autoprobe and multiple cards.
 
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 82b9bddcdcd..21d117ada84 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -744,7 +744,8 @@ config SND_VIRTUOSO
 	select SND_OXYGEN_LIB
 	help
 	  Say Y here to include support for sound cards based on the
-	  Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X.
+	  Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and
+	  Essence STX.
 	  Support for the HDAV1.3 (Deluxe) is very experimental.
 
 	  To compile this driver as a module, choose M here: the module
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 00dc97806f1..bc5ce11c8b1 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -112,6 +112,34 @@
  * CS4362A: AD0 <- 0
  */
 
+/*
+ * Xonar Essence STX
+ * -----------------
+ *
+ * CMI8788:
+ *
+ * I²C <-> PCM1792A
+ *
+ * GPI 0 <- external power present
+ *
+ * GPIO 0 -> enable output to speakers
+ * GPIO 1 -> route HP to front panel (0) or rear jack (1)
+ * GPIO 2 -> M0 of CS5381
+ * GPIO 3 -> M1 of CS5381
+ * GPIO 7 -> route output to speaker jacks (0) or HP (1)
+ * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
+ *
+ * PCM1792A:
+ *
+ * AD0 <- 0
+ *
+ * H6 daughterboard
+ * ----------------
+ *
+ * GPIO 4 <- 0
+ * GPIO 5 <- 0
+ */
+
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
@@ -152,6 +180,7 @@ enum {
 	MODEL_DX,
 	MODEL_HDAV,	/* without daughterboard */
 	MODEL_HDAV_H6,	/* with H6 daughterboard */
+	MODEL_STX,
 };
 
 static struct pci_device_id xonar_ids[] __devinitdata = {
@@ -160,6 +189,7 @@ static struct pci_device_id xonar_ids[] __devinitdata = {
 	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 },
+	{ OXYGEN_PCI_SUBID(0x1043, 0x835c), .driver_data = MODEL_STX },
 	{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
 	{ }
 };
@@ -184,6 +214,9 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
 #define GPIO_HDAV_DB_H6		0x0000
 #define GPIO_HDAV_DB_XX		0x0020
 
+#define GPIO_ST_HP_REAR		0x0002
+#define GPIO_ST_HP		0x0080
+
 #define I2C_DEVICE_PCM1796(i)	(0x98 + ((i) << 1))	/* 10011, ADx=i, /W=0 */
 #define I2C_DEVICE_CS4398	0x9e	/* 10011, AD1=1, AD0=1, /W=0 */
 #define I2C_DEVICE_CS4362A	0x30	/* 001100, AD0=0, /W=0 */
@@ -497,6 +530,36 @@ static void xonar_hdav_init(struct oxygen *chip)
 	snd_component_add(chip->card, "CS5381");
 }
 
+static void xonar_stx_init(struct oxygen *chip)
+{
+	struct xonar_data *data = chip->model_data;
+
+	oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
+		       OXYGEN_2WIRE_LENGTH_8 |
+		       OXYGEN_2WIRE_INTERRUPT_MASK |
+		       OXYGEN_2WIRE_SPEED_FAST);
+
+	data->anti_pop_delay = 100;
+	data->dacs = 1;
+	data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
+	data->ext_power_reg = OXYGEN_GPI_DATA;
+	data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
+	data->ext_power_bit = GPI_DX_EXT_POWER;
+	data->pcm1796_oversampling = PCM1796_OS_64;
+
+	pcm1796_init(chip);
+
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+			  GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
+	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
+			    GPIO_DX_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP);
+
+	xonar_common_init(chip);
+
+	snd_component_add(chip->card, "PCM1792A");
+	snd_component_add(chip->card, "CS5381");
+}
+
 static void xonar_disable_output(struct oxygen *chip)
 {
 	struct xonar_data *data = chip->model_data;
@@ -524,6 +587,11 @@ static void xonar_hdav_cleanup(struct oxygen *chip)
 	xonar_disable_output(chip);
 }
 
+static void xonar_st_cleanup(struct oxygen *chip)
+{
+	xonar_disable_output(chip);
+}
+
 static void xonar_d2_suspend(struct oxygen *chip)
 {
 	xonar_d2_cleanup(chip);
@@ -540,6 +608,11 @@ static void xonar_hdav_suspend(struct oxygen *chip)
 	msleep(2);
 }
 
+static void xonar_st_suspend(struct oxygen *chip)
+{
+	xonar_st_cleanup(chip);
+}
+
 static void xonar_d2_resume(struct oxygen *chip)
 {
 	pcm1796_init(chip);
@@ -567,6 +640,12 @@ static void xonar_hdav_resume(struct oxygen *chip)
 	xonar_enable_output(chip);
 }
 
+static void xonar_st_resume(struct oxygen *chip)
+{
+	pcm1796_init(chip);
+	xonar_enable_output(chip);
+}
+
 static void xonar_hdav_pcm_hardware_filter(unsigned int channel,
 					   struct snd_pcm_hardware *hardware)
 {
@@ -746,6 +825,72 @@ static const struct snd_kcontrol_new front_panel_switch = {
 	.private_value = GPIO_DX_FRONT_PANEL,
 };
 
+static int st_output_switch_info(struct snd_kcontrol *ctl,
+				 struct snd_ctl_elem_info *info)
+{
+	static const char *const names[3] = {
+		"Speakers", "Headphones", "FP Headphones"
+	};
+
+	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	info->count = 1;
+	info->value.enumerated.items = 3;
+	if (info->value.enumerated.item >= 3)
+		info->value.enumerated.item = 2;
+	strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
+	return 0;
+}
+
+static int st_output_switch_get(struct snd_kcontrol *ctl,
+				struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	u16 gpio;
+
+	gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+	if (!(gpio & GPIO_ST_HP))
+		value->value.enumerated.item[0] = 0;
+	else if (gpio & GPIO_ST_HP_REAR)
+		value->value.enumerated.item[0] = 1;
+	else
+		value->value.enumerated.item[0] = 2;
+	return 0;
+}
+
+
+static int st_output_switch_put(struct snd_kcontrol *ctl,
+				struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	u16 gpio_old, gpio;
+
+	mutex_lock(&chip->mutex);
+	gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+	gpio = gpio_old;
+	switch (value->value.enumerated.item[0]) {
+	case 0:
+		gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR);
+		break;
+	case 1:
+		gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR;
+		break;
+	case 2:
+		gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR;
+		break;
+	}
+	oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
+	mutex_unlock(&chip->mutex);
+	return gpio != gpio_old;
+}
+
+static const struct snd_kcontrol_new st_output_switch = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Analog Output",
+	.info = st_output_switch_info,
+	.get = st_output_switch_get,
+	.put = st_output_switch_put,
+};
+
 static void xonar_line_mic_ac97_switch(struct oxygen *chip,
 				       unsigned int reg, unsigned int mute)
 {
@@ -776,6 +921,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
 	return 0;
 }
 
+static int xonar_st_control_filter(struct snd_kcontrol_new *template)
+{
+	if (!strncmp(template->name, "CD Capture ", 11))
+		return 1; /* no CD input */
+	if (!strcmp(template->name, "Stereo Upmixing"))
+		return 1; /* stereo only - we don't need upmixing */
+	return 0;
+}
+
 static int xonar_d2_mixer_init(struct oxygen *chip)
 {
 	return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
@@ -786,6 +940,11 @@ static int xonar_d1_mixer_init(struct oxygen *chip)
 	return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
 }
 
+static int xonar_st_mixer_init(struct oxygen *chip)
+{
+	return snd_ctl_add(chip->card, snd_ctl_new1(&st_output_switch, chip));
+}
+
 static const struct oxygen_model model_xonar_d2 = {
 	.longname = "Asus Virtuoso 200",
 	.chip = "AV200",
@@ -872,6 +1031,33 @@ static const struct oxygen_model model_xonar_hdav = {
 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
+static const struct oxygen_model model_xonar_st = {
+	.longname = "Asus Virtuoso 100",
+	.chip = "AV200",
+	.init = xonar_stx_init,
+	.control_filter = xonar_st_control_filter,
+	.mixer_init = xonar_st_mixer_init,
+	.cleanup = xonar_st_cleanup,
+	.suspend = xonar_st_suspend,
+	.resume = xonar_st_resume,
+	.set_dac_params = set_pcm1796_params,
+	.set_adc_params = set_cs53x1_params,
+	.update_dac_volume = update_pcm1796_volume,
+	.update_dac_mute = update_pcm1796_mute,
+	.ac97_switch = xonar_line_mic_ac97_switch,
+	.dac_tlv = pcm1796_db_scale,
+	.model_data_size = sizeof(struct xonar_data),
+	.device_config = PLAYBACK_0_TO_I2S |
+			 PLAYBACK_1_TO_SPDIF |
+			 CAPTURE_0_FROM_I2S_2,
+	.dac_channels = 2,
+	.dac_volume_min = 255 - 2*60,
+	.dac_volume_max = 255,
+	.function_flags = OXYGEN_FUNCTION_2WIRE,
+	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+};
+
 static int __devinit get_xonar_model(struct oxygen *chip,
 				     const struct pci_device_id *id)
 {
@@ -881,6 +1067,7 @@ static int __devinit get_xonar_model(struct oxygen *chip,
 		[MODEL_D2]	= &model_xonar_d2,
 		[MODEL_D2X]	= &model_xonar_d2,
 		[MODEL_HDAV]	= &model_xonar_hdav,
+		[MODEL_STX]	= &model_xonar_st,
 	};
 	static const char *const names[] = {
 		[MODEL_D1]	= "Xonar D1",
@@ -889,6 +1076,7 @@ static int __devinit get_xonar_model(struct oxygen *chip,
 		[MODEL_D2X]	= "Xonar D2X",
 		[MODEL_HDAV]	= "Xonar HDAV1.3",
 		[MODEL_HDAV_H6]	= "Xonar HDAV1.3+H6",
+		[MODEL_STX]	= "Xonar Essence STX",
 	};
 	unsigned int model = id->driver_data;
 
@@ -916,6 +1104,10 @@ static int __devinit get_xonar_model(struct oxygen *chip,
 			return -ENODEV;
 		}
 		break;
+	case MODEL_STX:
+		oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
+				    GPIO_HDAV_DB_MASK);
+		break;
 	}
 
 	chip->model.shortname = names[model];
-- 
cgit v1.2.3-70-g09d2


From 1607b8ea0a4cc20752978fadb027daafc8a2d93c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 26 Feb 2009 16:50:43 +0100
Subject: ALSA: hda - Add model=auto for STAC/IDT codecs

Added the model=auto to STAC/IDT codecs to use the BIOS default setup
explicitly.  It can be used to disable the device-specific model quirk
in the driver.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt |  8 ++++++++
 sound/pci/hda/patch_sigmatel.c               | 16 ++++++++++++++++
 2 files changed, 24 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 0e52d273ce9..a448bbefd48 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -280,6 +280,7 @@ STAC9200
   gateway-m4	Gateway laptops with EAPD control
   gateway-m4-2	Gateway laptops with EAPD control
   panasonic	Panasonic CF-74
+  auto		BIOS setup (default)
 
 STAC9205/9254
 =============
@@ -288,6 +289,7 @@ STAC9205/9254
   dell-m43	Dell Precision
   dell-m44	Dell Inspiron
   eapd		Keep EAPD on (e.g. Gateway T1616)
+  auto		BIOS setup (default)
 
 STAC9220/9221
 =============
@@ -311,6 +313,7 @@ STAC9220/9221
   dell-d82	Dell (unknown)
   dell-m81	Dell (unknown)
   dell-m82	Dell XPS M1210
+  auto		BIOS setup (default)
 
 STAC9202/9250/9251
 ==================
@@ -322,6 +325,7 @@ STAC9202/9250/9251
   m3		Some Gateway MX series laptops
   m5		Some Gateway MX series laptops (MP6954)
   m6		Some Gateway NX series laptops
+  auto		BIOS setup (default)
 
 STAC9227/9228/9229/927x
 =======================
@@ -331,6 +335,7 @@ STAC9227/9228/9229/927x
   5stack	D965 5stack + SPDIF
   dell-3stack	Dell Dimension E520
   dell-bios	Fixes with Dell BIOS setup
+  auto		BIOS setup (default)
 
 STAC92HD71B*
 ============
@@ -339,6 +344,7 @@ STAC92HD71B*
   dell-m4-2	Dell desktops
   dell-m4-3	Dell desktops
   hp-m4		HP dv laptops
+  auto		BIOS setup (default)
 
 STAC92HD73*
 ===========
@@ -348,11 +354,13 @@ STAC92HD73*
   dell-m6-dmic	Dell desktops/laptops with digital mics
   dell-m6	Dell desktops/laptops with both type of mics
   dell-eq	Dell desktops/laptops
+  auto		BIOS setup (default)
 
 STAC92HD83*
 ===========
   ref		Reference board
   mic-ref	Reference board with power managment for ports
+  auto		BIOS setup (default)
 
 STAC9872
 ========
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index da48d8c0b29..37ffd96a9ff 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -43,6 +43,7 @@ enum {
 };
 
 enum {
+	STAC_AUTO,
 	STAC_REF,
 	STAC_9200_OQO,
 	STAC_9200_DELL_D21,
@@ -62,6 +63,7 @@ enum {
 };
 
 enum {
+	STAC_9205_AUTO,
 	STAC_9205_REF,
 	STAC_9205_DELL_M42,
 	STAC_9205_DELL_M43,
@@ -71,6 +73,7 @@ enum {
 };
 
 enum {
+	STAC_92HD73XX_AUTO,
 	STAC_92HD73XX_NO_JD, /* no jack-detection */
 	STAC_92HD73XX_REF,
 	STAC_DELL_M6_AMIC,
@@ -81,6 +84,7 @@ enum {
 };
 
 enum {
+	STAC_92HD83XXX_AUTO,
 	STAC_92HD83XXX_REF,
 	STAC_92HD83XXX_PWR_REF,
 	STAC_DELL_S14,
@@ -88,6 +92,7 @@ enum {
 };
 
 enum {
+	STAC_92HD71BXX_AUTO,
 	STAC_92HD71BXX_REF,
 	STAC_DELL_M4_1,
 	STAC_DELL_M4_2,
@@ -98,6 +103,7 @@ enum {
 };
 
 enum {
+	STAC_925x_AUTO,
 	STAC_925x_REF,
 	STAC_M1,
 	STAC_M1_2,
@@ -110,6 +116,7 @@ enum {
 };
 
 enum {
+	STAC_922X_AUTO,
 	STAC_D945_REF,
 	STAC_D945GTP3,
 	STAC_D945GTP5,
@@ -137,6 +144,7 @@ enum {
 };
 
 enum {
+	STAC_927X_AUTO,
 	STAC_D965_REF_NO_JD, /* no jack-detection */
 	STAC_D965_REF,
 	STAC_D965_3ST,
@@ -1488,6 +1496,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
 };
 
 static const char *stac9200_models[STAC_9200_MODELS] = {
+	[STAC_AUTO] = "auto",
 	[STAC_REF] = "ref",
 	[STAC_9200_OQO] = "oqo",
 	[STAC_9200_DELL_D21] = "dell-d21",
@@ -1633,6 +1642,7 @@ static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
 };
 
 static const char *stac925x_models[STAC_925x_MODELS] = {
+	[STAC_925x_AUTO] = "auto",
 	[STAC_REF] = "ref",
 	[STAC_M1] = "m1",
 	[STAC_M1_2] = "m1-2",
@@ -1692,6 +1702,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
 };
 
 static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
+	[STAC_92HD73XX_AUTO] = "auto",
 	[STAC_92HD73XX_NO_JD] = "no-jd",
 	[STAC_92HD73XX_REF] = "ref",
 	[STAC_DELL_M6_AMIC] = "dell-m6-amic",
@@ -1748,6 +1759,7 @@ static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
 };
 
 static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
+	[STAC_92HD83XXX_AUTO] = "auto",
 	[STAC_92HD83XXX_REF] = "ref",
 	[STAC_92HD83XXX_PWR_REF] = "mic-ref",
 	[STAC_DELL_S14] = "dell-s14",
@@ -1802,6 +1814,7 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
 };
 
 static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
+	[STAC_92HD71BXX_AUTO] = "auto",
 	[STAC_92HD71BXX_REF] = "ref",
 	[STAC_DELL_M4_1] = "dell-m4-1",
 	[STAC_DELL_M4_2] = "dell-m4-2",
@@ -1973,6 +1986,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
 };
 
 static const char *stac922x_models[STAC_922X_MODELS] = {
+	[STAC_922X_AUTO] = "auto",
 	[STAC_D945_REF]	= "ref",
 	[STAC_D945GTP5]	= "5stack",
 	[STAC_D945GTP3]	= "3stack",
@@ -2125,6 +2139,7 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
 };
 
 static const char *stac927x_models[STAC_927X_MODELS] = {
+	[STAC_927X_AUTO]	= "auto",
 	[STAC_D965_REF_NO_JD]	= "ref-no-jd",
 	[STAC_D965_REF]		= "ref",
 	[STAC_D965_3ST]		= "3stack",
@@ -2222,6 +2237,7 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
 };
 
 static const char *stac9205_models[STAC_9205_MODELS] = {
+	[STAC_9205_AUTO] = "auto",
 	[STAC_9205_REF] = "ref",
 	[STAC_9205_DELL_M42] = "dell-m42",
 	[STAC_9205_DELL_M43] = "dell-m43",
-- 
cgit v1.2.3-70-g09d2


From 0c5f9b8830aa0ff8f97e4efdfe1e1c4fe08ec71c Mon Sep 17 00:00:00 2001
From: Andy Grover <andy.grover@oracle.com>
Date: Tue, 24 Feb 2009 15:30:38 +0000
Subject: RDS: Documentation

This file documents the specifics of the RDS sockets API,
as well as covering some of the details of its internal
implementation.

Signed-off-by: Andy Grover <andy.grover@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/rds.txt | 356 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 356 insertions(+)
 create mode 100644 Documentation/networking/rds.txt

(limited to 'Documentation')

diff --git a/Documentation/networking/rds.txt b/Documentation/networking/rds.txt
new file mode 100644
index 00000000000..c67077cbeb8
--- /dev/null
+++ b/Documentation/networking/rds.txt
@@ -0,0 +1,356 @@
+
+Overview
+========
+
+This readme tries to provide some background on the hows and whys of RDS,
+and will hopefully help you find your way around the code.
+
+In addition, please see this email about RDS origins:
+http://oss.oracle.com/pipermail/rds-devel/2007-November/000228.html
+
+RDS Architecture
+================
+
+RDS provides reliable, ordered datagram delivery by using a single
+reliable connection between any two nodes in the cluster. This allows
+applications to use a single socket to talk to any other process in the
+cluster - so in a cluster with N processes you need N sockets, in contrast
+to N*N if you use a connection-oriented socket transport like TCP.
+
+RDS is not Infiniband-specific; it was designed to support different
+transports.  The current implementation used to support RDS over TCP as well
+as IB. Work is in progress to support RDS over iWARP, and using DCE to
+guarantee no dropped packets on Ethernet, it may be possible to use RDS over
+UDP in the future.
+
+The high-level semantics of RDS from the application's point of view are
+
+ *	Addressing
+        RDS uses IPv4 addresses and 16bit port numbers to identify
+        the end point of a connection. All socket operations that involve
+        passing addresses between kernel and user space generally
+        use a struct sockaddr_in.
+
+        The fact that IPv4 addresses are used does not mean the underlying
+        transport has to be IP-based. In fact, RDS over IB uses a
+        reliable IB connection; the IP address is used exclusively to
+        locate the remote node's GID (by ARPing for the given IP).
+
+        The port space is entirely independent of UDP, TCP or any other
+        protocol.
+
+ *	Socket interface
+        RDS sockets work *mostly* as you would expect from a BSD
+        socket. The next section will cover the details. At any rate,
+        all I/O is performed through the standard BSD socket API.
+        Some additions like zerocopy support are implemented through
+        control messages, while other extensions use the getsockopt/
+        setsockopt calls.
+
+        Sockets must be bound before you can send or receive data.
+        This is needed because binding also selects a transport and
+        attaches it to the socket. Once bound, the transport assignment
+        does not change. RDS will tolerate IPs moving around (eg in
+        a active-active HA scenario), but only as long as the address
+        doesn't move to a different transport.
+
+ *	sysctls
+        RDS supports a number of sysctls in /proc/sys/net/rds
+
+
+Socket Interface
+================
+
+  AF_RDS, PF_RDS, SOL_RDS
+        These constants haven't been assigned yet, because RDS isn't in
+        mainline yet. Currently, the kernel module assigns some constant
+        and publishes it to user space through two sysctl files
+                /proc/sys/net/rds/pf_rds
+                /proc/sys/net/rds/sol_rds
+
+  fd = socket(PF_RDS, SOCK_SEQPACKET, 0);
+        This creates a new, unbound RDS socket.
+
+  setsockopt(SOL_SOCKET): send and receive buffer size
+        RDS honors the send and receive buffer size socket options.
+        You are not allowed to queue more than SO_SNDSIZE bytes to
+        a socket. A message is queued when sendmsg is called, and
+        it leaves the queue when the remote system acknowledges
+        its arrival.
+
+        The SO_RCVSIZE option controls the maximum receive queue length.
+        This is a soft limit rather than a hard limit - RDS will
+        continue to accept and queue incoming messages, even if that
+        takes the queue length over the limit. However, it will also
+        mark the port as "congested" and send a congestion update to
+        the source node. The source node is supposed to throttle any
+        processes sending to this congested port.
+
+  bind(fd, &sockaddr_in, ...)
+        This binds the socket to a local IP address and port, and a
+        transport.
+
+  sendmsg(fd, ...)
+        Sends a message to the indicated recipient. The kernel will
+        transparently establish the underlying reliable connection
+        if it isn't up yet.
+
+        An attempt to send a message that exceeds SO_SNDSIZE will
+        return with -EMSGSIZE
+
+        An attempt to send a message that would take the total number
+        of queued bytes over the SO_SNDSIZE threshold will return
+        EAGAIN.
+
+        An attempt to send a message to a destination that is marked
+        as "congested" will return ENOBUFS.
+
+  recvmsg(fd, ...)
+        Receives a message that was queued to this socket. The sockets
+        recv queue accounting is adjusted, and if the queue length
+        drops below SO_SNDSIZE, the port is marked uncongested, and
+        a congestion update is sent to all peers.
+
+        Applications can ask the RDS kernel module to receive
+        notifications via control messages (for instance, there is a
+        notification when a congestion update arrived, or when a RDMA
+        operation completes). These notifications are received through
+        the msg.msg_control buffer of struct msghdr. The format of the
+        messages is described in manpages.
+
+  poll(fd)
+        RDS supports the poll interface to allow the application
+        to implement async I/O.
+
+        POLLIN handling is pretty straightforward. When there's an
+        incoming message queued to the socket, or a pending notification,
+        we signal POLLIN.
+
+        POLLOUT is a little harder. Since you can essentially send
+        to any destination, RDS will always signal POLLOUT as long as
+        there's room on the send queue (ie the number of bytes queued
+        is less than the sendbuf size).
+
+        However, the kernel will refuse to accept messages to
+        a destination marked congested - in this case you will loop
+        forever if you rely on poll to tell you what to do.
+        This isn't a trivial problem, but applications can deal with
+        this - by using congestion notifications, and by checking for
+        ENOBUFS errors returned by sendmsg.
+
+  setsockopt(SOL_RDS, RDS_CANCEL_SENT_TO, &sockaddr_in)
+        This allows the application to discard all messages queued to a
+        specific destination on this particular socket.
+
+        This allows the application to cancel outstanding messages if
+        it detects a timeout. For instance, if it tried to send a message,
+        and the remote host is unreachable, RDS will keep trying forever.
+        The application may decide it's not worth it, and cancel the
+        operation. In this case, it would use RDS_CANCEL_SENT_TO to
+        nuke any pending messages.
+
+
+RDMA for RDS
+============
+
+  see rds-rdma(7) manpage (available in rds-tools)
+
+
+Congestion Notifications
+========================
+
+  see rds(7) manpage
+
+
+RDS Protocol
+============
+
+  Message header
+
+    The message header is a 'struct rds_header' (see rds.h):
+    Fields:
+      h_sequence:
+          per-packet sequence number
+      h_ack:
+          piggybacked acknowledgment of last packet received
+      h_len:
+          length of data, not including header
+      h_sport:
+          source port
+      h_dport:
+          destination port
+      h_flags:
+          CONG_BITMAP - this is a congestion update bitmap
+          ACK_REQUIRED - receiver must ack this packet
+          RETRANSMITTED - packet has previously been sent
+      h_credit:
+          indicate to other end of connection that
+          it has more credits available (i.e. there is
+          more send room)
+      h_padding[4]:
+          unused, for future use
+      h_csum:
+          header checksum
+      h_exthdr:
+          optional data can be passed here. This is currently used for
+          passing RDMA-related information.
+
+  ACK and retransmit handling
+
+      One might think that with reliable IB connections you wouldn't need
+      to ack messages that have been received.  The problem is that IB
+      hardware generates an ack message before it has DMAed the message
+      into memory.  This creates a potential message loss if the HCA is
+      disabled for any reason between when it sends the ack and before
+      the message is DMAed and processed.  This is only a potential issue
+      if another HCA is available for fail-over.
+
+      Sending an ack immediately would allow the sender to free the sent
+      message from their send queue quickly, but could cause excessive
+      traffic to be used for acks. RDS piggybacks acks on sent data
+      packets.  Ack-only packets are reduced by only allowing one to be
+      in flight at a time, and by the sender only asking for acks when
+      its send buffers start to fill up. All retransmissions are also
+      acked.
+
+  Flow Control
+
+      RDS's IB transport uses a credit-based mechanism to verify that
+      there is space in the peer's receive buffers for more data. This
+      eliminates the need for hardware retries on the connection.
+
+  Congestion
+
+      Messages waiting in the receive queue on the receiving socket
+      are accounted against the sockets SO_RCVBUF option value.  Only
+      the payload bytes in the message are accounted for.  If the
+      number of bytes queued equals or exceeds rcvbuf then the socket
+      is congested.  All sends attempted to this socket's address
+      should return block or return -EWOULDBLOCK.
+
+      Applications are expected to be reasonably tuned such that this
+      situation very rarely occurs.  An application encountering this
+      "back-pressure" is considered a bug.
+
+      This is implemented by having each node maintain bitmaps which
+      indicate which ports on bound addresses are congested.  As the
+      bitmap changes it is sent through all the connections which
+      terminate in the local address of the bitmap which changed.
+
+      The bitmaps are allocated as connections are brought up.  This
+      avoids allocation in the interrupt handling path which queues
+      sages on sockets.  The dense bitmaps let transports send the
+      entire bitmap on any bitmap change reasonably efficiently.  This
+      is much easier to implement than some finer-grained
+      communication of per-port congestion.  The sender does a very
+      inexpensive bit test to test if the port it's about to send to
+      is congested or not.
+
+
+RDS Transport Layer
+==================
+
+  As mentioned above, RDS is not IB-specific. Its code is divided
+  into a general RDS layer and a transport layer.
+
+  The general layer handles the socket API, congestion handling,
+  loopback, stats, usermem pinning, and the connection state machine.
+
+  The transport layer handles the details of the transport. The IB
+  transport, for example, handles all the queue pairs, work requests,
+  CM event handlers, and other Infiniband details.
+
+
+RDS Kernel Structures
+=====================
+
+  struct rds_message
+    aka possibly "rds_outgoing", the generic RDS layer copies data to
+    be sent and sets header fields as needed, based on the socket API.
+    This is then queued for the individual connection and sent by the
+    connection's transport.
+  struct rds_incoming
+    a generic struct referring to incoming data that can be handed from
+    the transport to the general code and queued by the general code
+    while the socket is awoken. It is then passed back to the transport
+    code to handle the actual copy-to-user.
+  struct rds_socket
+    per-socket information
+  struct rds_connection
+    per-connection information
+  struct rds_transport
+    pointers to transport-specific functions
+  struct rds_statistics
+    non-transport-specific statistics
+  struct rds_cong_map
+    wraps the raw congestion bitmap, contains rbnode, waitq, etc.
+
+Connection management
+=====================
+
+  Connections may be in UP, DOWN, CONNECTING, DISCONNECTING, and
+  ERROR states.
+
+  The first time an attempt is made by an RDS socket to send data to
+  a node, a connection is allocated and connected. That connection is
+  then maintained forever -- if there are transport errors, the
+  connection will be dropped and re-established.
+
+  Dropping a connection while packets are queued will cause queued or
+  partially-sent datagrams to be retransmitted when the connection is
+  re-established.
+
+
+The send path
+=============
+
+  rds_sendmsg()
+    struct rds_message built from incoming data
+    CMSGs parsed (e.g. RDMA ops)
+    transport connection alloced and connected if not already
+    rds_message placed on send queue
+    send worker awoken
+  rds_send_worker()
+    calls rds_send_xmit() until queue is empty
+  rds_send_xmit()
+    transmits congestion map if one is pending
+    may set ACK_REQUIRED
+    calls transport to send either non-RDMA or RDMA message
+    (RDMA ops never retransmitted)
+  rds_ib_xmit()
+    allocs work requests from send ring
+    adds any new send credits available to peer (h_credits)
+    maps the rds_message's sg list
+    piggybacks ack
+    populates work requests
+    post send to connection's queue pair
+
+The recv path
+=============
+
+  rds_ib_recv_cq_comp_handler()
+    looks at write completions
+    unmaps recv buffer from device
+    no errors, call rds_ib_process_recv()
+    refill recv ring
+  rds_ib_process_recv()
+    validate header checksum
+    copy header to rds_ib_incoming struct if start of a new datagram
+    add to ibinc's fraglist
+    if competed datagram:
+      update cong map if datagram was cong update
+      call rds_recv_incoming() otherwise
+      note if ack is required
+  rds_recv_incoming()
+    drop duplicate packets
+    respond to pings
+    find the sock associated with this datagram
+    add to sock queue
+    wake up sock
+    do some congestion calculations
+  rds_recvmsg
+    copy data into user iovec
+    handle CMSGs
+    return to application
+
+
-- 
cgit v1.2.3-70-g09d2


From 72fd455ba54b5a02b9c74221b9ded8b1845b464a Mon Sep 17 00:00:00 2001
From: Wang Chen <wangchen@cn.fujitsu.com>
Date: Mon, 2 Mar 2009 13:55:14 +0800
Subject: sched, documentation: remove old O(1) scheduler document

Since we don't have O(1) scheduler implementation anymore,
remove the legacy doc.

Signed-off-by: Wang Chen <wangchen@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 Documentation/scheduler/00-INDEX         |   2 -
 Documentation/scheduler/sched-coding.txt | 126 -------------------------------
 2 files changed, 128 deletions(-)
 delete mode 100644 Documentation/scheduler/sched-coding.txt

(limited to 'Documentation')

diff --git a/Documentation/scheduler/00-INDEX b/Documentation/scheduler/00-INDEX
index aabcc3a089b..3c00c9c3219 100644
--- a/Documentation/scheduler/00-INDEX
+++ b/Documentation/scheduler/00-INDEX
@@ -2,8 +2,6 @@
 	- this file.
 sched-arch.txt
 	- CPU Scheduler implementation hints for architecture specific code.
-sched-coding.txt
-	- reference for various scheduler-related methods in the O(1) scheduler.
 sched-design-CFS.txt
 	- goals, design and implementation of the Complete Fair Scheduler.
 sched-domains.txt
diff --git a/Documentation/scheduler/sched-coding.txt b/Documentation/scheduler/sched-coding.txt
deleted file mode 100644
index cbd8db752ac..00000000000
--- a/Documentation/scheduler/sched-coding.txt
+++ /dev/null
@@ -1,126 +0,0 @@
-     Reference for various scheduler-related methods in the O(1) scheduler
-		Robert Love <rml@tech9.net>, MontaVista Software
-
-
-Note most of these methods are local to kernel/sched.c - this is by design.
-The scheduler is meant to be self-contained and abstracted away.  This document
-is primarily for understanding the scheduler, not interfacing to it.  Some of
-the discussed interfaces, however, are general process/scheduling methods.
-They are typically defined in include/linux/sched.h.
-
-
-Main Scheduling Methods
------------------------
-
-void load_balance(runqueue_t *this_rq, int idle)
-	Attempts to pull tasks from one cpu to another to balance cpu usage,
-	if needed.  This method is called explicitly if the runqueues are
-	imbalanced or periodically by the timer tick.  Prior to calling,
-	the current runqueue must be locked and interrupts disabled.
-
-void schedule()
-	The main scheduling function.  Upon return, the highest priority
-	process will be active.
-
-
-Locking
--------
-
-Each runqueue has its own lock, rq->lock.  When multiple runqueues need
-to be locked, lock acquires must be ordered by ascending &runqueue value.
-
-A specific runqueue is locked via
-
-	task_rq_lock(task_t pid, unsigned long *flags)
-
-which disables preemption, disables interrupts, and locks the runqueue pid is
-running on.  Likewise,
-
-	task_rq_unlock(task_t pid, unsigned long *flags)
-
-unlocks the runqueue pid is running on, restores interrupts to their previous
-state, and reenables preemption.
-
-The routines
-
-	double_rq_lock(runqueue_t *rq1, runqueue_t *rq2)
-
-and
-
-	double_rq_unlock(runqueue_t *rq1, runqueue_t *rq2)
-
-safely lock and unlock, respectively, the two specified runqueues.  They do
-not, however, disable and restore interrupts.  Users are required to do so
-manually before and after calls.
-
-
-Values
-------
-
-MAX_PRIO
-	The maximum priority of the system, stored in the task as task->prio.
-	Lower priorities are higher.  Normal (non-RT) priorities range from
-	MAX_RT_PRIO to (MAX_PRIO - 1).
-MAX_RT_PRIO
-	The maximum real-time priority of the system.  Valid RT priorities
-	range from 0 to (MAX_RT_PRIO - 1).
-MAX_USER_RT_PRIO
-	The maximum real-time priority that is exported to user-space.  Should
-	always be equal to or less than MAX_RT_PRIO.  Setting it less allows
-	kernel threads to have higher priorities than any user-space task.
-MIN_TIMESLICE
-MAX_TIMESLICE
-	Respectively, the minimum and maximum timeslices (quanta) of a process.
-
-Data
-----
-
-struct runqueue
-	The main per-CPU runqueue data structure.
-struct task_struct
-	The main per-process data structure.
-
-
-General Methods
----------------
-
-cpu_rq(cpu)
-	Returns the runqueue of the specified cpu.
-this_rq()
-	Returns the runqueue of the current cpu.
-task_rq(pid)
-	Returns the runqueue which holds the specified pid.
-cpu_curr(cpu)
-	Returns the task currently running on the given cpu.
-rt_task(pid)
-	Returns true if pid is real-time, false if not.
-
-
-Process Control Methods
------------------------
-
-void set_user_nice(task_t *p, long nice)
-	Sets the "nice" value of task p to the given value.
-int setscheduler(pid_t pid, int policy, struct sched_param *param)
-	Sets the scheduling policy and parameters for the given pid.
-int set_cpus_allowed(task_t *p, unsigned long new_mask)
-	Sets a given task's CPU affinity and migrates it to a proper cpu.
-	Callers must have a valid reference to the task and assure the
-	task not exit prematurely.  No locks can be held during the call.
-set_task_state(tsk, state_value)
-	Sets the given task's state to the given value.
-set_current_state(state_value)
-	Sets the current task's state to the given value.
-void set_tsk_need_resched(struct task_struct *tsk)
-	Sets need_resched in the given task.
-void clear_tsk_need_resched(struct task_struct *tsk)
-	Clears need_resched in the given task.
-void set_need_resched()
-	Sets need_resched in the current task.
-void clear_need_resched()
-	Clears need_resched in the current task.
-int need_resched()
-	Returns true if need_resched is set in the current task, false
-	otherwise.
-yield()
-	Place the current process at the end of the runqueue and call schedule.
-- 
cgit v1.2.3-70-g09d2


From d02b1f3910f12cfe377a31afebcbbde4f5664b74 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 2 Mar 2009 17:34:51 +0100
Subject: ALSA: hda - Update documetation for hints sysfs entry

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio.txt | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 99958be7b45..c5948f2f9a2 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -365,10 +365,13 @@ modelname::
   to this file.
 init_verbs::
   The extra verbs to execute at initialization.  You can add a verb by
-  writing to this file.  Pass three numbers: nid, verb and parameter.
+  writing to this file.  Pass three numbers: nid, verb and parameter
+  (separated with a space).
 hints::
-  Shows hint strings for codec parsers for any use.  Right now it's
-  not used.
+  Shows / stores hint strings for codec parsers for any use.
+  Its format is `key = value`.  For example, passing `hp_detect = yes`
+  to IDT/STAC codec parser will result in the disablement of the
+  headphone detection.
 init_pin_configs::
   Shows the initial pin default config values set by BIOS.
 driver_pin_configs::
-- 
cgit v1.2.3-70-g09d2


From 79d7d5333b598e9a559bf27833f0ad2b8bf6ad2c Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Wed, 4 Mar 2009 09:03:50 +0100
Subject: ALSA: hda - Fix HP dv6736 mic input

Fix the mic input of HP dv6736 with Conexant 5051 codec chip.
This laptop seems have no mic-switching per jack connection.
A new model hp-dv6736 is introduced to match with the h/w implementation.

Reference: Novell bnc#480753
	https://bugzilla.novell.com/show_bug.cgi?id=480753

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt |  1 +
 sound/pci/hda/patch_conexant.c               | 63 +++++++++++++++++++++++++---
 2 files changed, 59 insertions(+), 5 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index a448bbefd48..80b796e4a80 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -262,6 +262,7 @@ Conexant 5051
 =============
   laptop	Basic Laptop config (default)
   hp		HP Spartan laptop
+  hp-dv6736	HP dv6736
   lenovo-x200	Lenovo X200 laptop
 
 STAC9200
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index b8de73ecfde..1938e92e1f0 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -72,6 +72,7 @@ struct conexant_spec {
 					 */
 	unsigned int cur_eapd;
 	unsigned int hp_present;
+	unsigned int no_auto_mic;
 	unsigned int need_dac_fix;
 
 	/* capture */
@@ -1665,8 +1666,11 @@ static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 /* toggle input of built-in and mic jack appropriately */
 static void cxt5051_portb_automic(struct hda_codec *codec)
 {
+	struct conexant_spec *spec = codec->spec;
 	unsigned int present;
 
+	if (spec->no_auto_mic)
+		return;
 	present = snd_hda_codec_read(codec, 0x17, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) &
 		AC_PINSENSE_PRESENCE;
@@ -1682,6 +1686,8 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
 	unsigned int present;
 	hda_nid_t new_adc;
 
+	if (spec->no_auto_mic)
+		return;
 	present = snd_hda_codec_read(codec, 0x18, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) &
 		AC_PINSENSE_PRESENCE;
@@ -1768,6 +1774,22 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
 	{}
 };
 
+static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
+	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = cxt_eapd_info,
+		.get = cxt_eapd_get,
+		.put = cxt5051_hp_master_sw_put,
+		.private_value = 0x1a,
+	},
+
+	{}
+};
+
 static struct hda_verb cxt5051_init_verbs[] = {
 	/* Line in, Mic */
 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
@@ -1798,6 +1820,32 @@ static struct hda_verb cxt5051_init_verbs[] = {
 	{ } /* end */
 };
 
+static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
+	/* Line in, Mic */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
+	/* SPK  */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP, Amp  */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* DAC1 */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Record selector: Int mic */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
+	/* SPDIF route: PCM */
+	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* EAPD */
+	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
+	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
+	{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
+	{ } /* end */
+};
+
 static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
 	/* Line in, Mic */
 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
@@ -1849,6 +1897,7 @@ static int cxt5051_init(struct hda_codec *codec)
 enum {
 	CXT5051_LAPTOP,	 /* Laptops w/ EAPD support */
 	CXT5051_HP,	/* no docking */
+	CXT5051_HP_DV6736,	/* HP without mic switch */
 	CXT5051_LENOVO_X200,	/* Lenovo X200 laptop */
 	CXT5051_MODELS
 };
@@ -1856,10 +1905,12 @@ enum {
 static const char *cxt5051_models[CXT5051_MODELS] = {
 	[CXT5051_LAPTOP]	= "laptop",
 	[CXT5051_HP]		= "hp",
+	[CXT5051_HP_DV6736]	= "hp-dv6736",
 	[CXT5051_LENOVO_X200]	= "lenovo-x200",
 };
 
 static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
 	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
 		      CXT5051_LAPTOP),
 	SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
@@ -1896,20 +1947,22 @@ static int patch_cxt5051(struct hda_codec *codec)
 	spec->cur_adc = 0;
 	spec->cur_adc_idx = 0;
 
+	codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
+
 	board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
 						  cxt5051_models,
 						  cxt5051_cfg_tbl);
 	switch (board_config) {
 	case CXT5051_HP:
-		codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
 		spec->mixers[0] = cxt5051_hp_mixers;
 		break;
+	case CXT5051_HP_DV6736:
+		spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
+		spec->mixers[0] = cxt5051_hp_dv6736_mixers;
+		spec->no_auto_mic = 1;
+		break;
 	case CXT5051_LENOVO_X200:
 		spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
-		/* fallthru */
-	default:
-	case CXT5051_LAPTOP:
-		codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
 		break;
 	}
 
-- 
cgit v1.2.3-70-g09d2


From 4e59c25dcbc1f033d043f1009a7f6aaa1f2aef26 Mon Sep 17 00:00:00 2001
From: Ben Dooks <ben-linux@fluff.org>
Date: Fri, 12 Dec 2008 00:24:18 +0000
Subject: [ARM] S3C: Rename s3c2410_pm_init to s3c_pm_init.

Since we have moved a large proportion of the PM code to the common
support area, remove the cpu specific name from the initialisation
function.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
---
 Documentation/arm/Samsung-S3C24XX/Suspend.txt | 8 ++++----
 arch/arm/mach-s3c2410/mach-h1940.c            | 2 +-
 arch/arm/mach-s3c2410/mach-qt2410.c           | 2 +-
 arch/arm/mach-s3c2412/mach-jive.c             | 2 +-
 arch/arm/mach-s3c2440/mach-rx3715.c           | 2 +-
 arch/arm/plat-s3c/include/plat/pm.h           | 6 +++---
 arch/arm/plat-s3c/pm.c                        | 4 ++--
 arch/arm/plat-s3c24xx/common-smdk.c           | 2 +-
 arch/arm/plat-s3c24xx/pm-simtec.c             | 2 +-
 9 files changed, 15 insertions(+), 15 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/arm/Samsung-S3C24XX/Suspend.txt b/Documentation/arm/Samsung-S3C24XX/Suspend.txt
index 0dab6e32c13..a30fe510572 100644
--- a/Documentation/arm/Samsung-S3C24XX/Suspend.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Suspend.txt
@@ -40,13 +40,13 @@ Resuming
 Machine Support
 ---------------
 
-  The machine specific functions must call the s3c2410_pm_init() function
+  The machine specific functions must call the s3c_pm_init() function
   to say that its bootloader is capable of resuming. This can be as
   simple as adding the following to the machine's definition:
 
-  INITMACHINE(s3c2410_pm_init)
+  INITMACHINE(s3c_pm_init)
 
-  A board can do its own setup before calling s3c2410_pm_init, if it
+  A board can do its own setup before calling s3c_pm_init, if it
   needs to setup anything else for power management support.
 
   There is currently no support for over-riding the default method of
@@ -74,7 +74,7 @@ statuc void __init machine_init(void)
 
 	enable_irq_wake(IRQ_EINT0);
 
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
 
 
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 821a1668c3a..7a7c4da4c25 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -203,7 +203,7 @@ static void __init h1940_map_io(void)
 #ifdef CONFIG_PM_H1940
 	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
 #endif
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
 
 static void __init h1940_init_irq(void)
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index 9678a53ceeb..9f1ba9b63f7 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -355,7 +355,7 @@ static void __init qt2410_machine_init(void)
 	s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
 
 	platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
 
 MACHINE_START(QT2410, "QT2410")
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index ecddbbb3483..50d8054292c 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -630,7 +630,7 @@ static void __init jive_machine_init(void)
 
 	/* initialise the power management now we've setup everything. */
 
-	s3c2410_pm_init();
+	s3c_pm_init();
 
 	s3c_device_nand.dev.platform_data = &jive_nand_info;
 
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index 12d378f84ad..bc8d8d1ebd1 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -203,7 +203,7 @@ static void __init rx3715_init_machine(void)
 #ifdef CONFIG_PM_H1940
 	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
 #endif
-	s3c2410_pm_init();
+	s3c_pm_init();
 
 	s3c24xx_fb_set_platdata(&rx3715_fb_info);
 	platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h
index 5e27de955da..a6104c8055f 100644
--- a/arch/arm/plat-s3c/include/plat/pm.h
+++ b/arch/arm/plat-s3c/include/plat/pm.h
@@ -9,7 +9,7 @@
  * published by the Free Software Foundation.
 */
 
-/* s3c2410_pm_init
+/* s3c_pm_init
  *
  * called from board at initialisation time to setup the power
  * management
@@ -17,11 +17,11 @@
 
 #ifdef CONFIG_PM
 
-extern __init int s3c2410_pm_init(void);
+extern __init int s3c_pm_init(void);
 
 #else
 
-static inline int s3c2410_pm_init(void)
+static inline int s3c_pm_init(void)
 {
 	return 0;
 }
diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c
index 7c736deff8a..e82ec628ced 100644
--- a/arch/arm/plat-s3c/pm.c
+++ b/arch/arm/plat-s3c/pm.c
@@ -316,14 +316,14 @@ static struct platform_suspend_ops s3c_pm_ops = {
 	.valid		= suspend_valid_only_mem,
 };
 
-/* s3c2410_pm_init
+/* s3c_pm_init
  *
  * Attach the power management functions. This should be called
  * from the board specific initialisation if the board supports
  * it.
 */
 
-int __init s3c2410_pm_init(void)
+int __init s3c_pm_init(void)
 {
 	printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
 
diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
index 3d4837021ac..1a8347cec20 100644
--- a/arch/arm/plat-s3c24xx/common-smdk.c
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -201,5 +201,5 @@ void __init smdk_machine_init(void)
 
 	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
 
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
diff --git a/arch/arm/plat-s3c24xx/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c
index 21dfa74773d..da0d3217d3e 100644
--- a/arch/arm/plat-s3c24xx/pm-simtec.c
+++ b/arch/arm/plat-s3c24xx/pm-simtec.c
@@ -61,7 +61,7 @@ static __init int pm_simtec_init(void)
 
 	__raw_writel(gstatus4, S3C2410_GSTATUS4);
 
-	return s3c2410_pm_init();
+	return s3c_pm_init();
 }
 
 arch_initcall(pm_simtec_init);
-- 
cgit v1.2.3-70-g09d2


From 79c7cdd5441f5d3900c1632adcc8cd2bee35c8da Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 9 Feb 2009 14:47:19 +0100
Subject: ALSA: Add kernel-doc comments to vmaster stuff

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 .../sound/alsa/DocBook/alsa-driver-api.tmpl        |  4 +++
 include/sound/control.h                            | 32 ++++++++++++++++++++++
 sound/core/vmaster.c                               | 16 +++++++++--
 3 files changed, 50 insertions(+), 2 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index 9d644f7e241..115962827c8 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -71,6 +71,10 @@
 !Esound/pci/ac97/ac97_codec.c
 !Esound/pci/ac97/ac97_pcm.c
      </sect1>
+     <sect1><title>Virtual Master Control API</title>
+!Esound/core/vmaster.c
+!Iinclude/sound/control.h
+     </sect1>
   </chapter>
   <chapter><title>MIDI API</title>
      <sect1><title>Raw MIDI API</title>
diff --git a/include/sound/control.h b/include/sound/control.h
index 4cf8f7aaa13..ef96f07aa03 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -176,12 +176,44 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
 /* optional flags for slave */
 #define SND_CTL_SLAVE_NEED_UPDATE	(1 << 0)
 
+/**
+ * snd_ctl_add_slave - Add a virtual slave control
+ * @master: vmaster element
+ * @slave: slave element to add
+ *
+ * Add a virtual slave control to the given master element created via
+ * snd_ctl_create_virtual_master() beforehand.
+ * Returns zero if successful or a negative error code.
+ *
+ * All slaves must be the same type (returning the same information
+ * via info callback).  The fucntion doesn't check it, so it's your
+ * responsibility.
+ *
+ * Also, some additional limitations:
+ * at most two channels,
+ * logarithmic volume control (dB level) thus no linear volume,
+ * master can only attenuate the volume without gain
+ */
 static inline int
 snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
 {
 	return _snd_ctl_add_slave(master, slave, 0);
 }
 
+/**
+ * snd_ctl_add_slave_uncached - Add a virtual slave control
+ * @master: vmaster element
+ * @slave: slave element to add
+ *
+ * Add a virtual slave control to the given master.
+ * Unlike snd_ctl_add_slave(), the element added via this function
+ * is supposed to have volatile values, and get callback is called
+ * at each time quried from the master.
+ *
+ * When the control peeks the hardware values directly and the value
+ * can be changed by other means than the put callback of the element,
+ * this function should be used to keep the value always up-to-date.
+ */
 static inline int
 snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
 			   struct snd_kcontrol *slave)
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index d51b198d06d..257624bd199 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -340,8 +340,20 @@ static void master_free(struct snd_kcontrol *kcontrol)
 }
 
 
-/*
- * Create a virtual master control with the given name
+/**
+ * snd_ctl_make_virtual_master - Create a virtual master control
+ * @name: name string of the control element to create
+ * @tlv: optional TLV int array for dB information
+ *
+ * Creates a virtual matster control with the given name string.
+ * Returns the created control element, or NULL for errors (ENOMEM).
+ *
+ * After creating a vmaster element, you can add the slave controls
+ * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
+ *
+ * The optional argument @tlv can be used to specify the TLV information
+ * for dB scale of the master control.  It should be a single element
+ * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB.
  */
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 						 const unsigned int *tlv)
-- 
cgit v1.2.3-70-g09d2


From 662c319ae4b4fb60001816dfe1dde5fdfc7a2af9 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 9 Feb 2009 08:53:50 +0100
Subject: ALSA: Add sound/core/jack.c to driver-API docbook entry

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index 9d644f7e241..37b006cdf2f 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -88,6 +88,9 @@
   <chapter><title>Miscellaneous Functions</title>
      <sect1><title>Hardware-Dependent Devices API</title>
 !Esound/core/hwdep.c
+     </sect1>
+     <sect1><title>Jack Abstraction Layer API</title>
+!Esound/core/jack.c
      </sect1>
      <sect1><title>ISA DMA Helpers</title>
 !Esound/core/isadma.c
-- 
cgit v1.2.3-70-g09d2


From 5f8206c04857965cc2ff6c395633c4fdd977dd77 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 9 Feb 2009 08:50:43 +0100
Subject: ALSA: Fix DocBook headers

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl        | 10 ++++++----
 Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl |  8 ++++----
 2 files changed, 10 insertions(+), 8 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index 90f163c4bde..0230a96f056 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -1,11 +1,11 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
-
-<book>
-<?dbhtml filename="index.html">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
 
 <!-- ****************************************************** -->
 <!-- Header  -->
 <!-- ****************************************************** -->
+<book id="ALSA-Driver-API">
   <bookinfo>
     <title>The ALSA Driver API</title>
 
@@ -35,6 +35,8 @@
 
   </bookinfo>
 
+<toc></toc>
+
   <chapter><title>Management of Cards and Devices</title>
      <sect1><title>Card Management</title>
 !Esound/core/init.c
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 320384c1791..46b08fef374 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -1,11 +1,11 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
-
-<book>
-<?dbhtml filename="index.html">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
 
 <!-- ****************************************************** -->
 <!-- Header  -->
 <!-- ****************************************************** -->
+<book id="Writing-an-ALSA-Driver">
   <bookinfo>
     <title>Writing an ALSA Driver</title>
     <author>
-- 
cgit v1.2.3-70-g09d2


From e776ec19a47a325ee1d9ece2d983526dcd626c53 Mon Sep 17 00:00:00 2001
From: Randy Dunlap <randy.dunlap@oracle.com>
Date: Sat, 28 Feb 2009 17:40:18 +0100
Subject: ALSA: Move ALSA docbooks to be with the rest of the kernel docbooks

Move ALSA docbooks to be with the rest of the kernel docbooks and add
them to the Makefile so that they build.  Latter required a few minor
changes to alsa .tmpl files.
(I did not remove all of the trailing whitespace in the .tmpl files.)

Fixes kernel bugzilla #12726: http://bugzilla.kernel.org/show_bug.cgi?id=12726

Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: documentation_man-pages@kernel-bugs.osdl.org
Cc: Nicola Soranzo <nsoranzo@tiscali.it>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/DocBook/Makefile                     |    3 +-
 Documentation/DocBook/alsa-driver-api.tmpl         |  109 +
 Documentation/DocBook/writing-an-alsa-driver.tmpl  | 6216 ++++++++++++++++++++
 .../sound/alsa/DocBook/alsa-driver-api.tmpl        |  109 -
 .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 6216 --------------------
 5 files changed, 6327 insertions(+), 6326 deletions(-)
 create mode 100644 Documentation/DocBook/alsa-driver-api.tmpl
 create mode 100644 Documentation/DocBook/writing-an-alsa-driver.tmpl
 delete mode 100644 Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
 delete mode 100644 Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl

(limited to 'Documentation')

diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 1462ed86d40..a3a83d38f96 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -12,7 +12,8 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
 	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
-	    mac80211.xml debugobjects.xml sh.xml regulator.xml
+	    mac80211.xml debugobjects.xml sh.xml regulator.xml \
+	    alsa-driver-api.xml writing-an-alsa-driver.xml
 
 ###
 # The build process is as follows (targets):
diff --git a/Documentation/DocBook/alsa-driver-api.tmpl b/Documentation/DocBook/alsa-driver-api.tmpl
new file mode 100644
index 00000000000..0230a96f056
--- /dev/null
+++ b/Documentation/DocBook/alsa-driver-api.tmpl
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<!-- ****************************************************** -->
+<!-- Header  -->
+<!-- ****************************************************** -->
+<book id="ALSA-Driver-API">
+  <bookinfo>
+    <title>The ALSA Driver API</title>
+
+    <legalnotice>
+    <para>
+    This document is free; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version. 
+    </para>
+
+    <para>
+    This document is distributed in the hope that it will be useful,
+    but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
+    implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
+    PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
+    for more details.
+    </para>
+
+    <para>
+    You should have received a copy of the GNU General Public
+    License along with this program; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+    MA 02111-1307 USA
+    </para>
+    </legalnotice>
+
+  </bookinfo>
+
+<toc></toc>
+
+  <chapter><title>Management of Cards and Devices</title>
+     <sect1><title>Card Management</title>
+!Esound/core/init.c
+     </sect1>
+     <sect1><title>Device Components</title>
+!Esound/core/device.c
+     </sect1>
+     <sect1><title>Module requests and Device File Entries</title>
+!Esound/core/sound.c
+     </sect1>
+     <sect1><title>Memory Management Helpers</title>
+!Esound/core/memory.c
+!Esound/core/memalloc.c
+     </sect1>
+  </chapter>
+  <chapter><title>PCM API</title>
+     <sect1><title>PCM Core</title>
+!Esound/core/pcm.c
+!Esound/core/pcm_lib.c
+!Esound/core/pcm_native.c
+     </sect1>
+     <sect1><title>PCM Format Helpers</title>
+!Esound/core/pcm_misc.c
+     </sect1>
+     <sect1><title>PCM Memory Management</title>
+!Esound/core/pcm_memory.c
+     </sect1>
+  </chapter>
+  <chapter><title>Control/Mixer API</title>
+     <sect1><title>General Control Interface</title>
+!Esound/core/control.c
+     </sect1>
+     <sect1><title>AC97 Codec API</title>
+!Esound/pci/ac97/ac97_codec.c
+!Esound/pci/ac97/ac97_pcm.c
+     </sect1>
+     <sect1><title>Virtual Master Control API</title>
+!Esound/core/vmaster.c
+!Iinclude/sound/control.h
+     </sect1>
+  </chapter>
+  <chapter><title>MIDI API</title>
+     <sect1><title>Raw MIDI API</title>
+!Esound/core/rawmidi.c
+     </sect1>
+     <sect1><title>MPU401-UART API</title>
+!Esound/drivers/mpu401/mpu401_uart.c
+     </sect1>
+  </chapter>
+  <chapter><title>Proc Info API</title>
+     <sect1><title>Proc Info Interface</title>
+!Esound/core/info.c
+     </sect1>
+  </chapter>
+  <chapter><title>Miscellaneous Functions</title>
+     <sect1><title>Hardware-Dependent Devices API</title>
+!Esound/core/hwdep.c
+     </sect1>
+     <sect1><title>Jack Abstraction Layer API</title>
+!Esound/core/jack.c
+     </sect1>
+     <sect1><title>ISA DMA Helpers</title>
+!Esound/core/isadma.c
+     </sect1>
+     <sect1><title>Other Helper Macros</title>
+!Iinclude/sound/core.h
+     </sect1>
+  </chapter>
+
+</book>
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
new file mode 100644
index 00000000000..46b08fef374
--- /dev/null
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -0,0 +1,6216 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<!-- ****************************************************** -->
+<!-- Header  -->
+<!-- ****************************************************** -->
+<book id="Writing-an-ALSA-Driver">
+  <bookinfo>
+    <title>Writing an ALSA Driver</title>
+    <author>
+      <firstname>Takashi</firstname>
+      <surname>Iwai</surname>
+      <affiliation>
+        <address>
+          <email>tiwai@suse.de</email>
+        </address>
+      </affiliation>
+     </author>
+
+     <date>Oct 15, 2007</date>
+     <edition>0.3.7</edition>
+
+    <abstract>
+      <para>
+        This document describes how to write an ALSA (Advanced Linux
+        Sound Architecture) driver.
+      </para>
+    </abstract>
+
+    <legalnotice>
+    <para>
+    Copyright (c) 2002-2005  Takashi Iwai <email>tiwai@suse.de</email>
+    </para>
+
+    <para>
+    This document is free; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version. 
+    </para>
+
+    <para>
+    This document is distributed in the hope that it will be useful,
+    but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
+    implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
+    PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
+    for more details.
+    </para>
+
+    <para>
+    You should have received a copy of the GNU General Public
+    License along with this program; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+    MA 02111-1307 USA
+    </para>
+    </legalnotice>
+
+  </bookinfo>
+
+<!-- ****************************************************** -->
+<!-- Preface  -->
+<!-- ****************************************************** -->
+  <preface id="preface">
+    <title>Preface</title>
+    <para>
+      This document describes how to write an
+      <ulink url="http://www.alsa-project.org/"><citetitle>
+      ALSA (Advanced Linux Sound Architecture)</citetitle></ulink>
+      driver. The document focuses mainly on PCI soundcards.
+      In the case of other device types, the API might
+      be different, too. However, at least the ALSA kernel API is
+      consistent, and therefore it would be still a bit help for
+      writing them.
+    </para>
+
+    <para>
+    This document targets people who already have enough
+    C language skills and have basic linux kernel programming
+    knowledge.  This document doesn't explain the general
+    topic of linux kernel coding and doesn't cover low-level
+    driver implementation details. It only describes
+    the standard way to write a PCI sound driver on ALSA.
+    </para>
+
+    <para>
+      If you are already familiar with the older ALSA ver.0.5.x API, you
+    can check the drivers such as <filename>sound/pci/es1938.c</filename> or
+    <filename>sound/pci/maestro3.c</filename> which have also almost the same
+    code-base in the ALSA 0.5.x tree, so you can compare the differences.
+    </para>
+
+    <para>
+      This document is still a draft version. Any feedback and
+    corrections, please!!
+    </para>
+  </preface>
+
+
+<!-- ****************************************************** -->
+<!-- File Tree Structure  -->
+<!-- ****************************************************** -->
+  <chapter id="file-tree">
+    <title>File Tree Structure</title>
+
+    <section id="file-tree-general">
+      <title>General</title>
+      <para>
+        The ALSA drivers are provided in two ways.
+      </para>
+
+      <para>
+        One is the trees provided as a tarball or via cvs from the
+      ALSA's ftp site, and another is the 2.6 (or later) Linux kernel
+      tree. To synchronize both, the ALSA driver tree is split into
+      two different trees: alsa-kernel and alsa-driver. The former
+      contains purely the source code for the Linux 2.6 (or later)
+      tree. This tree is designed only for compilation on 2.6 or
+      later environment. The latter, alsa-driver, contains many subtle
+      files for compiling ALSA drivers outside of the Linux kernel tree,
+      wrapper functions for older 2.2 and 2.4 kernels, to adapt the latest kernel API,
+      and additional drivers which are still in development or in
+      tests.  The drivers in alsa-driver tree will be moved to
+      alsa-kernel (and eventually to the 2.6 kernel tree) when they are
+      finished and confirmed to work fine.
+      </para>
+
+      <para>
+        The file tree structure of ALSA driver is depicted below. Both
+        alsa-kernel and alsa-driver have almost the same file
+        structure, except for <quote>core</quote> directory. It's
+        named as <quote>acore</quote> in alsa-driver tree. 
+
+        <example>
+          <title>ALSA File Tree Structure</title>
+          <literallayout>
+        sound
+                /core
+                        /oss
+                        /seq
+                                /oss
+                                /instr
+                /ioctl32
+                /include
+                /drivers
+                        /mpu401
+                        /opl3
+                /i2c
+                        /l3
+                /synth
+                        /emux
+                /pci
+                        /(cards)
+                /isa
+                        /(cards)
+                /arm
+                /ppc
+                /sparc
+                /usb
+                /pcmcia /(cards)
+                /oss
+          </literallayout>
+        </example>
+      </para>
+    </section>
+
+    <section id="file-tree-core-directory">
+      <title>core directory</title>
+      <para>
+        This directory contains the middle layer which is the heart
+      of ALSA drivers. In this directory, the native ALSA modules are
+      stored. The sub-directories contain different modules and are
+      dependent upon the kernel config. 
+      </para>
+
+      <section id="file-tree-core-directory-oss">
+        <title>core/oss</title>
+
+        <para>
+          The codes for PCM and mixer OSS emulation modules are stored
+        in this directory. The rawmidi OSS emulation is included in
+        the ALSA rawmidi code since it's quite small. The sequencer
+        code is stored in <filename>core/seq/oss</filename> directory (see
+        <link linkend="file-tree-core-directory-seq-oss"><citetitle>
+        below</citetitle></link>).
+        </para>
+      </section>
+
+      <section id="file-tree-core-directory-ioctl32">
+        <title>core/ioctl32</title>
+
+        <para>
+          This directory contains the 32bit-ioctl wrappers for 64bit
+        architectures such like x86-64, ppc64 and sparc64. For 32bit
+        and alpha architectures, these are not compiled. 
+        </para>
+      </section>
+
+      <section id="file-tree-core-directory-seq">
+        <title>core/seq</title>
+        <para>
+          This directory and its sub-directories are for the ALSA
+        sequencer. This directory contains the sequencer core and
+        primary sequencer modules such like snd-seq-midi,
+        snd-seq-virmidi, etc. They are compiled only when
+        <constant>CONFIG_SND_SEQUENCER</constant> is set in the kernel
+        config. 
+        </para>
+      </section>
+
+      <section id="file-tree-core-directory-seq-oss">
+        <title>core/seq/oss</title>
+        <para>
+          This contains the OSS sequencer emulation codes.
+        </para>
+      </section>
+
+      <section id="file-tree-core-directory-deq-instr">
+        <title>core/seq/instr</title>
+        <para>
+          This directory contains the modules for the sequencer
+        instrument layer. 
+        </para>
+      </section>
+    </section>
+
+    <section id="file-tree-include-directory">
+      <title>include directory</title>
+      <para>
+        This is the place for the public header files of ALSA drivers,
+      which are to be exported to user-space, or included by
+      several files at different directories. Basically, the private
+      header files should not be placed in this directory, but you may
+      still find files there, due to historical reasons :) 
+      </para>
+    </section>
+
+    <section id="file-tree-drivers-directory">
+      <title>drivers directory</title>
+      <para>
+        This directory contains code shared among different drivers
+      on different architectures.  They are hence supposed not to be
+      architecture-specific.
+      For example, the dummy pcm driver and the serial MIDI
+      driver are found in this directory. In the sub-directories,
+      there is code for components which are independent from
+      bus and cpu architectures. 
+      </para>
+
+      <section id="file-tree-drivers-directory-mpu401">
+        <title>drivers/mpu401</title>
+        <para>
+          The MPU401 and MPU401-UART modules are stored here.
+        </para>
+      </section>
+
+      <section id="file-tree-drivers-directory-opl3">
+        <title>drivers/opl3 and opl4</title>
+        <para>
+          The OPL3 and OPL4 FM-synth stuff is found here.
+        </para>
+      </section>
+    </section>
+
+    <section id="file-tree-i2c-directory">
+      <title>i2c directory</title>
+      <para>
+        This contains the ALSA i2c components.
+      </para>
+
+      <para>
+        Although there is a standard i2c layer on Linux, ALSA has its
+      own i2c code for some cards, because the soundcard needs only a
+      simple operation and the standard i2c API is too complicated for
+      such a purpose. 
+      </para>
+
+      <section id="file-tree-i2c-directory-l3">
+        <title>i2c/l3</title>
+        <para>
+          This is a sub-directory for ARM L3 i2c.
+        </para>
+      </section>
+    </section>
+
+    <section id="file-tree-synth-directory">
+        <title>synth directory</title>
+        <para>
+          This contains the synth middle-level modules.
+        </para>
+
+        <para>
+          So far, there is only Emu8000/Emu10k1 synth driver under
+        the <filename>synth/emux</filename> sub-directory. 
+        </para>
+    </section>
+
+    <section id="file-tree-pci-directory">
+      <title>pci directory</title>
+      <para>
+        This directory and its sub-directories hold the top-level card modules
+      for PCI soundcards and the code specific to the PCI BUS.
+      </para>
+
+      <para>
+        The drivers compiled from a single file are stored directly
+      in the pci directory, while the drivers with several source files are
+      stored on their own sub-directory (e.g. emu10k1, ice1712). 
+      </para>
+    </section>
+
+    <section id="file-tree-isa-directory">
+      <title>isa directory</title>
+      <para>
+        This directory and its sub-directories hold the top-level card modules
+      for ISA soundcards. 
+      </para>
+    </section>
+
+    <section id="file-tree-arm-ppc-sparc-directories">
+      <title>arm, ppc, and sparc directories</title>
+      <para>
+        They are used for top-level card modules which are
+      specific to one of these architectures. 
+      </para>
+    </section>
+
+    <section id="file-tree-usb-directory">
+      <title>usb directory</title>
+      <para>
+        This directory contains the USB-audio driver. In the latest version, the
+      USB MIDI driver is integrated in the usb-audio driver. 
+      </para>
+    </section>
+
+    <section id="file-tree-pcmcia-directory">
+      <title>pcmcia directory</title>
+      <para>
+        The PCMCIA, especially PCCard drivers will go here. CardBus
+      drivers will be in the pci directory, because their API is identical
+      to that of standard PCI cards. 
+      </para>
+    </section>
+
+    <section id="file-tree-oss-directory">
+      <title>oss directory</title>
+      <para>
+        The OSS/Lite source files are stored here in Linux 2.6 (or
+      later) tree. In the ALSA driver tarball, this directory is empty,
+      of course :) 
+      </para>
+    </section>
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Basic Flow for PCI Drivers  -->
+<!-- ****************************************************** -->
+  <chapter id="basic-flow">
+    <title>Basic Flow for PCI Drivers</title>
+
+    <section id="basic-flow-outline">
+      <title>Outline</title>
+      <para>
+        The minimum flow for PCI soundcards is as follows:
+
+        <itemizedlist>
+          <listitem><para>define the PCI ID table (see the section
+          <link linkend="pci-resource-entries"><citetitle>PCI Entries
+          </citetitle></link>).</para></listitem> 
+          <listitem><para>create <function>probe()</function> callback.</para></listitem>
+          <listitem><para>create <function>remove()</function> callback.</para></listitem>
+          <listitem><para>create a <structname>pci_driver</structname> structure
+	  containing the three pointers above.</para></listitem>
+          <listitem><para>create an <function>init()</function> function just calling
+	  the <function>pci_register_driver()</function> to register the pci_driver table
+	  defined above.</para></listitem>
+          <listitem><para>create an <function>exit()</function> function to call
+	  the <function>pci_unregister_driver()</function> function.</para></listitem>
+        </itemizedlist>
+      </para>
+    </section>
+
+    <section id="basic-flow-example">
+      <title>Full Code Example</title>
+      <para>
+        The code example is shown below. Some parts are kept
+      unimplemented at this moment but will be filled in the
+      next sections. The numbers in the comment lines of the
+      <function>snd_mychip_probe()</function> function
+      refer to details explained in the following section. 
+
+        <example>
+          <title>Basic Flow for PCI Drivers - Example</title>
+          <programlisting>
+<![CDATA[
+  #include <linux/init.h>
+  #include <linux/pci.h>
+  #include <linux/slab.h>
+  #include <sound/core.h>
+  #include <sound/initval.h>
+
+  /* module parameters (see "Module Parameters") */
+  /* SNDRV_CARDS: maximum number of cards supported by this module */
+  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+  static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+  /* definition of the chip-specific record */
+  struct mychip {
+          struct snd_card *card;
+          /* the rest of the implementation will be in section
+           * "PCI Resource Management"
+           */
+  };
+
+  /* chip-specific destructor
+   * (see "PCI Resource Management")
+   */
+  static int snd_mychip_free(struct mychip *chip)
+  {
+          .... /* will be implemented later... */
+  }
+
+  /* component-destructor
+   * (see "Management of Cards and Components")
+   */
+  static int snd_mychip_dev_free(struct snd_device *device)
+  {
+          return snd_mychip_free(device->device_data);
+  }
+
+  /* chip-specific constructor
+   * (see "Management of Cards and Components")
+   */
+  static int __devinit snd_mychip_create(struct snd_card *card,
+                                         struct pci_dev *pci,
+                                         struct mychip **rchip)
+  {
+          struct mychip *chip;
+          int err;
+          static struct snd_device_ops ops = {
+                 .dev_free = snd_mychip_dev_free,
+          };
+
+          *rchip = NULL;
+
+          /* check PCI availability here
+           * (see "PCI Resource Management")
+           */
+          ....
+
+          /* allocate a chip-specific data with zero filled */
+          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+          if (chip == NULL)
+                  return -ENOMEM;
+
+          chip->card = card;
+
+          /* rest of initialization here; will be implemented
+           * later, see "PCI Resource Management"
+           */
+          ....
+
+          err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+          if (err < 0) {
+                  snd_mychip_free(chip);
+                  return err;
+          }
+
+          snd_card_set_dev(card, &pci->dev);
+
+          *rchip = chip;
+          return 0;
+  }
+
+  /* constructor -- see "Constructor" sub-section */
+  static int __devinit snd_mychip_probe(struct pci_dev *pci,
+                               const struct pci_device_id *pci_id)
+  {
+          static int dev;
+          struct snd_card *card;
+          struct mychip *chip;
+          int err;
+
+          /* (1) */
+          if (dev >= SNDRV_CARDS)
+                  return -ENODEV;
+          if (!enable[dev]) {
+                  dev++;
+                  return -ENOENT;
+          }
+
+          /* (2) */
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+          if (err < 0)
+                  return err;
+
+          /* (3) */
+          err = snd_mychip_create(card, pci, &chip);
+          if (err < 0) {
+                  snd_card_free(card);
+                  return err;
+          }
+
+          /* (4) */
+          strcpy(card->driver, "My Chip");
+          strcpy(card->shortname, "My Own Chip 123");
+          sprintf(card->longname, "%s at 0x%lx irq %i",
+                  card->shortname, chip->ioport, chip->irq);
+
+          /* (5) */
+          .... /* implemented later */
+
+          /* (6) */
+          err = snd_card_register(card);
+          if (err < 0) {
+                  snd_card_free(card);
+                  return err;
+          }
+
+          /* (7) */
+          pci_set_drvdata(pci, card);
+          dev++;
+          return 0;
+  }
+
+  /* destructor -- see the "Destructor" sub-section */
+  static void __devexit snd_mychip_remove(struct pci_dev *pci)
+  {
+          snd_card_free(pci_get_drvdata(pci));
+          pci_set_drvdata(pci, NULL);
+  }
+]]>
+          </programlisting>
+        </example>
+      </para>
+    </section>
+
+    <section id="basic-flow-constructor">
+      <title>Constructor</title>
+      <para>
+        The real constructor of PCI drivers is the <function>probe</function> callback.
+      The <function>probe</function> callback and other component-constructors which are called
+      from the <function>probe</function> callback should be defined with
+      the <parameter>__devinit</parameter> prefix. You 
+      cannot use the <parameter>__init</parameter> prefix for them,
+      because any PCI device could be a hotplug device. 
+      </para>
+
+      <para>
+        In the <function>probe</function> callback, the following scheme is often used.
+      </para>
+
+      <section id="basic-flow-constructor-device-index">
+        <title>1) Check and increment the device index.</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int dev;
+  ....
+  if (dev >= SNDRV_CARDS)
+          return -ENODEV;
+  if (!enable[dev]) {
+          dev++;
+          return -ENOENT;
+  }
+]]>
+            </programlisting>
+          </informalexample>
+
+        where enable[dev] is the module option.
+        </para>
+
+        <para>
+          Each time the <function>probe</function> callback is called, check the
+        availability of the device. If not available, simply increment
+        the device index and returns. dev will be incremented also
+        later (<link
+        linkend="basic-flow-constructor-set-pci"><citetitle>step
+        7</citetitle></link>). 
+        </para>
+      </section>
+
+      <section id="basic-flow-constructor-create-card">
+        <title>2) Create a card instance</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  struct snd_card *card;
+  int err;
+  ....
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          The details will be explained in the section
+          <link linkend="card-management-card-instance"><citetitle>
+          Management of Cards and Components</citetitle></link>.
+        </para>
+      </section>
+
+      <section id="basic-flow-constructor-create-main">
+        <title>3) Create a main component</title>
+        <para>
+          In this part, the PCI resources are allocated.
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  struct mychip *chip;
+  ....
+  err = snd_mychip_create(card, pci, &chip);
+  if (err < 0) {
+          snd_card_free(card);
+          return err;
+  }
+]]>
+            </programlisting>
+          </informalexample>
+
+          The details will be explained in the section <link
+        linkend="pci-resource"><citetitle>PCI Resource
+        Management</citetitle></link>.
+        </para>
+      </section>
+
+      <section id="basic-flow-constructor-main-component">
+        <title>4) Set the driver ID and name strings.</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  strcpy(card->driver, "My Chip");
+  strcpy(card->shortname, "My Own Chip 123");
+  sprintf(card->longname, "%s at 0x%lx irq %i",
+          card->shortname, chip->ioport, chip->irq);
+]]>
+            </programlisting>
+          </informalexample>
+
+          The driver field holds the minimal ID string of the
+        chip. This is used by alsa-lib's configurator, so keep it
+        simple but unique. 
+          Even the same driver can have different driver IDs to
+        distinguish the functionality of each chip type. 
+        </para>
+
+        <para>
+          The shortname field is a string shown as more verbose
+        name. The longname field contains the information
+        shown in <filename>/proc/asound/cards</filename>. 
+        </para>
+      </section>
+
+      <section id="basic-flow-constructor-create-other">
+        <title>5) Create other components, such as mixer, MIDI, etc.</title>
+        <para>
+          Here you define the basic components such as
+          <link linkend="pcm-interface"><citetitle>PCM</citetitle></link>,
+          mixer (e.g. <link linkend="api-ac97"><citetitle>AC97</citetitle></link>),
+          MIDI (e.g. <link linkend="midi-interface"><citetitle>MPU-401</citetitle></link>),
+          and other interfaces.
+          Also, if you want a <link linkend="proc-interface"><citetitle>proc
+        file</citetitle></link>, define it here, too.
+        </para>
+      </section>
+
+      <section id="basic-flow-constructor-register-card">
+        <title>6) Register the card instance.</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  err = snd_card_register(card);
+  if (err < 0) {
+          snd_card_free(card);
+          return err;
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          Will be explained in the section <link
+        linkend="card-management-registration"><citetitle>Management
+        of Cards and Components</citetitle></link>, too. 
+        </para>
+      </section>
+
+      <section id="basic-flow-constructor-set-pci">
+        <title>7) Set the PCI driver data and return zero.</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+        pci_set_drvdata(pci, card);
+        dev++;
+        return 0;
+]]>
+            </programlisting>
+          </informalexample>
+
+          In the above, the card record is stored. This pointer is
+        used in the remove callback and power-management
+        callbacks, too. 
+        </para>
+      </section>
+    </section>
+
+    <section id="basic-flow-destructor">
+      <title>Destructor</title>
+      <para>
+        The destructor, remove callback, simply releases the card
+      instance. Then the ALSA middle layer will release all the
+      attached components automatically. 
+      </para>
+
+      <para>
+        It would be typically like the following:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void __devexit snd_mychip_remove(struct pci_dev *pci)
+  {
+          snd_card_free(pci_get_drvdata(pci));
+          pci_set_drvdata(pci, NULL);
+  }
+]]>
+          </programlisting>
+        </informalexample>
+
+        The above code assumes that the card pointer is set to the PCI
+	driver data.
+      </para>
+    </section>
+
+    <section id="basic-flow-header-files">
+      <title>Header Files</title>
+      <para>
+        For the above example, at least the following include files
+      are necessary. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  #include <linux/init.h>
+  #include <linux/pci.h>
+  #include <linux/slab.h>
+  #include <sound/core.h>
+  #include <sound/initval.h>
+]]>
+          </programlisting>
+        </informalexample>
+
+	where the last one is necessary only when module options are
+      defined in the source file.  If the code is split into several
+      files, the files without module options don't need them.
+      </para>
+
+      <para>
+        In addition to these headers, you'll need
+      <filename>&lt;linux/interrupt.h&gt;</filename> for interrupt
+      handling, and <filename>&lt;asm/io.h&gt;</filename> for I/O
+      access. If you use the <function>mdelay()</function> or
+      <function>udelay()</function> functions, you'll need to include
+      <filename>&lt;linux/delay.h&gt;</filename> too. 
+      </para>
+
+      <para>
+      The ALSA interfaces like the PCM and control APIs are defined in other
+      <filename>&lt;sound/xxx.h&gt;</filename> header files.
+      They have to be included after
+      <filename>&lt;sound/core.h&gt;</filename>.
+      </para>
+
+    </section>
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Management of Cards and Components  -->
+<!-- ****************************************************** -->
+  <chapter id="card-management">
+    <title>Management of Cards and Components</title>
+
+    <section id="card-management-card-instance">
+      <title>Card Instance</title>
+      <para>
+      For each soundcard, a <quote>card</quote> record must be allocated.
+      </para>
+
+      <para>
+      A card record is the headquarters of the soundcard.  It manages
+      the whole list of devices (components) on the soundcard, such as
+      PCM, mixers, MIDI, synthesizer, and so on.  Also, the card
+      record holds the ID and the name strings of the card, manages
+      the root of proc files, and controls the power-management states
+      and hotplug disconnections.  The component list on the card
+      record is used to manage the correct release of resources at
+      destruction. 
+      </para>
+
+      <para>
+        As mentioned above, to create a card instance, call
+      <function>snd_card_create()</function>.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_card *card;
+  int err;
+  err = snd_card_create(index, id, module, extra_size, &card);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The function takes five arguments, the card-index number, the
+        id string, the module pointer (usually
+        <constant>THIS_MODULE</constant>),
+        the size of extra-data space, and the pointer to return the
+        card instance.  The extra_size argument is used to
+        allocate card-&gt;private_data for the
+        chip-specific data.  Note that these data
+        are allocated by <function>snd_card_create()</function>.
+      </para>
+    </section>
+
+    <section id="card-management-component">
+      <title>Components</title>
+      <para>
+        After the card is created, you can attach the components
+      (devices) to the card instance. In an ALSA driver, a component is
+      represented as a struct <structname>snd_device</structname> object.
+      A component can be a PCM instance, a control interface, a raw
+      MIDI interface, etc.  Each such instance has one component
+      entry.
+      </para>
+
+      <para>
+        A component can be created via
+        <function>snd_device_new()</function> function. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        This takes the card pointer, the device-level
+      (<constant>SNDRV_DEV_XXX</constant>), the data pointer, and the
+      callback pointers (<parameter>&amp;ops</parameter>). The
+      device-level defines the type of components and the order of
+      registration and de-registration.  For most components, the
+      device-level is already defined.  For a user-defined component,
+      you can use <constant>SNDRV_DEV_LOWLEVEL</constant>.
+      </para>
+
+      <para>
+      This function itself doesn't allocate the data space. The data
+      must be allocated manually beforehand, and its pointer is passed
+      as the argument. This pointer is used as the
+      (<parameter>chip</parameter> identifier in the above example)
+      for the instance. 
+      </para>
+
+      <para>
+        Each pre-defined ALSA component such as ac97 and pcm calls
+      <function>snd_device_new()</function> inside its
+      constructor. The destructor for each component is defined in the
+      callback pointers.  Hence, you don't need to take care of
+      calling a destructor for such a component.
+      </para>
+
+      <para>
+        If you wish to create your own component, you need to
+      set the destructor function to the dev_free callback in
+      the <parameter>ops</parameter>, so that it can be released
+      automatically via <function>snd_card_free()</function>.
+      The next example will show an implementation of chip-specific
+      data.
+      </para>
+    </section>
+
+    <section id="card-management-chip-specific">
+      <title>Chip-Specific Data</title>
+      <para>
+      Chip-specific information, e.g. the I/O port address, its
+      resource pointer, or the irq number, is stored in the
+      chip-specific record.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct mychip {
+          ....
+  };
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        In general, there are two ways of allocating the chip record.
+      </para>
+
+      <section id="card-management-chip-specific-snd-card-new">
+        <title>1. Allocating via <function>snd_card_create()</function>.</title>
+        <para>
+          As mentioned above, you can pass the extra-data-length
+	  to the 4th argument of <function>snd_card_create()</function>, i.e.
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                        sizeof(struct mychip), &card);
+]]>
+            </programlisting>
+          </informalexample>
+
+          struct <structname>mychip</structname> is the type of the chip record.
+        </para>
+
+        <para>
+          In return, the allocated record can be accessed as
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  struct mychip *chip = card->private_data;
+]]>
+            </programlisting>
+          </informalexample>
+
+          With this method, you don't have to allocate twice.
+          The record is released together with the card instance.
+        </para>
+      </section>
+
+      <section id="card-management-chip-specific-allocate-extra">
+        <title>2. Allocating an extra device.</title>
+
+        <para>
+          After allocating a card instance via
+          <function>snd_card_create()</function> (with
+          <constant>0</constant> on the 4th arg), call
+          <function>kzalloc()</function>. 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  struct snd_card *card;
+  struct mychip *chip;
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+  .....
+  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          The chip record should have the field to hold the card
+          pointer at least, 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  struct mychip {
+          struct snd_card *card;
+          ....
+  };
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          Then, set the card pointer in the returned chip instance.
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  chip->card = card;
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          Next, initialize the fields, and register this chip
+          record as a low-level device with a specified
+          <parameter>ops</parameter>, 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static struct snd_device_ops ops = {
+          .dev_free =        snd_mychip_dev_free,
+  };
+  ....
+  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+]]>
+            </programlisting>
+          </informalexample>
+
+          <function>snd_mychip_dev_free()</function> is the
+        device-destructor function, which will call the real
+        destructor. 
+        </para>
+
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_mychip_dev_free(struct snd_device *device)
+  {
+          return snd_mychip_free(device->device_data);
+  }
+]]>
+            </programlisting>
+          </informalexample>
+
+          where <function>snd_mychip_free()</function> is the real destructor.
+        </para>
+      </section>
+    </section>
+
+    <section id="card-management-registration">
+      <title>Registration and Release</title>
+      <para>
+        After all components are assigned, register the card instance
+      by calling <function>snd_card_register()</function>. Access
+      to the device files is enabled at this point. That is, before
+      <function>snd_card_register()</function> is called, the
+      components are safely inaccessible from external side. If this
+      call fails, exit the probe function after releasing the card via
+      <function>snd_card_free()</function>. 
+      </para>
+
+      <para>
+        For releasing the card instance, you can call simply
+      <function>snd_card_free()</function>. As mentioned earlier, all
+      components are released automatically by this call. 
+      </para>
+
+      <para>
+        As further notes, the destructors (both
+      <function>snd_mychip_dev_free</function> and
+      <function>snd_mychip_free</function>) cannot be defined with
+      the <parameter>__devexit</parameter> prefix, because they may be
+      called from the constructor, too, at the false path. 
+      </para>
+
+      <para>
+      For a device which allows hotplugging, you can use
+      <function>snd_card_free_when_closed</function>.  This one will
+      postpone the destruction until all devices are closed.
+      </para>
+
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- PCI Resource Management  -->
+<!-- ****************************************************** -->
+  <chapter id="pci-resource">
+    <title>PCI Resource Management</title>
+
+    <section id="pci-resource-example">
+      <title>Full Code Example</title>
+      <para>
+        In this section, we'll complete the chip-specific constructor,
+      destructor and PCI entries. Example code is shown first,
+      below. 
+
+        <example>
+          <title>PCI Resource Management Example</title>
+          <programlisting>
+<![CDATA[
+  struct mychip {
+          struct snd_card *card;
+          struct pci_dev *pci;
+
+          unsigned long port;
+          int irq;
+  };
+
+  static int snd_mychip_free(struct mychip *chip)
+  {
+          /* disable hardware here if any */
+          .... /* (not implemented in this document) */
+
+          /* release the irq */
+          if (chip->irq >= 0)
+                  free_irq(chip->irq, chip);
+          /* release the I/O ports & memory */
+          pci_release_regions(chip->pci);
+          /* disable the PCI entry */
+          pci_disable_device(chip->pci);
+          /* release the data */
+          kfree(chip);
+          return 0;
+  }
+
+  /* chip-specific constructor */
+  static int __devinit snd_mychip_create(struct snd_card *card,
+                                         struct pci_dev *pci,
+                                         struct mychip **rchip)
+  {
+          struct mychip *chip;
+          int err;
+          static struct snd_device_ops ops = {
+                 .dev_free = snd_mychip_dev_free,
+          };
+
+          *rchip = NULL;
+
+          /* initialize the PCI entry */
+          err = pci_enable_device(pci);
+          if (err < 0)
+                  return err;
+          /* check PCI availability (28bit DMA) */
+          if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+              pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
+                  printk(KERN_ERR "error to set 28bit mask DMA\n");
+                  pci_disable_device(pci);
+                  return -ENXIO;
+          }
+
+          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+          if (chip == NULL) {
+                  pci_disable_device(pci);
+                  return -ENOMEM;
+          }
+
+          /* initialize the stuff */
+          chip->card = card;
+          chip->pci = pci;
+          chip->irq = -1;
+
+          /* (1) PCI resource allocation */
+          err = pci_request_regions(pci, "My Chip");
+          if (err < 0) {
+                  kfree(chip);
+                  pci_disable_device(pci);
+                  return err;
+          }
+          chip->port = pci_resource_start(pci, 0);
+          if (request_irq(pci->irq, snd_mychip_interrupt,
+                          IRQF_SHARED, "My Chip", chip)) {
+                  printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+                  snd_mychip_free(chip);
+                  return -EBUSY;
+          }
+          chip->irq = pci->irq;
+
+          /* (2) initialization of the chip hardware */
+          .... /*   (not implemented in this document) */
+
+          err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+          if (err < 0) {
+                  snd_mychip_free(chip);
+                  return err;
+          }
+
+          snd_card_set_dev(card, &pci->dev);
+
+          *rchip = chip;
+          return 0;
+  }        
+
+  /* PCI IDs */
+  static struct pci_device_id snd_mychip_ids[] = {
+          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
+            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+          ....
+          { 0, }
+  };
+  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
+
+  /* pci_driver definition */
+  static struct pci_driver driver = {
+          .name = "My Own Chip",
+          .id_table = snd_mychip_ids,
+          .probe = snd_mychip_probe,
+          .remove = __devexit_p(snd_mychip_remove),
+  };
+
+  /* module initialization */
+  static int __init alsa_card_mychip_init(void)
+  {
+          return pci_register_driver(&driver);
+  }
+
+  /* module clean up */
+  static void __exit alsa_card_mychip_exit(void)
+  {
+          pci_unregister_driver(&driver);
+  }
+
+  module_init(alsa_card_mychip_init)
+  module_exit(alsa_card_mychip_exit)
+
+  EXPORT_NO_SYMBOLS; /* for old kernels only */
+]]>
+          </programlisting>
+        </example>
+      </para>
+    </section>
+
+    <section id="pci-resource-some-haftas">
+      <title>Some Hafta's</title>
+      <para>
+        The allocation of PCI resources is done in the
+      <function>probe()</function> function, and usually an extra
+      <function>xxx_create()</function> function is written for this
+      purpose.
+      </para>
+
+      <para>
+        In the case of PCI devices, you first have to call
+      the <function>pci_enable_device()</function> function before
+      allocating resources. Also, you need to set the proper PCI DMA
+      mask to limit the accessed I/O range. In some cases, you might
+      need to call <function>pci_set_master()</function> function,
+      too.
+      </para>
+
+      <para>
+        Suppose the 28bit mask, and the code to be added would be like:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  err = pci_enable_device(pci);
+  if (err < 0)
+          return err;
+  if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+      pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
+          printk(KERN_ERR "error to set 28bit mask DMA\n");
+          pci_disable_device(pci);
+          return -ENXIO;
+  }
+  
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+    </section>
+
+    <section id="pci-resource-resource-allocation">
+      <title>Resource Allocation</title>
+      <para>
+        The allocation of I/O ports and irqs is done via standard kernel
+      functions. Unlike ALSA ver.0.5.x., there are no helpers for
+      that. And these resources must be released in the destructor
+      function (see below). Also, on ALSA 0.9.x, you don't need to
+      allocate (pseudo-)DMA for PCI like in ALSA 0.5.x.
+      </para>
+
+      <para>
+        Now assume that the PCI device has an I/O port with 8 bytes
+        and an interrupt. Then struct <structname>mychip</structname> will have the
+        following fields:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct mychip {
+          struct snd_card *card;
+
+          unsigned long port;
+          int irq;
+  };
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        For an I/O port (and also a memory region), you need to have
+      the resource pointer for the standard resource management. For
+      an irq, you have to keep only the irq number (integer). But you
+      need to initialize this number as -1 before actual allocation,
+      since irq 0 is valid. The port address and its resource pointer
+      can be initialized as null by
+      <function>kzalloc()</function> automatically, so you
+      don't have to take care of resetting them. 
+      </para>
+
+      <para>
+        The allocation of an I/O port is done like this:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  err = pci_request_regions(pci, "My Chip");
+  if (err < 0) { 
+          kfree(chip);
+          pci_disable_device(pci);
+          return err;
+  }
+  chip->port = pci_resource_start(pci, 0);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        <!-- obsolete -->
+        It will reserve the I/O port region of 8 bytes of the given
+      PCI device. The returned value, chip-&gt;res_port, is allocated
+      via <function>kmalloc()</function> by
+      <function>request_region()</function>. The pointer must be
+      released via <function>kfree()</function>, but there is a
+      problem with this. This issue will be explained later.
+      </para>
+
+      <para>
+        The allocation of an interrupt source is done like this:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  if (request_irq(pci->irq, snd_mychip_interrupt,
+                  IRQF_SHARED, "My Chip", chip)) {
+          printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+          snd_mychip_free(chip);
+          return -EBUSY;
+  }
+  chip->irq = pci->irq;
+]]>
+          </programlisting>
+        </informalexample>
+
+        where <function>snd_mychip_interrupt()</function> is the
+      interrupt handler defined <link
+      linkend="pcm-interface-interrupt-handler"><citetitle>later</citetitle></link>.
+      Note that chip-&gt;irq should be defined
+      only when <function>request_irq()</function> succeeded.
+      </para>
+
+      <para>
+      On the PCI bus, interrupts can be shared. Thus,
+      <constant>IRQF_SHARED</constant> is used as the interrupt flag of
+      <function>request_irq()</function>. 
+      </para>
+
+      <para>
+        The last argument of <function>request_irq()</function> is the
+      data pointer passed to the interrupt handler. Usually, the
+      chip-specific record is used for that, but you can use what you
+      like, too. 
+      </para>
+
+      <para>
+        I won't give details about the interrupt handler at this
+        point, but at least its appearance can be explained now. The
+        interrupt handler looks usually like the following: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+  {
+          struct mychip *chip = dev_id;
+          ....
+          return IRQ_HANDLED;
+  }
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        Now let's write the corresponding destructor for the resources
+      above. The role of destructor is simple: disable the hardware
+      (if already activated) and release the resources. So far, we
+      have no hardware part, so the disabling code is not written here. 
+      </para>
+
+      <para>
+        To release the resources, the <quote>check-and-release</quote>
+        method is a safer way. For the interrupt, do like this: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  if (chip->irq >= 0)
+          free_irq(chip->irq, chip);
+]]>
+          </programlisting>
+        </informalexample>
+
+        Since the irq number can start from 0, you should initialize
+        chip-&gt;irq with a negative value (e.g. -1), so that you can
+        check the validity of the irq number as above.
+      </para>
+
+      <para>
+        When you requested I/O ports or memory regions via
+	<function>pci_request_region()</function> or
+	<function>pci_request_regions()</function> like in this example,
+	release the resource(s) using the corresponding function,
+	<function>pci_release_region()</function> or
+	<function>pci_release_regions()</function>.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  pci_release_regions(chip->pci);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+	When you requested manually via <function>request_region()</function>
+	or <function>request_mem_region</function>, you can release it via
+	<function>release_resource()</function>.  Suppose that you keep
+	the resource pointer returned from <function>request_region()</function>
+	in chip-&gt;res_port, the release procedure looks like:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  release_and_free_resource(chip->res_port);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+      Don't forget to call <function>pci_disable_device()</function>
+      before the end.
+      </para>
+
+      <para>
+        And finally, release the chip-specific record.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  kfree(chip);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+      Again, remember that you cannot
+      use the <parameter>__devexit</parameter> prefix for this destructor. 
+      </para>
+
+      <para>
+      We didn't implement the hardware disabling part in the above.
+      If you need to do this, please note that the destructor may be
+      called even before the initialization of the chip is completed.
+      It would be better to have a flag to skip hardware disabling
+      if the hardware was not initialized yet.
+      </para>
+
+      <para>
+      When the chip-data is assigned to the card using
+      <function>snd_device_new()</function> with
+      <constant>SNDRV_DEV_LOWLELVEL</constant> , its destructor is 
+      called at the last.  That is, it is assured that all other
+      components like PCMs and controls have already been released.
+      You don't have to stop PCMs, etc. explicitly, but just
+      call low-level hardware stopping.
+      </para>
+
+      <para>
+        The management of a memory-mapped region is almost as same as
+        the management of an I/O port. You'll need three fields like
+        the following: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct mychip {
+          ....
+          unsigned long iobase_phys;
+          void __iomem *iobase_virt;
+  };
+]]>
+          </programlisting>
+        </informalexample>
+
+        and the allocation would be like below:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+          kfree(chip);
+          return err;
+  }
+  chip->iobase_phys = pci_resource_start(pci, 0);
+  chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
+                                      pci_resource_len(pci, 0));
+]]>
+          </programlisting>
+        </informalexample>
+        
+        and the corresponding destructor would be:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int snd_mychip_free(struct mychip *chip)
+  {
+          ....
+          if (chip->iobase_virt)
+                  iounmap(chip->iobase_virt);
+          ....
+          pci_release_regions(chip->pci);
+          ....
+  }
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+    </section>
+
+    <section id="pci-resource-device-struct">
+      <title>Registration of Device Struct</title>
+      <para>
+	At some point, typically after calling <function>snd_device_new()</function>,
+	you need to register the struct <structname>device</structname> of the chip
+	you're handling for udev and co.  ALSA provides a macro for compatibility with
+	older kernels.  Simply call like the following:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_card_set_dev(card, &pci->dev);
+]]>
+          </programlisting>
+        </informalexample>
+	so that it stores the PCI's device pointer to the card.  This will be
+	referred by ALSA core functions later when the devices are registered.
+      </para>
+      <para>
+	In the case of non-PCI, pass the proper device struct pointer of the BUS
+	instead.  (In the case of legacy ISA without PnP, you don't have to do
+	anything.)
+      </para>
+    </section>
+
+    <section id="pci-resource-entries">
+      <title>PCI Entries</title>
+      <para>
+        So far, so good. Let's finish the missing PCI
+      stuff. At first, we need a
+      <structname>pci_device_id</structname> table for this
+      chipset. It's a table of PCI vendor/device ID number, and some
+      masks. 
+      </para>
+
+      <para>
+        For example,
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static struct pci_device_id snd_mychip_ids[] = {
+          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
+            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+          ....
+          { 0, }
+  };
+  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The first and second fields of
+      the <structname>pci_device_id</structname> structure are the vendor and
+      device IDs. If you have no reason to filter the matching
+      devices, you can leave the remaining fields as above. The last
+      field of the <structname>pci_device_id</structname> struct contains
+      private data for this entry. You can specify any value here, for
+      example, to define specific operations for supported device IDs.
+      Such an example is found in the intel8x0 driver. 
+      </para>
+
+      <para>
+        The last entry of this list is the terminator. You must
+      specify this all-zero entry. 
+      </para>
+
+      <para>
+        Then, prepare the <structname>pci_driver</structname> record:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static struct pci_driver driver = {
+          .name = "My Own Chip",
+          .id_table = snd_mychip_ids,
+          .probe = snd_mychip_probe,
+          .remove = __devexit_p(snd_mychip_remove),
+  };
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The <structfield>probe</structfield> and
+      <structfield>remove</structfield> functions have already
+      been defined in the previous sections.
+      The <structfield>remove</structfield> function should
+      be defined with the 
+      <function>__devexit_p()</function> macro, so that it's not
+      defined for built-in (and non-hot-pluggable) case. The
+      <structfield>name</structfield> 
+      field is the name string of this device. Note that you must not
+      use a slash <quote>/</quote> in this string. 
+      </para>
+
+      <para>
+        And at last, the module entries:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int __init alsa_card_mychip_init(void)
+  {
+          return pci_register_driver(&driver);
+  }
+
+  static void __exit alsa_card_mychip_exit(void)
+  {
+          pci_unregister_driver(&driver);
+  }
+
+  module_init(alsa_card_mychip_init)
+  module_exit(alsa_card_mychip_exit)
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        Note that these module entries are tagged with
+      <parameter>__init</parameter> and 
+      <parameter>__exit</parameter> prefixes, not
+      <parameter>__devinit</parameter> nor
+      <parameter>__devexit</parameter>.
+      </para>
+
+      <para>
+        Oh, one thing was forgotten. If you have no exported symbols,
+        you need to declare it in 2.2 or 2.4 kernels (it's not necessary in 2.6 kernels).
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  EXPORT_NO_SYMBOLS;
+]]>
+          </programlisting>
+        </informalexample>
+
+        That's all!
+      </para>
+    </section>
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- PCM Interface  -->
+<!-- ****************************************************** -->
+  <chapter id="pcm-interface">
+    <title>PCM Interface</title>
+
+    <section id="pcm-interface-general">
+      <title>General</title>
+      <para>
+        The PCM middle layer of ALSA is quite powerful and it is only
+      necessary for each driver to implement the low-level functions
+      to access its hardware.
+      </para>
+
+      <para>
+        For accessing to the PCM layer, you need to include
+      <filename>&lt;sound/pcm.h&gt;</filename> first. In addition,
+      <filename>&lt;sound/pcm_params.h&gt;</filename> might be needed
+      if you access to some functions related with hw_param. 
+      </para>
+
+      <para>
+        Each card device can have up to four pcm instances. A pcm
+      instance corresponds to a pcm device file. The limitation of
+      number of instances comes only from the available bit size of
+      the Linux's device numbers. Once when 64bit device number is
+      used, we'll have more pcm instances available. 
+      </para>
+
+      <para>
+        A pcm instance consists of pcm playback and capture streams,
+      and each pcm stream consists of one or more pcm substreams. Some
+      soundcards support multiple playback functions. For example,
+      emu10k1 has a PCM playback of 32 stereo substreams. In this case, at
+      each open, a free substream is (usually) automatically chosen
+      and opened. Meanwhile, when only one substream exists and it was
+      already opened, the successful open will either block
+      or error with <constant>EAGAIN</constant> according to the
+      file open mode. But you don't have to care about such details in your
+      driver. The PCM middle layer will take care of such work.
+      </para>
+    </section>
+
+    <section id="pcm-interface-example">
+      <title>Full Code Example</title>
+      <para>
+      The example code below does not include any hardware access
+      routines but shows only the skeleton, how to build up the PCM
+      interfaces.
+
+        <example>
+          <title>PCM Example Code</title>
+          <programlisting>
+<![CDATA[
+  #include <sound/pcm.h>
+  ....
+
+  /* hardware definition */
+  static struct snd_pcm_hardware snd_mychip_playback_hw = {
+          .info = (SNDRV_PCM_INFO_MMAP |
+                   SNDRV_PCM_INFO_INTERLEAVED |
+                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                   SNDRV_PCM_INFO_MMAP_VALID),
+          .formats =          SNDRV_PCM_FMTBIT_S16_LE,
+          .rates =            SNDRV_PCM_RATE_8000_48000,
+          .rate_min =         8000,
+          .rate_max =         48000,
+          .channels_min =     2,
+          .channels_max =     2,
+          .buffer_bytes_max = 32768,
+          .period_bytes_min = 4096,
+          .period_bytes_max = 32768,
+          .periods_min =      1,
+          .periods_max =      1024,
+  };
+
+  /* hardware definition */
+  static struct snd_pcm_hardware snd_mychip_capture_hw = {
+          .info = (SNDRV_PCM_INFO_MMAP |
+                   SNDRV_PCM_INFO_INTERLEAVED |
+                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                   SNDRV_PCM_INFO_MMAP_VALID),
+          .formats =          SNDRV_PCM_FMTBIT_S16_LE,
+          .rates =            SNDRV_PCM_RATE_8000_48000,
+          .rate_min =         8000,
+          .rate_max =         48000,
+          .channels_min =     2,
+          .channels_max =     2,
+          .buffer_bytes_max = 32768,
+          .period_bytes_min = 4096,
+          .period_bytes_max = 32768,
+          .periods_min =      1,
+          .periods_max =      1024,
+  };
+
+  /* open callback */
+  static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          struct snd_pcm_runtime *runtime = substream->runtime;
+
+          runtime->hw = snd_mychip_playback_hw;
+          /* more hardware-initialization will be done here */
+          ....
+          return 0;
+  }
+
+  /* close callback */
+  static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          /* the hardware-specific codes will be here */
+          ....
+          return 0;
+
+  }
+
+  /* open callback */
+  static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          struct snd_pcm_runtime *runtime = substream->runtime;
+
+          runtime->hw = snd_mychip_capture_hw;
+          /* more hardware-initialization will be done here */
+          ....
+          return 0;
+  }
+
+  /* close callback */
+  static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          /* the hardware-specific codes will be here */
+          ....
+          return 0;
+
+  }
+
+  /* hw_params callback */
+  static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *hw_params)
+  {
+          return snd_pcm_lib_malloc_pages(substream,
+                                     params_buffer_bytes(hw_params));
+  }
+
+  /* hw_free callback */
+  static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
+  {
+          return snd_pcm_lib_free_pages(substream);
+  }
+
+  /* prepare callback */
+  static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          struct snd_pcm_runtime *runtime = substream->runtime;
+
+          /* set up the hardware with the current configuration
+           * for example...
+           */
+          mychip_set_sample_format(chip, runtime->format);
+          mychip_set_sample_rate(chip, runtime->rate);
+          mychip_set_channels(chip, runtime->channels);
+          mychip_set_dma_setup(chip, runtime->dma_addr,
+                               chip->buffer_size,
+                               chip->period_size);
+          return 0;
+  }
+
+  /* trigger callback */
+  static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
+                                    int cmd)
+  {
+          switch (cmd) {
+          case SNDRV_PCM_TRIGGER_START:
+                  /* do something to start the PCM engine */
+                  ....
+                  break;
+          case SNDRV_PCM_TRIGGER_STOP:
+                  /* do something to stop the PCM engine */
+                  ....
+                  break;
+          default:
+                  return -EINVAL;
+          }
+  }
+
+  /* pointer callback */
+  static snd_pcm_uframes_t
+  snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          unsigned int current_ptr;
+
+          /* get the current hardware pointer */
+          current_ptr = mychip_get_hw_pointer(chip);
+          return current_ptr;
+  }
+
+  /* operators */
+  static struct snd_pcm_ops snd_mychip_playback_ops = {
+          .open =        snd_mychip_playback_open,
+          .close =       snd_mychip_playback_close,
+          .ioctl =       snd_pcm_lib_ioctl,
+          .hw_params =   snd_mychip_pcm_hw_params,
+          .hw_free =     snd_mychip_pcm_hw_free,
+          .prepare =     snd_mychip_pcm_prepare,
+          .trigger =     snd_mychip_pcm_trigger,
+          .pointer =     snd_mychip_pcm_pointer,
+  };
+
+  /* operators */
+  static struct snd_pcm_ops snd_mychip_capture_ops = {
+          .open =        snd_mychip_capture_open,
+          .close =       snd_mychip_capture_close,
+          .ioctl =       snd_pcm_lib_ioctl,
+          .hw_params =   snd_mychip_pcm_hw_params,
+          .hw_free =     snd_mychip_pcm_hw_free,
+          .prepare =     snd_mychip_pcm_prepare,
+          .trigger =     snd_mychip_pcm_trigger,
+          .pointer =     snd_mychip_pcm_pointer,
+  };
+
+  /*
+   *  definitions of capture are omitted here...
+   */
+
+  /* create a pcm device */
+  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+  {
+          struct snd_pcm *pcm;
+          int err;
+
+          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+          if (err < 0) 
+                  return err;
+          pcm->private_data = chip;
+          strcpy(pcm->name, "My Chip");
+          chip->pcm = pcm;
+          /* set operators */
+          snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                          &snd_mychip_playback_ops);
+          snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                          &snd_mychip_capture_ops);
+          /* pre-allocation of buffers */
+          /* NOTE: this may fail */
+          snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                                snd_dma_pci_data(chip->pci),
+                                                64*1024, 64*1024);
+          return 0;
+  }
+]]>
+          </programlisting>
+        </example>
+      </para>
+    </section>
+
+    <section id="pcm-interface-constructor">
+      <title>Constructor</title>
+      <para>
+        A pcm instance is allocated by the <function>snd_pcm_new()</function>
+      function. It would be better to create a constructor for pcm,
+      namely, 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+  {
+          struct snd_pcm *pcm;
+          int err;
+
+          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+          if (err < 0) 
+                  return err;
+          pcm->private_data = chip;
+          strcpy(pcm->name, "My Chip");
+          chip->pcm = pcm;
+	  ....
+          return 0;
+  }
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The <function>snd_pcm_new()</function> function takes four
+      arguments. The first argument is the card pointer to which this
+      pcm is assigned, and the second is the ID string. 
+      </para>
+
+      <para>
+        The third argument (<parameter>index</parameter>, 0 in the
+      above) is the index of this new pcm. It begins from zero. If
+      you create more than one pcm instances, specify the
+      different numbers in this argument. For example,
+      <parameter>index</parameter> = 1 for the second PCM device.  
+      </para>
+
+      <para>
+        The fourth and fifth arguments are the number of substreams
+      for playback and capture, respectively. Here 1 is used for
+      both arguments. When no playback or capture substreams are available,
+      pass 0 to the corresponding argument.
+      </para>
+
+      <para>
+        If a chip supports multiple playbacks or captures, you can
+      specify more numbers, but they must be handled properly in
+      open/close, etc. callbacks.  When you need to know which
+      substream you are referring to, then it can be obtained from
+      struct <structname>snd_pcm_substream</structname> data passed to each callback
+      as follows: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_pcm_substream *substream;
+  int index = substream->number;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        After the pcm is created, you need to set operators for each
+        pcm stream. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                  &snd_mychip_playback_ops);
+  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                  &snd_mychip_capture_ops);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The operators are defined typically like this:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static struct snd_pcm_ops snd_mychip_playback_ops = {
+          .open =        snd_mychip_pcm_open,
+          .close =       snd_mychip_pcm_close,
+          .ioctl =       snd_pcm_lib_ioctl,
+          .hw_params =   snd_mychip_pcm_hw_params,
+          .hw_free =     snd_mychip_pcm_hw_free,
+          .prepare =     snd_mychip_pcm_prepare,
+          .trigger =     snd_mychip_pcm_trigger,
+          .pointer =     snd_mychip_pcm_pointer,
+  };
+]]>
+          </programlisting>
+        </informalexample>
+
+        All the callbacks are described in the
+        <link linkend="pcm-interface-operators"><citetitle>
+        Operators</citetitle></link> subsection.
+      </para>
+
+      <para>
+        After setting the operators, you probably will want to
+        pre-allocate the buffer. For the pre-allocation, simply call
+        the following: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                        snd_dma_pci_data(chip->pci),
+                                        64*1024, 64*1024);
+]]>
+          </programlisting>
+        </informalexample>
+
+        It will allocate a buffer up to 64kB as default.
+      Buffer management details will be described in the later section <link
+      linkend="buffer-and-memory"><citetitle>Buffer and Memory
+      Management</citetitle></link>. 
+      </para>
+
+      <para>
+        Additionally, you can set some extra information for this pcm
+        in pcm-&gt;info_flags.
+        The available values are defined as
+        <constant>SNDRV_PCM_INFO_XXX</constant> in
+        <filename>&lt;sound/asound.h&gt;</filename>, which is used for
+        the hardware definition (described later). When your soundchip
+        supports only half-duplex, specify like this: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+    </section>
+
+    <section id="pcm-interface-destructor">
+      <title>... And the Destructor?</title>
+      <para>
+        The destructor for a pcm instance is not always
+      necessary. Since the pcm device will be released by the middle
+      layer code automatically, you don't have to call the destructor
+      explicitly.
+      </para>
+
+      <para>
+        The destructor would be necessary if you created
+        special records internally and needed to release them. In such a
+        case, set the destructor function to
+        pcm-&gt;private_free: 
+
+        <example>
+          <title>PCM Instance with a Destructor</title>
+          <programlisting>
+<![CDATA[
+  static void mychip_pcm_free(struct snd_pcm *pcm)
+  {
+          struct mychip *chip = snd_pcm_chip(pcm);
+          /* free your own data */
+          kfree(chip->my_private_pcm_data);
+          /* do what you like else */
+          ....
+  }
+
+  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
+  {
+          struct snd_pcm *pcm;
+          ....
+          /* allocate your own data */
+          chip->my_private_pcm_data = kmalloc(...);
+          /* set the destructor */
+          pcm->private_data = chip;
+          pcm->private_free = mychip_pcm_free;
+          ....
+  }
+]]>
+          </programlisting>
+        </example>
+      </para>
+    </section>
+
+    <section id="pcm-interface-runtime">
+      <title>Runtime Pointer - The Chest of PCM Information</title>
+	<para>
+	  When the PCM substream is opened, a PCM runtime instance is
+	allocated and assigned to the substream. This pointer is
+	accessible via <constant>substream-&gt;runtime</constant>.
+	This runtime pointer holds most information you need
+	to control the PCM: the copy of hw_params and sw_params configurations, the buffer
+	pointers, mmap records, spinlocks, etc.
+	</para>
+
+	<para>
+	The definition of runtime instance is found in
+	<filename>&lt;sound/pcm.h&gt;</filename>.  Here are
+       the contents of this file:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+struct _snd_pcm_runtime {
+	/* -- Status -- */
+	struct snd_pcm_substream *trigger_master;
+	snd_timestamp_t trigger_tstamp;	/* trigger timestamp */
+	int overrange;
+	snd_pcm_uframes_t avail_max;
+	snd_pcm_uframes_t hw_ptr_base;	/* Position at buffer restart */
+	snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
+
+	/* -- HW params -- */
+	snd_pcm_access_t access;	/* access mode */
+	snd_pcm_format_t format;	/* SNDRV_PCM_FORMAT_* */
+	snd_pcm_subformat_t subformat;	/* subformat */
+	unsigned int rate;		/* rate in Hz */
+	unsigned int channels;		/* channels */
+	snd_pcm_uframes_t period_size;	/* period size */
+	unsigned int periods;		/* periods */
+	snd_pcm_uframes_t buffer_size;	/* buffer size */
+	unsigned int tick_time;		/* tick time */
+	snd_pcm_uframes_t min_align;	/* Min alignment for the format */
+	size_t byte_align;
+	unsigned int frame_bits;
+	unsigned int sample_bits;
+	unsigned int info;
+	unsigned int rate_num;
+	unsigned int rate_den;
+
+	/* -- SW params -- */
+	struct timespec tstamp_mode;	/* mmap timestamp is updated */
+  	unsigned int period_step;
+	unsigned int sleep_min;		/* min ticks to sleep */
+	snd_pcm_uframes_t start_threshold;
+	snd_pcm_uframes_t stop_threshold;
+	snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
+						noise is nearest than this */
+	snd_pcm_uframes_t silence_size;	/* Silence filling size */
+	snd_pcm_uframes_t boundary;	/* pointers wrap point */
+
+	snd_pcm_uframes_t silenced_start;
+	snd_pcm_uframes_t silenced_size;
+
+	snd_pcm_sync_id_t sync;		/* hardware synchronization ID */
+
+	/* -- mmap -- */
+	volatile struct snd_pcm_mmap_status *status;
+	volatile struct snd_pcm_mmap_control *control;
+	atomic_t mmap_count;
+
+	/* -- locking / scheduling -- */
+	spinlock_t lock;
+	wait_queue_head_t sleep;
+	struct timer_list tick_timer;
+	struct fasync_struct *fasync;
+
+	/* -- private section -- */
+	void *private_data;
+	void (*private_free)(struct snd_pcm_runtime *runtime);
+
+	/* -- hardware description -- */
+	struct snd_pcm_hardware hw;
+	struct snd_pcm_hw_constraints hw_constraints;
+
+	/* -- interrupt callbacks -- */
+	void (*transfer_ack_begin)(struct snd_pcm_substream *substream);
+	void (*transfer_ack_end)(struct snd_pcm_substream *substream);
+
+	/* -- timer -- */
+	unsigned int timer_resolution;	/* timer resolution */
+
+	/* -- DMA -- */           
+	unsigned char *dma_area;	/* DMA area */
+	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
+	size_t dma_bytes;		/* size of DMA area */
+
+	struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
+
+#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
+	/* -- OSS things -- */
+	struct snd_pcm_oss_runtime oss;
+#endif
+};
+]]>
+            </programlisting>
+          </informalexample>
+	</para>
+
+	<para>
+	  For the operators (callbacks) of each sound driver, most of
+	these records are supposed to be read-only.  Only the PCM
+	middle-layer changes / updates them.  The exceptions are
+	the hardware description (hw), interrupt callbacks
+	(transfer_ack_xxx), DMA buffer information, and the private
+	data.  Besides, if you use the standard buffer allocation
+	method via <function>snd_pcm_lib_malloc_pages()</function>,
+	you don't need to set the DMA buffer information by yourself.
+	</para>
+
+	<para>
+	In the sections below, important records are explained.
+	</para>
+
+	<section id="pcm-interface-runtime-hw">
+	<title>Hardware Description</title>
+	<para>
+	  The hardware descriptor (struct <structname>snd_pcm_hardware</structname>)
+	contains the definitions of the fundamental hardware
+	configuration.  Above all, you'll need to define this in
+	<link linkend="pcm-interface-operators-open-callback"><citetitle>
+	the open callback</citetitle></link>.
+	Note that the runtime instance holds the copy of the
+	descriptor, not the pointer to the existing descriptor.  That
+	is, in the open callback, you can modify the copied descriptor
+	(<constant>runtime-&gt;hw</constant>) as you need.  For example, if the maximum
+	number of channels is 1 only on some chip models, you can
+	still use the same hardware descriptor and change the
+	channels_max later:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+          struct snd_pcm_runtime *runtime = substream->runtime;
+          ...
+          runtime->hw = snd_mychip_playback_hw; /* common definition */
+          if (chip->model == VERY_OLD_ONE)
+                  runtime->hw.channels_max = 1;
+]]>
+            </programlisting>
+          </informalexample>
+	</para>
+
+	<para>
+	  Typically, you'll have a hardware descriptor as below:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static struct snd_pcm_hardware snd_mychip_playback_hw = {
+          .info = (SNDRV_PCM_INFO_MMAP |
+                   SNDRV_PCM_INFO_INTERLEAVED |
+                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                   SNDRV_PCM_INFO_MMAP_VALID),
+          .formats =          SNDRV_PCM_FMTBIT_S16_LE,
+          .rates =            SNDRV_PCM_RATE_8000_48000,
+          .rate_min =         8000,
+          .rate_max =         48000,
+          .channels_min =     2,
+          .channels_max =     2,
+          .buffer_bytes_max = 32768,
+          .period_bytes_min = 4096,
+          .period_bytes_max = 32768,
+          .periods_min =      1,
+          .periods_max =      1024,
+  };
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+	<itemizedlist>
+	<listitem><para>
+          The <structfield>info</structfield> field contains the type and
+        capabilities of this pcm. The bit flags are defined in
+        <filename>&lt;sound/asound.h&gt;</filename> as
+        <constant>SNDRV_PCM_INFO_XXX</constant>. Here, at least, you
+        have to specify whether the mmap is supported and which
+        interleaved format is supported.
+        When the is supported, add the
+        <constant>SNDRV_PCM_INFO_MMAP</constant> flag here. When the
+        hardware supports the interleaved or the non-interleaved
+        formats, <constant>SNDRV_PCM_INFO_INTERLEAVED</constant> or
+        <constant>SNDRV_PCM_INFO_NONINTERLEAVED</constant> flag must
+        be set, respectively. If both are supported, you can set both,
+        too. 
+        </para>
+
+        <para>
+          In the above example, <constant>MMAP_VALID</constant> and
+        <constant>BLOCK_TRANSFER</constant> are specified for the OSS mmap
+        mode. Usually both are set. Of course,
+        <constant>MMAP_VALID</constant> is set only if the mmap is
+        really supported. 
+        </para>
+
+        <para>
+          The other possible flags are
+        <constant>SNDRV_PCM_INFO_PAUSE</constant> and
+        <constant>SNDRV_PCM_INFO_RESUME</constant>. The
+        <constant>PAUSE</constant> bit means that the pcm supports the
+        <quote>pause</quote> operation, while the
+        <constant>RESUME</constant> bit means that the pcm supports
+        the full <quote>suspend/resume</quote> operation.
+	If the <constant>PAUSE</constant> flag is set,
+	the <structfield>trigger</structfield> callback below
+        must handle the corresponding (pause push/release) commands.
+	The suspend/resume trigger commands can be defined even without
+	the <constant>RESUME</constant> flag.  See <link
+	linkend="power-management"><citetitle>
+	Power Management</citetitle></link> section for details.
+        </para>
+
+	<para>
+	  When the PCM substreams can be synchronized (typically,
+	synchronized start/stop of a playback and a capture streams),
+	you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
+	too.  In this case, you'll need to check the linked-list of
+	PCM substreams in the trigger callback.  This will be
+	described in the later section.
+	</para>
+	</listitem>
+
+	<listitem>
+        <para>
+          <structfield>formats</structfield> field contains the bit-flags
+        of supported formats (<constant>SNDRV_PCM_FMTBIT_XXX</constant>).
+        If the hardware supports more than one format, give all or'ed
+        bits.  In the example above, the signed 16bit little-endian
+        format is specified.
+        </para>
+	</listitem>
+
+	<listitem>
+        <para>
+        <structfield>rates</structfield> field contains the bit-flags of
+        supported rates (<constant>SNDRV_PCM_RATE_XXX</constant>).
+        When the chip supports continuous rates, pass
+        <constant>CONTINUOUS</constant> bit additionally.
+        The pre-defined rate bits are provided only for typical
+	rates. If your chip supports unconventional rates, you need to add
+        the <constant>KNOT</constant> bit and set up the hardware
+        constraint manually (explained later).
+        </para>
+	</listitem>
+
+	<listitem>
+	<para>
+	<structfield>rate_min</structfield> and
+	<structfield>rate_max</structfield> define the minimum and
+	maximum sample rate.  This should correspond somehow to
+	<structfield>rates</structfield> bits.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	<structfield>channel_min</structfield> and
+	<structfield>channel_max</structfield> 
+	define, as you might already expected, the minimum and maximum
+	number of channels.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	<structfield>buffer_bytes_max</structfield> defines the
+	maximum buffer size in bytes.  There is no
+	<structfield>buffer_bytes_min</structfield> field, since
+	it can be calculated from the minimum period size and the
+	minimum number of periods.
+	Meanwhile, <structfield>period_bytes_min</structfield> and
+	define the minimum and maximum size of the period in bytes.
+	<structfield>periods_max</structfield> and
+	<structfield>periods_min</structfield> define the maximum and
+	minimum number of periods in the buffer.
+        </para>
+
+	<para>
+	The <quote>period</quote> is a term that corresponds to
+	a fragment in the OSS world. The period defines the size at
+	which a PCM interrupt is generated. This size strongly
+	depends on the hardware. 
+	Generally, the smaller period size will give you more
+	interrupts, that is, more controls. 
+	In the case of capture, this size defines the input latency.
+	On the other hand, the whole buffer size defines the
+	output latency for the playback direction.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	There is also a field <structfield>fifo_size</structfield>.
+	This specifies the size of the hardware FIFO, but currently it
+	is neither used in the driver nor in the alsa-lib.  So, you
+	can ignore this field.
+	</para>
+	</listitem>
+	</itemizedlist>
+	</para>
+	</section>
+
+	<section id="pcm-interface-runtime-config">
+	<title>PCM Configurations</title>
+	<para>
+	Ok, let's go back again to the PCM runtime records.
+	The most frequently referred records in the runtime instance are
+	the PCM configurations.
+	The PCM configurations are stored in the runtime instance
+	after the application sends <type>hw_params</type> data via
+	alsa-lib.  There are many fields copied from hw_params and
+	sw_params structs.  For example,
+	<structfield>format</structfield> holds the format type
+	chosen by the application.  This field contains the enum value
+	<constant>SNDRV_PCM_FORMAT_XXX</constant>.
+	</para>
+
+	<para>
+	One thing to be noted is that the configured buffer and period
+	sizes are stored in <quote>frames</quote> in the runtime.
+        In the ALSA world, 1 frame = channels * samples-size.
+	For conversion between frames and bytes, you can use the
+	<function>frames_to_bytes()</function> and
+          <function>bytes_to_frames()</function> helper functions. 
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  period_bytes = frames_to_bytes(runtime, runtime->period_size);
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+	<para>
+	Also, many software parameters (sw_params) are
+	stored in frames, too.  Please check the type of the field.
+	<type>snd_pcm_uframes_t</type> is for the frames as unsigned
+	integer while <type>snd_pcm_sframes_t</type> is for the frames
+	as signed integer.
+	</para>
+	</section>
+
+	<section id="pcm-interface-runtime-dma">
+	<title>DMA Buffer Information</title>
+	<para>
+	The DMA buffer is defined by the following four fields,
+	<structfield>dma_area</structfield>,
+	<structfield>dma_addr</structfield>,
+	<structfield>dma_bytes</structfield> and
+	<structfield>dma_private</structfield>.
+	The <structfield>dma_area</structfield> holds the buffer
+	pointer (the logical address).  You can call
+	<function>memcpy</function> from/to 
+	this pointer.  Meanwhile, <structfield>dma_addr</structfield>
+	holds the physical address of the buffer.  This field is
+	specified only when the buffer is a linear buffer.
+	<structfield>dma_bytes</structfield> holds the size of buffer
+	in bytes.  <structfield>dma_private</structfield> is used for
+	the ALSA DMA allocator.
+	</para>
+
+	<para>
+	If you use a standard ALSA function,
+	<function>snd_pcm_lib_malloc_pages()</function>, for
+	allocating the buffer, these fields are set by the ALSA middle
+	layer, and you should <emphasis>not</emphasis> change them by
+	yourself.  You can read them but not write them.
+	On the other hand, if you want to allocate the buffer by
+	yourself, you'll need to manage it in hw_params callback.
+	At least, <structfield>dma_bytes</structfield> is mandatory.
+	<structfield>dma_area</structfield> is necessary when the
+	buffer is mmapped.  If your driver doesn't support mmap, this
+	field is not necessary.  <structfield>dma_addr</structfield>
+	is also optional.  You can use
+	<structfield>dma_private</structfield> as you like, too.
+	</para>
+	</section>
+
+	<section id="pcm-interface-runtime-status">
+	<title>Running Status</title>
+	<para>
+	The running status can be referred via <constant>runtime-&gt;status</constant>.
+	This is the pointer to the struct <structname>snd_pcm_mmap_status</structname>
+	record.  For example, you can get the current DMA hardware
+	pointer via <constant>runtime-&gt;status-&gt;hw_ptr</constant>.
+	</para>
+
+	<para>
+	The DMA application pointer can be referred via
+	<constant>runtime-&gt;control</constant>, which points to the
+	struct <structname>snd_pcm_mmap_control</structname> record.
+	However, accessing directly to this value is not recommended.
+	</para>
+	</section>
+
+	<section id="pcm-interface-runtime-private">
+	<title>Private Data</title> 
+	<para>
+	You can allocate a record for the substream and store it in
+	<constant>runtime-&gt;private_data</constant>.  Usually, this
+	is done in
+	<link linkend="pcm-interface-operators-open-callback"><citetitle>
+	the open callback</citetitle></link>.
+	Don't mix this with <constant>pcm-&gt;private_data</constant>.
+	The <constant>pcm-&gt;private_data</constant> usually points to the
+	chip instance assigned statically at the creation of PCM, while the 
+	<constant>runtime-&gt;private_data</constant> points to a dynamic
+	data structure created at the PCM open callback.
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_open(struct snd_pcm_substream *substream)
+  {
+          struct my_pcm_data *data;
+          ....
+          data = kmalloc(sizeof(*data), GFP_KERNEL);
+          substream->runtime->private_data = data;
+          ....
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          The allocated object must be released in
+	<link linkend="pcm-interface-operators-open-callback"><citetitle>
+	the close callback</citetitle></link>.
+        </para>
+	</section>
+
+	<section id="pcm-interface-runtime-intr">
+	<title>Interrupt Callbacks</title>
+	<para>
+	The field <structfield>transfer_ack_begin</structfield> and
+	<structfield>transfer_ack_end</structfield> are called at
+	the beginning and at the end of
+	<function>snd_pcm_period_elapsed()</function>, respectively. 
+	</para>
+	</section>
+
+    </section>
+
+    <section id="pcm-interface-operators">
+      <title>Operators</title>
+      <para>
+        OK, now let me give details about each pcm callback
+      (<parameter>ops</parameter>). In general, every callback must
+      return 0 if successful, or a negative error number
+      such as <constant>-EINVAL</constant>. To choose an appropriate
+      error number, it is advised to check what value other parts of
+      the kernel return when the same kind of request fails.
+      </para>
+
+      <para>
+        The callback function takes at least the argument with
+        <structname>snd_pcm_substream</structname> pointer. To retrieve
+        the chip record from the given substream instance, you can use the
+        following macro. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  int xxx() {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          ....
+  }
+]]>
+          </programlisting>
+        </informalexample>
+
+	The macro reads <constant>substream-&gt;private_data</constant>,
+	which is a copy of <constant>pcm-&gt;private_data</constant>.
+	You can override the former if you need to assign different data
+	records per PCM substream.  For example, the cmi8330 driver assigns
+	different private_data for playback and capture directions,
+	because it uses two different codecs (SB- and AD-compatible) for
+	different directions.
+      </para>
+
+      <section id="pcm-interface-operators-open-callback">
+        <title>open callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_open(struct snd_pcm_substream *substream);
+]]>
+            </programlisting>
+          </informalexample>
+
+          This is called when a pcm substream is opened.
+        </para>
+
+        <para>
+          At least, here you have to initialize the runtime-&gt;hw
+          record. Typically, this is done by like this: 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_open(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          struct snd_pcm_runtime *runtime = substream->runtime;
+
+          runtime->hw = snd_mychip_playback_hw;
+          return 0;
+  }
+]]>
+            </programlisting>
+          </informalexample>
+
+          where <parameter>snd_mychip_playback_hw</parameter> is the
+          pre-defined hardware description.
+	</para>
+
+	<para>
+	You can allocate a private data in this callback, as described
+	in <link linkend="pcm-interface-runtime-private"><citetitle>
+	Private Data</citetitle></link> section.
+	</para>
+
+	<para>
+	If the hardware configuration needs more constraints, set the
+	hardware constraints here, too.
+	See <link linkend="pcm-interface-constraints"><citetitle>
+	Constraints</citetitle></link> for more details.
+	</para>
+      </section>
+
+      <section id="pcm-interface-operators-close-callback">
+        <title>close callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_close(struct snd_pcm_substream *substream);
+]]>
+            </programlisting>
+          </informalexample>
+
+          Obviously, this is called when a pcm substream is closed.
+        </para>
+
+        <para>
+          Any private instance for a pcm substream allocated in the
+          open callback will be released here. 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_close(struct snd_pcm_substream *substream)
+  {
+          ....
+          kfree(substream->runtime->private_data);
+          ....
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-ioctl-callback">
+        <title>ioctl callback</title>
+        <para>
+          This is used for any special call to pcm ioctls. But
+        usually you can pass a generic ioctl callback, 
+        <function>snd_pcm_lib_ioctl</function>.
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-hw-params-callback">
+        <title>hw_params callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *hw_params);
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          This is called when the hardware parameter
+        (<structfield>hw_params</structfield>) is set
+        up by the application, 
+        that is, once when the buffer size, the period size, the
+        format, etc. are defined for the pcm substream. 
+        </para>
+
+        <para>
+          Many hardware setups should be done in this callback,
+        including the allocation of buffers. 
+        </para>
+
+        <para>
+          Parameters to be initialized are retrieved by
+          <function>params_xxx()</function> macros. To allocate
+          buffer, you can call a helper function, 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+]]>
+            </programlisting>
+          </informalexample>
+
+          <function>snd_pcm_lib_malloc_pages()</function> is available
+	  only when the DMA buffers have been pre-allocated.
+	  See the section <link
+	  linkend="buffer-and-memory-buffer-types"><citetitle>
+	  Buffer Types</citetitle></link> for more details.
+        </para>
+
+        <para>
+          Note that this and <structfield>prepare</structfield> callbacks
+        may be called multiple times per initialization.
+        For example, the OSS emulation may
+        call these callbacks at each change via its ioctl. 
+        </para>
+
+        <para>
+          Thus, you need to be careful not to allocate the same buffers
+        many times, which will lead to memory leaks!  Calling the
+        helper function above many times is OK. It will release the
+        previous buffer automatically when it was already allocated. 
+        </para>
+
+        <para>
+          Another note is that this callback is non-atomic
+        (schedulable). This is important, because the
+        <structfield>trigger</structfield> callback 
+        is atomic (non-schedulable). That is, mutexes or any
+        schedule-related functions are not available in
+        <structfield>trigger</structfield> callback.
+	Please see the subsection
+	<link linkend="pcm-interface-atomicity"><citetitle>
+	Atomicity</citetitle></link> for details.
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-hw-free-callback">
+        <title>hw_free callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          This is called to release the resources allocated via
+          <structfield>hw_params</structfield>. For example, releasing the
+          buffer via 
+          <function>snd_pcm_lib_malloc_pages()</function> is done by
+          calling the following: 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  snd_pcm_lib_free_pages(substream);
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          This function is always called before the close callback is called.
+          Also, the callback may be called multiple times, too.
+          Keep track whether the resource was already released. 
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-prepare-callback">
+       <title>prepare callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_prepare(struct snd_pcm_substream *substream);
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          This callback is called when the pcm is
+        <quote>prepared</quote>. You can set the format type, sample
+        rate, etc. here. The difference from
+        <structfield>hw_params</structfield> is that the 
+        <structfield>prepare</structfield> callback will be called each
+        time 
+        <function>snd_pcm_prepare()</function> is called, i.e. when
+        recovering after underruns, etc. 
+        </para>
+
+        <para>
+	Note that this callback is now non-atomic.
+	You can use schedule-related functions safely in this callback.
+        </para>
+
+        <para>
+          In this and the following callbacks, you can refer to the
+        values via the runtime record,
+        substream-&gt;runtime.
+        For example, to get the current
+        rate, format or channels, access to
+        runtime-&gt;rate,
+        runtime-&gt;format or
+        runtime-&gt;channels, respectively. 
+        The physical address of the allocated buffer is set to
+	runtime-&gt;dma_area.  The buffer and period sizes are
+	in runtime-&gt;buffer_size and runtime-&gt;period_size,
+	respectively.
+        </para>
+
+        <para>
+          Be careful that this callback will be called many times at
+        each setup, too. 
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-trigger-callback">
+        <title>trigger callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);
+]]>
+            </programlisting>
+          </informalexample>
+
+          This is called when the pcm is started, stopped or paused.
+        </para>
+
+        <para>
+          Which action is specified in the second argument,
+          <constant>SNDRV_PCM_TRIGGER_XXX</constant> in
+          <filename>&lt;sound/pcm.h&gt;</filename>. At least,
+          the <constant>START</constant> and <constant>STOP</constant>
+          commands must be defined in this callback. 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  switch (cmd) {
+  case SNDRV_PCM_TRIGGER_START:
+          /* do something to start the PCM engine */
+          break;
+  case SNDRV_PCM_TRIGGER_STOP:
+          /* do something to stop the PCM engine */
+          break;
+  default:
+          return -EINVAL;
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+          When the pcm supports the pause operation (given in the info
+        field of the hardware table), the <constant>PAUSE_PUSE</constant>
+        and <constant>PAUSE_RELEASE</constant> commands must be
+        handled here, too. The former is the command to pause the pcm,
+        and the latter to restart the pcm again. 
+        </para>
+
+        <para>
+          When the pcm supports the suspend/resume operation,
+	regardless of full or partial suspend/resume support,
+        the <constant>SUSPEND</constant> and <constant>RESUME</constant>
+        commands must be handled, too.
+        These commands are issued when the power-management status is
+        changed.  Obviously, the <constant>SUSPEND</constant> and
+        <constant>RESUME</constant> commands
+        suspend and resume the pcm substream, and usually, they
+        are identical to the <constant>STOP</constant> and
+        <constant>START</constant> commands, respectively.
+	  See the <link linkend="power-management"><citetitle>
+	Power Management</citetitle></link> section for details.
+        </para>
+
+        <para>
+          As mentioned, this callback is atomic.  You cannot call
+	  functions which may sleep.
+	  The trigger callback should be as minimal as possible,
+	  just really triggering the DMA.  The other stuff should be
+	  initialized hw_params and prepare callbacks properly
+	  beforehand.
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-pointer-callback">
+        <title>pointer callback</title>
+        <para>
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)
+]]>
+            </programlisting>
+          </informalexample>
+
+          This callback is called when the PCM middle layer inquires
+        the current hardware position on the buffer. The position must
+        be returned in frames,
+        ranging from 0 to buffer_size - 1.
+        </para>
+
+        <para>
+          This is called usually from the buffer-update routine in the
+        pcm middle layer, which is invoked when
+        <function>snd_pcm_period_elapsed()</function> is called in the
+        interrupt routine. Then the pcm middle layer updates the
+        position and calculates the available space, and wakes up the
+        sleeping poll threads, etc. 
+        </para>
+
+        <para>
+          This callback is also atomic.
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-copy-silence">
+        <title>copy and silence callbacks</title>
+        <para>
+          These callbacks are not mandatory, and can be omitted in
+        most cases. These callbacks are used when the hardware buffer
+        cannot be in the normal memory space. Some chips have their
+        own buffer on the hardware which is not mappable. In such a
+        case, you have to transfer the data manually from the memory
+        buffer to the hardware buffer. Or, if the buffer is
+        non-contiguous on both physical and virtual memory spaces,
+        these callbacks must be defined, too. 
+        </para>
+
+        <para>
+          If these two callbacks are defined, copy and set-silence
+        operations are done by them. The detailed will be described in
+        the later section <link
+        linkend="buffer-and-memory"><citetitle>Buffer and Memory
+        Management</citetitle></link>. 
+        </para>
+      </section>
+
+      <section id="pcm-interface-operators-ack">
+        <title>ack callback</title>
+        <para>
+          This callback is also not mandatory. This callback is called
+        when the appl_ptr is updated in read or write operations.
+        Some drivers like emu10k1-fx and cs46xx need to track the
+	current appl_ptr for the internal buffer, and this callback
+	is useful only for such a purpose.
+	</para>
+	<para>
+	  This callback is atomic.
+	</para>
+      </section>
+
+      <section id="pcm-interface-operators-page-callback">
+        <title>page callback</title>
+
+        <para>
+          This callback is optional too. This callback is used
+        mainly for non-contiguous buffers. The mmap calls this
+        callback to get the page address. Some examples will be
+        explained in the later section <link
+        linkend="buffer-and-memory"><citetitle>Buffer and Memory
+        Management</citetitle></link>, too. 
+        </para>
+      </section>
+    </section>
+
+    <section id="pcm-interface-interrupt-handler">
+      <title>Interrupt Handler</title>
+      <para>
+        The rest of pcm stuff is the PCM interrupt handler. The
+      role of PCM interrupt handler in the sound driver is to update
+      the buffer position and to tell the PCM middle layer when the
+      buffer position goes across the prescribed period size. To
+      inform this, call the <function>snd_pcm_period_elapsed()</function>
+      function. 
+      </para>
+
+      <para>
+        There are several types of sound chips to generate the interrupts.
+      </para>
+
+      <section id="pcm-interface-interrupt-handler-boundary">
+        <title>Interrupts at the period (fragment) boundary</title>
+        <para>
+          This is the most frequently found type:  the hardware
+        generates an interrupt at each period boundary.
+	In this case, you can call
+        <function>snd_pcm_period_elapsed()</function> at each 
+        interrupt. 
+        </para>
+
+        <para>
+          <function>snd_pcm_period_elapsed()</function> takes the
+        substream pointer as its argument. Thus, you need to keep the
+        substream pointer accessible from the chip instance. For
+        example, define substream field in the chip record to hold the
+        current running substream pointer, and set the pointer value
+        at open callback (and reset at close callback). 
+        </para>
+
+        <para>
+          If you acquire a spinlock in the interrupt handler, and the
+        lock is used in other pcm callbacks, too, then you have to
+        release the lock before calling
+        <function>snd_pcm_period_elapsed()</function>, because
+        <function>snd_pcm_period_elapsed()</function> calls other pcm
+        callbacks inside. 
+        </para>
+
+        <para>
+          Typical code would be like:
+
+          <example>
+	    <title>Interrupt Handler Case #1</title>
+            <programlisting>
+<![CDATA[
+  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+  {
+          struct mychip *chip = dev_id;
+          spin_lock(&chip->lock);
+          ....
+          if (pcm_irq_invoked(chip)) {
+                  /* call updater, unlock before it */
+                  spin_unlock(&chip->lock);
+                  snd_pcm_period_elapsed(chip->substream);
+                  spin_lock(&chip->lock);
+                  /* acknowledge the interrupt if necessary */
+          }
+          ....
+          spin_unlock(&chip->lock);
+          return IRQ_HANDLED;
+  }
+]]>
+            </programlisting>
+          </example>
+        </para>
+      </section>
+
+      <section id="pcm-interface-interrupt-handler-timer">
+        <title>High frequency timer interrupts</title>
+        <para>
+	This happense when the hardware doesn't generate interrupts
+        at the period boundary but issues timer interrupts at a fixed
+        timer rate (e.g. es1968 or ymfpci drivers). 
+        In this case, you need to check the current hardware
+        position and accumulate the processed sample length at each
+        interrupt.  When the accumulated size exceeds the period
+        size, call 
+        <function>snd_pcm_period_elapsed()</function> and reset the
+        accumulator. 
+        </para>
+
+        <para>
+          Typical code would be like the following.
+
+          <example>
+	    <title>Interrupt Handler Case #2</title>
+            <programlisting>
+<![CDATA[
+  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+  {
+          struct mychip *chip = dev_id;
+          spin_lock(&chip->lock);
+          ....
+          if (pcm_irq_invoked(chip)) {
+                  unsigned int last_ptr, size;
+                  /* get the current hardware pointer (in frames) */
+                  last_ptr = get_hw_ptr(chip);
+                  /* calculate the processed frames since the
+                   * last update
+                   */
+                  if (last_ptr < chip->last_ptr)
+                          size = runtime->buffer_size + last_ptr 
+                                   - chip->last_ptr; 
+                  else
+                          size = last_ptr - chip->last_ptr;
+                  /* remember the last updated point */
+                  chip->last_ptr = last_ptr;
+                  /* accumulate the size */
+                  chip->size += size;
+                  /* over the period boundary? */
+                  if (chip->size >= runtime->period_size) {
+                          /* reset the accumulator */
+                          chip->size %= runtime->period_size;
+                          /* call updater */
+                          spin_unlock(&chip->lock);
+                          snd_pcm_period_elapsed(substream);
+                          spin_lock(&chip->lock);
+                  }
+                  /* acknowledge the interrupt if necessary */
+          }
+          ....
+          spin_unlock(&chip->lock);
+          return IRQ_HANDLED;
+  }
+]]>
+            </programlisting>
+          </example>
+        </para>
+      </section>
+
+      <section id="pcm-interface-interrupt-handler-both">
+        <title>On calling <function>snd_pcm_period_elapsed()</function></title>
+        <para>
+          In both cases, even if more than one period are elapsed, you
+        don't have to call
+        <function>snd_pcm_period_elapsed()</function> many times. Call
+        only once. And the pcm layer will check the current hardware
+        pointer and update to the latest status. 
+        </para>
+      </section>
+    </section>
+
+    <section id="pcm-interface-atomicity">
+      <title>Atomicity</title>
+      <para>
+      One of the most important (and thus difficult to debug) problems
+      in kernel programming are race conditions.
+      In the Linux kernel, they are usually avoided via spin-locks, mutexes
+      or semaphores.  In general, if a race condition can happen
+      in an interrupt handler, it has to be managed atomically, and you
+      have to use a spinlock to protect the critical session. If the
+      critical section is not in interrupt handler code and
+      if taking a relatively long time to execute is acceptable, you
+      should use mutexes or semaphores instead.
+      </para>
+
+      <para>
+      As already seen, some pcm callbacks are atomic and some are
+      not.  For example, the <parameter>hw_params</parameter> callback is
+      non-atomic, while <parameter>trigger</parameter> callback is
+      atomic.  This means, the latter is called already in a spinlock
+      held by the PCM middle layer. Please take this atomicity into
+      account when you choose a locking scheme in the callbacks.
+      </para>
+
+      <para>
+      In the atomic callbacks, you cannot use functions which may call
+      <function>schedule</function> or go to
+      <function>sleep</function>.  Semaphores and mutexes can sleep,
+      and hence they cannot be used inside the atomic callbacks
+      (e.g. <parameter>trigger</parameter> callback).
+      To implement some delay in such a callback, please use
+      <function>udelay()</function> or <function>mdelay()</function>.
+      </para>
+
+      <para>
+      All three atomic callbacks (trigger, pointer, and ack) are
+      called with local interrupts disabled.
+      </para>
+
+    </section>
+    <section id="pcm-interface-constraints">
+      <title>Constraints</title>
+      <para>
+        If your chip supports unconventional sample rates, or only the
+      limited samples, you need to set a constraint for the
+      condition. 
+      </para>
+
+      <para>
+        For example, in order to restrict the sample rates in the some
+        supported values, use
+	<function>snd_pcm_hw_constraint_list()</function>.
+	You need to call this function in the open callback.
+
+        <example>
+	  <title>Example of Hardware Constraints</title>
+          <programlisting>
+<![CDATA[
+  static unsigned int rates[] =
+          {4000, 10000, 22050, 44100};
+  static struct snd_pcm_hw_constraint_list constraints_rates = {
+          .count = ARRAY_SIZE(rates),
+          .list = rates,
+          .mask = 0,
+  };
+
+  static int snd_mychip_pcm_open(struct snd_pcm_substream *substream)
+  {
+          int err;
+          ....
+          err = snd_pcm_hw_constraint_list(substream->runtime, 0,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           &constraints_rates);
+          if (err < 0)
+                  return err;
+          ....
+  }
+]]>
+          </programlisting>
+        </example>
+      </para>
+
+      <para>
+        There are many different constraints.
+        Look at <filename>sound/pcm.h</filename> for a complete list.
+        You can even define your own constraint rules.
+        For example, let's suppose my_chip can manage a substream of 1 channel
+        if and only if the format is S16_LE, otherwise it supports any format
+        specified in the <structname>snd_pcm_hardware</structname> structure (or in any
+        other constraint_list). You can build a rule like this:
+
+        <example>
+	  <title>Example of Hardware Constraints for Channels</title>
+	  <programlisting>
+<![CDATA[
+  static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params,
+                                        struct snd_pcm_hw_rule *rule)
+  {
+          struct snd_interval *c = hw_param_interval(params,
+                SNDRV_PCM_HW_PARAM_CHANNELS);
+          struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+          struct snd_mask fmt;
+
+          snd_mask_any(&fmt);    /* Init the struct */
+          if (c->min < 2) {
+                  fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_LE;
+                  return snd_mask_refine(f, &fmt);
+          }
+          return 0;
+  }
+]]>
+          </programlisting>
+        </example>
+      </para>
+ 
+      <para>
+        Then you need to call this function to add your rule:
+
+       <informalexample>
+	 <programlisting>
+<![CDATA[
+  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                      hw_rule_channels_by_format, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+                      -1);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The rule function is called when an application sets the number of
+        channels. But an application can set the format before the number of
+        channels. Thus you also need to define the inverse rule:
+
+       <example>
+	 <title>Example of Hardware Constraints for Channels</title>
+	 <programlisting>
+<![CDATA[
+  static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params,
+                                        struct snd_pcm_hw_rule *rule)
+  {
+          struct snd_interval *c = hw_param_interval(params,
+                        SNDRV_PCM_HW_PARAM_CHANNELS);
+          struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+          struct snd_interval ch;
+
+          snd_interval_any(&ch);
+          if (f->bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
+                  ch.min = ch.max = 1;
+                  ch.integer = 1;
+                  return snd_interval_refine(c, &ch);
+          }
+          return 0;
+  }
+]]>
+          </programlisting>
+        </example>
+      </para>
+
+      <para>
+      ...and in the open callback:
+       <informalexample>
+	 <programlisting>
+<![CDATA[
+  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+                      hw_rule_format_by_channels, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                      -1);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        I won't give more details here, rather I
+        would like to say, <quote>Luke, use the source.</quote>
+      </para>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Control Interface  -->
+<!-- ****************************************************** -->
+  <chapter id="control-interface">
+    <title>Control Interface</title>
+
+    <section id="control-interface-general">
+      <title>General</title>
+      <para>
+        The control interface is used widely for many switches,
+      sliders, etc. which are accessed from user-space. Its most
+      important use is the mixer interface. In other words, since ALSA
+      0.9.x, all the mixer stuff is implemented on the control kernel API.
+      </para>
+
+      <para>
+        ALSA has a well-defined AC97 control module. If your chip
+      supports only the AC97 and nothing else, you can skip this
+      section. 
+      </para>
+
+      <para>
+        The control API is defined in
+      <filename>&lt;sound/control.h&gt;</filename>.
+      Include this file if you want to add your own controls.
+      </para>
+    </section>
+
+    <section id="control-interface-definition">
+      <title>Definition of Controls</title>
+      <para>
+        To create a new control, you need to define the
+	following three
+      callbacks: <structfield>info</structfield>,
+      <structfield>get</structfield> and
+      <structfield>put</structfield>. Then, define a
+      struct <structname>snd_kcontrol_new</structname> record, such as: 
+
+        <example>
+	  <title>Definition of a Control</title>
+          <programlisting>
+<![CDATA[
+  static struct snd_kcontrol_new my_control __devinitdata = {
+          .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+          .name = "PCM Playback Switch",
+          .index = 0,
+          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+          .private_value = 0xffff,
+          .info = my_control_info,
+          .get = my_control_get,
+          .put = my_control_put
+  };
+]]>
+          </programlisting>
+        </example>
+      </para>
+
+      <para>
+        Most likely the control is created via
+      <function>snd_ctl_new1()</function>, and in such a case, you can
+      add the <parameter>__devinitdata</parameter> prefix to the
+      definition as above. 
+      </para>
+
+      <para>
+        The <structfield>iface</structfield> field specifies the control
+      type, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
+      is usually <constant>MIXER</constant>.
+      Use <constant>CARD</constant> for global controls that are not
+      logically part of the mixer.
+      If the control is closely associated with some specific device on
+      the sound card, use <constant>HWDEP</constant>,
+      <constant>PCM</constant>, <constant>RAWMIDI</constant>,
+      <constant>TIMER</constant>, or <constant>SEQUENCER</constant>, and
+      specify the device number with the
+      <structfield>device</structfield> and
+      <structfield>subdevice</structfield> fields.
+      </para>
+
+      <para>
+        The <structfield>name</structfield> is the name identifier
+      string. Since ALSA 0.9.x, the control name is very important,
+      because its role is classified from its name. There are
+      pre-defined standard control names. The details are described in
+      the <link linkend="control-interface-control-names"><citetitle>
+      Control Names</citetitle></link> subsection.
+      </para>
+
+      <para>
+        The <structfield>index</structfield> field holds the index number
+      of this control. If there are several different controls with
+      the same name, they can be distinguished by the index
+      number. This is the case when 
+      several codecs exist on the card. If the index is zero, you can
+      omit the definition above. 
+      </para>
+
+      <para>
+        The <structfield>access</structfield> field contains the access
+      type of this control. Give the combination of bit masks,
+      <constant>SNDRV_CTL_ELEM_ACCESS_XXX</constant>, there.
+      The details will be explained in
+      the <link linkend="control-interface-access-flags"><citetitle>
+      Access Flags</citetitle></link> subsection.
+      </para>
+
+      <para>
+        The <structfield>private_value</structfield> field contains
+      an arbitrary long integer value for this record. When using
+      the generic <structfield>info</structfield>,
+      <structfield>get</structfield> and
+      <structfield>put</structfield> callbacks, you can pass a value 
+      through this field. If several small numbers are necessary, you can
+      combine them in bitwise. Or, it's possible to give a pointer
+      (casted to unsigned long) of some record to this field, too. 
+      </para>
+
+      <para>
+      The <structfield>tlv</structfield> field can be used to provide
+      metadata about the control; see the
+      <link linkend="control-interface-tlv">
+      <citetitle>Metadata</citetitle></link> subsection.
+      </para>
+
+      <para>
+        The other three are
+	<link linkend="control-interface-callbacks"><citetitle>
+	callback functions</citetitle></link>.
+      </para>
+    </section>
+
+    <section id="control-interface-control-names">
+      <title>Control Names</title>
+      <para>
+        There are some standards to define the control names. A
+      control is usually defined from the three parts as
+      <quote>SOURCE DIRECTION FUNCTION</quote>. 
+      </para>
+
+      <para>
+        The first, <constant>SOURCE</constant>, specifies the source
+      of the control, and is a string such as <quote>Master</quote>,
+      <quote>PCM</quote>, <quote>CD</quote> and
+      <quote>Line</quote>. There are many pre-defined sources. 
+      </para>
+
+      <para>
+        The second, <constant>DIRECTION</constant>, is one of the
+      following strings according to the direction of the control:
+      <quote>Playback</quote>, <quote>Capture</quote>, <quote>Bypass
+      Playback</quote> and <quote>Bypass Capture</quote>. Or, it can
+      be omitted, meaning both playback and capture directions. 
+      </para>
+
+      <para>
+        The third, <constant>FUNCTION</constant>, is one of the
+      following strings according to the function of the control:
+      <quote>Switch</quote>, <quote>Volume</quote> and
+      <quote>Route</quote>. 
+      </para>
+
+      <para>
+        The example of control names are, thus, <quote>Master Capture
+      Switch</quote> or <quote>PCM Playback Volume</quote>. 
+      </para>
+
+      <para>
+        There are some exceptions:
+      </para>
+
+      <section id="control-interface-control-names-global">
+        <title>Global capture and playback</title>
+        <para>
+          <quote>Capture Source</quote>, <quote>Capture Switch</quote>
+        and <quote>Capture Volume</quote> are used for the global
+        capture (input) source, switch and volume. Similarly,
+        <quote>Playback Switch</quote> and <quote>Playback
+        Volume</quote> are used for the global output gain switch and
+        volume. 
+        </para>
+      </section>
+
+      <section id="control-interface-control-names-tone">
+        <title>Tone-controls</title>
+        <para>
+          tone-control switch and volumes are specified like
+        <quote>Tone Control - XXX</quote>, e.g. <quote>Tone Control -
+        Switch</quote>, <quote>Tone Control - Bass</quote>,
+        <quote>Tone Control - Center</quote>.  
+        </para>
+      </section>
+
+      <section id="control-interface-control-names-3d">
+        <title>3D controls</title>
+        <para>
+          3D-control switches and volumes are specified like <quote>3D
+        Control - XXX</quote>, e.g. <quote>3D Control -
+        Switch</quote>, <quote>3D Control - Center</quote>, <quote>3D
+        Control - Space</quote>. 
+        </para>
+      </section>
+
+      <section id="control-interface-control-names-mic">
+        <title>Mic boost</title>
+        <para>
+          Mic-boost switch is set as <quote>Mic Boost</quote> or
+        <quote>Mic Boost (6dB)</quote>. 
+        </para>
+
+        <para>
+          More precise information can be found in
+        <filename>Documentation/sound/alsa/ControlNames.txt</filename>.
+        </para>
+      </section>
+    </section>
+
+    <section id="control-interface-access-flags">
+      <title>Access Flags</title>
+
+      <para>
+      The access flag is the bitmask which specifies the access type
+      of the given control.  The default access type is
+      <constant>SNDRV_CTL_ELEM_ACCESS_READWRITE</constant>, 
+      which means both read and write are allowed to this control.
+      When the access flag is omitted (i.e. = 0), it is
+      considered as <constant>READWRITE</constant> access as default. 
+      </para>
+
+      <para>
+      When the control is read-only, pass
+      <constant>SNDRV_CTL_ELEM_ACCESS_READ</constant> instead.
+      In this case, you don't have to define
+      the <structfield>put</structfield> callback.
+      Similarly, when the control is write-only (although it's a rare
+      case), you can use the <constant>WRITE</constant> flag instead, and
+      you don't need the <structfield>get</structfield> callback.
+      </para>
+
+      <para>
+      If the control value changes frequently (e.g. the VU meter),
+      <constant>VOLATILE</constant> flag should be given.  This means
+      that the control may be changed without
+      <link linkend="control-interface-change-notification"><citetitle>
+      notification</citetitle></link>. Applications should poll such
+      a control constantly.
+      </para>
+
+      <para>
+      When the control is inactive, set
+      the <constant>INACTIVE</constant> flag, too.
+      There are <constant>LOCK</constant> and
+      <constant>OWNER</constant> flags to change the write
+      permissions.
+      </para>
+
+    </section>
+
+    <section id="control-interface-callbacks">
+      <title>Callbacks</title>
+
+      <section id="control-interface-callbacks-info">
+        <title>info callback</title>
+        <para>
+          The <structfield>info</structfield> callback is used to get
+        detailed information on this control. This must store the
+        values of the given struct <structname>snd_ctl_elem_info</structname>
+        object. For example, for a boolean control with a single
+        element: 
+
+          <example>
+	    <title>Example of info callback</title>
+            <programlisting>
+<![CDATA[
+  static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_info *uinfo)
+  {
+          uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+          uinfo->count = 1;
+          uinfo->value.integer.min = 0;
+          uinfo->value.integer.max = 1;
+          return 0;
+  }
+]]>
+            </programlisting>
+          </example>
+        </para>
+
+        <para>
+          The <structfield>type</structfield> field specifies the type
+        of the control. There are <constant>BOOLEAN</constant>,
+        <constant>INTEGER</constant>, <constant>ENUMERATED</constant>,
+        <constant>BYTES</constant>, <constant>IEC958</constant> and
+        <constant>INTEGER64</constant>. The
+        <structfield>count</structfield> field specifies the 
+        number of elements in this control. For example, a stereo
+        volume would have count = 2. The
+        <structfield>value</structfield> field is a union, and 
+        the values stored are depending on the type. The boolean and
+        integer types are identical. 
+        </para>
+
+        <para>
+          The enumerated type is a bit different from others.  You'll
+          need to set the string for the currently given item index. 
+
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_info *uinfo)
+  {
+          static char *texts[4] = {
+                  "First", "Second", "Third", "Fourth"
+          };
+          uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+          uinfo->count = 1;
+          uinfo->value.enumerated.items = 4;
+          if (uinfo->value.enumerated.item > 3)
+                  uinfo->value.enumerated.item = 3;
+          strcpy(uinfo->value.enumerated.name,
+                 texts[uinfo->value.enumerated.item]);
+          return 0;
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+	  Some common info callbacks are available for your convenience:
+	<function>snd_ctl_boolean_mono_info()</function> and
+	<function>snd_ctl_boolean_stereo_info()</function>.
+	Obviously, the former is an info callback for a mono channel
+	boolean item, just like <function>snd_myctl_mono_info</function>
+	above, and the latter is for a stereo channel boolean item.
+	</para>
+
+      </section>
+
+      <section id="control-interface-callbacks-get">
+        <title>get callback</title>
+
+        <para>
+          This callback is used to read the current value of the
+        control and to return to user-space. 
+        </para>
+
+        <para>
+          For example,
+
+          <example>
+	    <title>Example of get callback</title>
+            <programlisting>
+<![CDATA[
+  static int snd_myctl_get(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+  {
+          struct mychip *chip = snd_kcontrol_chip(kcontrol);
+          ucontrol->value.integer.value[0] = get_some_value(chip);
+          return 0;
+  }
+]]>
+            </programlisting>
+          </example>
+        </para>
+
+        <para>
+	The <structfield>value</structfield> field depends on 
+        the type of control as well as on the info callback.  For example,
+	the sb driver uses this field to store the register offset,
+        the bit-shift and the bit-mask.  The
+        <structfield>private_value</structfield> field is set as follows:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  .private_value = reg | (shift << 16) | (mask << 24)
+]]>
+            </programlisting>
+          </informalexample>
+	and is retrieved in callbacks like
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+  {
+          int reg = kcontrol->private_value & 0xff;
+          int shift = (kcontrol->private_value >> 16) & 0xff;
+          int mask = (kcontrol->private_value >> 24) & 0xff;
+          ....
+  }
+]]>
+            </programlisting>
+          </informalexample>
+	</para>
+
+	<para>
+	In the <structfield>get</structfield> callback,
+	you have to fill all the elements if the
+        control has more than one elements,
+        i.e. <structfield>count</structfield> &gt; 1.
+	In the example above, we filled only one element
+        (<structfield>value.integer.value[0]</structfield>) since it's
+        assumed as <structfield>count</structfield> = 1.
+        </para>
+      </section>
+
+      <section id="control-interface-callbacks-put">
+        <title>put callback</title>
+
+        <para>
+          This callback is used to write a value from user-space.
+        </para>
+
+        <para>
+          For example,
+
+          <example>
+	    <title>Example of put callback</title>
+            <programlisting>
+<![CDATA[
+  static int snd_myctl_put(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+  {
+          struct mychip *chip = snd_kcontrol_chip(kcontrol);
+          int changed = 0;
+          if (chip->current_value !=
+               ucontrol->value.integer.value[0]) {
+                  change_current_value(chip,
+                              ucontrol->value.integer.value[0]);
+                  changed = 1;
+          }
+          return changed;
+  }
+]]>
+            </programlisting>
+          </example>
+
+          As seen above, you have to return 1 if the value is
+        changed. If the value is not changed, return 0 instead. 
+	If any fatal error happens, return a negative error code as
+        usual.
+        </para>
+
+        <para>
+	As in the <structfield>get</structfield> callback,
+	when the control has more than one elements,
+	all elements must be evaluated in this callback, too.
+        </para>
+      </section>
+
+      <section id="control-interface-callbacks-all">
+        <title>Callbacks are not atomic</title>
+        <para>
+          All these three callbacks are basically not atomic.
+        </para>
+      </section>
+    </section>
+
+    <section id="control-interface-constructor">
+      <title>Constructor</title>
+      <para>
+        When everything is ready, finally we can create a new
+      control. To create a control, there are two functions to be
+      called, <function>snd_ctl_new1()</function> and
+      <function>snd_ctl_add()</function>. 
+      </para>
+
+      <para>
+        In the simplest way, you can do like this:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip));
+  if (err < 0)
+          return err;
+]]>
+          </programlisting>
+        </informalexample>
+
+        where <parameter>my_control</parameter> is the
+      struct <structname>snd_kcontrol_new</structname> object defined above, and chip
+      is the object pointer to be passed to
+      kcontrol-&gt;private_data 
+      which can be referred to in callbacks. 
+      </para>
+
+      <para>
+        <function>snd_ctl_new1()</function> allocates a new
+      <structname>snd_kcontrol</structname> instance (that's why the definition
+      of <parameter>my_control</parameter> can be with
+      the <parameter>__devinitdata</parameter> 
+      prefix), and <function>snd_ctl_add</function> assigns the given
+      control component to the card. 
+      </para>
+    </section>
+
+    <section id="control-interface-change-notification">
+      <title>Change Notification</title>
+      <para>
+        If you need to change and update a control in the interrupt
+      routine, you can call <function>snd_ctl_notify()</function>. For
+      example, 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer);
+]]>
+          </programlisting>
+        </informalexample>
+
+        This function takes the card pointer, the event-mask, and the
+      control id pointer for the notification. The event-mask
+      specifies the types of notification, for example, in the above
+      example, the change of control values is notified.
+      The id pointer is the pointer of struct <structname>snd_ctl_elem_id</structname>
+      to be notified.
+      You can find some examples in <filename>es1938.c</filename> or
+      <filename>es1968.c</filename> for hardware volume interrupts. 
+      </para>
+    </section>
+
+    <section id="control-interface-tlv">
+      <title>Metadata</title>
+      <para>
+      To provide information about the dB values of a mixer control, use
+      on of the <constant>DECLARE_TLV_xxx</constant> macros from
+      <filename>&lt;sound/tlv.h&gt;</filename> to define a variable
+      containing this information, set the<structfield>tlv.p
+      </structfield> field to point to this variable, and include the
+      <constant>SNDRV_CTL_ELEM_ACCESS_TLV_READ</constant> flag in the
+      <structfield>access</structfield> field; like this:
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
+
+  static struct snd_kcontrol_new my_control __devinitdata = {
+          ...
+          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                    SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+          ...
+          .tlv.p = db_scale_my_control,
+  };
+]]>
+        </programlisting>
+      </informalexample>
+      </para>
+
+      <para>
+      The <function>DECLARE_TLV_DB_SCALE</function> macro defines
+      information about a mixer control where each step in the control's
+      value changes the dB value by a constant dB amount.
+      The first parameter is the name of the variable to be defined.
+      The second parameter is the minimum value, in units of 0.01 dB.
+      The third parameter is the step size, in units of 0.01 dB.
+      Set the fourth parameter to 1 if the minimum value actually mutes
+      the control.
+      </para>
+
+      <para>
+      The <function>DECLARE_TLV_DB_LINEAR</function> macro defines
+      information about a mixer control where the control's value affects
+      the output linearly.
+      The first parameter is the name of the variable to be defined.
+      The second parameter is the minimum value, in units of 0.01 dB.
+      The third parameter is the maximum value, in units of 0.01 dB.
+      If the minimum value mutes the control, set the second parameter to
+      <constant>TLV_DB_GAIN_MUTE</constant>.
+      </para>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- API for AC97 Codec  -->
+<!-- ****************************************************** -->
+  <chapter id="api-ac97">
+    <title>API for AC97 Codec</title>
+
+    <section>
+      <title>General</title>
+      <para>
+        The ALSA AC97 codec layer is a well-defined one, and you don't
+      have to write much code to control it. Only low-level control
+      routines are necessary. The AC97 codec API is defined in
+      <filename>&lt;sound/ac97_codec.h&gt;</filename>. 
+      </para>
+    </section>
+
+    <section id="api-ac97-example">
+      <title>Full Code Example</title>
+      <para>
+          <example>
+	    <title>Example of AC97 Interface</title>
+            <programlisting>
+<![CDATA[
+  struct mychip {
+          ....
+          struct snd_ac97 *ac97;
+          ....
+  };
+
+  static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
+                                             unsigned short reg)
+  {
+          struct mychip *chip = ac97->private_data;
+          ....
+          /* read a register value here from the codec */
+          return the_register_value;
+  }
+
+  static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
+                                   unsigned short reg, unsigned short val)
+  {
+          struct mychip *chip = ac97->private_data;
+          ....
+          /* write the given register value to the codec */
+  }
+
+  static int snd_mychip_ac97(struct mychip *chip)
+  {
+          struct snd_ac97_bus *bus;
+          struct snd_ac97_template ac97;
+          int err;
+          static struct snd_ac97_bus_ops ops = {
+                  .write = snd_mychip_ac97_write,
+                  .read = snd_mychip_ac97_read,
+          };
+
+          err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
+          if (err < 0)
+                  return err;
+          memset(&ac97, 0, sizeof(ac97));
+          ac97.private_data = chip;
+          return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+  }
+
+]]>
+          </programlisting>
+        </example>
+      </para>
+    </section>
+
+    <section id="api-ac97-constructor">
+      <title>Constructor</title>
+      <para>
+        To create an ac97 instance, first call <function>snd_ac97_bus</function>
+      with an <type>ac97_bus_ops_t</type> record with callback functions.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_ac97_bus *bus;
+  static struct snd_ac97_bus_ops ops = {
+        .write = snd_mychip_ac97_write,
+        .read = snd_mychip_ac97_read,
+  };
+
+  snd_ac97_bus(card, 0, &ops, NULL, &pbus);
+]]>
+          </programlisting>
+        </informalexample>
+
+      The bus record is shared among all belonging ac97 instances.
+      </para>
+
+      <para>
+      And then call <function>snd_ac97_mixer()</function> with an
+      struct <structname>snd_ac97_template</structname>
+      record together with the bus pointer created above.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_ac97_template ac97;
+  int err;
+
+  memset(&ac97, 0, sizeof(ac97));
+  ac97.private_data = chip;
+  snd_ac97_mixer(bus, &ac97, &chip->ac97);
+]]>
+          </programlisting>
+        </informalexample>
+
+        where chip-&gt;ac97 is a pointer to a newly created
+        <type>ac97_t</type> instance.
+        In this case, the chip pointer is set as the private data, so that
+        the read/write callback functions can refer to this chip instance.
+        This instance is not necessarily stored in the chip
+	record.  If you need to change the register values from the
+        driver, or need the suspend/resume of ac97 codecs, keep this
+        pointer to pass to the corresponding functions.
+      </para>
+    </section>
+
+    <section id="api-ac97-callbacks">
+      <title>Callbacks</title>
+      <para>
+        The standard callbacks are <structfield>read</structfield> and
+      <structfield>write</structfield>. Obviously they 
+      correspond to the functions for read and write accesses to the
+      hardware low-level codes. 
+      </para>
+
+      <para>
+        The <structfield>read</structfield> callback returns the
+        register value specified in the argument. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
+                                             unsigned short reg)
+  {
+          struct mychip *chip = ac97->private_data;
+          ....
+          return the_register_value;
+  }
+]]>
+          </programlisting>
+        </informalexample>
+
+        Here, the chip can be cast from ac97-&gt;private_data.
+      </para>
+
+      <para>
+        Meanwhile, the <structfield>write</structfield> callback is
+        used to set the register value. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
+                       unsigned short reg, unsigned short val)
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+      These callbacks are non-atomic like the control API callbacks.
+      </para>
+
+      <para>
+        There are also other callbacks:
+      <structfield>reset</structfield>,
+      <structfield>wait</structfield> and
+      <structfield>init</structfield>. 
+      </para>
+
+      <para>
+        The <structfield>reset</structfield> callback is used to reset
+      the codec. If the chip requires a special kind of reset, you can
+      define this callback. 
+      </para>
+
+      <para>
+        The <structfield>wait</structfield> callback is used to
+      add some waiting time in the standard initialization of the codec. If the
+      chip requires the extra waiting time, define this callback. 
+      </para>
+
+      <para>
+        The <structfield>init</structfield> callback is used for
+      additional initialization of the codec.
+      </para>
+    </section>
+
+    <section id="api-ac97-updating-registers">
+      <title>Updating Registers in The Driver</title>
+      <para>
+        If you need to access to the codec from the driver, you can
+      call the following functions:
+      <function>snd_ac97_write()</function>,
+      <function>snd_ac97_read()</function>,
+      <function>snd_ac97_update()</function> and
+      <function>snd_ac97_update_bits()</function>. 
+      </para>
+
+      <para>
+        Both <function>snd_ac97_write()</function> and
+        <function>snd_ac97_update()</function> functions are used to
+        set a value to the given register
+        (<constant>AC97_XXX</constant>). The difference between them is
+        that <function>snd_ac97_update()</function> doesn't write a
+        value if the given value has been already set, while
+        <function>snd_ac97_write()</function> always rewrites the
+        value. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_ac97_write(ac97, AC97_MASTER, 0x8080);
+  snd_ac97_update(ac97, AC97_MASTER, 0x8080);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        <function>snd_ac97_read()</function> is used to read the value
+        of the given register. For example, 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  value = snd_ac97_read(ac97, AC97_MASTER);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        <function>snd_ac97_update_bits()</function> is used to update
+        some bits in the given register.  
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_ac97_update_bits(ac97, reg, mask, value);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        Also, there is a function to change the sample rate (of a
+        given register such as
+        <constant>AC97_PCM_FRONT_DAC_RATE</constant>) when VRA or
+        DRA is supported by the codec:
+        <function>snd_ac97_set_rate()</function>. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The following registers are available to set the rate:
+      <constant>AC97_PCM_MIC_ADC_RATE</constant>,
+      <constant>AC97_PCM_FRONT_DAC_RATE</constant>,
+      <constant>AC97_PCM_LR_ADC_RATE</constant>,
+      <constant>AC97_SPDIF</constant>. When
+      <constant>AC97_SPDIF</constant> is specified, the register is
+      not really changed but the corresponding IEC958 status bits will
+      be updated. 
+      </para>
+    </section>
+
+    <section id="api-ac97-clock-adjustment">
+      <title>Clock Adjustment</title>
+      <para>
+        In some chips, the clock of the codec isn't 48000 but using a
+      PCI clock (to save a quartz!). In this case, change the field
+      bus-&gt;clock to the corresponding
+      value. For example, intel8x0 
+      and es1968 drivers have their own function to read from the clock.
+      </para>
+    </section>
+
+    <section id="api-ac97-proc-files">
+      <title>Proc Files</title>
+      <para>
+        The ALSA AC97 interface will create a proc file such as
+      <filename>/proc/asound/card0/codec97#0/ac97#0-0</filename> and
+      <filename>ac97#0-0+regs</filename>. You can refer to these files to
+      see the current status and registers of the codec. 
+      </para>
+    </section>
+
+    <section id="api-ac97-multiple-codecs">
+      <title>Multiple Codecs</title>
+      <para>
+        When there are several codecs on the same card, you need to
+      call <function>snd_ac97_mixer()</function> multiple times with
+      ac97.num=1 or greater. The <structfield>num</structfield> field
+      specifies the codec number. 
+      </para>
+
+      <para>
+        If you set up multiple codecs, you either need to write
+      different callbacks for each codec or check
+      ac97-&gt;num in the callback routines. 
+      </para>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- MIDI (MPU401-UART) Interface  -->
+<!-- ****************************************************** -->
+  <chapter id="midi-interface">
+    <title>MIDI (MPU401-UART) Interface</title>
+
+    <section id="midi-interface-general">
+      <title>General</title>
+      <para>
+        Many soundcards have built-in MIDI (MPU401-UART)
+      interfaces. When the soundcard supports the standard MPU401-UART
+      interface, most likely you can use the ALSA MPU401-UART API. The
+      MPU401-UART API is defined in
+      <filename>&lt;sound/mpu401.h&gt;</filename>. 
+      </para>
+
+      <para>
+        Some soundchips have a similar but slightly different
+      implementation of mpu401 stuff. For example, emu10k1 has its own
+      mpu401 routines. 
+      </para>
+    </section>
+
+    <section id="midi-interface-constructor">
+      <title>Constructor</title>
+      <para>
+        To create a rawmidi object, call
+      <function>snd_mpu401_uart_new()</function>. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_rawmidi *rmidi;
+  snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
+                      irq, irq_flags, &rmidi);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The first argument is the card pointer, and the second is the
+      index of this component. You can create up to 8 rawmidi
+      devices. 
+      </para>
+
+      <para>
+        The third argument is the type of the hardware,
+      <constant>MPU401_HW_XXX</constant>. If it's not a special one,
+      you can use <constant>MPU401_HW_MPU401</constant>. 
+      </para>
+
+      <para>
+        The 4th argument is the I/O port address. Many
+      backward-compatible MPU401 have an I/O port such as 0x330. Or, it
+      might be a part of its own PCI I/O region. It depends on the
+      chip design. 
+      </para>
+
+      <para>
+	The 5th argument is a bitflag for additional information.
+        When the I/O port address above is part of the PCI I/O
+      region, the MPU401 I/O port might have been already allocated
+      (reserved) by the driver itself. In such a case, pass a bit flag
+      <constant>MPU401_INFO_INTEGRATED</constant>,
+      and the mpu401-uart layer will allocate the I/O ports by itself. 
+      </para>
+
+	<para>
+	When the controller supports only the input or output MIDI stream,
+	pass the <constant>MPU401_INFO_INPUT</constant> or
+	<constant>MPU401_INFO_OUTPUT</constant> bitflag, respectively.
+	Then the rawmidi instance is created as a single stream.
+	</para>
+
+	<para>
+	<constant>MPU401_INFO_MMIO</constant> bitflag is used to change
+	the access method to MMIO (via readb and writeb) instead of
+	iob and outb. In this case, you have to pass the iomapped address
+	to <function>snd_mpu401_uart_new()</function>.
+	</para>
+
+	<para>
+	When <constant>MPU401_INFO_TX_IRQ</constant> is set, the output
+	stream isn't checked in the default interrupt handler.  The driver
+	needs to call <function>snd_mpu401_uart_interrupt_tx()</function>
+	by itself to start processing the output stream in the irq handler.
+	</para>
+
+      <para>
+        Usually, the port address corresponds to the command port and
+        port + 1 corresponds to the data port. If not, you may change
+        the <structfield>cport</structfield> field of
+        struct <structname>snd_mpu401</structname> manually 
+        afterward. However, <structname>snd_mpu401</structname> pointer is not
+        returned explicitly by
+        <function>snd_mpu401_uart_new()</function>. You need to cast
+        rmidi-&gt;private_data to
+        <structname>snd_mpu401</structname> explicitly, 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_mpu401 *mpu;
+  mpu = rmidi->private_data;
+]]>
+          </programlisting>
+        </informalexample>
+
+        and reset the cport as you like:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  mpu->cport = my_own_control_port;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The 6th argument specifies the irq number for UART. If the irq
+      is already allocated, pass 0 to the 7th argument
+      (<parameter>irq_flags</parameter>). Otherwise, pass the flags
+      for irq allocation 
+      (<constant>SA_XXX</constant> bits) to it, and the irq will be
+      reserved by the mpu401-uart layer. If the card doesn't generate
+      UART interrupts, pass -1 as the irq number. Then a timer
+      interrupt will be invoked for polling. 
+      </para>
+    </section>
+
+    <section id="midi-interface-interrupt-handler">
+      <title>Interrupt Handler</title>
+      <para>
+        When the interrupt is allocated in
+      <function>snd_mpu401_uart_new()</function>, the private
+      interrupt handler is used, hence you don't have anything else to do
+      than creating the mpu401 stuff. Otherwise, you have to call
+      <function>snd_mpu401_uart_interrupt()</function> explicitly when
+      a UART interrupt is invoked and checked in your own interrupt
+      handler.  
+      </para>
+
+      <para>
+        In this case, you need to pass the private_data of the
+        returned rawmidi object from
+        <function>snd_mpu401_uart_new()</function> as the second
+        argument of <function>snd_mpu401_uart_interrupt()</function>. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- RawMIDI Interface  -->
+<!-- ****************************************************** -->
+  <chapter id="rawmidi-interface">
+    <title>RawMIDI Interface</title>
+
+    <section id="rawmidi-interface-overview">
+      <title>Overview</title>
+
+      <para>
+      The raw MIDI interface is used for hardware MIDI ports that can
+      be accessed as a byte stream.  It is not used for synthesizer
+      chips that do not directly understand MIDI.
+      </para>
+
+      <para>
+      ALSA handles file and buffer management.  All you have to do is
+      to write some code to move data between the buffer and the
+      hardware.
+      </para>
+
+      <para>
+      The rawmidi API is defined in
+      <filename>&lt;sound/rawmidi.h&gt;</filename>.
+      </para>
+    </section>
+
+    <section id="rawmidi-interface-constructor">
+      <title>Constructor</title>
+
+      <para>
+      To create a rawmidi device, call the
+      <function>snd_rawmidi_new</function> function:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_rawmidi *rmidi;
+  err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
+  if (err < 0)
+          return err;
+  rmidi->private_data = chip;
+  strcpy(rmidi->name, "My MIDI");
+  rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+                      SNDRV_RAWMIDI_INFO_INPUT |
+                      SNDRV_RAWMIDI_INFO_DUPLEX;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+      The first argument is the card pointer, the second argument is
+      the ID string.
+      </para>
+
+      <para>
+      The third argument is the index of this component.  You can
+      create up to 8 rawmidi devices.
+      </para>
+
+      <para>
+      The fourth and fifth arguments are the number of output and
+      input substreams, respectively, of this device (a substream is
+      the equivalent of a MIDI port).
+      </para>
+
+      <para>
+      Set the <structfield>info_flags</structfield> field to specify
+      the capabilities of the device.
+      Set <constant>SNDRV_RAWMIDI_INFO_OUTPUT</constant> if there is
+      at least one output port,
+      <constant>SNDRV_RAWMIDI_INFO_INPUT</constant> if there is at
+      least one input port,
+      and <constant>SNDRV_RAWMIDI_INFO_DUPLEX</constant> if the device
+      can handle output and input at the same time.
+      </para>
+
+      <para>
+      After the rawmidi device is created, you need to set the
+      operators (callbacks) for each substream.  There are helper
+      functions to set the operators for all the substreams of a device:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
+  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+      The operators are usually defined like this:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static struct snd_rawmidi_ops snd_mymidi_output_ops = {
+          .open =    snd_mymidi_output_open,
+          .close =   snd_mymidi_output_close,
+          .trigger = snd_mymidi_output_trigger,
+  };
+]]>
+          </programlisting>
+        </informalexample>
+      These callbacks are explained in the <link
+      linkend="rawmidi-interface-callbacks"><citetitle>Callbacks</citetitle></link>
+      section.
+      </para>
+
+      <para>
+      If there are more than one substream, you should give a
+      unique name to each of them:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_rawmidi_substream *substream;
+  list_for_each_entry(substream,
+                      &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
+                      list {
+          sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
+  }
+  /* same for SNDRV_RAWMIDI_STREAM_INPUT */
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+    </section>
+
+    <section id="rawmidi-interface-callbacks">
+      <title>Callbacks</title>
+
+      <para>
+      In all the callbacks, the private data that you've set for the
+      rawmidi device can be accessed as
+      substream-&gt;rmidi-&gt;private_data.
+      <!-- <code> isn't available before DocBook 4.3 -->
+      </para>
+
+      <para>
+      If there is more than one port, your callbacks can determine the
+      port index from the struct snd_rawmidi_substream data passed to each
+      callback:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_rawmidi_substream *substream;
+  int index = substream->number;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <section id="rawmidi-interface-op-open">
+      <title><function>open</function> callback</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int snd_xxx_open(struct snd_rawmidi_substream *substream);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is called when a substream is opened.
+        You can initialize the hardware here, but you shouldn't
+        start transmitting/receiving data yet.
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-close">
+      <title><function>close</function> callback</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int snd_xxx_close(struct snd_rawmidi_substream *substream);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        Guess what.
+        </para>
+
+        <para>
+        The <function>open</function> and <function>close</function>
+        callbacks of a rawmidi device are serialized with a mutex,
+        and can sleep.
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-trigger-out">
+      <title><function>trigger</function> callback for output
+      substreams</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void snd_xxx_output_trigger(struct snd_rawmidi_substream *substream, int up);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is called with a nonzero <parameter>up</parameter>
+        parameter when there is some data in the substream buffer that
+        must be transmitted.
+        </para>
+
+        <para>
+        To read data from the buffer, call
+        <function>snd_rawmidi_transmit_peek</function>.  It will
+        return the number of bytes that have been read; this will be
+        less than the number of bytes requested when there are no more
+        data in the buffer.
+        After the data have been transmitted successfully, call
+        <function>snd_rawmidi_transmit_ack</function> to remove the
+        data from the substream buffer:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  unsigned char data;
+  while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
+          if (snd_mychip_try_to_transmit(data))
+                  snd_rawmidi_transmit_ack(substream, 1);
+          else
+                  break; /* hardware FIFO full */
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+        If you know beforehand that the hardware will accept data, you
+        can use the <function>snd_rawmidi_transmit</function> function
+        which reads some data and removes them from the buffer at once:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  while (snd_mychip_transmit_possible()) {
+          unsigned char data;
+          if (snd_rawmidi_transmit(substream, &data, 1) != 1)
+                  break; /* no more data */
+          snd_mychip_transmit(data);
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+        If you know beforehand how many bytes you can accept, you can
+        use a buffer size greater than one with the
+        <function>snd_rawmidi_transmit*</function> functions.
+        </para>
+
+        <para>
+        The <function>trigger</function> callback must not sleep.  If
+        the hardware FIFO is full before the substream buffer has been
+        emptied, you have to continue transmitting data later, either
+        in an interrupt handler, or with a timer if the hardware
+        doesn't have a MIDI transmit interrupt.
+        </para>
+
+        <para>
+        The <function>trigger</function> callback is called with a
+        zero <parameter>up</parameter> parameter when the transmission
+        of data should be aborted.
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-trigger-in">
+      <title><function>trigger</function> callback for input
+      substreams</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void snd_xxx_input_trigger(struct snd_rawmidi_substream *substream, int up);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is called with a nonzero <parameter>up</parameter>
+        parameter to enable receiving data, or with a zero
+        <parameter>up</parameter> parameter do disable receiving data.
+        </para>
+
+        <para>
+        The <function>trigger</function> callback must not sleep; the
+        actual reading of data from the device is usually done in an
+        interrupt handler.
+        </para>
+
+        <para>
+        When data reception is enabled, your interrupt handler should
+        call <function>snd_rawmidi_receive</function> for all received
+        data:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  void snd_mychip_midi_interrupt(...)
+  {
+          while (mychip_midi_available()) {
+                  unsigned char data;
+                  data = mychip_midi_read();
+                  snd_rawmidi_receive(substream, &data, 1);
+          }
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-drain">
+      <title><function>drain</function> callback</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void snd_xxx_drain(struct snd_rawmidi_substream *substream);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is only used with output substreams.  This function should wait
+        until all data read from the substream buffer have been transmitted.
+        This ensures that the device can be closed and the driver unloaded
+        without losing data.
+        </para>
+
+        <para>
+        This callback is optional. If you do not set
+        <structfield>drain</structfield> in the struct snd_rawmidi_ops
+        structure, ALSA will simply wait for 50&nbsp;milliseconds
+        instead.
+        </para>
+      </section>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Miscellaneous Devices  -->
+<!-- ****************************************************** -->
+  <chapter id="misc-devices">
+    <title>Miscellaneous Devices</title>
+
+    <section id="misc-devices-opl3">
+      <title>FM OPL3</title>
+      <para>
+        The FM OPL3 is still used in many chips (mainly for backward
+      compatibility). ALSA has a nice OPL3 FM control layer, too. The
+      OPL3 API is defined in
+      <filename>&lt;sound/opl3.h&gt;</filename>. 
+      </para>
+
+      <para>
+        FM registers can be directly accessed through the direct-FM API,
+      defined in <filename>&lt;sound/asound_fm.h&gt;</filename>. In
+      ALSA native mode, FM registers are accessed through
+      the Hardware-Dependant Device direct-FM extension API, whereas in
+      OSS compatible mode, FM registers can be accessed with the OSS
+      direct-FM compatible API in <filename>/dev/dmfmX</filename> device. 
+      </para>
+
+      <para>
+        To create the OPL3 component, you have two functions to
+        call. The first one is a constructor for the <type>opl3_t</type>
+        instance. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_opl3 *opl3;
+  snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,
+                  integrated, &opl3);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The first argument is the card pointer, the second one is the
+      left port address, and the third is the right port address. In
+      most cases, the right port is placed at the left port + 2. 
+      </para>
+
+      <para>
+        The fourth argument is the hardware type.
+      </para>
+
+      <para>
+        When the left and right ports have been already allocated by
+      the card driver, pass non-zero to the fifth argument
+      (<parameter>integrated</parameter>). Otherwise, the opl3 module will
+      allocate the specified ports by itself. 
+      </para>
+
+      <para>
+        When the accessing the hardware requires special method
+        instead of the standard I/O access, you can create opl3 instance
+        separately with <function>snd_opl3_new()</function>.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_opl3 *opl3;
+  snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+	Then set <structfield>command</structfield>,
+	<structfield>private_data</structfield> and
+	<structfield>private_free</structfield> for the private
+	access function, the private data and the destructor.
+	The l_port and r_port are not necessarily set.  Only the
+	command must be set properly.  You can retrieve the data
+	from the opl3-&gt;private_data field.
+      </para>
+
+      <para>
+	After creating the opl3 instance via <function>snd_opl3_new()</function>,
+	call <function>snd_opl3_init()</function> to initialize the chip to the
+	proper state. Note that <function>snd_opl3_create()</function> always
+	calls it internally.
+      </para>
+
+      <para>
+        If the opl3 instance is created successfully, then create a
+        hwdep device for this opl3. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_hwdep *opl3hwdep;
+  snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The first argument is the <type>opl3_t</type> instance you
+      created, and the second is the index number, usually 0. 
+      </para>
+
+      <para>
+        The third argument is the index-offset for the sequencer
+      client assigned to the OPL3 port. When there is an MPU401-UART,
+      give 1 for here (UART always takes 0). 
+      </para>
+    </section>
+
+    <section id="misc-devices-hardware-dependent">
+      <title>Hardware-Dependent Devices</title>
+      <para>
+        Some chips need user-space access for special
+      controls or for loading the micro code. In such a case, you can
+      create a hwdep (hardware-dependent) device. The hwdep API is
+      defined in <filename>&lt;sound/hwdep.h&gt;</filename>. You can
+      find examples in opl3 driver or
+      <filename>isa/sb/sb16_csp.c</filename>. 
+      </para>
+
+      <para>
+        The creation of the <type>hwdep</type> instance is done via
+        <function>snd_hwdep_new()</function>. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_hwdep *hw;
+  snd_hwdep_new(card, "My HWDEP", 0, &hw);
+]]>
+          </programlisting>
+        </informalexample>
+
+        where the third argument is the index number.
+      </para>
+
+      <para>
+        You can then pass any pointer value to the
+        <parameter>private_data</parameter>.
+        If you assign a private data, you should define the
+        destructor, too. The destructor function is set in
+        the <structfield>private_free</structfield> field.  
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);
+  hw->private_data = p;
+  hw->private_free = mydata_free;
+]]>
+          </programlisting>
+        </informalexample>
+
+        and the implementation of the destructor would be:
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void mydata_free(struct snd_hwdep *hw)
+  {
+          struct mydata *p = hw->private_data;
+          kfree(p);
+  }
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The arbitrary file operations can be defined for this
+        instance. The file operators are defined in
+        the <parameter>ops</parameter> table. For example, assume that
+        this chip needs an ioctl. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  hw->ops.open = mydata_open;
+  hw->ops.ioctl = mydata_ioctl;
+  hw->ops.release = mydata_release;
+]]>
+          </programlisting>
+        </informalexample>
+
+        And implement the callback functions as you like.
+      </para>
+    </section>
+
+    <section id="misc-devices-IEC958">
+      <title>IEC958 (S/PDIF)</title>
+      <para>
+        Usually the controls for IEC958 devices are implemented via
+      the control interface. There is a macro to compose a name string for
+      IEC958 controls, <function>SNDRV_CTL_NAME_IEC958()</function>
+      defined in <filename>&lt;include/asound.h&gt;</filename>.  
+      </para>
+
+      <para>
+        There are some standard controls for IEC958 status bits. These
+      controls use the type <type>SNDRV_CTL_ELEM_TYPE_IEC958</type>,
+      and the size of element is fixed as 4 bytes array
+      (value.iec958.status[x]). For the <structfield>info</structfield>
+      callback, you don't specify 
+      the value field for this type (the count field must be set,
+      though). 
+      </para>
+
+      <para>
+        <quote>IEC958 Playback Con Mask</quote> is used to return the
+      bit-mask for the IEC958 status bits of consumer mode. Similarly,
+      <quote>IEC958 Playback Pro Mask</quote> returns the bitmask for
+      professional mode. They are read-only controls, and are defined
+      as MIXER controls (iface =
+      <constant>SNDRV_CTL_ELEM_IFACE_MIXER</constant>).  
+      </para>
+
+      <para>
+        Meanwhile, <quote>IEC958 Playback Default</quote> control is
+      defined for getting and setting the current default IEC958
+      bits. Note that this one is usually defined as a PCM control
+      (iface = <constant>SNDRV_CTL_ELEM_IFACE_PCM</constant>),
+      although in some places it's defined as a MIXER control. 
+      </para>
+
+      <para>
+        In addition, you can define the control switches to
+      enable/disable or to set the raw bit mode. The implementation
+      will depend on the chip, but the control should be named as
+      <quote>IEC958 xxx</quote>, preferably using
+      the <function>SNDRV_CTL_NAME_IEC958()</function> macro. 
+      </para>
+
+      <para>
+        You can find several cases, for example,
+      <filename>pci/emu10k1</filename>,
+      <filename>pci/ice1712</filename>, or
+      <filename>pci/cmipci.c</filename>.  
+      </para>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Buffer and Memory Management  -->
+<!-- ****************************************************** -->
+  <chapter id="buffer-and-memory">
+    <title>Buffer and Memory Management</title>
+
+    <section id="buffer-and-memory-buffer-types">
+      <title>Buffer Types</title>
+      <para>
+        ALSA provides several different buffer allocation functions
+      depending on the bus and the architecture. All these have a
+      consistent API. The allocation of physically-contiguous pages is
+      done via 
+      <function>snd_malloc_xxx_pages()</function> function, where xxx
+      is the bus type. 
+      </para>
+
+      <para>
+        The allocation of pages with fallback is
+      <function>snd_malloc_xxx_pages_fallback()</function>. This
+      function tries to allocate the specified pages but if the pages
+      are not available, it tries to reduce the page sizes until
+      enough space is found.
+      </para>
+
+      <para>
+      The release the pages, call
+      <function>snd_free_xxx_pages()</function> function. 
+      </para>
+
+      <para>
+      Usually, ALSA drivers try to allocate and reserve
+       a large contiguous physical space
+       at the time the module is loaded for the later use.
+       This is called <quote>pre-allocation</quote>.
+       As already written, you can call the following function at 
+       pcm instance construction time (in the case of PCI bus). 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                        snd_dma_pci_data(pci), size, max);
+]]>
+          </programlisting>
+        </informalexample>
+
+        where <parameter>size</parameter> is the byte size to be
+      pre-allocated and the <parameter>max</parameter> is the maximum
+      size to be changed via the <filename>prealloc</filename> proc file.
+      The allocator will try to get an area as large as possible
+      within the given size. 
+      </para>
+
+      <para>
+      The second argument (type) and the third argument (device pointer)
+      are dependent on the bus.
+      In the case of the ISA bus, pass <function>snd_dma_isa_data()</function>
+      as the third argument with <constant>SNDRV_DMA_TYPE_DEV</constant> type.
+      For the continuous buffer unrelated to the bus can be pre-allocated
+      with <constant>SNDRV_DMA_TYPE_CONTINUOUS</constant> type and the
+      <function>snd_dma_continuous_data(GFP_KERNEL)</function> device pointer,
+      where <constant>GFP_KERNEL</constant> is the kernel allocation flag to
+      use.
+      For the PCI scatter-gather buffers, use
+      <constant>SNDRV_DMA_TYPE_DEV_SG</constant> with
+      <function>snd_dma_pci_data(pci)</function>
+      (see the 
+          <link linkend="buffer-and-memory-non-contiguous"><citetitle>Non-Contiguous Buffers
+          </citetitle></link> section).
+      </para>
+
+      <para>
+        Once the buffer is pre-allocated, you can use the
+        allocator in the <structfield>hw_params</structfield> callback: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_pcm_lib_malloc_pages(substream, size);
+]]>
+          </programlisting>
+        </informalexample>
+
+        Note that you have to pre-allocate to use this function.
+      </para>
+    </section>
+
+    <section id="buffer-and-memory-external-hardware">
+      <title>External Hardware Buffers</title>
+      <para>
+        Some chips have their own hardware buffers and the DMA
+      transfer from the host memory is not available. In such a case,
+      you need to either 1) copy/set the audio data directly to the
+      external hardware buffer, or 2) make an intermediate buffer and
+      copy/set the data from it to the external hardware buffer in
+      interrupts (or in tasklets, preferably).
+      </para>
+
+      <para>
+        The first case works fine if the external hardware buffer is large
+      enough.  This method doesn't need any extra buffers and thus is
+      more effective. You need to define the
+      <structfield>copy</structfield> and
+      <structfield>silence</structfield> callbacks for 
+      the data transfer. However, there is a drawback: it cannot
+      be mmapped. The examples are GUS's GF1 PCM or emu8000's
+      wavetable PCM. 
+      </para>
+
+      <para>
+        The second case allows for mmap on the buffer, although you have
+      to handle an interrupt or a tasklet to transfer the data
+      from the intermediate buffer to the hardware buffer. You can find an
+      example in the vxpocket driver. 
+      </para>
+
+      <para>
+        Another case is when the chip uses a PCI memory-map
+      region for the buffer instead of the host memory. In this case,
+      mmap is available only on certain architectures like the Intel one.
+      In non-mmap mode, the data cannot be transferred as in the normal
+      way. Thus you need to define the <structfield>copy</structfield> and
+      <structfield>silence</structfield> callbacks as well, 
+      as in the cases above. The examples are found in
+      <filename>rme32.c</filename> and <filename>rme96.c</filename>. 
+      </para>
+
+      <para>
+        The implementation of the <structfield>copy</structfield> and
+        <structfield>silence</structfield> callbacks depends upon 
+        whether the hardware supports interleaved or non-interleaved
+        samples. The <structfield>copy</structfield> callback is
+        defined like below, a bit 
+        differently depending whether the direction is playback or
+        capture: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int playback_copy(struct snd_pcm_substream *substream, int channel,
+               snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
+  static int capture_copy(struct snd_pcm_substream *substream, int channel,
+               snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        In the case of interleaved samples, the second argument
+      (<parameter>channel</parameter>) is not used. The third argument
+      (<parameter>pos</parameter>) points the 
+      current position offset in frames. 
+      </para>
+
+      <para>
+        The meaning of the fourth argument is different between
+      playback and capture. For playback, it holds the source data
+      pointer, and for capture, it's the destination data pointer. 
+      </para>
+
+      <para>
+        The last argument is the number of frames to be copied.
+      </para>
+
+      <para>
+        What you have to do in this callback is again different
+        between playback and capture directions. In the
+        playback case, you copy the given amount of data
+        (<parameter>count</parameter>) at the specified pointer
+        (<parameter>src</parameter>) to the specified offset
+        (<parameter>pos</parameter>) on the hardware buffer. When
+        coded like memcpy-like way, the copy would be like: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
+            frames_to_bytes(runtime, count));
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        For the capture direction, you copy the given amount of
+        data (<parameter>count</parameter>) at the specified offset
+        (<parameter>pos</parameter>) on the hardware buffer to the
+        specified pointer (<parameter>dst</parameter>). 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
+            frames_to_bytes(runtime, count));
+]]>
+          </programlisting>
+        </informalexample>
+
+        Note that both the position and the amount of data are given
+      in frames. 
+      </para>
+
+      <para>
+        In the case of non-interleaved samples, the implementation
+      will be a bit more complicated. 
+      </para>
+
+      <para>
+        You need to check the channel argument, and if it's -1, copy
+      the whole channels. Otherwise, you have to copy only the
+      specified channel. Please check
+      <filename>isa/gus/gus_pcm.c</filename> as an example. 
+      </para>
+
+      <para>
+        The <structfield>silence</structfield> callback is also
+        implemented in a similar way. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int silence(struct snd_pcm_substream *substream, int channel,
+                     snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        The meanings of arguments are the same as in the
+      <structfield>copy</structfield> 
+      callback, although there is no <parameter>src/dst</parameter>
+      argument. In the case of interleaved samples, the channel
+      argument has no meaning, as well as on
+      <structfield>copy</structfield> callback.  
+      </para>
+
+      <para>
+        The role of <structfield>silence</structfield> callback is to
+        set the given amount 
+        (<parameter>count</parameter>) of silence data at the
+        specified offset (<parameter>pos</parameter>) on the hardware
+        buffer. Suppose that the data format is signed (that is, the
+        silent-data is 0), and the implementation using a memset-like
+        function would be like: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0,
+            frames_to_bytes(runtime, count));
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        In the case of non-interleaved samples, again, the
+      implementation becomes a bit more complicated. See, for example,
+      <filename>isa/gus/gus_pcm.c</filename>. 
+      </para>
+    </section>
+
+    <section id="buffer-and-memory-non-contiguous">
+      <title>Non-Contiguous Buffers</title>
+      <para>
+        If your hardware supports the page table as in emu10k1 or the
+      buffer descriptors as in via82xx, you can use the scatter-gather
+      (SG) DMA. ALSA provides an interface for handling SG-buffers.
+      The API is provided in <filename>&lt;sound/pcm.h&gt;</filename>. 
+      </para>
+
+      <para>
+        For creating the SG-buffer handler, call
+        <function>snd_pcm_lib_preallocate_pages()</function> or
+        <function>snd_pcm_lib_preallocate_pages_for_all()</function>
+        with <constant>SNDRV_DMA_TYPE_DEV_SG</constant>
+	in the PCM constructor like other PCI pre-allocator.
+        You need to pass <function>snd_dma_pci_data(pci)</function>,
+        where pci is the struct <structname>pci_dev</structname> pointer
+        of the chip as well.
+        The <type>struct snd_sg_buf</type> instance is created as
+        substream-&gt;dma_private. You can cast
+        the pointer like: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        Then call <function>snd_pcm_lib_malloc_pages()</function>
+      in the <structfield>hw_params</structfield> callback
+      as well as in the case of normal PCI buffer.
+      The SG-buffer handler will allocate the non-contiguous kernel
+      pages of the given size and map them onto the virtually contiguous
+      memory.  The virtual pointer is addressed in runtime-&gt;dma_area.
+      The physical address (runtime-&gt;dma_addr) is set to zero,
+      because the buffer is physically non-contigous.
+      The physical address table is set up in sgbuf-&gt;table.
+      You can get the physical address at a certain offset via
+      <function>snd_pcm_sgbuf_get_addr()</function>. 
+      </para>
+
+      <para>
+        When a SG-handler is used, you need to set
+      <function>snd_pcm_sgbuf_ops_page</function> as
+      the <structfield>page</structfield> callback.
+      (See <link linkend="pcm-interface-operators-page-callback">
+      <citetitle>page callback section</citetitle></link>.)
+      </para>
+
+      <para>
+        To release the data, call
+      <function>snd_pcm_lib_free_pages()</function> in the
+      <structfield>hw_free</structfield> callback as usual.
+      </para>
+    </section>
+
+    <section id="buffer-and-memory-vmalloced">
+      <title>Vmalloc'ed Buffers</title>
+      <para>
+        It's possible to use a buffer allocated via
+      <function>vmalloc</function>, for example, for an intermediate
+      buffer. Since the allocated pages are not contiguous, you need
+      to set the <structfield>page</structfield> callback to obtain
+      the physical address at every offset. 
+      </para>
+
+      <para>
+        The implementation of <structfield>page</structfield> callback
+        would be like this: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  #include <linux/vmalloc.h>
+
+  /* get the physical page pointer on the given offset */
+  static struct page *mychip_page(struct snd_pcm_substream *substream,
+                                  unsigned long offset)
+  {
+          void *pageptr = substream->runtime->dma_area + offset;
+          return vmalloc_to_page(pageptr);
+  }
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Proc Interface  -->
+<!-- ****************************************************** -->
+  <chapter id="proc-interface">
+    <title>Proc Interface</title>
+    <para>
+      ALSA provides an easy interface for procfs. The proc files are
+      very useful for debugging. I recommend you set up proc files if
+      you write a driver and want to get a running status or register
+      dumps. The API is found in
+      <filename>&lt;sound/info.h&gt;</filename>. 
+    </para>
+
+    <para>
+      To create a proc file, call
+      <function>snd_card_proc_new()</function>. 
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  struct snd_info_entry *entry;
+  int err = snd_card_proc_new(card, "my-file", &entry);
+]]>
+        </programlisting>
+      </informalexample>
+
+      where the second argument specifies the name of the proc file to be
+    created. The above example will create a file
+    <filename>my-file</filename> under the card directory,
+    e.g. <filename>/proc/asound/card0/my-file</filename>. 
+    </para>
+
+    <para>
+    Like other components, the proc entry created via
+    <function>snd_card_proc_new()</function> will be registered and
+    released automatically in the card registration and release
+    functions.
+    </para>
+
+    <para>
+      When the creation is successful, the function stores a new
+    instance in the pointer given in the third argument.
+    It is initialized as a text proc file for read only.  To use
+    this proc file as a read-only text file as it is, set the read
+    callback with a private data via 
+     <function>snd_info_set_text_ops()</function>.
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  snd_info_set_text_ops(entry, chip, my_proc_read);
+]]>
+        </programlisting>
+      </informalexample>
+    
+    where the second argument (<parameter>chip</parameter>) is the
+    private data to be used in the callbacks. The third parameter
+    specifies the read buffer size and the fourth
+    (<parameter>my_proc_read</parameter>) is the callback function, which
+    is defined like
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static void my_proc_read(struct snd_info_entry *entry,
+                           struct snd_info_buffer *buffer);
+]]>
+        </programlisting>
+      </informalexample>
+    
+    </para>
+
+    <para>
+    In the read callback, use <function>snd_iprintf()</function> for
+    output strings, which works just like normal
+    <function>printf()</function>.  For example,
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static void my_proc_read(struct snd_info_entry *entry,
+                           struct snd_info_buffer *buffer)
+  {
+          struct my_chip *chip = entry->private_data;
+
+          snd_iprintf(buffer, "This is my chip!\n");
+          snd_iprintf(buffer, "Port = %ld\n", chip->port);
+  }
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+    The file permissions can be changed afterwards.  As default, it's
+    set as read only for all users.  If you want to add write
+    permission for the user (root as default), do as follows:
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+ entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
+]]>
+        </programlisting>
+      </informalexample>
+
+    and set the write buffer size and the callback
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  entry->c.text.write = my_proc_write;
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+      For the write callback, you can use
+    <function>snd_info_get_line()</function> to get a text line, and
+    <function>snd_info_get_str()</function> to retrieve a string from
+    the line. Some examples are found in
+    <filename>core/oss/mixer_oss.c</filename>, core/oss/and
+    <filename>pcm_oss.c</filename>. 
+    </para>
+
+    <para>
+      For a raw-data proc-file, set the attributes as follows:
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static struct snd_info_entry_ops my_file_io_ops = {
+          .read = my_file_io_read,
+  };
+
+  entry->content = SNDRV_INFO_CONTENT_DATA;
+  entry->private_data = chip;
+  entry->c.ops = &my_file_io_ops;
+  entry->size = 4096;
+  entry->mode = S_IFREG | S_IRUGO;
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+      The callback is much more complicated than the text-file
+      version. You need to use a low-level I/O functions such as
+      <function>copy_from/to_user()</function> to transfer the
+      data.
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static long my_file_io_read(struct snd_info_entry *entry,
+                              void *file_private_data,
+                              struct file *file,
+                              char *buf,
+                              unsigned long count,
+                              unsigned long pos)
+  {
+          long size = count;
+          if (pos + size > local_max_size)
+                  size = local_max_size - pos;
+          if (copy_to_user(buf, local_data + pos, size))
+                  return -EFAULT;
+          return size;
+  }
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Power Management  -->
+<!-- ****************************************************** -->
+  <chapter id="power-management">
+    <title>Power Management</title>
+    <para>
+      If the chip is supposed to work with suspend/resume
+      functions, you need to add power-management code to the
+      driver. The additional code for power-management should be
+      <function>ifdef</function>'ed with
+      <constant>CONFIG_PM</constant>. 
+    </para>
+
+	<para>
+	If the driver <emphasis>fully</emphasis> supports suspend/resume
+	that is, the device can be
+	properly resumed to its state when suspend was called,
+	you can set the <constant>SNDRV_PCM_INFO_RESUME</constant> flag
+	in the pcm info field.  Usually, this is possible when the
+	registers of the chip can be safely saved and restored to
+	RAM. If this is set, the trigger callback is called with
+	<constant>SNDRV_PCM_TRIGGER_RESUME</constant> after the resume
+	callback completes. 
+	</para>
+
+	<para>
+	Even if the driver doesn't support PM fully but 
+	partial suspend/resume is still possible, it's still worthy to
+	implement suspend/resume callbacks. In such a case, applications
+	would reset the status by calling
+	<function>snd_pcm_prepare()</function> and restart the stream
+	appropriately.  Hence, you can define suspend/resume callbacks
+	below but don't set <constant>SNDRV_PCM_INFO_RESUME</constant>
+	info flag to the PCM.
+	</para>
+	
+	<para>
+	Note that the trigger with SUSPEND can always be called when
+	<function>snd_pcm_suspend_all</function> is called,
+	regardless of the <constant>SNDRV_PCM_INFO_RESUME</constant> flag.
+	The <constant>RESUME</constant> flag affects only the behavior
+	of <function>snd_pcm_resume()</function>.
+	(Thus, in theory,
+	<constant>SNDRV_PCM_TRIGGER_RESUME</constant> isn't needed
+	to be handled in the trigger callback when no
+	<constant>SNDRV_PCM_INFO_RESUME</constant> flag is set.  But,
+	it's better to keep it for compatibility reasons.)
+	</para>
+    <para>
+      In the earlier version of ALSA drivers, a common
+      power-management layer was provided, but it has been removed.
+      The driver needs to define the suspend/resume hooks according to
+      the bus the device is connected to.  In the case of PCI drivers, the
+      callbacks look like below:
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  #ifdef CONFIG_PM
+  static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
+  {
+          .... /* do things for suspend */
+          return 0;
+  }
+  static int snd_my_resume(struct pci_dev *pci)
+  {
+          .... /* do things for suspend */
+          return 0;
+  }
+  #endif
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+      The scheme of the real suspend job is as follows.
+
+      <orderedlist>
+        <listitem><para>Retrieve the card and the chip data.</para></listitem>
+        <listitem><para>Call <function>snd_power_change_state()</function> with
+	  <constant>SNDRV_CTL_POWER_D3hot</constant> to change the
+	  power status.</para></listitem>
+        <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem>
+	<listitem><para>If AC97 codecs are used, call
+	<function>snd_ac97_suspend()</function> for each codec.</para></listitem>
+        <listitem><para>Save the register values if necessary.</para></listitem>
+        <listitem><para>Stop the hardware if necessary.</para></listitem>
+        <listitem><para>Disable the PCI device by calling
+	  <function>pci_disable_device()</function>.  Then, call
+          <function>pci_save_state()</function> at last.</para></listitem>
+      </orderedlist>
+    </para>
+
+    <para>
+      A typical code would be like:
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static int mychip_suspend(struct pci_dev *pci, pm_message_t state)
+  {
+          /* (1) */
+          struct snd_card *card = pci_get_drvdata(pci);
+          struct mychip *chip = card->private_data;
+          /* (2) */
+          snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+          /* (3) */
+          snd_pcm_suspend_all(chip->pcm);
+          /* (4) */
+          snd_ac97_suspend(chip->ac97);
+          /* (5) */
+          snd_mychip_save_registers(chip);
+          /* (6) */
+          snd_mychip_stop_hardware(chip);
+          /* (7) */
+          pci_disable_device(pci);
+          pci_save_state(pci);
+          return 0;
+  }
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+    The scheme of the real resume job is as follows.
+
+    <orderedlist>
+    <listitem><para>Retrieve the card and the chip data.</para></listitem>
+    <listitem><para>Set up PCI. First, call <function>pci_restore_state()</function>.
+    	Then enable the pci device again by calling <function>pci_enable_device()</function>.
+	Call <function>pci_set_master()</function> if necessary, too.</para></listitem>
+    <listitem><para>Re-initialize the chip.</para></listitem>
+    <listitem><para>Restore the saved registers if necessary.</para></listitem>
+    <listitem><para>Resume the mixer, e.g. calling
+    <function>snd_ac97_resume()</function>.</para></listitem>
+    <listitem><para>Restart the hardware (if any).</para></listitem>
+    <listitem><para>Call <function>snd_power_change_state()</function> with
+	<constant>SNDRV_CTL_POWER_D0</constant> to notify the processes.</para></listitem>
+    </orderedlist>
+    </para>
+
+    <para>
+    A typical code would be like:
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static int mychip_resume(struct pci_dev *pci)
+  {
+          /* (1) */
+          struct snd_card *card = pci_get_drvdata(pci);
+          struct mychip *chip = card->private_data;
+          /* (2) */
+          pci_restore_state(pci);
+          pci_enable_device(pci);
+          pci_set_master(pci);
+          /* (3) */
+          snd_mychip_reinit_chip(chip);
+          /* (4) */
+          snd_mychip_restore_registers(chip);
+          /* (5) */
+          snd_ac97_resume(chip->ac97);
+          /* (6) */
+          snd_mychip_restart_chip(chip);
+          /* (7) */
+          snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+          return 0;
+  }
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+	As shown in the above, it's better to save registers after
+	suspending the PCM operations via
+	<function>snd_pcm_suspend_all()</function> or
+	<function>snd_pcm_suspend()</function>.  It means that the PCM
+	streams are already stoppped when the register snapshot is
+	taken.  But, remember that you don't have to restart the PCM
+	stream in the resume callback. It'll be restarted via 
+	trigger call with <constant>SNDRV_PCM_TRIGGER_RESUME</constant>
+	when necessary.
+    </para>
+
+    <para>
+      OK, we have all callbacks now. Let's set them up. In the
+      initialization of the card, make sure that you can get the chip
+      data from the card instance, typically via
+      <structfield>private_data</structfield> field, in case you
+      created the chip data individually.
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static int __devinit snd_mychip_probe(struct pci_dev *pci,
+                               const struct pci_device_id *pci_id)
+  {
+          ....
+          struct snd_card *card;
+          struct mychip *chip;
+          int err;
+          ....
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+          ....
+          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+          ....
+          card->private_data = chip;
+          ....
+  }
+]]>
+        </programlisting>
+      </informalexample>
+
+	When you created the chip data with
+	<function>snd_card_create()</function>, it's anyway accessible
+	via <structfield>private_data</structfield> field.
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static int __devinit snd_mychip_probe(struct pci_dev *pci,
+                               const struct pci_device_id *pci_id)
+  {
+          ....
+          struct snd_card *card;
+          struct mychip *chip;
+          int err;
+          ....
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                                sizeof(struct mychip), &card);
+          ....
+          chip = card->private_data;
+          ....
+  }
+]]>
+        </programlisting>
+      </informalexample>
+
+    </para>
+
+    <para>
+      If you need a space to save the registers, allocate the
+	buffer for it here, too, since it would be fatal
+    if you cannot allocate a memory in the suspend phase.
+    The allocated buffer should be released in the corresponding
+    destructor.
+    </para>
+
+    <para>
+      And next, set suspend/resume callbacks to the pci_driver.
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static struct pci_driver driver = {
+          .name = "My Chip",
+          .id_table = snd_my_ids,
+          .probe = snd_my_probe,
+          .remove = __devexit_p(snd_my_remove),
+  #ifdef CONFIG_PM
+          .suspend = snd_my_suspend,
+          .resume = snd_my_resume,
+  #endif
+  };
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Module Parameters  -->
+<!-- ****************************************************** -->
+  <chapter id="module-parameters">
+    <title>Module Parameters</title>
+    <para>
+      There are standard module options for ALSA. At least, each
+      module should have the <parameter>index</parameter>,
+      <parameter>id</parameter> and <parameter>enable</parameter>
+      options. 
+    </para>
+
+    <para>
+      If the module supports multiple cards (usually up to
+      8 = <constant>SNDRV_CARDS</constant> cards), they should be
+      arrays. The default initial values are defined already as
+      constants for easier programming:
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+  static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+      If the module supports only a single card, they could be single
+    variables, instead.  <parameter>enable</parameter> option is not
+    always necessary in this case, but it would be better to have a
+    dummy option for compatibility.
+    </para>
+
+    <para>
+      The module parameters must be declared with the standard
+    <function>module_param()()</function>,
+    <function>module_param_array()()</function> and
+    <function>MODULE_PARM_DESC()</function> macros.
+    </para>
+
+    <para>
+      The typical coding would be like below:
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  #define CARD_NAME "My Chip"
+
+  module_param_array(index, int, NULL, 0444);
+  MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
+  module_param_array(id, charp, NULL, 0444);
+  MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
+  module_param_array(enable, bool, NULL, 0444);
+  MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+    <para>
+      Also, don't forget to define the module description, classes,
+      license and devices. Especially, the recent modprobe requires to
+      define the module license as GPL, etc., otherwise the system is
+      shown as <quote>tainted</quote>. 
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  MODULE_DESCRIPTION("My Chip");
+  MODULE_LICENSE("GPL");
+  MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
+]]>
+        </programlisting>
+      </informalexample>
+    </para>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- How To Put Your Driver  -->
+<!-- ****************************************************** -->
+  <chapter id="how-to-put-your-driver">
+    <title>How To Put Your Driver Into ALSA Tree</title>
+	<section>
+	<title>General</title>
+	<para>
+	So far, you've learned how to write the driver codes.
+	And you might have a question now: how to put my own
+	driver into the ALSA driver tree?
+	Here (finally :) the standard procedure is described briefly.
+	</para>
+
+	<para>
+	Suppose that you create a new PCI driver for the card
+	<quote>xyz</quote>.  The card module name would be
+	snd-xyz.  The new driver is usually put into the alsa-driver
+	tree, <filename>alsa-driver/pci</filename> directory in
+	the case of PCI cards.
+	Then the driver is evaluated, audited and tested
+	by developers and users.  After a certain time, the driver
+	will go to the alsa-kernel tree (to the corresponding directory,
+	such as <filename>alsa-kernel/pci</filename>) and eventually
+ 	will be integrated into the Linux 2.6 tree (the directory would be
+	<filename>linux/sound/pci</filename>).
+	</para>
+
+	<para>
+	In the following sections, the driver code is supposed
+	to be put into alsa-driver tree. The two cases are covered:
+	a driver consisting of a single source file and one consisting
+	of several source files.
+	</para>
+	</section>
+
+	<section>
+	<title>Driver with A Single Source File</title>
+	<para>
+	<orderedlist>
+	<listitem>
+	<para>
+	Modify alsa-driver/pci/Makefile
+	</para>
+
+	<para>
+	Suppose you have a file xyz.c.  Add the following
+	two lines
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  snd-xyz-objs := xyz.o
+  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+]]>
+        </programlisting>
+      </informalexample>
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Create the Kconfig entry
+	</para>
+
+	<para>
+	Add the new entry of Kconfig for your xyz driver.
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  config SND_XYZ
+          tristate "Foobar XYZ"
+          depends on SND
+          select SND_PCM
+          help
+            Say Y here to include support for Foobar XYZ soundcard.
+
+            To compile this driver as a module, choose M here: the module
+            will be called snd-xyz.
+]]>
+        </programlisting>
+      </informalexample>
+
+	the line, select SND_PCM, specifies that the driver xyz supports
+	PCM.  In addition to SND_PCM, the following components are
+	supported for select command:
+	SND_RAWMIDI, SND_TIMER, SND_HWDEP, SND_MPU401_UART,
+	SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB, SND_AC97_CODEC.
+	Add the select command for each supported component.
+	</para>
+
+	<para>
+	Note that some selections imply the lowlevel selections.
+	For example, PCM includes TIMER, MPU401_UART includes RAWMIDI,
+	AC97_CODEC includes PCM, and OPL3_LIB includes HWDEP.
+	You don't need to give the lowlevel selections again.
+	</para>
+
+	<para>
+	For the details of Kconfig script, refer to the kbuild
+	documentation.
+	</para>
+
+	</listitem>
+
+	<listitem>
+	<para>
+	Run cvscompile script to re-generate the configure script and
+	build the whole stuff again.
+	</para>
+	</listitem>
+	</orderedlist>
+	</para>
+	</section>
+
+	<section>
+	<title>Drivers with Several Source Files</title>
+	<para>
+	Suppose that the driver snd-xyz have several source files.
+	They are located in the new subdirectory,
+	pci/xyz.
+
+	<orderedlist>
+	<listitem>
+	<para>
+	Add a new directory (<filename>xyz</filename>) in
+	<filename>alsa-driver/pci/Makefile</filename> as below
+
+      <informalexample>
+        <programlisting>
+<![CDATA[
+  obj-$(CONFIG_SND) += xyz/
+]]>
+        </programlisting>
+      </informalexample>
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Under the directory <filename>xyz</filename>, create a Makefile
+
+      <example>
+	<title>Sample Makefile for a driver xyz</title>
+        <programlisting>
+<![CDATA[
+  ifndef SND_TOPDIR
+  SND_TOPDIR=../..
+  endif
+
+  include $(SND_TOPDIR)/toplevel.config
+  include $(SND_TOPDIR)/Makefile.conf
+
+  snd-xyz-objs := xyz.o abc.o def.o
+
+  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+
+  include $(SND_TOPDIR)/Rules.make
+]]>
+        </programlisting>
+      </example>
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Create the Kconfig entry
+	</para>
+
+	<para>
+	This procedure is as same as in the last section.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Run cvscompile script to re-generate the configure script and
+	build the whole stuff again.
+	</para>
+	</listitem>
+	</orderedlist>
+	</para>
+	</section>
+
+  </chapter>
+
+<!-- ****************************************************** -->
+<!-- Useful Functions  -->
+<!-- ****************************************************** -->
+  <chapter id="useful-functions">
+    <title>Useful Functions</title>
+
+    <section id="useful-functions-snd-printk">
+      <title><function>snd_printk()</function> and friends</title>
+      <para>
+        ALSA provides a verbose version of the
+      <function>printk()</function> function. If a kernel config
+      <constant>CONFIG_SND_VERBOSE_PRINTK</constant> is set, this
+      function prints the given message together with the file name
+      and the line of the caller. The <constant>KERN_XXX</constant>
+      prefix is processed as 
+      well as the original <function>printk()</function> does, so it's
+      recommended to add this prefix, e.g. 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\n");
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+        There are also <function>printk()</function>'s for
+      debugging. <function>snd_printd()</function> can be used for
+      general debugging purposes. If
+      <constant>CONFIG_SND_DEBUG</constant> is set, this function is
+      compiled, and works just like
+      <function>snd_printk()</function>. If the ALSA is compiled
+      without the debugging flag, it's ignored. 
+      </para>
+
+      <para>
+        <function>snd_printdd()</function> is compiled in only when
+      <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is set. Please note
+      that <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is not set as default
+      even if you configure the alsa-driver with
+      <option>--with-debug=full</option> option. You need to give
+      explicitly <option>--with-debug=detect</option> option instead. 
+      </para>
+    </section>
+
+    <section id="useful-functions-snd-bug">
+      <title><function>snd_BUG()</function></title>
+      <para>
+        It shows the <computeroutput>BUG?</computeroutput> message and
+      stack trace as well as <function>snd_BUG_ON</function> at the point.
+      It's useful to show that a fatal error happens there. 
+      </para>
+      <para>
+	 When no debug flag is set, this macro is ignored. 
+      </para>
+    </section>
+
+    <section id="useful-functions-snd-bug-on">
+      <title><function>snd_BUG_ON()</function></title>
+      <para>
+        <function>snd_BUG_ON()</function> macro is similar with
+	<function>WARN_ON()</function> macro. For example,  
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_BUG_ON(!pointer);
+]]>
+          </programlisting>
+        </informalexample>
+
+	or it can be used as the condition,
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  if (snd_BUG_ON(non_zero_is_bug))
+          return -EINVAL;
+]]>
+          </programlisting>
+        </informalexample>
+
+      </para>
+
+      <para>
+        The macro takes an conditional expression to evaluate.
+	When <constant>CONFIG_SND_DEBUG</constant>, is set, the
+	expression is actually evaluated. If it's non-zero, it shows
+	the warning message such as
+	<computeroutput>BUG? (xxx)</computeroutput>
+	normally followed by stack trace.  It returns the evaluated
+	value.
+	When no <constant>CONFIG_SND_DEBUG</constant> is set, this
+	macro always returns zero.
+      </para>
+
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
+<!-- Acknowledgments  -->
+<!-- ****************************************************** -->
+  <chapter id="acknowledgments">
+    <title>Acknowledgments</title>
+    <para>
+      I would like to thank Phil Kerr for his help for improvement and
+      corrections of this document. 
+    </para>
+    <para>
+    Kevin Conder reformatted the original plain-text to the
+    DocBook format.
+    </para>
+    <para>
+    Giuliano Pochini corrected typos and contributed the example codes
+    in the hardware constraints section.
+    </para>
+  </chapter>
+</book>
diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
deleted file mode 100644
index 0230a96f056..00000000000
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<!-- ****************************************************** -->
-<!-- Header  -->
-<!-- ****************************************************** -->
-<book id="ALSA-Driver-API">
-  <bookinfo>
-    <title>The ALSA Driver API</title>
-
-    <legalnotice>
-    <para>
-    This document is free; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version. 
-    </para>
-
-    <para>
-    This document is distributed in the hope that it will be useful,
-    but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
-    implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
-    PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
-    for more details.
-    </para>
-
-    <para>
-    You should have received a copy of the GNU General Public
-    License along with this program; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-    MA 02111-1307 USA
-    </para>
-    </legalnotice>
-
-  </bookinfo>
-
-<toc></toc>
-
-  <chapter><title>Management of Cards and Devices</title>
-     <sect1><title>Card Management</title>
-!Esound/core/init.c
-     </sect1>
-     <sect1><title>Device Components</title>
-!Esound/core/device.c
-     </sect1>
-     <sect1><title>Module requests and Device File Entries</title>
-!Esound/core/sound.c
-     </sect1>
-     <sect1><title>Memory Management Helpers</title>
-!Esound/core/memory.c
-!Esound/core/memalloc.c
-     </sect1>
-  </chapter>
-  <chapter><title>PCM API</title>
-     <sect1><title>PCM Core</title>
-!Esound/core/pcm.c
-!Esound/core/pcm_lib.c
-!Esound/core/pcm_native.c
-     </sect1>
-     <sect1><title>PCM Format Helpers</title>
-!Esound/core/pcm_misc.c
-     </sect1>
-     <sect1><title>PCM Memory Management</title>
-!Esound/core/pcm_memory.c
-     </sect1>
-  </chapter>
-  <chapter><title>Control/Mixer API</title>
-     <sect1><title>General Control Interface</title>
-!Esound/core/control.c
-     </sect1>
-     <sect1><title>AC97 Codec API</title>
-!Esound/pci/ac97/ac97_codec.c
-!Esound/pci/ac97/ac97_pcm.c
-     </sect1>
-     <sect1><title>Virtual Master Control API</title>
-!Esound/core/vmaster.c
-!Iinclude/sound/control.h
-     </sect1>
-  </chapter>
-  <chapter><title>MIDI API</title>
-     <sect1><title>Raw MIDI API</title>
-!Esound/core/rawmidi.c
-     </sect1>
-     <sect1><title>MPU401-UART API</title>
-!Esound/drivers/mpu401/mpu401_uart.c
-     </sect1>
-  </chapter>
-  <chapter><title>Proc Info API</title>
-     <sect1><title>Proc Info Interface</title>
-!Esound/core/info.c
-     </sect1>
-  </chapter>
-  <chapter><title>Miscellaneous Functions</title>
-     <sect1><title>Hardware-Dependent Devices API</title>
-!Esound/core/hwdep.c
-     </sect1>
-     <sect1><title>Jack Abstraction Layer API</title>
-!Esound/core/jack.c
-     </sect1>
-     <sect1><title>ISA DMA Helpers</title>
-!Esound/core/isadma.c
-     </sect1>
-     <sect1><title>Other Helper Macros</title>
-!Iinclude/sound/core.h
-     </sect1>
-  </chapter>
-
-</book>
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
deleted file mode 100644
index 46b08fef374..00000000000
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ /dev/null
@@ -1,6216 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<!-- ****************************************************** -->
-<!-- Header  -->
-<!-- ****************************************************** -->
-<book id="Writing-an-ALSA-Driver">
-  <bookinfo>
-    <title>Writing an ALSA Driver</title>
-    <author>
-      <firstname>Takashi</firstname>
-      <surname>Iwai</surname>
-      <affiliation>
-        <address>
-          <email>tiwai@suse.de</email>
-        </address>
-      </affiliation>
-     </author>
-
-     <date>Oct 15, 2007</date>
-     <edition>0.3.7</edition>
-
-    <abstract>
-      <para>
-        This document describes how to write an ALSA (Advanced Linux
-        Sound Architecture) driver.
-      </para>
-    </abstract>
-
-    <legalnotice>
-    <para>
-    Copyright (c) 2002-2005  Takashi Iwai <email>tiwai@suse.de</email>
-    </para>
-
-    <para>
-    This document is free; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version. 
-    </para>
-
-    <para>
-    This document is distributed in the hope that it will be useful,
-    but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
-    implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
-    PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
-    for more details.
-    </para>
-
-    <para>
-    You should have received a copy of the GNU General Public
-    License along with this program; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-    MA 02111-1307 USA
-    </para>
-    </legalnotice>
-
-  </bookinfo>
-
-<!-- ****************************************************** -->
-<!-- Preface  -->
-<!-- ****************************************************** -->
-  <preface id="preface">
-    <title>Preface</title>
-    <para>
-      This document describes how to write an
-      <ulink url="http://www.alsa-project.org/"><citetitle>
-      ALSA (Advanced Linux Sound Architecture)</citetitle></ulink>
-      driver. The document focuses mainly on PCI soundcards.
-      In the case of other device types, the API might
-      be different, too. However, at least the ALSA kernel API is
-      consistent, and therefore it would be still a bit help for
-      writing them.
-    </para>
-
-    <para>
-    This document targets people who already have enough
-    C language skills and have basic linux kernel programming
-    knowledge.  This document doesn't explain the general
-    topic of linux kernel coding and doesn't cover low-level
-    driver implementation details. It only describes
-    the standard way to write a PCI sound driver on ALSA.
-    </para>
-
-    <para>
-      If you are already familiar with the older ALSA ver.0.5.x API, you
-    can check the drivers such as <filename>sound/pci/es1938.c</filename> or
-    <filename>sound/pci/maestro3.c</filename> which have also almost the same
-    code-base in the ALSA 0.5.x tree, so you can compare the differences.
-    </para>
-
-    <para>
-      This document is still a draft version. Any feedback and
-    corrections, please!!
-    </para>
-  </preface>
-
-
-<!-- ****************************************************** -->
-<!-- File Tree Structure  -->
-<!-- ****************************************************** -->
-  <chapter id="file-tree">
-    <title>File Tree Structure</title>
-
-    <section id="file-tree-general">
-      <title>General</title>
-      <para>
-        The ALSA drivers are provided in two ways.
-      </para>
-
-      <para>
-        One is the trees provided as a tarball or via cvs from the
-      ALSA's ftp site, and another is the 2.6 (or later) Linux kernel
-      tree. To synchronize both, the ALSA driver tree is split into
-      two different trees: alsa-kernel and alsa-driver. The former
-      contains purely the source code for the Linux 2.6 (or later)
-      tree. This tree is designed only for compilation on 2.6 or
-      later environment. The latter, alsa-driver, contains many subtle
-      files for compiling ALSA drivers outside of the Linux kernel tree,
-      wrapper functions for older 2.2 and 2.4 kernels, to adapt the latest kernel API,
-      and additional drivers which are still in development or in
-      tests.  The drivers in alsa-driver tree will be moved to
-      alsa-kernel (and eventually to the 2.6 kernel tree) when they are
-      finished and confirmed to work fine.
-      </para>
-
-      <para>
-        The file tree structure of ALSA driver is depicted below. Both
-        alsa-kernel and alsa-driver have almost the same file
-        structure, except for <quote>core</quote> directory. It's
-        named as <quote>acore</quote> in alsa-driver tree. 
-
-        <example>
-          <title>ALSA File Tree Structure</title>
-          <literallayout>
-        sound
-                /core
-                        /oss
-                        /seq
-                                /oss
-                                /instr
-                /ioctl32
-                /include
-                /drivers
-                        /mpu401
-                        /opl3
-                /i2c
-                        /l3
-                /synth
-                        /emux
-                /pci
-                        /(cards)
-                /isa
-                        /(cards)
-                /arm
-                /ppc
-                /sparc
-                /usb
-                /pcmcia /(cards)
-                /oss
-          </literallayout>
-        </example>
-      </para>
-    </section>
-
-    <section id="file-tree-core-directory">
-      <title>core directory</title>
-      <para>
-        This directory contains the middle layer which is the heart
-      of ALSA drivers. In this directory, the native ALSA modules are
-      stored. The sub-directories contain different modules and are
-      dependent upon the kernel config. 
-      </para>
-
-      <section id="file-tree-core-directory-oss">
-        <title>core/oss</title>
-
-        <para>
-          The codes for PCM and mixer OSS emulation modules are stored
-        in this directory. The rawmidi OSS emulation is included in
-        the ALSA rawmidi code since it's quite small. The sequencer
-        code is stored in <filename>core/seq/oss</filename> directory (see
-        <link linkend="file-tree-core-directory-seq-oss"><citetitle>
-        below</citetitle></link>).
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-ioctl32">
-        <title>core/ioctl32</title>
-
-        <para>
-          This directory contains the 32bit-ioctl wrappers for 64bit
-        architectures such like x86-64, ppc64 and sparc64. For 32bit
-        and alpha architectures, these are not compiled. 
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-seq">
-        <title>core/seq</title>
-        <para>
-          This directory and its sub-directories are for the ALSA
-        sequencer. This directory contains the sequencer core and
-        primary sequencer modules such like snd-seq-midi,
-        snd-seq-virmidi, etc. They are compiled only when
-        <constant>CONFIG_SND_SEQUENCER</constant> is set in the kernel
-        config. 
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-seq-oss">
-        <title>core/seq/oss</title>
-        <para>
-          This contains the OSS sequencer emulation codes.
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-deq-instr">
-        <title>core/seq/instr</title>
-        <para>
-          This directory contains the modules for the sequencer
-        instrument layer. 
-        </para>
-      </section>
-    </section>
-
-    <section id="file-tree-include-directory">
-      <title>include directory</title>
-      <para>
-        This is the place for the public header files of ALSA drivers,
-      which are to be exported to user-space, or included by
-      several files at different directories. Basically, the private
-      header files should not be placed in this directory, but you may
-      still find files there, due to historical reasons :) 
-      </para>
-    </section>
-
-    <section id="file-tree-drivers-directory">
-      <title>drivers directory</title>
-      <para>
-        This directory contains code shared among different drivers
-      on different architectures.  They are hence supposed not to be
-      architecture-specific.
-      For example, the dummy pcm driver and the serial MIDI
-      driver are found in this directory. In the sub-directories,
-      there is code for components which are independent from
-      bus and cpu architectures. 
-      </para>
-
-      <section id="file-tree-drivers-directory-mpu401">
-        <title>drivers/mpu401</title>
-        <para>
-          The MPU401 and MPU401-UART modules are stored here.
-        </para>
-      </section>
-
-      <section id="file-tree-drivers-directory-opl3">
-        <title>drivers/opl3 and opl4</title>
-        <para>
-          The OPL3 and OPL4 FM-synth stuff is found here.
-        </para>
-      </section>
-    </section>
-
-    <section id="file-tree-i2c-directory">
-      <title>i2c directory</title>
-      <para>
-        This contains the ALSA i2c components.
-      </para>
-
-      <para>
-        Although there is a standard i2c layer on Linux, ALSA has its
-      own i2c code for some cards, because the soundcard needs only a
-      simple operation and the standard i2c API is too complicated for
-      such a purpose. 
-      </para>
-
-      <section id="file-tree-i2c-directory-l3">
-        <title>i2c/l3</title>
-        <para>
-          This is a sub-directory for ARM L3 i2c.
-        </para>
-      </section>
-    </section>
-
-    <section id="file-tree-synth-directory">
-        <title>synth directory</title>
-        <para>
-          This contains the synth middle-level modules.
-        </para>
-
-        <para>
-          So far, there is only Emu8000/Emu10k1 synth driver under
-        the <filename>synth/emux</filename> sub-directory. 
-        </para>
-    </section>
-
-    <section id="file-tree-pci-directory">
-      <title>pci directory</title>
-      <para>
-        This directory and its sub-directories hold the top-level card modules
-      for PCI soundcards and the code specific to the PCI BUS.
-      </para>
-
-      <para>
-        The drivers compiled from a single file are stored directly
-      in the pci directory, while the drivers with several source files are
-      stored on their own sub-directory (e.g. emu10k1, ice1712). 
-      </para>
-    </section>
-
-    <section id="file-tree-isa-directory">
-      <title>isa directory</title>
-      <para>
-        This directory and its sub-directories hold the top-level card modules
-      for ISA soundcards. 
-      </para>
-    </section>
-
-    <section id="file-tree-arm-ppc-sparc-directories">
-      <title>arm, ppc, and sparc directories</title>
-      <para>
-        They are used for top-level card modules which are
-      specific to one of these architectures. 
-      </para>
-    </section>
-
-    <section id="file-tree-usb-directory">
-      <title>usb directory</title>
-      <para>
-        This directory contains the USB-audio driver. In the latest version, the
-      USB MIDI driver is integrated in the usb-audio driver. 
-      </para>
-    </section>
-
-    <section id="file-tree-pcmcia-directory">
-      <title>pcmcia directory</title>
-      <para>
-        The PCMCIA, especially PCCard drivers will go here. CardBus
-      drivers will be in the pci directory, because their API is identical
-      to that of standard PCI cards. 
-      </para>
-    </section>
-
-    <section id="file-tree-oss-directory">
-      <title>oss directory</title>
-      <para>
-        The OSS/Lite source files are stored here in Linux 2.6 (or
-      later) tree. In the ALSA driver tarball, this directory is empty,
-      of course :) 
-      </para>
-    </section>
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Basic Flow for PCI Drivers  -->
-<!-- ****************************************************** -->
-  <chapter id="basic-flow">
-    <title>Basic Flow for PCI Drivers</title>
-
-    <section id="basic-flow-outline">
-      <title>Outline</title>
-      <para>
-        The minimum flow for PCI soundcards is as follows:
-
-        <itemizedlist>
-          <listitem><para>define the PCI ID table (see the section
-          <link linkend="pci-resource-entries"><citetitle>PCI Entries
-          </citetitle></link>).</para></listitem> 
-          <listitem><para>create <function>probe()</function> callback.</para></listitem>
-          <listitem><para>create <function>remove()</function> callback.</para></listitem>
-          <listitem><para>create a <structname>pci_driver</structname> structure
-	  containing the three pointers above.</para></listitem>
-          <listitem><para>create an <function>init()</function> function just calling
-	  the <function>pci_register_driver()</function> to register the pci_driver table
-	  defined above.</para></listitem>
-          <listitem><para>create an <function>exit()</function> function to call
-	  the <function>pci_unregister_driver()</function> function.</para></listitem>
-        </itemizedlist>
-      </para>
-    </section>
-
-    <section id="basic-flow-example">
-      <title>Full Code Example</title>
-      <para>
-        The code example is shown below. Some parts are kept
-      unimplemented at this moment but will be filled in the
-      next sections. The numbers in the comment lines of the
-      <function>snd_mychip_probe()</function> function
-      refer to details explained in the following section. 
-
-        <example>
-          <title>Basic Flow for PCI Drivers - Example</title>
-          <programlisting>
-<![CDATA[
-  #include <linux/init.h>
-  #include <linux/pci.h>
-  #include <linux/slab.h>
-  #include <sound/core.h>
-  #include <sound/initval.h>
-
-  /* module parameters (see "Module Parameters") */
-  /* SNDRV_CARDS: maximum number of cards supported by this module */
-  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-  static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-
-  /* definition of the chip-specific record */
-  struct mychip {
-          struct snd_card *card;
-          /* the rest of the implementation will be in section
-           * "PCI Resource Management"
-           */
-  };
-
-  /* chip-specific destructor
-   * (see "PCI Resource Management")
-   */
-  static int snd_mychip_free(struct mychip *chip)
-  {
-          .... /* will be implemented later... */
-  }
-
-  /* component-destructor
-   * (see "Management of Cards and Components")
-   */
-  static int snd_mychip_dev_free(struct snd_device *device)
-  {
-          return snd_mychip_free(device->device_data);
-  }
-
-  /* chip-specific constructor
-   * (see "Management of Cards and Components")
-   */
-  static int __devinit snd_mychip_create(struct snd_card *card,
-                                         struct pci_dev *pci,
-                                         struct mychip **rchip)
-  {
-          struct mychip *chip;
-          int err;
-          static struct snd_device_ops ops = {
-                 .dev_free = snd_mychip_dev_free,
-          };
-
-          *rchip = NULL;
-
-          /* check PCI availability here
-           * (see "PCI Resource Management")
-           */
-          ....
-
-          /* allocate a chip-specific data with zero filled */
-          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-          if (chip == NULL)
-                  return -ENOMEM;
-
-          chip->card = card;
-
-          /* rest of initialization here; will be implemented
-           * later, see "PCI Resource Management"
-           */
-          ....
-
-          err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-          if (err < 0) {
-                  snd_mychip_free(chip);
-                  return err;
-          }
-
-          snd_card_set_dev(card, &pci->dev);
-
-          *rchip = chip;
-          return 0;
-  }
-
-  /* constructor -- see "Constructor" sub-section */
-  static int __devinit snd_mychip_probe(struct pci_dev *pci,
-                               const struct pci_device_id *pci_id)
-  {
-          static int dev;
-          struct snd_card *card;
-          struct mychip *chip;
-          int err;
-
-          /* (1) */
-          if (dev >= SNDRV_CARDS)
-                  return -ENODEV;
-          if (!enable[dev]) {
-                  dev++;
-                  return -ENOENT;
-          }
-
-          /* (2) */
-          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
-          if (err < 0)
-                  return err;
-
-          /* (3) */
-          err = snd_mychip_create(card, pci, &chip);
-          if (err < 0) {
-                  snd_card_free(card);
-                  return err;
-          }
-
-          /* (4) */
-          strcpy(card->driver, "My Chip");
-          strcpy(card->shortname, "My Own Chip 123");
-          sprintf(card->longname, "%s at 0x%lx irq %i",
-                  card->shortname, chip->ioport, chip->irq);
-
-          /* (5) */
-          .... /* implemented later */
-
-          /* (6) */
-          err = snd_card_register(card);
-          if (err < 0) {
-                  snd_card_free(card);
-                  return err;
-          }
-
-          /* (7) */
-          pci_set_drvdata(pci, card);
-          dev++;
-          return 0;
-  }
-
-  /* destructor -- see the "Destructor" sub-section */
-  static void __devexit snd_mychip_remove(struct pci_dev *pci)
-  {
-          snd_card_free(pci_get_drvdata(pci));
-          pci_set_drvdata(pci, NULL);
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="basic-flow-constructor">
-      <title>Constructor</title>
-      <para>
-        The real constructor of PCI drivers is the <function>probe</function> callback.
-      The <function>probe</function> callback and other component-constructors which are called
-      from the <function>probe</function> callback should be defined with
-      the <parameter>__devinit</parameter> prefix. You 
-      cannot use the <parameter>__init</parameter> prefix for them,
-      because any PCI device could be a hotplug device. 
-      </para>
-
-      <para>
-        In the <function>probe</function> callback, the following scheme is often used.
-      </para>
-
-      <section id="basic-flow-constructor-device-index">
-        <title>1) Check and increment the device index.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int dev;
-  ....
-  if (dev >= SNDRV_CARDS)
-          return -ENODEV;
-  if (!enable[dev]) {
-          dev++;
-          return -ENOENT;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-        where enable[dev] is the module option.
-        </para>
-
-        <para>
-          Each time the <function>probe</function> callback is called, check the
-        availability of the device. If not available, simply increment
-        the device index and returns. dev will be incremented also
-        later (<link
-        linkend="basic-flow-constructor-set-pci"><citetitle>step
-        7</citetitle></link>). 
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-create-card">
-        <title>2) Create a card instance</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct snd_card *card;
-  int err;
-  ....
-  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          The details will be explained in the section
-          <link linkend="card-management-card-instance"><citetitle>
-          Management of Cards and Components</citetitle></link>.
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-create-main">
-        <title>3) Create a main component</title>
-        <para>
-          In this part, the PCI resources are allocated.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct mychip *chip;
-  ....
-  err = snd_mychip_create(card, pci, &chip);
-  if (err < 0) {
-          snd_card_free(card);
-          return err;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-          The details will be explained in the section <link
-        linkend="pci-resource"><citetitle>PCI Resource
-        Management</citetitle></link>.
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-main-component">
-        <title>4) Set the driver ID and name strings.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  strcpy(card->driver, "My Chip");
-  strcpy(card->shortname, "My Own Chip 123");
-  sprintf(card->longname, "%s at 0x%lx irq %i",
-          card->shortname, chip->ioport, chip->irq);
-]]>
-            </programlisting>
-          </informalexample>
-
-          The driver field holds the minimal ID string of the
-        chip. This is used by alsa-lib's configurator, so keep it
-        simple but unique. 
-          Even the same driver can have different driver IDs to
-        distinguish the functionality of each chip type. 
-        </para>
-
-        <para>
-          The shortname field is a string shown as more verbose
-        name. The longname field contains the information
-        shown in <filename>/proc/asound/cards</filename>. 
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-create-other">
-        <title>5) Create other components, such as mixer, MIDI, etc.</title>
-        <para>
-          Here you define the basic components such as
-          <link linkend="pcm-interface"><citetitle>PCM</citetitle></link>,
-          mixer (e.g. <link linkend="api-ac97"><citetitle>AC97</citetitle></link>),
-          MIDI (e.g. <link linkend="midi-interface"><citetitle>MPU-401</citetitle></link>),
-          and other interfaces.
-          Also, if you want a <link linkend="proc-interface"><citetitle>proc
-        file</citetitle></link>, define it here, too.
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-register-card">
-        <title>6) Register the card instance.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  err = snd_card_register(card);
-  if (err < 0) {
-          snd_card_free(card);
-          return err;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          Will be explained in the section <link
-        linkend="card-management-registration"><citetitle>Management
-        of Cards and Components</citetitle></link>, too. 
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-set-pci">
-        <title>7) Set the PCI driver data and return zero.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-        pci_set_drvdata(pci, card);
-        dev++;
-        return 0;
-]]>
-            </programlisting>
-          </informalexample>
-
-          In the above, the card record is stored. This pointer is
-        used in the remove callback and power-management
-        callbacks, too. 
-        </para>
-      </section>
-    </section>
-
-    <section id="basic-flow-destructor">
-      <title>Destructor</title>
-      <para>
-        The destructor, remove callback, simply releases the card
-      instance. Then the ALSA middle layer will release all the
-      attached components automatically. 
-      </para>
-
-      <para>
-        It would be typically like the following:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void __devexit snd_mychip_remove(struct pci_dev *pci)
-  {
-          snd_card_free(pci_get_drvdata(pci));
-          pci_set_drvdata(pci, NULL);
-  }
-]]>
-          </programlisting>
-        </informalexample>
-
-        The above code assumes that the card pointer is set to the PCI
-	driver data.
-      </para>
-    </section>
-
-    <section id="basic-flow-header-files">
-      <title>Header Files</title>
-      <para>
-        For the above example, at least the following include files
-      are necessary. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  #include <linux/init.h>
-  #include <linux/pci.h>
-  #include <linux/slab.h>
-  #include <sound/core.h>
-  #include <sound/initval.h>
-]]>
-          </programlisting>
-        </informalexample>
-
-	where the last one is necessary only when module options are
-      defined in the source file.  If the code is split into several
-      files, the files without module options don't need them.
-      </para>
-
-      <para>
-        In addition to these headers, you'll need
-      <filename>&lt;linux/interrupt.h&gt;</filename> for interrupt
-      handling, and <filename>&lt;asm/io.h&gt;</filename> for I/O
-      access. If you use the <function>mdelay()</function> or
-      <function>udelay()</function> functions, you'll need to include
-      <filename>&lt;linux/delay.h&gt;</filename> too. 
-      </para>
-
-      <para>
-      The ALSA interfaces like the PCM and control APIs are defined in other
-      <filename>&lt;sound/xxx.h&gt;</filename> header files.
-      They have to be included after
-      <filename>&lt;sound/core.h&gt;</filename>.
-      </para>
-
-    </section>
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Management of Cards and Components  -->
-<!-- ****************************************************** -->
-  <chapter id="card-management">
-    <title>Management of Cards and Components</title>
-
-    <section id="card-management-card-instance">
-      <title>Card Instance</title>
-      <para>
-      For each soundcard, a <quote>card</quote> record must be allocated.
-      </para>
-
-      <para>
-      A card record is the headquarters of the soundcard.  It manages
-      the whole list of devices (components) on the soundcard, such as
-      PCM, mixers, MIDI, synthesizer, and so on.  Also, the card
-      record holds the ID and the name strings of the card, manages
-      the root of proc files, and controls the power-management states
-      and hotplug disconnections.  The component list on the card
-      record is used to manage the correct release of resources at
-      destruction. 
-      </para>
-
-      <para>
-        As mentioned above, to create a card instance, call
-      <function>snd_card_create()</function>.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_card *card;
-  int err;
-  err = snd_card_create(index, id, module, extra_size, &card);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The function takes five arguments, the card-index number, the
-        id string, the module pointer (usually
-        <constant>THIS_MODULE</constant>),
-        the size of extra-data space, and the pointer to return the
-        card instance.  The extra_size argument is used to
-        allocate card-&gt;private_data for the
-        chip-specific data.  Note that these data
-        are allocated by <function>snd_card_create()</function>.
-      </para>
-    </section>
-
-    <section id="card-management-component">
-      <title>Components</title>
-      <para>
-        After the card is created, you can attach the components
-      (devices) to the card instance. In an ALSA driver, a component is
-      represented as a struct <structname>snd_device</structname> object.
-      A component can be a PCM instance, a control interface, a raw
-      MIDI interface, etc.  Each such instance has one component
-      entry.
-      </para>
-
-      <para>
-        A component can be created via
-        <function>snd_device_new()</function> function. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        This takes the card pointer, the device-level
-      (<constant>SNDRV_DEV_XXX</constant>), the data pointer, and the
-      callback pointers (<parameter>&amp;ops</parameter>). The
-      device-level defines the type of components and the order of
-      registration and de-registration.  For most components, the
-      device-level is already defined.  For a user-defined component,
-      you can use <constant>SNDRV_DEV_LOWLEVEL</constant>.
-      </para>
-
-      <para>
-      This function itself doesn't allocate the data space. The data
-      must be allocated manually beforehand, and its pointer is passed
-      as the argument. This pointer is used as the
-      (<parameter>chip</parameter> identifier in the above example)
-      for the instance. 
-      </para>
-
-      <para>
-        Each pre-defined ALSA component such as ac97 and pcm calls
-      <function>snd_device_new()</function> inside its
-      constructor. The destructor for each component is defined in the
-      callback pointers.  Hence, you don't need to take care of
-      calling a destructor for such a component.
-      </para>
-
-      <para>
-        If you wish to create your own component, you need to
-      set the destructor function to the dev_free callback in
-      the <parameter>ops</parameter>, so that it can be released
-      automatically via <function>snd_card_free()</function>.
-      The next example will show an implementation of chip-specific
-      data.
-      </para>
-    </section>
-
-    <section id="card-management-chip-specific">
-      <title>Chip-Specific Data</title>
-      <para>
-      Chip-specific information, e.g. the I/O port address, its
-      resource pointer, or the irq number, is stored in the
-      chip-specific record.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          ....
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        In general, there are two ways of allocating the chip record.
-      </para>
-
-      <section id="card-management-chip-specific-snd-card-new">
-        <title>1. Allocating via <function>snd_card_create()</function>.</title>
-        <para>
-          As mentioned above, you can pass the extra-data-length
-	  to the 4th argument of <function>snd_card_create()</function>, i.e.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  err = snd_card_create(index[dev], id[dev], THIS_MODULE,
-                        sizeof(struct mychip), &card);
-]]>
-            </programlisting>
-          </informalexample>
-
-          struct <structname>mychip</structname> is the type of the chip record.
-        </para>
-
-        <para>
-          In return, the allocated record can be accessed as
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct mychip *chip = card->private_data;
-]]>
-            </programlisting>
-          </informalexample>
-
-          With this method, you don't have to allocate twice.
-          The record is released together with the card instance.
-        </para>
-      </section>
-
-      <section id="card-management-chip-specific-allocate-extra">
-        <title>2. Allocating an extra device.</title>
-
-        <para>
-          After allocating a card instance via
-          <function>snd_card_create()</function> (with
-          <constant>0</constant> on the 4th arg), call
-          <function>kzalloc()</function>. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct snd_card *card;
-  struct mychip *chip;
-  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
-  .....
-  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          The chip record should have the field to hold the card
-          pointer at least, 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct mychip {
-          struct snd_card *card;
-          ....
-  };
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          Then, set the card pointer in the returned chip instance.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  chip->card = card;
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          Next, initialize the fields, and register this chip
-          record as a low-level device with a specified
-          <parameter>ops</parameter>, 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static struct snd_device_ops ops = {
-          .dev_free =        snd_mychip_dev_free,
-  };
-  ....
-  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-]]>
-            </programlisting>
-          </informalexample>
-
-          <function>snd_mychip_dev_free()</function> is the
-        device-destructor function, which will call the real
-        destructor. 
-        </para>
-
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_mychip_dev_free(struct snd_device *device)
-  {
-          return snd_mychip_free(device->device_data);
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-          where <function>snd_mychip_free()</function> is the real destructor.
-        </para>
-      </section>
-    </section>
-
-    <section id="card-management-registration">
-      <title>Registration and Release</title>
-      <para>
-        After all components are assigned, register the card instance
-      by calling <function>snd_card_register()</function>. Access
-      to the device files is enabled at this point. That is, before
-      <function>snd_card_register()</function> is called, the
-      components are safely inaccessible from external side. If this
-      call fails, exit the probe function after releasing the card via
-      <function>snd_card_free()</function>. 
-      </para>
-
-      <para>
-        For releasing the card instance, you can call simply
-      <function>snd_card_free()</function>. As mentioned earlier, all
-      components are released automatically by this call. 
-      </para>
-
-      <para>
-        As further notes, the destructors (both
-      <function>snd_mychip_dev_free</function> and
-      <function>snd_mychip_free</function>) cannot be defined with
-      the <parameter>__devexit</parameter> prefix, because they may be
-      called from the constructor, too, at the false path. 
-      </para>
-
-      <para>
-      For a device which allows hotplugging, you can use
-      <function>snd_card_free_when_closed</function>.  This one will
-      postpone the destruction until all devices are closed.
-      </para>
-
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- PCI Resource Management  -->
-<!-- ****************************************************** -->
-  <chapter id="pci-resource">
-    <title>PCI Resource Management</title>
-
-    <section id="pci-resource-example">
-      <title>Full Code Example</title>
-      <para>
-        In this section, we'll complete the chip-specific constructor,
-      destructor and PCI entries. Example code is shown first,
-      below. 
-
-        <example>
-          <title>PCI Resource Management Example</title>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          struct snd_card *card;
-          struct pci_dev *pci;
-
-          unsigned long port;
-          int irq;
-  };
-
-  static int snd_mychip_free(struct mychip *chip)
-  {
-          /* disable hardware here if any */
-          .... /* (not implemented in this document) */
-
-          /* release the irq */
-          if (chip->irq >= 0)
-                  free_irq(chip->irq, chip);
-          /* release the I/O ports & memory */
-          pci_release_regions(chip->pci);
-          /* disable the PCI entry */
-          pci_disable_device(chip->pci);
-          /* release the data */
-          kfree(chip);
-          return 0;
-  }
-
-  /* chip-specific constructor */
-  static int __devinit snd_mychip_create(struct snd_card *card,
-                                         struct pci_dev *pci,
-                                         struct mychip **rchip)
-  {
-          struct mychip *chip;
-          int err;
-          static struct snd_device_ops ops = {
-                 .dev_free = snd_mychip_dev_free,
-          };
-
-          *rchip = NULL;
-
-          /* initialize the PCI entry */
-          err = pci_enable_device(pci);
-          if (err < 0)
-                  return err;
-          /* check PCI availability (28bit DMA) */
-          if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
-              pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
-                  printk(KERN_ERR "error to set 28bit mask DMA\n");
-                  pci_disable_device(pci);
-                  return -ENXIO;
-          }
-
-          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-          if (chip == NULL) {
-                  pci_disable_device(pci);
-                  return -ENOMEM;
-          }
-
-          /* initialize the stuff */
-          chip->card = card;
-          chip->pci = pci;
-          chip->irq = -1;
-
-          /* (1) PCI resource allocation */
-          err = pci_request_regions(pci, "My Chip");
-          if (err < 0) {
-                  kfree(chip);
-                  pci_disable_device(pci);
-                  return err;
-          }
-          chip->port = pci_resource_start(pci, 0);
-          if (request_irq(pci->irq, snd_mychip_interrupt,
-                          IRQF_SHARED, "My Chip", chip)) {
-                  printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
-                  snd_mychip_free(chip);
-                  return -EBUSY;
-          }
-          chip->irq = pci->irq;
-
-          /* (2) initialization of the chip hardware */
-          .... /*   (not implemented in this document) */
-
-          err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-          if (err < 0) {
-                  snd_mychip_free(chip);
-                  return err;
-          }
-
-          snd_card_set_dev(card, &pci->dev);
-
-          *rchip = chip;
-          return 0;
-  }        
-
-  /* PCI IDs */
-  static struct pci_device_id snd_mychip_ids[] = {
-          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
-            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-          ....
-          { 0, }
-  };
-  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
-
-  /* pci_driver definition */
-  static struct pci_driver driver = {
-          .name = "My Own Chip",
-          .id_table = snd_mychip_ids,
-          .probe = snd_mychip_probe,
-          .remove = __devexit_p(snd_mychip_remove),
-  };
-
-  /* module initialization */
-  static int __init alsa_card_mychip_init(void)
-  {
-          return pci_register_driver(&driver);
-  }
-
-  /* module clean up */
-  static void __exit alsa_card_mychip_exit(void)
-  {
-          pci_unregister_driver(&driver);
-  }
-
-  module_init(alsa_card_mychip_init)
-  module_exit(alsa_card_mychip_exit)
-
-  EXPORT_NO_SYMBOLS; /* for old kernels only */
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="pci-resource-some-haftas">
-      <title>Some Hafta's</title>
-      <para>
-        The allocation of PCI resources is done in the
-      <function>probe()</function> function, and usually an extra
-      <function>xxx_create()</function> function is written for this
-      purpose.
-      </para>
-
-      <para>
-        In the case of PCI devices, you first have to call
-      the <function>pci_enable_device()</function> function before
-      allocating resources. Also, you need to set the proper PCI DMA
-      mask to limit the accessed I/O range. In some cases, you might
-      need to call <function>pci_set_master()</function> function,
-      too.
-      </para>
-
-      <para>
-        Suppose the 28bit mask, and the code to be added would be like:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  err = pci_enable_device(pci);
-  if (err < 0)
-          return err;
-  if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
-      pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
-          printk(KERN_ERR "error to set 28bit mask DMA\n");
-          pci_disable_device(pci);
-          return -ENXIO;
-  }
-  
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-    <section id="pci-resource-resource-allocation">
-      <title>Resource Allocation</title>
-      <para>
-        The allocation of I/O ports and irqs is done via standard kernel
-      functions. Unlike ALSA ver.0.5.x., there are no helpers for
-      that. And these resources must be released in the destructor
-      function (see below). Also, on ALSA 0.9.x, you don't need to
-      allocate (pseudo-)DMA for PCI like in ALSA 0.5.x.
-      </para>
-
-      <para>
-        Now assume that the PCI device has an I/O port with 8 bytes
-        and an interrupt. Then struct <structname>mychip</structname> will have the
-        following fields:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          struct snd_card *card;
-
-          unsigned long port;
-          int irq;
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        For an I/O port (and also a memory region), you need to have
-      the resource pointer for the standard resource management. For
-      an irq, you have to keep only the irq number (integer). But you
-      need to initialize this number as -1 before actual allocation,
-      since irq 0 is valid. The port address and its resource pointer
-      can be initialized as null by
-      <function>kzalloc()</function> automatically, so you
-      don't have to take care of resetting them. 
-      </para>
-
-      <para>
-        The allocation of an I/O port is done like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  err = pci_request_regions(pci, "My Chip");
-  if (err < 0) { 
-          kfree(chip);
-          pci_disable_device(pci);
-          return err;
-  }
-  chip->port = pci_resource_start(pci, 0);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        <!-- obsolete -->
-        It will reserve the I/O port region of 8 bytes of the given
-      PCI device. The returned value, chip-&gt;res_port, is allocated
-      via <function>kmalloc()</function> by
-      <function>request_region()</function>. The pointer must be
-      released via <function>kfree()</function>, but there is a
-      problem with this. This issue will be explained later.
-      </para>
-
-      <para>
-        The allocation of an interrupt source is done like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (request_irq(pci->irq, snd_mychip_interrupt,
-                  IRQF_SHARED, "My Chip", chip)) {
-          printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
-          snd_mychip_free(chip);
-          return -EBUSY;
-  }
-  chip->irq = pci->irq;
-]]>
-          </programlisting>
-        </informalexample>
-
-        where <function>snd_mychip_interrupt()</function> is the
-      interrupt handler defined <link
-      linkend="pcm-interface-interrupt-handler"><citetitle>later</citetitle></link>.
-      Note that chip-&gt;irq should be defined
-      only when <function>request_irq()</function> succeeded.
-      </para>
-
-      <para>
-      On the PCI bus, interrupts can be shared. Thus,
-      <constant>IRQF_SHARED</constant> is used as the interrupt flag of
-      <function>request_irq()</function>. 
-      </para>
-
-      <para>
-        The last argument of <function>request_irq()</function> is the
-      data pointer passed to the interrupt handler. Usually, the
-      chip-specific record is used for that, but you can use what you
-      like, too. 
-      </para>
-
-      <para>
-        I won't give details about the interrupt handler at this
-        point, but at least its appearance can be explained now. The
-        interrupt handler looks usually like the following: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
-  {
-          struct mychip *chip = dev_id;
-          ....
-          return IRQ_HANDLED;
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Now let's write the corresponding destructor for the resources
-      above. The role of destructor is simple: disable the hardware
-      (if already activated) and release the resources. So far, we
-      have no hardware part, so the disabling code is not written here. 
-      </para>
-
-      <para>
-        To release the resources, the <quote>check-and-release</quote>
-        method is a safer way. For the interrupt, do like this: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (chip->irq >= 0)
-          free_irq(chip->irq, chip);
-]]>
-          </programlisting>
-        </informalexample>
-
-        Since the irq number can start from 0, you should initialize
-        chip-&gt;irq with a negative value (e.g. -1), so that you can
-        check the validity of the irq number as above.
-      </para>
-
-      <para>
-        When you requested I/O ports or memory regions via
-	<function>pci_request_region()</function> or
-	<function>pci_request_regions()</function> like in this example,
-	release the resource(s) using the corresponding function,
-	<function>pci_release_region()</function> or
-	<function>pci_release_regions()</function>.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  pci_release_regions(chip->pci);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-	When you requested manually via <function>request_region()</function>
-	or <function>request_mem_region</function>, you can release it via
-	<function>release_resource()</function>.  Suppose that you keep
-	the resource pointer returned from <function>request_region()</function>
-	in chip-&gt;res_port, the release procedure looks like:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  release_and_free_resource(chip->res_port);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      Don't forget to call <function>pci_disable_device()</function>
-      before the end.
-      </para>
-
-      <para>
-        And finally, release the chip-specific record.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  kfree(chip);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      Again, remember that you cannot
-      use the <parameter>__devexit</parameter> prefix for this destructor. 
-      </para>
-
-      <para>
-      We didn't implement the hardware disabling part in the above.
-      If you need to do this, please note that the destructor may be
-      called even before the initialization of the chip is completed.
-      It would be better to have a flag to skip hardware disabling
-      if the hardware was not initialized yet.
-      </para>
-
-      <para>
-      When the chip-data is assigned to the card using
-      <function>snd_device_new()</function> with
-      <constant>SNDRV_DEV_LOWLELVEL</constant> , its destructor is 
-      called at the last.  That is, it is assured that all other
-      components like PCMs and controls have already been released.
-      You don't have to stop PCMs, etc. explicitly, but just
-      call low-level hardware stopping.
-      </para>
-
-      <para>
-        The management of a memory-mapped region is almost as same as
-        the management of an I/O port. You'll need three fields like
-        the following: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          ....
-          unsigned long iobase_phys;
-          void __iomem *iobase_virt;
-  };
-]]>
-          </programlisting>
-        </informalexample>
-
-        and the allocation would be like below:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if ((err = pci_request_regions(pci, "My Chip")) < 0) {
-          kfree(chip);
-          return err;
-  }
-  chip->iobase_phys = pci_resource_start(pci, 0);
-  chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
-                                      pci_resource_len(pci, 0));
-]]>
-          </programlisting>
-        </informalexample>
-        
-        and the corresponding destructor would be:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int snd_mychip_free(struct mychip *chip)
-  {
-          ....
-          if (chip->iobase_virt)
-                  iounmap(chip->iobase_virt);
-          ....
-          pci_release_regions(chip->pci);
-          ....
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-    </section>
-
-    <section id="pci-resource-device-struct">
-      <title>Registration of Device Struct</title>
-      <para>
-	At some point, typically after calling <function>snd_device_new()</function>,
-	you need to register the struct <structname>device</structname> of the chip
-	you're handling for udev and co.  ALSA provides a macro for compatibility with
-	older kernels.  Simply call like the following:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_card_set_dev(card, &pci->dev);
-]]>
-          </programlisting>
-        </informalexample>
-	so that it stores the PCI's device pointer to the card.  This will be
-	referred by ALSA core functions later when the devices are registered.
-      </para>
-      <para>
-	In the case of non-PCI, pass the proper device struct pointer of the BUS
-	instead.  (In the case of legacy ISA without PnP, you don't have to do
-	anything.)
-      </para>
-    </section>
-
-    <section id="pci-resource-entries">
-      <title>PCI Entries</title>
-      <para>
-        So far, so good. Let's finish the missing PCI
-      stuff. At first, we need a
-      <structname>pci_device_id</structname> table for this
-      chipset. It's a table of PCI vendor/device ID number, and some
-      masks. 
-      </para>
-
-      <para>
-        For example,
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct pci_device_id snd_mychip_ids[] = {
-          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
-            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-          ....
-          { 0, }
-  };
-  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first and second fields of
-      the <structname>pci_device_id</structname> structure are the vendor and
-      device IDs. If you have no reason to filter the matching
-      devices, you can leave the remaining fields as above. The last
-      field of the <structname>pci_device_id</structname> struct contains
-      private data for this entry. You can specify any value here, for
-      example, to define specific operations for supported device IDs.
-      Such an example is found in the intel8x0 driver. 
-      </para>
-
-      <para>
-        The last entry of this list is the terminator. You must
-      specify this all-zero entry. 
-      </para>
-
-      <para>
-        Then, prepare the <structname>pci_driver</structname> record:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct pci_driver driver = {
-          .name = "My Own Chip",
-          .id_table = snd_mychip_ids,
-          .probe = snd_mychip_probe,
-          .remove = __devexit_p(snd_mychip_remove),
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The <structfield>probe</structfield> and
-      <structfield>remove</structfield> functions have already
-      been defined in the previous sections.
-      The <structfield>remove</structfield> function should
-      be defined with the 
-      <function>__devexit_p()</function> macro, so that it's not
-      defined for built-in (and non-hot-pluggable) case. The
-      <structfield>name</structfield> 
-      field is the name string of this device. Note that you must not
-      use a slash <quote>/</quote> in this string. 
-      </para>
-
-      <para>
-        And at last, the module entries:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int __init alsa_card_mychip_init(void)
-  {
-          return pci_register_driver(&driver);
-  }
-
-  static void __exit alsa_card_mychip_exit(void)
-  {
-          pci_unregister_driver(&driver);
-  }
-
-  module_init(alsa_card_mychip_init)
-  module_exit(alsa_card_mychip_exit)
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Note that these module entries are tagged with
-      <parameter>__init</parameter> and 
-      <parameter>__exit</parameter> prefixes, not
-      <parameter>__devinit</parameter> nor
-      <parameter>__devexit</parameter>.
-      </para>
-
-      <para>
-        Oh, one thing was forgotten. If you have no exported symbols,
-        you need to declare it in 2.2 or 2.4 kernels (it's not necessary in 2.6 kernels).
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  EXPORT_NO_SYMBOLS;
-]]>
-          </programlisting>
-        </informalexample>
-
-        That's all!
-      </para>
-    </section>
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- PCM Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="pcm-interface">
-    <title>PCM Interface</title>
-
-    <section id="pcm-interface-general">
-      <title>General</title>
-      <para>
-        The PCM middle layer of ALSA is quite powerful and it is only
-      necessary for each driver to implement the low-level functions
-      to access its hardware.
-      </para>
-
-      <para>
-        For accessing to the PCM layer, you need to include
-      <filename>&lt;sound/pcm.h&gt;</filename> first. In addition,
-      <filename>&lt;sound/pcm_params.h&gt;</filename> might be needed
-      if you access to some functions related with hw_param. 
-      </para>
-
-      <para>
-        Each card device can have up to four pcm instances. A pcm
-      instance corresponds to a pcm device file. The limitation of
-      number of instances comes only from the available bit size of
-      the Linux's device numbers. Once when 64bit device number is
-      used, we'll have more pcm instances available. 
-      </para>
-
-      <para>
-        A pcm instance consists of pcm playback and capture streams,
-      and each pcm stream consists of one or more pcm substreams. Some
-      soundcards support multiple playback functions. For example,
-      emu10k1 has a PCM playback of 32 stereo substreams. In this case, at
-      each open, a free substream is (usually) automatically chosen
-      and opened. Meanwhile, when only one substream exists and it was
-      already opened, the successful open will either block
-      or error with <constant>EAGAIN</constant> according to the
-      file open mode. But you don't have to care about such details in your
-      driver. The PCM middle layer will take care of such work.
-      </para>
-    </section>
-
-    <section id="pcm-interface-example">
-      <title>Full Code Example</title>
-      <para>
-      The example code below does not include any hardware access
-      routines but shows only the skeleton, how to build up the PCM
-      interfaces.
-
-        <example>
-          <title>PCM Example Code</title>
-          <programlisting>
-<![CDATA[
-  #include <sound/pcm.h>
-  ....
-
-  /* hardware definition */
-  static struct snd_pcm_hardware snd_mychip_playback_hw = {
-          .info = (SNDRV_PCM_INFO_MMAP |
-                   SNDRV_PCM_INFO_INTERLEAVED |
-                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                   SNDRV_PCM_INFO_MMAP_VALID),
-          .formats =          SNDRV_PCM_FMTBIT_S16_LE,
-          .rates =            SNDRV_PCM_RATE_8000_48000,
-          .rate_min =         8000,
-          .rate_max =         48000,
-          .channels_min =     2,
-          .channels_max =     2,
-          .buffer_bytes_max = 32768,
-          .period_bytes_min = 4096,
-          .period_bytes_max = 32768,
-          .periods_min =      1,
-          .periods_max =      1024,
-  };
-
-  /* hardware definition */
-  static struct snd_pcm_hardware snd_mychip_capture_hw = {
-          .info = (SNDRV_PCM_INFO_MMAP |
-                   SNDRV_PCM_INFO_INTERLEAVED |
-                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                   SNDRV_PCM_INFO_MMAP_VALID),
-          .formats =          SNDRV_PCM_FMTBIT_S16_LE,
-          .rates =            SNDRV_PCM_RATE_8000_48000,
-          .rate_min =         8000,
-          .rate_max =         48000,
-          .channels_min =     2,
-          .channels_max =     2,
-          .buffer_bytes_max = 32768,
-          .period_bytes_min = 4096,
-          .period_bytes_max = 32768,
-          .periods_min =      1,
-          .periods_max =      1024,
-  };
-
-  /* open callback */
-  static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          runtime->hw = snd_mychip_playback_hw;
-          /* more hardware-initialization will be done here */
-          ....
-          return 0;
-  }
-
-  /* close callback */
-  static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          /* the hardware-specific codes will be here */
-          ....
-          return 0;
-
-  }
-
-  /* open callback */
-  static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          runtime->hw = snd_mychip_capture_hw;
-          /* more hardware-initialization will be done here */
-          ....
-          return 0;
-  }
-
-  /* close callback */
-  static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          /* the hardware-specific codes will be here */
-          ....
-          return 0;
-
-  }
-
-  /* hw_params callback */
-  static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params)
-  {
-          return snd_pcm_lib_malloc_pages(substream,
-                                     params_buffer_bytes(hw_params));
-  }
-
-  /* hw_free callback */
-  static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
-  {
-          return snd_pcm_lib_free_pages(substream);
-  }
-
-  /* prepare callback */
-  static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          /* set up the hardware with the current configuration
-           * for example...
-           */
-          mychip_set_sample_format(chip, runtime->format);
-          mychip_set_sample_rate(chip, runtime->rate);
-          mychip_set_channels(chip, runtime->channels);
-          mychip_set_dma_setup(chip, runtime->dma_addr,
-                               chip->buffer_size,
-                               chip->period_size);
-          return 0;
-  }
-
-  /* trigger callback */
-  static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
-                                    int cmd)
-  {
-          switch (cmd) {
-          case SNDRV_PCM_TRIGGER_START:
-                  /* do something to start the PCM engine */
-                  ....
-                  break;
-          case SNDRV_PCM_TRIGGER_STOP:
-                  /* do something to stop the PCM engine */
-                  ....
-                  break;
-          default:
-                  return -EINVAL;
-          }
-  }
-
-  /* pointer callback */
-  static snd_pcm_uframes_t
-  snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          unsigned int current_ptr;
-
-          /* get the current hardware pointer */
-          current_ptr = mychip_get_hw_pointer(chip);
-          return current_ptr;
-  }
-
-  /* operators */
-  static struct snd_pcm_ops snd_mychip_playback_ops = {
-          .open =        snd_mychip_playback_open,
-          .close =       snd_mychip_playback_close,
-          .ioctl =       snd_pcm_lib_ioctl,
-          .hw_params =   snd_mychip_pcm_hw_params,
-          .hw_free =     snd_mychip_pcm_hw_free,
-          .prepare =     snd_mychip_pcm_prepare,
-          .trigger =     snd_mychip_pcm_trigger,
-          .pointer =     snd_mychip_pcm_pointer,
-  };
-
-  /* operators */
-  static struct snd_pcm_ops snd_mychip_capture_ops = {
-          .open =        snd_mychip_capture_open,
-          .close =       snd_mychip_capture_close,
-          .ioctl =       snd_pcm_lib_ioctl,
-          .hw_params =   snd_mychip_pcm_hw_params,
-          .hw_free =     snd_mychip_pcm_hw_free,
-          .prepare =     snd_mychip_pcm_prepare,
-          .trigger =     snd_mychip_pcm_trigger,
-          .pointer =     snd_mychip_pcm_pointer,
-  };
-
-  /*
-   *  definitions of capture are omitted here...
-   */
-
-  /* create a pcm device */
-  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
-  {
-          struct snd_pcm *pcm;
-          int err;
-
-          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
-          if (err < 0) 
-                  return err;
-          pcm->private_data = chip;
-          strcpy(pcm->name, "My Chip");
-          chip->pcm = pcm;
-          /* set operators */
-          snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                          &snd_mychip_playback_ops);
-          snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                          &snd_mychip_capture_ops);
-          /* pre-allocation of buffers */
-          /* NOTE: this may fail */
-          snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                snd_dma_pci_data(chip->pci),
-                                                64*1024, 64*1024);
-          return 0;
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="pcm-interface-constructor">
-      <title>Constructor</title>
-      <para>
-        A pcm instance is allocated by the <function>snd_pcm_new()</function>
-      function. It would be better to create a constructor for pcm,
-      namely, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
-  {
-          struct snd_pcm *pcm;
-          int err;
-
-          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
-          if (err < 0) 
-                  return err;
-          pcm->private_data = chip;
-          strcpy(pcm->name, "My Chip");
-          chip->pcm = pcm;
-	  ....
-          return 0;
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The <function>snd_pcm_new()</function> function takes four
-      arguments. The first argument is the card pointer to which this
-      pcm is assigned, and the second is the ID string. 
-      </para>
-
-      <para>
-        The third argument (<parameter>index</parameter>, 0 in the
-      above) is the index of this new pcm. It begins from zero. If
-      you create more than one pcm instances, specify the
-      different numbers in this argument. For example,
-      <parameter>index</parameter> = 1 for the second PCM device.  
-      </para>
-
-      <para>
-        The fourth and fifth arguments are the number of substreams
-      for playback and capture, respectively. Here 1 is used for
-      both arguments. When no playback or capture substreams are available,
-      pass 0 to the corresponding argument.
-      </para>
-
-      <para>
-        If a chip supports multiple playbacks or captures, you can
-      specify more numbers, but they must be handled properly in
-      open/close, etc. callbacks.  When you need to know which
-      substream you are referring to, then it can be obtained from
-      struct <structname>snd_pcm_substream</structname> data passed to each callback
-      as follows: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_pcm_substream *substream;
-  int index = substream->number;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        After the pcm is created, you need to set operators for each
-        pcm stream. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                  &snd_mychip_playback_ops);
-  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                  &snd_mychip_capture_ops);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The operators are defined typically like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct snd_pcm_ops snd_mychip_playback_ops = {
-          .open =        snd_mychip_pcm_open,
-          .close =       snd_mychip_pcm_close,
-          .ioctl =       snd_pcm_lib_ioctl,
-          .hw_params =   snd_mychip_pcm_hw_params,
-          .hw_free =     snd_mychip_pcm_hw_free,
-          .prepare =     snd_mychip_pcm_prepare,
-          .trigger =     snd_mychip_pcm_trigger,
-          .pointer =     snd_mychip_pcm_pointer,
-  };
-]]>
-          </programlisting>
-        </informalexample>
-
-        All the callbacks are described in the
-        <link linkend="pcm-interface-operators"><citetitle>
-        Operators</citetitle></link> subsection.
-      </para>
-
-      <para>
-        After setting the operators, you probably will want to
-        pre-allocate the buffer. For the pre-allocation, simply call
-        the following: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                        snd_dma_pci_data(chip->pci),
-                                        64*1024, 64*1024);
-]]>
-          </programlisting>
-        </informalexample>
-
-        It will allocate a buffer up to 64kB as default.
-      Buffer management details will be described in the later section <link
-      linkend="buffer-and-memory"><citetitle>Buffer and Memory
-      Management</citetitle></link>. 
-      </para>
-
-      <para>
-        Additionally, you can set some extra information for this pcm
-        in pcm-&gt;info_flags.
-        The available values are defined as
-        <constant>SNDRV_PCM_INFO_XXX</constant> in
-        <filename>&lt;sound/asound.h&gt;</filename>, which is used for
-        the hardware definition (described later). When your soundchip
-        supports only half-duplex, specify like this: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-    <section id="pcm-interface-destructor">
-      <title>... And the Destructor?</title>
-      <para>
-        The destructor for a pcm instance is not always
-      necessary. Since the pcm device will be released by the middle
-      layer code automatically, you don't have to call the destructor
-      explicitly.
-      </para>
-
-      <para>
-        The destructor would be necessary if you created
-        special records internally and needed to release them. In such a
-        case, set the destructor function to
-        pcm-&gt;private_free: 
-
-        <example>
-          <title>PCM Instance with a Destructor</title>
-          <programlisting>
-<![CDATA[
-  static void mychip_pcm_free(struct snd_pcm *pcm)
-  {
-          struct mychip *chip = snd_pcm_chip(pcm);
-          /* free your own data */
-          kfree(chip->my_private_pcm_data);
-          /* do what you like else */
-          ....
-  }
-
-  static int __devinit snd_mychip_new_pcm(struct mychip *chip)
-  {
-          struct snd_pcm *pcm;
-          ....
-          /* allocate your own data */
-          chip->my_private_pcm_data = kmalloc(...);
-          /* set the destructor */
-          pcm->private_data = chip;
-          pcm->private_free = mychip_pcm_free;
-          ....
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="pcm-interface-runtime">
-      <title>Runtime Pointer - The Chest of PCM Information</title>
-	<para>
-	  When the PCM substream is opened, a PCM runtime instance is
-	allocated and assigned to the substream. This pointer is
-	accessible via <constant>substream-&gt;runtime</constant>.
-	This runtime pointer holds most information you need
-	to control the PCM: the copy of hw_params and sw_params configurations, the buffer
-	pointers, mmap records, spinlocks, etc.
-	</para>
-
-	<para>
-	The definition of runtime instance is found in
-	<filename>&lt;sound/pcm.h&gt;</filename>.  Here are
-       the contents of this file:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-struct _snd_pcm_runtime {
-	/* -- Status -- */
-	struct snd_pcm_substream *trigger_master;
-	snd_timestamp_t trigger_tstamp;	/* trigger timestamp */
-	int overrange;
-	snd_pcm_uframes_t avail_max;
-	snd_pcm_uframes_t hw_ptr_base;	/* Position at buffer restart */
-	snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
-
-	/* -- HW params -- */
-	snd_pcm_access_t access;	/* access mode */
-	snd_pcm_format_t format;	/* SNDRV_PCM_FORMAT_* */
-	snd_pcm_subformat_t subformat;	/* subformat */
-	unsigned int rate;		/* rate in Hz */
-	unsigned int channels;		/* channels */
-	snd_pcm_uframes_t period_size;	/* period size */
-	unsigned int periods;		/* periods */
-	snd_pcm_uframes_t buffer_size;	/* buffer size */
-	unsigned int tick_time;		/* tick time */
-	snd_pcm_uframes_t min_align;	/* Min alignment for the format */
-	size_t byte_align;
-	unsigned int frame_bits;
-	unsigned int sample_bits;
-	unsigned int info;
-	unsigned int rate_num;
-	unsigned int rate_den;
-
-	/* -- SW params -- */
-	struct timespec tstamp_mode;	/* mmap timestamp is updated */
-  	unsigned int period_step;
-	unsigned int sleep_min;		/* min ticks to sleep */
-	snd_pcm_uframes_t start_threshold;
-	snd_pcm_uframes_t stop_threshold;
-	snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
-						noise is nearest than this */
-	snd_pcm_uframes_t silence_size;	/* Silence filling size */
-	snd_pcm_uframes_t boundary;	/* pointers wrap point */
-
-	snd_pcm_uframes_t silenced_start;
-	snd_pcm_uframes_t silenced_size;
-
-	snd_pcm_sync_id_t sync;		/* hardware synchronization ID */
-
-	/* -- mmap -- */
-	volatile struct snd_pcm_mmap_status *status;
-	volatile struct snd_pcm_mmap_control *control;
-	atomic_t mmap_count;
-
-	/* -- locking / scheduling -- */
-	spinlock_t lock;
-	wait_queue_head_t sleep;
-	struct timer_list tick_timer;
-	struct fasync_struct *fasync;
-
-	/* -- private section -- */
-	void *private_data;
-	void (*private_free)(struct snd_pcm_runtime *runtime);
-
-	/* -- hardware description -- */
-	struct snd_pcm_hardware hw;
-	struct snd_pcm_hw_constraints hw_constraints;
-
-	/* -- interrupt callbacks -- */
-	void (*transfer_ack_begin)(struct snd_pcm_substream *substream);
-	void (*transfer_ack_end)(struct snd_pcm_substream *substream);
-
-	/* -- timer -- */
-	unsigned int timer_resolution;	/* timer resolution */
-
-	/* -- DMA -- */           
-	unsigned char *dma_area;	/* DMA area */
-	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
-	size_t dma_bytes;		/* size of DMA area */
-
-	struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
-
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	/* -- OSS things -- */
-	struct snd_pcm_oss_runtime oss;
-#endif
-};
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	  For the operators (callbacks) of each sound driver, most of
-	these records are supposed to be read-only.  Only the PCM
-	middle-layer changes / updates them.  The exceptions are
-	the hardware description (hw), interrupt callbacks
-	(transfer_ack_xxx), DMA buffer information, and the private
-	data.  Besides, if you use the standard buffer allocation
-	method via <function>snd_pcm_lib_malloc_pages()</function>,
-	you don't need to set the DMA buffer information by yourself.
-	</para>
-
-	<para>
-	In the sections below, important records are explained.
-	</para>
-
-	<section id="pcm-interface-runtime-hw">
-	<title>Hardware Description</title>
-	<para>
-	  The hardware descriptor (struct <structname>snd_pcm_hardware</structname>)
-	contains the definitions of the fundamental hardware
-	configuration.  Above all, you'll need to define this in
-	<link linkend="pcm-interface-operators-open-callback"><citetitle>
-	the open callback</citetitle></link>.
-	Note that the runtime instance holds the copy of the
-	descriptor, not the pointer to the existing descriptor.  That
-	is, in the open callback, you can modify the copied descriptor
-	(<constant>runtime-&gt;hw</constant>) as you need.  For example, if the maximum
-	number of channels is 1 only on some chip models, you can
-	still use the same hardware descriptor and change the
-	channels_max later:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-          struct snd_pcm_runtime *runtime = substream->runtime;
-          ...
-          runtime->hw = snd_mychip_playback_hw; /* common definition */
-          if (chip->model == VERY_OLD_ONE)
-                  runtime->hw.channels_max = 1;
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	  Typically, you'll have a hardware descriptor as below:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static struct snd_pcm_hardware snd_mychip_playback_hw = {
-          .info = (SNDRV_PCM_INFO_MMAP |
-                   SNDRV_PCM_INFO_INTERLEAVED |
-                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                   SNDRV_PCM_INFO_MMAP_VALID),
-          .formats =          SNDRV_PCM_FMTBIT_S16_LE,
-          .rates =            SNDRV_PCM_RATE_8000_48000,
-          .rate_min =         8000,
-          .rate_max =         48000,
-          .channels_min =     2,
-          .channels_max =     2,
-          .buffer_bytes_max = 32768,
-          .period_bytes_min = 4096,
-          .period_bytes_max = 32768,
-          .periods_min =      1,
-          .periods_max =      1024,
-  };
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-	<itemizedlist>
-	<listitem><para>
-          The <structfield>info</structfield> field contains the type and
-        capabilities of this pcm. The bit flags are defined in
-        <filename>&lt;sound/asound.h&gt;</filename> as
-        <constant>SNDRV_PCM_INFO_XXX</constant>. Here, at least, you
-        have to specify whether the mmap is supported and which
-        interleaved format is supported.
-        When the is supported, add the
-        <constant>SNDRV_PCM_INFO_MMAP</constant> flag here. When the
-        hardware supports the interleaved or the non-interleaved
-        formats, <constant>SNDRV_PCM_INFO_INTERLEAVED</constant> or
-        <constant>SNDRV_PCM_INFO_NONINTERLEAVED</constant> flag must
-        be set, respectively. If both are supported, you can set both,
-        too. 
-        </para>
-
-        <para>
-          In the above example, <constant>MMAP_VALID</constant> and
-        <constant>BLOCK_TRANSFER</constant> are specified for the OSS mmap
-        mode. Usually both are set. Of course,
-        <constant>MMAP_VALID</constant> is set only if the mmap is
-        really supported. 
-        </para>
-
-        <para>
-          The other possible flags are
-        <constant>SNDRV_PCM_INFO_PAUSE</constant> and
-        <constant>SNDRV_PCM_INFO_RESUME</constant>. The
-        <constant>PAUSE</constant> bit means that the pcm supports the
-        <quote>pause</quote> operation, while the
-        <constant>RESUME</constant> bit means that the pcm supports
-        the full <quote>suspend/resume</quote> operation.
-	If the <constant>PAUSE</constant> flag is set,
-	the <structfield>trigger</structfield> callback below
-        must handle the corresponding (pause push/release) commands.
-	The suspend/resume trigger commands can be defined even without
-	the <constant>RESUME</constant> flag.  See <link
-	linkend="power-management"><citetitle>
-	Power Management</citetitle></link> section for details.
-        </para>
-
-	<para>
-	  When the PCM substreams can be synchronized (typically,
-	synchronized start/stop of a playback and a capture streams),
-	you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
-	too.  In this case, you'll need to check the linked-list of
-	PCM substreams in the trigger callback.  This will be
-	described in the later section.
-	</para>
-	</listitem>
-
-	<listitem>
-        <para>
-          <structfield>formats</structfield> field contains the bit-flags
-        of supported formats (<constant>SNDRV_PCM_FMTBIT_XXX</constant>).
-        If the hardware supports more than one format, give all or'ed
-        bits.  In the example above, the signed 16bit little-endian
-        format is specified.
-        </para>
-	</listitem>
-
-	<listitem>
-        <para>
-        <structfield>rates</structfield> field contains the bit-flags of
-        supported rates (<constant>SNDRV_PCM_RATE_XXX</constant>).
-        When the chip supports continuous rates, pass
-        <constant>CONTINUOUS</constant> bit additionally.
-        The pre-defined rate bits are provided only for typical
-	rates. If your chip supports unconventional rates, you need to add
-        the <constant>KNOT</constant> bit and set up the hardware
-        constraint manually (explained later).
-        </para>
-	</listitem>
-
-	<listitem>
-	<para>
-	<structfield>rate_min</structfield> and
-	<structfield>rate_max</structfield> define the minimum and
-	maximum sample rate.  This should correspond somehow to
-	<structfield>rates</structfield> bits.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	<structfield>channel_min</structfield> and
-	<structfield>channel_max</structfield> 
-	define, as you might already expected, the minimum and maximum
-	number of channels.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	<structfield>buffer_bytes_max</structfield> defines the
-	maximum buffer size in bytes.  There is no
-	<structfield>buffer_bytes_min</structfield> field, since
-	it can be calculated from the minimum period size and the
-	minimum number of periods.
-	Meanwhile, <structfield>period_bytes_min</structfield> and
-	define the minimum and maximum size of the period in bytes.
-	<structfield>periods_max</structfield> and
-	<structfield>periods_min</structfield> define the maximum and
-	minimum number of periods in the buffer.
-        </para>
-
-	<para>
-	The <quote>period</quote> is a term that corresponds to
-	a fragment in the OSS world. The period defines the size at
-	which a PCM interrupt is generated. This size strongly
-	depends on the hardware. 
-	Generally, the smaller period size will give you more
-	interrupts, that is, more controls. 
-	In the case of capture, this size defines the input latency.
-	On the other hand, the whole buffer size defines the
-	output latency for the playback direction.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	There is also a field <structfield>fifo_size</structfield>.
-	This specifies the size of the hardware FIFO, but currently it
-	is neither used in the driver nor in the alsa-lib.  So, you
-	can ignore this field.
-	</para>
-	</listitem>
-	</itemizedlist>
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-config">
-	<title>PCM Configurations</title>
-	<para>
-	Ok, let's go back again to the PCM runtime records.
-	The most frequently referred records in the runtime instance are
-	the PCM configurations.
-	The PCM configurations are stored in the runtime instance
-	after the application sends <type>hw_params</type> data via
-	alsa-lib.  There are many fields copied from hw_params and
-	sw_params structs.  For example,
-	<structfield>format</structfield> holds the format type
-	chosen by the application.  This field contains the enum value
-	<constant>SNDRV_PCM_FORMAT_XXX</constant>.
-	</para>
-
-	<para>
-	One thing to be noted is that the configured buffer and period
-	sizes are stored in <quote>frames</quote> in the runtime.
-        In the ALSA world, 1 frame = channels * samples-size.
-	For conversion between frames and bytes, you can use the
-	<function>frames_to_bytes()</function> and
-          <function>bytes_to_frames()</function> helper functions. 
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  period_bytes = frames_to_bytes(runtime, runtime->period_size);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-	<para>
-	Also, many software parameters (sw_params) are
-	stored in frames, too.  Please check the type of the field.
-	<type>snd_pcm_uframes_t</type> is for the frames as unsigned
-	integer while <type>snd_pcm_sframes_t</type> is for the frames
-	as signed integer.
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-dma">
-	<title>DMA Buffer Information</title>
-	<para>
-	The DMA buffer is defined by the following four fields,
-	<structfield>dma_area</structfield>,
-	<structfield>dma_addr</structfield>,
-	<structfield>dma_bytes</structfield> and
-	<structfield>dma_private</structfield>.
-	The <structfield>dma_area</structfield> holds the buffer
-	pointer (the logical address).  You can call
-	<function>memcpy</function> from/to 
-	this pointer.  Meanwhile, <structfield>dma_addr</structfield>
-	holds the physical address of the buffer.  This field is
-	specified only when the buffer is a linear buffer.
-	<structfield>dma_bytes</structfield> holds the size of buffer
-	in bytes.  <structfield>dma_private</structfield> is used for
-	the ALSA DMA allocator.
-	</para>
-
-	<para>
-	If you use a standard ALSA function,
-	<function>snd_pcm_lib_malloc_pages()</function>, for
-	allocating the buffer, these fields are set by the ALSA middle
-	layer, and you should <emphasis>not</emphasis> change them by
-	yourself.  You can read them but not write them.
-	On the other hand, if you want to allocate the buffer by
-	yourself, you'll need to manage it in hw_params callback.
-	At least, <structfield>dma_bytes</structfield> is mandatory.
-	<structfield>dma_area</structfield> is necessary when the
-	buffer is mmapped.  If your driver doesn't support mmap, this
-	field is not necessary.  <structfield>dma_addr</structfield>
-	is also optional.  You can use
-	<structfield>dma_private</structfield> as you like, too.
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-status">
-	<title>Running Status</title>
-	<para>
-	The running status can be referred via <constant>runtime-&gt;status</constant>.
-	This is the pointer to the struct <structname>snd_pcm_mmap_status</structname>
-	record.  For example, you can get the current DMA hardware
-	pointer via <constant>runtime-&gt;status-&gt;hw_ptr</constant>.
-	</para>
-
-	<para>
-	The DMA application pointer can be referred via
-	<constant>runtime-&gt;control</constant>, which points to the
-	struct <structname>snd_pcm_mmap_control</structname> record.
-	However, accessing directly to this value is not recommended.
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-private">
-	<title>Private Data</title> 
-	<para>
-	You can allocate a record for the substream and store it in
-	<constant>runtime-&gt;private_data</constant>.  Usually, this
-	is done in
-	<link linkend="pcm-interface-operators-open-callback"><citetitle>
-	the open callback</citetitle></link>.
-	Don't mix this with <constant>pcm-&gt;private_data</constant>.
-	The <constant>pcm-&gt;private_data</constant> usually points to the
-	chip instance assigned statically at the creation of PCM, while the 
-	<constant>runtime-&gt;private_data</constant> points to a dynamic
-	data structure created at the PCM open callback.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_pcm_substream *substream)
-  {
-          struct my_pcm_data *data;
-          ....
-          data = kmalloc(sizeof(*data), GFP_KERNEL);
-          substream->runtime->private_data = data;
-          ....
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          The allocated object must be released in
-	<link linkend="pcm-interface-operators-open-callback"><citetitle>
-	the close callback</citetitle></link>.
-        </para>
-	</section>
-
-	<section id="pcm-interface-runtime-intr">
-	<title>Interrupt Callbacks</title>
-	<para>
-	The field <structfield>transfer_ack_begin</structfield> and
-	<structfield>transfer_ack_end</structfield> are called at
-	the beginning and at the end of
-	<function>snd_pcm_period_elapsed()</function>, respectively. 
-	</para>
-	</section>
-
-    </section>
-
-    <section id="pcm-interface-operators">
-      <title>Operators</title>
-      <para>
-        OK, now let me give details about each pcm callback
-      (<parameter>ops</parameter>). In general, every callback must
-      return 0 if successful, or a negative error number
-      such as <constant>-EINVAL</constant>. To choose an appropriate
-      error number, it is advised to check what value other parts of
-      the kernel return when the same kind of request fails.
-      </para>
-
-      <para>
-        The callback function takes at least the argument with
-        <structname>snd_pcm_substream</structname> pointer. To retrieve
-        the chip record from the given substream instance, you can use the
-        following macro. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  int xxx() {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          ....
-  }
-]]>
-          </programlisting>
-        </informalexample>
-
-	The macro reads <constant>substream-&gt;private_data</constant>,
-	which is a copy of <constant>pcm-&gt;private_data</constant>.
-	You can override the former if you need to assign different data
-	records per PCM substream.  For example, the cmi8330 driver assigns
-	different private_data for playback and capture directions,
-	because it uses two different codecs (SB- and AD-compatible) for
-	different directions.
-      </para>
-
-      <section id="pcm-interface-operators-open-callback">
-        <title>open callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-
-          This is called when a pcm substream is opened.
-        </para>
-
-        <para>
-          At least, here you have to initialize the runtime-&gt;hw
-          record. Typically, this is done by like this: 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          runtime->hw = snd_mychip_playback_hw;
-          return 0;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-          where <parameter>snd_mychip_playback_hw</parameter> is the
-          pre-defined hardware description.
-	</para>
-
-	<para>
-	You can allocate a private data in this callback, as described
-	in <link linkend="pcm-interface-runtime-private"><citetitle>
-	Private Data</citetitle></link> section.
-	</para>
-
-	<para>
-	If the hardware configuration needs more constraints, set the
-	hardware constraints here, too.
-	See <link linkend="pcm-interface-constraints"><citetitle>
-	Constraints</citetitle></link> for more details.
-	</para>
-      </section>
-
-      <section id="pcm-interface-operators-close-callback">
-        <title>close callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_close(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-
-          Obviously, this is called when a pcm substream is closed.
-        </para>
-
-        <para>
-          Any private instance for a pcm substream allocated in the
-          open callback will be released here. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_close(struct snd_pcm_substream *substream)
-  {
-          ....
-          kfree(substream->runtime->private_data);
-          ....
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-ioctl-callback">
-        <title>ioctl callback</title>
-        <para>
-          This is used for any special call to pcm ioctls. But
-        usually you can pass a generic ioctl callback, 
-        <function>snd_pcm_lib_ioctl</function>.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-hw-params-callback">
-        <title>hw_params callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This is called when the hardware parameter
-        (<structfield>hw_params</structfield>) is set
-        up by the application, 
-        that is, once when the buffer size, the period size, the
-        format, etc. are defined for the pcm substream. 
-        </para>
-
-        <para>
-          Many hardware setups should be done in this callback,
-        including the allocation of buffers. 
-        </para>
-
-        <para>
-          Parameters to be initialized are retrieved by
-          <function>params_xxx()</function> macros. To allocate
-          buffer, you can call a helper function, 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-]]>
-            </programlisting>
-          </informalexample>
-
-          <function>snd_pcm_lib_malloc_pages()</function> is available
-	  only when the DMA buffers have been pre-allocated.
-	  See the section <link
-	  linkend="buffer-and-memory-buffer-types"><citetitle>
-	  Buffer Types</citetitle></link> for more details.
-        </para>
-
-        <para>
-          Note that this and <structfield>prepare</structfield> callbacks
-        may be called multiple times per initialization.
-        For example, the OSS emulation may
-        call these callbacks at each change via its ioctl. 
-        </para>
-
-        <para>
-          Thus, you need to be careful not to allocate the same buffers
-        many times, which will lead to memory leaks!  Calling the
-        helper function above many times is OK. It will release the
-        previous buffer automatically when it was already allocated. 
-        </para>
-
-        <para>
-          Another note is that this callback is non-atomic
-        (schedulable). This is important, because the
-        <structfield>trigger</structfield> callback 
-        is atomic (non-schedulable). That is, mutexes or any
-        schedule-related functions are not available in
-        <structfield>trigger</structfield> callback.
-	Please see the subsection
-	<link linkend="pcm-interface-atomicity"><citetitle>
-	Atomicity</citetitle></link> for details.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-hw-free-callback">
-        <title>hw_free callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This is called to release the resources allocated via
-          <structfield>hw_params</structfield>. For example, releasing the
-          buffer via 
-          <function>snd_pcm_lib_malloc_pages()</function> is done by
-          calling the following: 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  snd_pcm_lib_free_pages(substream);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This function is always called before the close callback is called.
-          Also, the callback may be called multiple times, too.
-          Keep track whether the resource was already released. 
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-prepare-callback">
-       <title>prepare callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_prepare(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This callback is called when the pcm is
-        <quote>prepared</quote>. You can set the format type, sample
-        rate, etc. here. The difference from
-        <structfield>hw_params</structfield> is that the 
-        <structfield>prepare</structfield> callback will be called each
-        time 
-        <function>snd_pcm_prepare()</function> is called, i.e. when
-        recovering after underruns, etc. 
-        </para>
-
-        <para>
-	Note that this callback is now non-atomic.
-	You can use schedule-related functions safely in this callback.
-        </para>
-
-        <para>
-          In this and the following callbacks, you can refer to the
-        values via the runtime record,
-        substream-&gt;runtime.
-        For example, to get the current
-        rate, format or channels, access to
-        runtime-&gt;rate,
-        runtime-&gt;format or
-        runtime-&gt;channels, respectively. 
-        The physical address of the allocated buffer is set to
-	runtime-&gt;dma_area.  The buffer and period sizes are
-	in runtime-&gt;buffer_size and runtime-&gt;period_size,
-	respectively.
-        </para>
-
-        <para>
-          Be careful that this callback will be called many times at
-        each setup, too. 
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-trigger-callback">
-        <title>trigger callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);
-]]>
-            </programlisting>
-          </informalexample>
-
-          This is called when the pcm is started, stopped or paused.
-        </para>
-
-        <para>
-          Which action is specified in the second argument,
-          <constant>SNDRV_PCM_TRIGGER_XXX</constant> in
-          <filename>&lt;sound/pcm.h&gt;</filename>. At least,
-          the <constant>START</constant> and <constant>STOP</constant>
-          commands must be defined in this callback. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  switch (cmd) {
-  case SNDRV_PCM_TRIGGER_START:
-          /* do something to start the PCM engine */
-          break;
-  case SNDRV_PCM_TRIGGER_STOP:
-          /* do something to stop the PCM engine */
-          break;
-  default:
-          return -EINVAL;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          When the pcm supports the pause operation (given in the info
-        field of the hardware table), the <constant>PAUSE_PUSE</constant>
-        and <constant>PAUSE_RELEASE</constant> commands must be
-        handled here, too. The former is the command to pause the pcm,
-        and the latter to restart the pcm again. 
-        </para>
-
-        <para>
-          When the pcm supports the suspend/resume operation,
-	regardless of full or partial suspend/resume support,
-        the <constant>SUSPEND</constant> and <constant>RESUME</constant>
-        commands must be handled, too.
-        These commands are issued when the power-management status is
-        changed.  Obviously, the <constant>SUSPEND</constant> and
-        <constant>RESUME</constant> commands
-        suspend and resume the pcm substream, and usually, they
-        are identical to the <constant>STOP</constant> and
-        <constant>START</constant> commands, respectively.
-	  See the <link linkend="power-management"><citetitle>
-	Power Management</citetitle></link> section for details.
-        </para>
-
-        <para>
-          As mentioned, this callback is atomic.  You cannot call
-	  functions which may sleep.
-	  The trigger callback should be as minimal as possible,
-	  just really triggering the DMA.  The other stuff should be
-	  initialized hw_params and prepare callbacks properly
-	  beforehand.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-pointer-callback">
-        <title>pointer callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)
-]]>
-            </programlisting>
-          </informalexample>
-
-          This callback is called when the PCM middle layer inquires
-        the current hardware position on the buffer. The position must
-        be returned in frames,
-        ranging from 0 to buffer_size - 1.
-        </para>
-
-        <para>
-          This is called usually from the buffer-update routine in the
-        pcm middle layer, which is invoked when
-        <function>snd_pcm_period_elapsed()</function> is called in the
-        interrupt routine. Then the pcm middle layer updates the
-        position and calculates the available space, and wakes up the
-        sleeping poll threads, etc. 
-        </para>
-
-        <para>
-          This callback is also atomic.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-copy-silence">
-        <title>copy and silence callbacks</title>
-        <para>
-          These callbacks are not mandatory, and can be omitted in
-        most cases. These callbacks are used when the hardware buffer
-        cannot be in the normal memory space. Some chips have their
-        own buffer on the hardware which is not mappable. In such a
-        case, you have to transfer the data manually from the memory
-        buffer to the hardware buffer. Or, if the buffer is
-        non-contiguous on both physical and virtual memory spaces,
-        these callbacks must be defined, too. 
-        </para>
-
-        <para>
-          If these two callbacks are defined, copy and set-silence
-        operations are done by them. The detailed will be described in
-        the later section <link
-        linkend="buffer-and-memory"><citetitle>Buffer and Memory
-        Management</citetitle></link>. 
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-ack">
-        <title>ack callback</title>
-        <para>
-          This callback is also not mandatory. This callback is called
-        when the appl_ptr is updated in read or write operations.
-        Some drivers like emu10k1-fx and cs46xx need to track the
-	current appl_ptr for the internal buffer, and this callback
-	is useful only for such a purpose.
-	</para>
-	<para>
-	  This callback is atomic.
-	</para>
-      </section>
-
-      <section id="pcm-interface-operators-page-callback">
-        <title>page callback</title>
-
-        <para>
-          This callback is optional too. This callback is used
-        mainly for non-contiguous buffers. The mmap calls this
-        callback to get the page address. Some examples will be
-        explained in the later section <link
-        linkend="buffer-and-memory"><citetitle>Buffer and Memory
-        Management</citetitle></link>, too. 
-        </para>
-      </section>
-    </section>
-
-    <section id="pcm-interface-interrupt-handler">
-      <title>Interrupt Handler</title>
-      <para>
-        The rest of pcm stuff is the PCM interrupt handler. The
-      role of PCM interrupt handler in the sound driver is to update
-      the buffer position and to tell the PCM middle layer when the
-      buffer position goes across the prescribed period size. To
-      inform this, call the <function>snd_pcm_period_elapsed()</function>
-      function. 
-      </para>
-
-      <para>
-        There are several types of sound chips to generate the interrupts.
-      </para>
-
-      <section id="pcm-interface-interrupt-handler-boundary">
-        <title>Interrupts at the period (fragment) boundary</title>
-        <para>
-          This is the most frequently found type:  the hardware
-        generates an interrupt at each period boundary.
-	In this case, you can call
-        <function>snd_pcm_period_elapsed()</function> at each 
-        interrupt. 
-        </para>
-
-        <para>
-          <function>snd_pcm_period_elapsed()</function> takes the
-        substream pointer as its argument. Thus, you need to keep the
-        substream pointer accessible from the chip instance. For
-        example, define substream field in the chip record to hold the
-        current running substream pointer, and set the pointer value
-        at open callback (and reset at close callback). 
-        </para>
-
-        <para>
-          If you acquire a spinlock in the interrupt handler, and the
-        lock is used in other pcm callbacks, too, then you have to
-        release the lock before calling
-        <function>snd_pcm_period_elapsed()</function>, because
-        <function>snd_pcm_period_elapsed()</function> calls other pcm
-        callbacks inside. 
-        </para>
-
-        <para>
-          Typical code would be like:
-
-          <example>
-	    <title>Interrupt Handler Case #1</title>
-            <programlisting>
-<![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
-  {
-          struct mychip *chip = dev_id;
-          spin_lock(&chip->lock);
-          ....
-          if (pcm_irq_invoked(chip)) {
-                  /* call updater, unlock before it */
-                  spin_unlock(&chip->lock);
-                  snd_pcm_period_elapsed(chip->substream);
-                  spin_lock(&chip->lock);
-                  /* acknowledge the interrupt if necessary */
-          }
-          ....
-          spin_unlock(&chip->lock);
-          return IRQ_HANDLED;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-      </section>
-
-      <section id="pcm-interface-interrupt-handler-timer">
-        <title>High frequency timer interrupts</title>
-        <para>
-	This happense when the hardware doesn't generate interrupts
-        at the period boundary but issues timer interrupts at a fixed
-        timer rate (e.g. es1968 or ymfpci drivers). 
-        In this case, you need to check the current hardware
-        position and accumulate the processed sample length at each
-        interrupt.  When the accumulated size exceeds the period
-        size, call 
-        <function>snd_pcm_period_elapsed()</function> and reset the
-        accumulator. 
-        </para>
-
-        <para>
-          Typical code would be like the following.
-
-          <example>
-	    <title>Interrupt Handler Case #2</title>
-            <programlisting>
-<![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
-  {
-          struct mychip *chip = dev_id;
-          spin_lock(&chip->lock);
-          ....
-          if (pcm_irq_invoked(chip)) {
-                  unsigned int last_ptr, size;
-                  /* get the current hardware pointer (in frames) */
-                  last_ptr = get_hw_ptr(chip);
-                  /* calculate the processed frames since the
-                   * last update
-                   */
-                  if (last_ptr < chip->last_ptr)
-                          size = runtime->buffer_size + last_ptr 
-                                   - chip->last_ptr; 
-                  else
-                          size = last_ptr - chip->last_ptr;
-                  /* remember the last updated point */
-                  chip->last_ptr = last_ptr;
-                  /* accumulate the size */
-                  chip->size += size;
-                  /* over the period boundary? */
-                  if (chip->size >= runtime->period_size) {
-                          /* reset the accumulator */
-                          chip->size %= runtime->period_size;
-                          /* call updater */
-                          spin_unlock(&chip->lock);
-                          snd_pcm_period_elapsed(substream);
-                          spin_lock(&chip->lock);
-                  }
-                  /* acknowledge the interrupt if necessary */
-          }
-          ....
-          spin_unlock(&chip->lock);
-          return IRQ_HANDLED;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-      </section>
-
-      <section id="pcm-interface-interrupt-handler-both">
-        <title>On calling <function>snd_pcm_period_elapsed()</function></title>
-        <para>
-          In both cases, even if more than one period are elapsed, you
-        don't have to call
-        <function>snd_pcm_period_elapsed()</function> many times. Call
-        only once. And the pcm layer will check the current hardware
-        pointer and update to the latest status. 
-        </para>
-      </section>
-    </section>
-
-    <section id="pcm-interface-atomicity">
-      <title>Atomicity</title>
-      <para>
-      One of the most important (and thus difficult to debug) problems
-      in kernel programming are race conditions.
-      In the Linux kernel, they are usually avoided via spin-locks, mutexes
-      or semaphores.  In general, if a race condition can happen
-      in an interrupt handler, it has to be managed atomically, and you
-      have to use a spinlock to protect the critical session. If the
-      critical section is not in interrupt handler code and
-      if taking a relatively long time to execute is acceptable, you
-      should use mutexes or semaphores instead.
-      </para>
-
-      <para>
-      As already seen, some pcm callbacks are atomic and some are
-      not.  For example, the <parameter>hw_params</parameter> callback is
-      non-atomic, while <parameter>trigger</parameter> callback is
-      atomic.  This means, the latter is called already in a spinlock
-      held by the PCM middle layer. Please take this atomicity into
-      account when you choose a locking scheme in the callbacks.
-      </para>
-
-      <para>
-      In the atomic callbacks, you cannot use functions which may call
-      <function>schedule</function> or go to
-      <function>sleep</function>.  Semaphores and mutexes can sleep,
-      and hence they cannot be used inside the atomic callbacks
-      (e.g. <parameter>trigger</parameter> callback).
-      To implement some delay in such a callback, please use
-      <function>udelay()</function> or <function>mdelay()</function>.
-      </para>
-
-      <para>
-      All three atomic callbacks (trigger, pointer, and ack) are
-      called with local interrupts disabled.
-      </para>
-
-    </section>
-    <section id="pcm-interface-constraints">
-      <title>Constraints</title>
-      <para>
-        If your chip supports unconventional sample rates, or only the
-      limited samples, you need to set a constraint for the
-      condition. 
-      </para>
-
-      <para>
-        For example, in order to restrict the sample rates in the some
-        supported values, use
-	<function>snd_pcm_hw_constraint_list()</function>.
-	You need to call this function in the open callback.
-
-        <example>
-	  <title>Example of Hardware Constraints</title>
-          <programlisting>
-<![CDATA[
-  static unsigned int rates[] =
-          {4000, 10000, 22050, 44100};
-  static struct snd_pcm_hw_constraint_list constraints_rates = {
-          .count = ARRAY_SIZE(rates),
-          .list = rates,
-          .mask = 0,
-  };
-
-  static int snd_mychip_pcm_open(struct snd_pcm_substream *substream)
-  {
-          int err;
-          ....
-          err = snd_pcm_hw_constraint_list(substream->runtime, 0,
-                                           SNDRV_PCM_HW_PARAM_RATE,
-                                           &constraints_rates);
-          if (err < 0)
-                  return err;
-          ....
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-
-      <para>
-        There are many different constraints.
-        Look at <filename>sound/pcm.h</filename> for a complete list.
-        You can even define your own constraint rules.
-        For example, let's suppose my_chip can manage a substream of 1 channel
-        if and only if the format is S16_LE, otherwise it supports any format
-        specified in the <structname>snd_pcm_hardware</structname> structure (or in any
-        other constraint_list). You can build a rule like this:
-
-        <example>
-	  <title>Example of Hardware Constraints for Channels</title>
-	  <programlisting>
-<![CDATA[
-  static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params,
-                                        struct snd_pcm_hw_rule *rule)
-  {
-          struct snd_interval *c = hw_param_interval(params,
-                SNDRV_PCM_HW_PARAM_CHANNELS);
-          struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-          struct snd_mask fmt;
-
-          snd_mask_any(&fmt);    /* Init the struct */
-          if (c->min < 2) {
-                  fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_LE;
-                  return snd_mask_refine(f, &fmt);
-          }
-          return 0;
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
- 
-      <para>
-        Then you need to call this function to add your rule:
-
-       <informalexample>
-	 <programlisting>
-<![CDATA[
-  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-                      hw_rule_channels_by_format, 0, SNDRV_PCM_HW_PARAM_FORMAT,
-                      -1);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The rule function is called when an application sets the number of
-        channels. But an application can set the format before the number of
-        channels. Thus you also need to define the inverse rule:
-
-       <example>
-	 <title>Example of Hardware Constraints for Channels</title>
-	 <programlisting>
-<![CDATA[
-  static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params,
-                                        struct snd_pcm_hw_rule *rule)
-  {
-          struct snd_interval *c = hw_param_interval(params,
-                        SNDRV_PCM_HW_PARAM_CHANNELS);
-          struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-          struct snd_interval ch;
-
-          snd_interval_any(&ch);
-          if (f->bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
-                  ch.min = ch.max = 1;
-                  ch.integer = 1;
-                  return snd_interval_refine(c, &ch);
-          }
-          return 0;
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-
-      <para>
-      ...and in the open callback:
-       <informalexample>
-	 <programlisting>
-<![CDATA[
-  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
-                      hw_rule_format_by_channels, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-                      -1);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        I won't give more details here, rather I
-        would like to say, <quote>Luke, use the source.</quote>
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Control Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="control-interface">
-    <title>Control Interface</title>
-
-    <section id="control-interface-general">
-      <title>General</title>
-      <para>
-        The control interface is used widely for many switches,
-      sliders, etc. which are accessed from user-space. Its most
-      important use is the mixer interface. In other words, since ALSA
-      0.9.x, all the mixer stuff is implemented on the control kernel API.
-      </para>
-
-      <para>
-        ALSA has a well-defined AC97 control module. If your chip
-      supports only the AC97 and nothing else, you can skip this
-      section. 
-      </para>
-
-      <para>
-        The control API is defined in
-      <filename>&lt;sound/control.h&gt;</filename>.
-      Include this file if you want to add your own controls.
-      </para>
-    </section>
-
-    <section id="control-interface-definition">
-      <title>Definition of Controls</title>
-      <para>
-        To create a new control, you need to define the
-	following three
-      callbacks: <structfield>info</structfield>,
-      <structfield>get</structfield> and
-      <structfield>put</structfield>. Then, define a
-      struct <structname>snd_kcontrol_new</structname> record, such as: 
-
-        <example>
-	  <title>Definition of a Control</title>
-          <programlisting>
-<![CDATA[
-  static struct snd_kcontrol_new my_control __devinitdata = {
-          .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-          .name = "PCM Playback Switch",
-          .index = 0,
-          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-          .private_value = 0xffff,
-          .info = my_control_info,
-          .get = my_control_get,
-          .put = my_control_put
-  };
-]]>
-          </programlisting>
-        </example>
-      </para>
-
-      <para>
-        Most likely the control is created via
-      <function>snd_ctl_new1()</function>, and in such a case, you can
-      add the <parameter>__devinitdata</parameter> prefix to the
-      definition as above. 
-      </para>
-
-      <para>
-        The <structfield>iface</structfield> field specifies the control
-      type, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
-      is usually <constant>MIXER</constant>.
-      Use <constant>CARD</constant> for global controls that are not
-      logically part of the mixer.
-      If the control is closely associated with some specific device on
-      the sound card, use <constant>HWDEP</constant>,
-      <constant>PCM</constant>, <constant>RAWMIDI</constant>,
-      <constant>TIMER</constant>, or <constant>SEQUENCER</constant>, and
-      specify the device number with the
-      <structfield>device</structfield> and
-      <structfield>subdevice</structfield> fields.
-      </para>
-
-      <para>
-        The <structfield>name</structfield> is the name identifier
-      string. Since ALSA 0.9.x, the control name is very important,
-      because its role is classified from its name. There are
-      pre-defined standard control names. The details are described in
-      the <link linkend="control-interface-control-names"><citetitle>
-      Control Names</citetitle></link> subsection.
-      </para>
-
-      <para>
-        The <structfield>index</structfield> field holds the index number
-      of this control. If there are several different controls with
-      the same name, they can be distinguished by the index
-      number. This is the case when 
-      several codecs exist on the card. If the index is zero, you can
-      omit the definition above. 
-      </para>
-
-      <para>
-        The <structfield>access</structfield> field contains the access
-      type of this control. Give the combination of bit masks,
-      <constant>SNDRV_CTL_ELEM_ACCESS_XXX</constant>, there.
-      The details will be explained in
-      the <link linkend="control-interface-access-flags"><citetitle>
-      Access Flags</citetitle></link> subsection.
-      </para>
-
-      <para>
-        The <structfield>private_value</structfield> field contains
-      an arbitrary long integer value for this record. When using
-      the generic <structfield>info</structfield>,
-      <structfield>get</structfield> and
-      <structfield>put</structfield> callbacks, you can pass a value 
-      through this field. If several small numbers are necessary, you can
-      combine them in bitwise. Or, it's possible to give a pointer
-      (casted to unsigned long) of some record to this field, too. 
-      </para>
-
-      <para>
-      The <structfield>tlv</structfield> field can be used to provide
-      metadata about the control; see the
-      <link linkend="control-interface-tlv">
-      <citetitle>Metadata</citetitle></link> subsection.
-      </para>
-
-      <para>
-        The other three are
-	<link linkend="control-interface-callbacks"><citetitle>
-	callback functions</citetitle></link>.
-      </para>
-    </section>
-
-    <section id="control-interface-control-names">
-      <title>Control Names</title>
-      <para>
-        There are some standards to define the control names. A
-      control is usually defined from the three parts as
-      <quote>SOURCE DIRECTION FUNCTION</quote>. 
-      </para>
-
-      <para>
-        The first, <constant>SOURCE</constant>, specifies the source
-      of the control, and is a string such as <quote>Master</quote>,
-      <quote>PCM</quote>, <quote>CD</quote> and
-      <quote>Line</quote>. There are many pre-defined sources. 
-      </para>
-
-      <para>
-        The second, <constant>DIRECTION</constant>, is one of the
-      following strings according to the direction of the control:
-      <quote>Playback</quote>, <quote>Capture</quote>, <quote>Bypass
-      Playback</quote> and <quote>Bypass Capture</quote>. Or, it can
-      be omitted, meaning both playback and capture directions. 
-      </para>
-
-      <para>
-        The third, <constant>FUNCTION</constant>, is one of the
-      following strings according to the function of the control:
-      <quote>Switch</quote>, <quote>Volume</quote> and
-      <quote>Route</quote>. 
-      </para>
-
-      <para>
-        The example of control names are, thus, <quote>Master Capture
-      Switch</quote> or <quote>PCM Playback Volume</quote>. 
-      </para>
-
-      <para>
-        There are some exceptions:
-      </para>
-
-      <section id="control-interface-control-names-global">
-        <title>Global capture and playback</title>
-        <para>
-          <quote>Capture Source</quote>, <quote>Capture Switch</quote>
-        and <quote>Capture Volume</quote> are used for the global
-        capture (input) source, switch and volume. Similarly,
-        <quote>Playback Switch</quote> and <quote>Playback
-        Volume</quote> are used for the global output gain switch and
-        volume. 
-        </para>
-      </section>
-
-      <section id="control-interface-control-names-tone">
-        <title>Tone-controls</title>
-        <para>
-          tone-control switch and volumes are specified like
-        <quote>Tone Control - XXX</quote>, e.g. <quote>Tone Control -
-        Switch</quote>, <quote>Tone Control - Bass</quote>,
-        <quote>Tone Control - Center</quote>.  
-        </para>
-      </section>
-
-      <section id="control-interface-control-names-3d">
-        <title>3D controls</title>
-        <para>
-          3D-control switches and volumes are specified like <quote>3D
-        Control - XXX</quote>, e.g. <quote>3D Control -
-        Switch</quote>, <quote>3D Control - Center</quote>, <quote>3D
-        Control - Space</quote>. 
-        </para>
-      </section>
-
-      <section id="control-interface-control-names-mic">
-        <title>Mic boost</title>
-        <para>
-          Mic-boost switch is set as <quote>Mic Boost</quote> or
-        <quote>Mic Boost (6dB)</quote>. 
-        </para>
-
-        <para>
-          More precise information can be found in
-        <filename>Documentation/sound/alsa/ControlNames.txt</filename>.
-        </para>
-      </section>
-    </section>
-
-    <section id="control-interface-access-flags">
-      <title>Access Flags</title>
-
-      <para>
-      The access flag is the bitmask which specifies the access type
-      of the given control.  The default access type is
-      <constant>SNDRV_CTL_ELEM_ACCESS_READWRITE</constant>, 
-      which means both read and write are allowed to this control.
-      When the access flag is omitted (i.e. = 0), it is
-      considered as <constant>READWRITE</constant> access as default. 
-      </para>
-
-      <para>
-      When the control is read-only, pass
-      <constant>SNDRV_CTL_ELEM_ACCESS_READ</constant> instead.
-      In this case, you don't have to define
-      the <structfield>put</structfield> callback.
-      Similarly, when the control is write-only (although it's a rare
-      case), you can use the <constant>WRITE</constant> flag instead, and
-      you don't need the <structfield>get</structfield> callback.
-      </para>
-
-      <para>
-      If the control value changes frequently (e.g. the VU meter),
-      <constant>VOLATILE</constant> flag should be given.  This means
-      that the control may be changed without
-      <link linkend="control-interface-change-notification"><citetitle>
-      notification</citetitle></link>. Applications should poll such
-      a control constantly.
-      </para>
-
-      <para>
-      When the control is inactive, set
-      the <constant>INACTIVE</constant> flag, too.
-      There are <constant>LOCK</constant> and
-      <constant>OWNER</constant> flags to change the write
-      permissions.
-      </para>
-
-    </section>
-
-    <section id="control-interface-callbacks">
-      <title>Callbacks</title>
-
-      <section id="control-interface-callbacks-info">
-        <title>info callback</title>
-        <para>
-          The <structfield>info</structfield> callback is used to get
-        detailed information on this control. This must store the
-        values of the given struct <structname>snd_ctl_elem_info</structname>
-        object. For example, for a boolean control with a single
-        element: 
-
-          <example>
-	    <title>Example of info callback</title>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_info *uinfo)
-  {
-          uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-          uinfo->count = 1;
-          uinfo->value.integer.min = 0;
-          uinfo->value.integer.max = 1;
-          return 0;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-
-        <para>
-          The <structfield>type</structfield> field specifies the type
-        of the control. There are <constant>BOOLEAN</constant>,
-        <constant>INTEGER</constant>, <constant>ENUMERATED</constant>,
-        <constant>BYTES</constant>, <constant>IEC958</constant> and
-        <constant>INTEGER64</constant>. The
-        <structfield>count</structfield> field specifies the 
-        number of elements in this control. For example, a stereo
-        volume would have count = 2. The
-        <structfield>value</structfield> field is a union, and 
-        the values stored are depending on the type. The boolean and
-        integer types are identical. 
-        </para>
-
-        <para>
-          The enumerated type is a bit different from others.  You'll
-          need to set the string for the currently given item index. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_info *uinfo)
-  {
-          static char *texts[4] = {
-                  "First", "Second", "Third", "Fourth"
-          };
-          uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-          uinfo->count = 1;
-          uinfo->value.enumerated.items = 4;
-          if (uinfo->value.enumerated.item > 3)
-                  uinfo->value.enumerated.item = 3;
-          strcpy(uinfo->value.enumerated.name,
-                 texts[uinfo->value.enumerated.item]);
-          return 0;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-	  Some common info callbacks are available for your convenience:
-	<function>snd_ctl_boolean_mono_info()</function> and
-	<function>snd_ctl_boolean_stereo_info()</function>.
-	Obviously, the former is an info callback for a mono channel
-	boolean item, just like <function>snd_myctl_mono_info</function>
-	above, and the latter is for a stereo channel boolean item.
-	</para>
-
-      </section>
-
-      <section id="control-interface-callbacks-get">
-        <title>get callback</title>
-
-        <para>
-          This callback is used to read the current value of the
-        control and to return to user-space. 
-        </para>
-
-        <para>
-          For example,
-
-          <example>
-	    <title>Example of get callback</title>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_get(struct snd_kcontrol *kcontrol,
-                           struct snd_ctl_elem_value *ucontrol)
-  {
-          struct mychip *chip = snd_kcontrol_chip(kcontrol);
-          ucontrol->value.integer.value[0] = get_some_value(chip);
-          return 0;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-
-        <para>
-	The <structfield>value</structfield> field depends on 
-        the type of control as well as on the info callback.  For example,
-	the sb driver uses this field to store the register offset,
-        the bit-shift and the bit-mask.  The
-        <structfield>private_value</structfield> field is set as follows:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  .private_value = reg | (shift << 16) | (mask << 24)
-]]>
-            </programlisting>
-          </informalexample>
-	and is retrieved in callbacks like
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
-                                    struct snd_ctl_elem_value *ucontrol)
-  {
-          int reg = kcontrol->private_value & 0xff;
-          int shift = (kcontrol->private_value >> 16) & 0xff;
-          int mask = (kcontrol->private_value >> 24) & 0xff;
-          ....
-  }
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	In the <structfield>get</structfield> callback,
-	you have to fill all the elements if the
-        control has more than one elements,
-        i.e. <structfield>count</structfield> &gt; 1.
-	In the example above, we filled only one element
-        (<structfield>value.integer.value[0]</structfield>) since it's
-        assumed as <structfield>count</structfield> = 1.
-        </para>
-      </section>
-
-      <section id="control-interface-callbacks-put">
-        <title>put callback</title>
-
-        <para>
-          This callback is used to write a value from user-space.
-        </para>
-
-        <para>
-          For example,
-
-          <example>
-	    <title>Example of put callback</title>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_put(struct snd_kcontrol *kcontrol,
-                           struct snd_ctl_elem_value *ucontrol)
-  {
-          struct mychip *chip = snd_kcontrol_chip(kcontrol);
-          int changed = 0;
-          if (chip->current_value !=
-               ucontrol->value.integer.value[0]) {
-                  change_current_value(chip,
-                              ucontrol->value.integer.value[0]);
-                  changed = 1;
-          }
-          return changed;
-  }
-]]>
-            </programlisting>
-          </example>
-
-          As seen above, you have to return 1 if the value is
-        changed. If the value is not changed, return 0 instead. 
-	If any fatal error happens, return a negative error code as
-        usual.
-        </para>
-
-        <para>
-	As in the <structfield>get</structfield> callback,
-	when the control has more than one elements,
-	all elements must be evaluated in this callback, too.
-        </para>
-      </section>
-
-      <section id="control-interface-callbacks-all">
-        <title>Callbacks are not atomic</title>
-        <para>
-          All these three callbacks are basically not atomic.
-        </para>
-      </section>
-    </section>
-
-    <section id="control-interface-constructor">
-      <title>Constructor</title>
-      <para>
-        When everything is ready, finally we can create a new
-      control. To create a control, there are two functions to be
-      called, <function>snd_ctl_new1()</function> and
-      <function>snd_ctl_add()</function>. 
-      </para>
-
-      <para>
-        In the simplest way, you can do like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip));
-  if (err < 0)
-          return err;
-]]>
-          </programlisting>
-        </informalexample>
-
-        where <parameter>my_control</parameter> is the
-      struct <structname>snd_kcontrol_new</structname> object defined above, and chip
-      is the object pointer to be passed to
-      kcontrol-&gt;private_data 
-      which can be referred to in callbacks. 
-      </para>
-
-      <para>
-        <function>snd_ctl_new1()</function> allocates a new
-      <structname>snd_kcontrol</structname> instance (that's why the definition
-      of <parameter>my_control</parameter> can be with
-      the <parameter>__devinitdata</parameter> 
-      prefix), and <function>snd_ctl_add</function> assigns the given
-      control component to the card. 
-      </para>
-    </section>
-
-    <section id="control-interface-change-notification">
-      <title>Change Notification</title>
-      <para>
-        If you need to change and update a control in the interrupt
-      routine, you can call <function>snd_ctl_notify()</function>. For
-      example, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer);
-]]>
-          </programlisting>
-        </informalexample>
-
-        This function takes the card pointer, the event-mask, and the
-      control id pointer for the notification. The event-mask
-      specifies the types of notification, for example, in the above
-      example, the change of control values is notified.
-      The id pointer is the pointer of struct <structname>snd_ctl_elem_id</structname>
-      to be notified.
-      You can find some examples in <filename>es1938.c</filename> or
-      <filename>es1968.c</filename> for hardware volume interrupts. 
-      </para>
-    </section>
-
-    <section id="control-interface-tlv">
-      <title>Metadata</title>
-      <para>
-      To provide information about the dB values of a mixer control, use
-      on of the <constant>DECLARE_TLV_xxx</constant> macros from
-      <filename>&lt;sound/tlv.h&gt;</filename> to define a variable
-      containing this information, set the<structfield>tlv.p
-      </structfield> field to point to this variable, and include the
-      <constant>SNDRV_CTL_ELEM_ACCESS_TLV_READ</constant> flag in the
-      <structfield>access</structfield> field; like this:
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
-
-  static struct snd_kcontrol_new my_control __devinitdata = {
-          ...
-          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-                    SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-          ...
-          .tlv.p = db_scale_my_control,
-  };
-]]>
-        </programlisting>
-      </informalexample>
-      </para>
-
-      <para>
-      The <function>DECLARE_TLV_DB_SCALE</function> macro defines
-      information about a mixer control where each step in the control's
-      value changes the dB value by a constant dB amount.
-      The first parameter is the name of the variable to be defined.
-      The second parameter is the minimum value, in units of 0.01 dB.
-      The third parameter is the step size, in units of 0.01 dB.
-      Set the fourth parameter to 1 if the minimum value actually mutes
-      the control.
-      </para>
-
-      <para>
-      The <function>DECLARE_TLV_DB_LINEAR</function> macro defines
-      information about a mixer control where the control's value affects
-      the output linearly.
-      The first parameter is the name of the variable to be defined.
-      The second parameter is the minimum value, in units of 0.01 dB.
-      The third parameter is the maximum value, in units of 0.01 dB.
-      If the minimum value mutes the control, set the second parameter to
-      <constant>TLV_DB_GAIN_MUTE</constant>.
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- API for AC97 Codec  -->
-<!-- ****************************************************** -->
-  <chapter id="api-ac97">
-    <title>API for AC97 Codec</title>
-
-    <section>
-      <title>General</title>
-      <para>
-        The ALSA AC97 codec layer is a well-defined one, and you don't
-      have to write much code to control it. Only low-level control
-      routines are necessary. The AC97 codec API is defined in
-      <filename>&lt;sound/ac97_codec.h&gt;</filename>. 
-      </para>
-    </section>
-
-    <section id="api-ac97-example">
-      <title>Full Code Example</title>
-      <para>
-          <example>
-	    <title>Example of AC97 Interface</title>
-            <programlisting>
-<![CDATA[
-  struct mychip {
-          ....
-          struct snd_ac97 *ac97;
-          ....
-  };
-
-  static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
-                                             unsigned short reg)
-  {
-          struct mychip *chip = ac97->private_data;
-          ....
-          /* read a register value here from the codec */
-          return the_register_value;
-  }
-
-  static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
-                                   unsigned short reg, unsigned short val)
-  {
-          struct mychip *chip = ac97->private_data;
-          ....
-          /* write the given register value to the codec */
-  }
-
-  static int snd_mychip_ac97(struct mychip *chip)
-  {
-          struct snd_ac97_bus *bus;
-          struct snd_ac97_template ac97;
-          int err;
-          static struct snd_ac97_bus_ops ops = {
-                  .write = snd_mychip_ac97_write,
-                  .read = snd_mychip_ac97_read,
-          };
-
-          err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
-          if (err < 0)
-                  return err;
-          memset(&ac97, 0, sizeof(ac97));
-          ac97.private_data = chip;
-          return snd_ac97_mixer(bus, &ac97, &chip->ac97);
-  }
-
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="api-ac97-constructor">
-      <title>Constructor</title>
-      <para>
-        To create an ac97 instance, first call <function>snd_ac97_bus</function>
-      with an <type>ac97_bus_ops_t</type> record with callback functions.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_ac97_bus *bus;
-  static struct snd_ac97_bus_ops ops = {
-        .write = snd_mychip_ac97_write,
-        .read = snd_mychip_ac97_read,
-  };
-
-  snd_ac97_bus(card, 0, &ops, NULL, &pbus);
-]]>
-          </programlisting>
-        </informalexample>
-
-      The bus record is shared among all belonging ac97 instances.
-      </para>
-
-      <para>
-      And then call <function>snd_ac97_mixer()</function> with an
-      struct <structname>snd_ac97_template</structname>
-      record together with the bus pointer created above.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_ac97_template ac97;
-  int err;
-
-  memset(&ac97, 0, sizeof(ac97));
-  ac97.private_data = chip;
-  snd_ac97_mixer(bus, &ac97, &chip->ac97);
-]]>
-          </programlisting>
-        </informalexample>
-
-        where chip-&gt;ac97 is a pointer to a newly created
-        <type>ac97_t</type> instance.
-        In this case, the chip pointer is set as the private data, so that
-        the read/write callback functions can refer to this chip instance.
-        This instance is not necessarily stored in the chip
-	record.  If you need to change the register values from the
-        driver, or need the suspend/resume of ac97 codecs, keep this
-        pointer to pass to the corresponding functions.
-      </para>
-    </section>
-
-    <section id="api-ac97-callbacks">
-      <title>Callbacks</title>
-      <para>
-        The standard callbacks are <structfield>read</structfield> and
-      <structfield>write</structfield>. Obviously they 
-      correspond to the functions for read and write accesses to the
-      hardware low-level codes. 
-      </para>
-
-      <para>
-        The <structfield>read</structfield> callback returns the
-        register value specified in the argument. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
-                                             unsigned short reg)
-  {
-          struct mychip *chip = ac97->private_data;
-          ....
-          return the_register_value;
-  }
-]]>
-          </programlisting>
-        </informalexample>
-
-        Here, the chip can be cast from ac97-&gt;private_data.
-      </para>
-
-      <para>
-        Meanwhile, the <structfield>write</structfield> callback is
-        used to set the register value. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
-                       unsigned short reg, unsigned short val)
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      These callbacks are non-atomic like the control API callbacks.
-      </para>
-
-      <para>
-        There are also other callbacks:
-      <structfield>reset</structfield>,
-      <structfield>wait</structfield> and
-      <structfield>init</structfield>. 
-      </para>
-
-      <para>
-        The <structfield>reset</structfield> callback is used to reset
-      the codec. If the chip requires a special kind of reset, you can
-      define this callback. 
-      </para>
-
-      <para>
-        The <structfield>wait</structfield> callback is used to
-      add some waiting time in the standard initialization of the codec. If the
-      chip requires the extra waiting time, define this callback. 
-      </para>
-
-      <para>
-        The <structfield>init</structfield> callback is used for
-      additional initialization of the codec.
-      </para>
-    </section>
-
-    <section id="api-ac97-updating-registers">
-      <title>Updating Registers in The Driver</title>
-      <para>
-        If you need to access to the codec from the driver, you can
-      call the following functions:
-      <function>snd_ac97_write()</function>,
-      <function>snd_ac97_read()</function>,
-      <function>snd_ac97_update()</function> and
-      <function>snd_ac97_update_bits()</function>. 
-      </para>
-
-      <para>
-        Both <function>snd_ac97_write()</function> and
-        <function>snd_ac97_update()</function> functions are used to
-        set a value to the given register
-        (<constant>AC97_XXX</constant>). The difference between them is
-        that <function>snd_ac97_update()</function> doesn't write a
-        value if the given value has been already set, while
-        <function>snd_ac97_write()</function> always rewrites the
-        value. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ac97_write(ac97, AC97_MASTER, 0x8080);
-  snd_ac97_update(ac97, AC97_MASTER, 0x8080);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        <function>snd_ac97_read()</function> is used to read the value
-        of the given register. For example, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  value = snd_ac97_read(ac97, AC97_MASTER);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        <function>snd_ac97_update_bits()</function> is used to update
-        some bits in the given register.  
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ac97_update_bits(ac97, reg, mask, value);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Also, there is a function to change the sample rate (of a
-        given register such as
-        <constant>AC97_PCM_FRONT_DAC_RATE</constant>) when VRA or
-        DRA is supported by the codec:
-        <function>snd_ac97_set_rate()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The following registers are available to set the rate:
-      <constant>AC97_PCM_MIC_ADC_RATE</constant>,
-      <constant>AC97_PCM_FRONT_DAC_RATE</constant>,
-      <constant>AC97_PCM_LR_ADC_RATE</constant>,
-      <constant>AC97_SPDIF</constant>. When
-      <constant>AC97_SPDIF</constant> is specified, the register is
-      not really changed but the corresponding IEC958 status bits will
-      be updated. 
-      </para>
-    </section>
-
-    <section id="api-ac97-clock-adjustment">
-      <title>Clock Adjustment</title>
-      <para>
-        In some chips, the clock of the codec isn't 48000 but using a
-      PCI clock (to save a quartz!). In this case, change the field
-      bus-&gt;clock to the corresponding
-      value. For example, intel8x0 
-      and es1968 drivers have their own function to read from the clock.
-      </para>
-    </section>
-
-    <section id="api-ac97-proc-files">
-      <title>Proc Files</title>
-      <para>
-        The ALSA AC97 interface will create a proc file such as
-      <filename>/proc/asound/card0/codec97#0/ac97#0-0</filename> and
-      <filename>ac97#0-0+regs</filename>. You can refer to these files to
-      see the current status and registers of the codec. 
-      </para>
-    </section>
-
-    <section id="api-ac97-multiple-codecs">
-      <title>Multiple Codecs</title>
-      <para>
-        When there are several codecs on the same card, you need to
-      call <function>snd_ac97_mixer()</function> multiple times with
-      ac97.num=1 or greater. The <structfield>num</structfield> field
-      specifies the codec number. 
-      </para>
-
-      <para>
-        If you set up multiple codecs, you either need to write
-      different callbacks for each codec or check
-      ac97-&gt;num in the callback routines. 
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- MIDI (MPU401-UART) Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="midi-interface">
-    <title>MIDI (MPU401-UART) Interface</title>
-
-    <section id="midi-interface-general">
-      <title>General</title>
-      <para>
-        Many soundcards have built-in MIDI (MPU401-UART)
-      interfaces. When the soundcard supports the standard MPU401-UART
-      interface, most likely you can use the ALSA MPU401-UART API. The
-      MPU401-UART API is defined in
-      <filename>&lt;sound/mpu401.h&gt;</filename>. 
-      </para>
-
-      <para>
-        Some soundchips have a similar but slightly different
-      implementation of mpu401 stuff. For example, emu10k1 has its own
-      mpu401 routines. 
-      </para>
-    </section>
-
-    <section id="midi-interface-constructor">
-      <title>Constructor</title>
-      <para>
-        To create a rawmidi object, call
-      <function>snd_mpu401_uart_new()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi *rmidi;
-  snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
-                      irq, irq_flags, &rmidi);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first argument is the card pointer, and the second is the
-      index of this component. You can create up to 8 rawmidi
-      devices. 
-      </para>
-
-      <para>
-        The third argument is the type of the hardware,
-      <constant>MPU401_HW_XXX</constant>. If it's not a special one,
-      you can use <constant>MPU401_HW_MPU401</constant>. 
-      </para>
-
-      <para>
-        The 4th argument is the I/O port address. Many
-      backward-compatible MPU401 have an I/O port such as 0x330. Or, it
-      might be a part of its own PCI I/O region. It depends on the
-      chip design. 
-      </para>
-
-      <para>
-	The 5th argument is a bitflag for additional information.
-        When the I/O port address above is part of the PCI I/O
-      region, the MPU401 I/O port might have been already allocated
-      (reserved) by the driver itself. In such a case, pass a bit flag
-      <constant>MPU401_INFO_INTEGRATED</constant>,
-      and the mpu401-uart layer will allocate the I/O ports by itself. 
-      </para>
-
-	<para>
-	When the controller supports only the input or output MIDI stream,
-	pass the <constant>MPU401_INFO_INPUT</constant> or
-	<constant>MPU401_INFO_OUTPUT</constant> bitflag, respectively.
-	Then the rawmidi instance is created as a single stream.
-	</para>
-
-	<para>
-	<constant>MPU401_INFO_MMIO</constant> bitflag is used to change
-	the access method to MMIO (via readb and writeb) instead of
-	iob and outb. In this case, you have to pass the iomapped address
-	to <function>snd_mpu401_uart_new()</function>.
-	</para>
-
-	<para>
-	When <constant>MPU401_INFO_TX_IRQ</constant> is set, the output
-	stream isn't checked in the default interrupt handler.  The driver
-	needs to call <function>snd_mpu401_uart_interrupt_tx()</function>
-	by itself to start processing the output stream in the irq handler.
-	</para>
-
-      <para>
-        Usually, the port address corresponds to the command port and
-        port + 1 corresponds to the data port. If not, you may change
-        the <structfield>cport</structfield> field of
-        struct <structname>snd_mpu401</structname> manually 
-        afterward. However, <structname>snd_mpu401</structname> pointer is not
-        returned explicitly by
-        <function>snd_mpu401_uart_new()</function>. You need to cast
-        rmidi-&gt;private_data to
-        <structname>snd_mpu401</structname> explicitly, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_mpu401 *mpu;
-  mpu = rmidi->private_data;
-]]>
-          </programlisting>
-        </informalexample>
-
-        and reset the cport as you like:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  mpu->cport = my_own_control_port;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The 6th argument specifies the irq number for UART. If the irq
-      is already allocated, pass 0 to the 7th argument
-      (<parameter>irq_flags</parameter>). Otherwise, pass the flags
-      for irq allocation 
-      (<constant>SA_XXX</constant> bits) to it, and the irq will be
-      reserved by the mpu401-uart layer. If the card doesn't generate
-      UART interrupts, pass -1 as the irq number. Then a timer
-      interrupt will be invoked for polling. 
-      </para>
-    </section>
-
-    <section id="midi-interface-interrupt-handler">
-      <title>Interrupt Handler</title>
-      <para>
-        When the interrupt is allocated in
-      <function>snd_mpu401_uart_new()</function>, the private
-      interrupt handler is used, hence you don't have anything else to do
-      than creating the mpu401 stuff. Otherwise, you have to call
-      <function>snd_mpu401_uart_interrupt()</function> explicitly when
-      a UART interrupt is invoked and checked in your own interrupt
-      handler.  
-      </para>
-
-      <para>
-        In this case, you need to pass the private_data of the
-        returned rawmidi object from
-        <function>snd_mpu401_uart_new()</function> as the second
-        argument of <function>snd_mpu401_uart_interrupt()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- RawMIDI Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="rawmidi-interface">
-    <title>RawMIDI Interface</title>
-
-    <section id="rawmidi-interface-overview">
-      <title>Overview</title>
-
-      <para>
-      The raw MIDI interface is used for hardware MIDI ports that can
-      be accessed as a byte stream.  It is not used for synthesizer
-      chips that do not directly understand MIDI.
-      </para>
-
-      <para>
-      ALSA handles file and buffer management.  All you have to do is
-      to write some code to move data between the buffer and the
-      hardware.
-      </para>
-
-      <para>
-      The rawmidi API is defined in
-      <filename>&lt;sound/rawmidi.h&gt;</filename>.
-      </para>
-    </section>
-
-    <section id="rawmidi-interface-constructor">
-      <title>Constructor</title>
-
-      <para>
-      To create a rawmidi device, call the
-      <function>snd_rawmidi_new</function> function:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi *rmidi;
-  err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
-  if (err < 0)
-          return err;
-  rmidi->private_data = chip;
-  strcpy(rmidi->name, "My MIDI");
-  rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
-                      SNDRV_RAWMIDI_INFO_INPUT |
-                      SNDRV_RAWMIDI_INFO_DUPLEX;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      The first argument is the card pointer, the second argument is
-      the ID string.
-      </para>
-
-      <para>
-      The third argument is the index of this component.  You can
-      create up to 8 rawmidi devices.
-      </para>
-
-      <para>
-      The fourth and fifth arguments are the number of output and
-      input substreams, respectively, of this device (a substream is
-      the equivalent of a MIDI port).
-      </para>
-
-      <para>
-      Set the <structfield>info_flags</structfield> field to specify
-      the capabilities of the device.
-      Set <constant>SNDRV_RAWMIDI_INFO_OUTPUT</constant> if there is
-      at least one output port,
-      <constant>SNDRV_RAWMIDI_INFO_INPUT</constant> if there is at
-      least one input port,
-      and <constant>SNDRV_RAWMIDI_INFO_DUPLEX</constant> if the device
-      can handle output and input at the same time.
-      </para>
-
-      <para>
-      After the rawmidi device is created, you need to set the
-      operators (callbacks) for each substream.  There are helper
-      functions to set the operators for all the substreams of a device:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
-  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      The operators are usually defined like this:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct snd_rawmidi_ops snd_mymidi_output_ops = {
-          .open =    snd_mymidi_output_open,
-          .close =   snd_mymidi_output_close,
-          .trigger = snd_mymidi_output_trigger,
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      These callbacks are explained in the <link
-      linkend="rawmidi-interface-callbacks"><citetitle>Callbacks</citetitle></link>
-      section.
-      </para>
-
-      <para>
-      If there are more than one substream, you should give a
-      unique name to each of them:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi_substream *substream;
-  list_for_each_entry(substream,
-                      &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
-                      list {
-          sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
-  }
-  /* same for SNDRV_RAWMIDI_STREAM_INPUT */
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-    <section id="rawmidi-interface-callbacks">
-      <title>Callbacks</title>
-
-      <para>
-      In all the callbacks, the private data that you've set for the
-      rawmidi device can be accessed as
-      substream-&gt;rmidi-&gt;private_data.
-      <!-- <code> isn't available before DocBook 4.3 -->
-      </para>
-
-      <para>
-      If there is more than one port, your callbacks can determine the
-      port index from the struct snd_rawmidi_substream data passed to each
-      callback:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi_substream *substream;
-  int index = substream->number;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <section id="rawmidi-interface-op-open">
-      <title><function>open</function> callback</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_rawmidi_substream *substream);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is called when a substream is opened.
-        You can initialize the hardware here, but you shouldn't
-        start transmitting/receiving data yet.
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-close">
-      <title><function>close</function> callback</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int snd_xxx_close(struct snd_rawmidi_substream *substream);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        Guess what.
-        </para>
-
-        <para>
-        The <function>open</function> and <function>close</function>
-        callbacks of a rawmidi device are serialized with a mutex,
-        and can sleep.
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-trigger-out">
-      <title><function>trigger</function> callback for output
-      substreams</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_xxx_output_trigger(struct snd_rawmidi_substream *substream, int up);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is called with a nonzero <parameter>up</parameter>
-        parameter when there is some data in the substream buffer that
-        must be transmitted.
-        </para>
-
-        <para>
-        To read data from the buffer, call
-        <function>snd_rawmidi_transmit_peek</function>.  It will
-        return the number of bytes that have been read; this will be
-        less than the number of bytes requested when there are no more
-        data in the buffer.
-        After the data have been transmitted successfully, call
-        <function>snd_rawmidi_transmit_ack</function> to remove the
-        data from the substream buffer:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  unsigned char data;
-  while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
-          if (snd_mychip_try_to_transmit(data))
-                  snd_rawmidi_transmit_ack(substream, 1);
-          else
-                  break; /* hardware FIFO full */
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-        If you know beforehand that the hardware will accept data, you
-        can use the <function>snd_rawmidi_transmit</function> function
-        which reads some data and removes them from the buffer at once:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  while (snd_mychip_transmit_possible()) {
-          unsigned char data;
-          if (snd_rawmidi_transmit(substream, &data, 1) != 1)
-                  break; /* no more data */
-          snd_mychip_transmit(data);
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-        If you know beforehand how many bytes you can accept, you can
-        use a buffer size greater than one with the
-        <function>snd_rawmidi_transmit*</function> functions.
-        </para>
-
-        <para>
-        The <function>trigger</function> callback must not sleep.  If
-        the hardware FIFO is full before the substream buffer has been
-        emptied, you have to continue transmitting data later, either
-        in an interrupt handler, or with a timer if the hardware
-        doesn't have a MIDI transmit interrupt.
-        </para>
-
-        <para>
-        The <function>trigger</function> callback is called with a
-        zero <parameter>up</parameter> parameter when the transmission
-        of data should be aborted.
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-trigger-in">
-      <title><function>trigger</function> callback for input
-      substreams</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_xxx_input_trigger(struct snd_rawmidi_substream *substream, int up);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is called with a nonzero <parameter>up</parameter>
-        parameter to enable receiving data, or with a zero
-        <parameter>up</parameter> parameter do disable receiving data.
-        </para>
-
-        <para>
-        The <function>trigger</function> callback must not sleep; the
-        actual reading of data from the device is usually done in an
-        interrupt handler.
-        </para>
-
-        <para>
-        When data reception is enabled, your interrupt handler should
-        call <function>snd_rawmidi_receive</function> for all received
-        data:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  void snd_mychip_midi_interrupt(...)
-  {
-          while (mychip_midi_available()) {
-                  unsigned char data;
-                  data = mychip_midi_read();
-                  snd_rawmidi_receive(substream, &data, 1);
-          }
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-drain">
-      <title><function>drain</function> callback</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_xxx_drain(struct snd_rawmidi_substream *substream);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is only used with output substreams.  This function should wait
-        until all data read from the substream buffer have been transmitted.
-        This ensures that the device can be closed and the driver unloaded
-        without losing data.
-        </para>
-
-        <para>
-        This callback is optional. If you do not set
-        <structfield>drain</structfield> in the struct snd_rawmidi_ops
-        structure, ALSA will simply wait for 50&nbsp;milliseconds
-        instead.
-        </para>
-      </section>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Miscellaneous Devices  -->
-<!-- ****************************************************** -->
-  <chapter id="misc-devices">
-    <title>Miscellaneous Devices</title>
-
-    <section id="misc-devices-opl3">
-      <title>FM OPL3</title>
-      <para>
-        The FM OPL3 is still used in many chips (mainly for backward
-      compatibility). ALSA has a nice OPL3 FM control layer, too. The
-      OPL3 API is defined in
-      <filename>&lt;sound/opl3.h&gt;</filename>. 
-      </para>
-
-      <para>
-        FM registers can be directly accessed through the direct-FM API,
-      defined in <filename>&lt;sound/asound_fm.h&gt;</filename>. In
-      ALSA native mode, FM registers are accessed through
-      the Hardware-Dependant Device direct-FM extension API, whereas in
-      OSS compatible mode, FM registers can be accessed with the OSS
-      direct-FM compatible API in <filename>/dev/dmfmX</filename> device. 
-      </para>
-
-      <para>
-        To create the OPL3 component, you have two functions to
-        call. The first one is a constructor for the <type>opl3_t</type>
-        instance. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_opl3 *opl3;
-  snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,
-                  integrated, &opl3);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first argument is the card pointer, the second one is the
-      left port address, and the third is the right port address. In
-      most cases, the right port is placed at the left port + 2. 
-      </para>
-
-      <para>
-        The fourth argument is the hardware type.
-      </para>
-
-      <para>
-        When the left and right ports have been already allocated by
-      the card driver, pass non-zero to the fifth argument
-      (<parameter>integrated</parameter>). Otherwise, the opl3 module will
-      allocate the specified ports by itself. 
-      </para>
-
-      <para>
-        When the accessing the hardware requires special method
-        instead of the standard I/O access, you can create opl3 instance
-        separately with <function>snd_opl3_new()</function>.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_opl3 *opl3;
-  snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-	Then set <structfield>command</structfield>,
-	<structfield>private_data</structfield> and
-	<structfield>private_free</structfield> for the private
-	access function, the private data and the destructor.
-	The l_port and r_port are not necessarily set.  Only the
-	command must be set properly.  You can retrieve the data
-	from the opl3-&gt;private_data field.
-      </para>
-
-      <para>
-	After creating the opl3 instance via <function>snd_opl3_new()</function>,
-	call <function>snd_opl3_init()</function> to initialize the chip to the
-	proper state. Note that <function>snd_opl3_create()</function> always
-	calls it internally.
-      </para>
-
-      <para>
-        If the opl3 instance is created successfully, then create a
-        hwdep device for this opl3. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_hwdep *opl3hwdep;
-  snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first argument is the <type>opl3_t</type> instance you
-      created, and the second is the index number, usually 0. 
-      </para>
-
-      <para>
-        The third argument is the index-offset for the sequencer
-      client assigned to the OPL3 port. When there is an MPU401-UART,
-      give 1 for here (UART always takes 0). 
-      </para>
-    </section>
-
-    <section id="misc-devices-hardware-dependent">
-      <title>Hardware-Dependent Devices</title>
-      <para>
-        Some chips need user-space access for special
-      controls or for loading the micro code. In such a case, you can
-      create a hwdep (hardware-dependent) device. The hwdep API is
-      defined in <filename>&lt;sound/hwdep.h&gt;</filename>. You can
-      find examples in opl3 driver or
-      <filename>isa/sb/sb16_csp.c</filename>. 
-      </para>
-
-      <para>
-        The creation of the <type>hwdep</type> instance is done via
-        <function>snd_hwdep_new()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_hwdep *hw;
-  snd_hwdep_new(card, "My HWDEP", 0, &hw);
-]]>
-          </programlisting>
-        </informalexample>
-
-        where the third argument is the index number.
-      </para>
-
-      <para>
-        You can then pass any pointer value to the
-        <parameter>private_data</parameter>.
-        If you assign a private data, you should define the
-        destructor, too. The destructor function is set in
-        the <structfield>private_free</structfield> field.  
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);
-  hw->private_data = p;
-  hw->private_free = mydata_free;
-]]>
-          </programlisting>
-        </informalexample>
-
-        and the implementation of the destructor would be:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void mydata_free(struct snd_hwdep *hw)
-  {
-          struct mydata *p = hw->private_data;
-          kfree(p);
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The arbitrary file operations can be defined for this
-        instance. The file operators are defined in
-        the <parameter>ops</parameter> table. For example, assume that
-        this chip needs an ioctl. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  hw->ops.open = mydata_open;
-  hw->ops.ioctl = mydata_ioctl;
-  hw->ops.release = mydata_release;
-]]>
-          </programlisting>
-        </informalexample>
-
-        And implement the callback functions as you like.
-      </para>
-    </section>
-
-    <section id="misc-devices-IEC958">
-      <title>IEC958 (S/PDIF)</title>
-      <para>
-        Usually the controls for IEC958 devices are implemented via
-      the control interface. There is a macro to compose a name string for
-      IEC958 controls, <function>SNDRV_CTL_NAME_IEC958()</function>
-      defined in <filename>&lt;include/asound.h&gt;</filename>.  
-      </para>
-
-      <para>
-        There are some standard controls for IEC958 status bits. These
-      controls use the type <type>SNDRV_CTL_ELEM_TYPE_IEC958</type>,
-      and the size of element is fixed as 4 bytes array
-      (value.iec958.status[x]). For the <structfield>info</structfield>
-      callback, you don't specify 
-      the value field for this type (the count field must be set,
-      though). 
-      </para>
-
-      <para>
-        <quote>IEC958 Playback Con Mask</quote> is used to return the
-      bit-mask for the IEC958 status bits of consumer mode. Similarly,
-      <quote>IEC958 Playback Pro Mask</quote> returns the bitmask for
-      professional mode. They are read-only controls, and are defined
-      as MIXER controls (iface =
-      <constant>SNDRV_CTL_ELEM_IFACE_MIXER</constant>).  
-      </para>
-
-      <para>
-        Meanwhile, <quote>IEC958 Playback Default</quote> control is
-      defined for getting and setting the current default IEC958
-      bits. Note that this one is usually defined as a PCM control
-      (iface = <constant>SNDRV_CTL_ELEM_IFACE_PCM</constant>),
-      although in some places it's defined as a MIXER control. 
-      </para>
-
-      <para>
-        In addition, you can define the control switches to
-      enable/disable or to set the raw bit mode. The implementation
-      will depend on the chip, but the control should be named as
-      <quote>IEC958 xxx</quote>, preferably using
-      the <function>SNDRV_CTL_NAME_IEC958()</function> macro. 
-      </para>
-
-      <para>
-        You can find several cases, for example,
-      <filename>pci/emu10k1</filename>,
-      <filename>pci/ice1712</filename>, or
-      <filename>pci/cmipci.c</filename>.  
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Buffer and Memory Management  -->
-<!-- ****************************************************** -->
-  <chapter id="buffer-and-memory">
-    <title>Buffer and Memory Management</title>
-
-    <section id="buffer-and-memory-buffer-types">
-      <title>Buffer Types</title>
-      <para>
-        ALSA provides several different buffer allocation functions
-      depending on the bus and the architecture. All these have a
-      consistent API. The allocation of physically-contiguous pages is
-      done via 
-      <function>snd_malloc_xxx_pages()</function> function, where xxx
-      is the bus type. 
-      </para>
-
-      <para>
-        The allocation of pages with fallback is
-      <function>snd_malloc_xxx_pages_fallback()</function>. This
-      function tries to allocate the specified pages but if the pages
-      are not available, it tries to reduce the page sizes until
-      enough space is found.
-      </para>
-
-      <para>
-      The release the pages, call
-      <function>snd_free_xxx_pages()</function> function. 
-      </para>
-
-      <para>
-      Usually, ALSA drivers try to allocate and reserve
-       a large contiguous physical space
-       at the time the module is loaded for the later use.
-       This is called <quote>pre-allocation</quote>.
-       As already written, you can call the following function at 
-       pcm instance construction time (in the case of PCI bus). 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                        snd_dma_pci_data(pci), size, max);
-]]>
-          </programlisting>
-        </informalexample>
-
-        where <parameter>size</parameter> is the byte size to be
-      pre-allocated and the <parameter>max</parameter> is the maximum
-      size to be changed via the <filename>prealloc</filename> proc file.
-      The allocator will try to get an area as large as possible
-      within the given size. 
-      </para>
-
-      <para>
-      The second argument (type) and the third argument (device pointer)
-      are dependent on the bus.
-      In the case of the ISA bus, pass <function>snd_dma_isa_data()</function>
-      as the third argument with <constant>SNDRV_DMA_TYPE_DEV</constant> type.
-      For the continuous buffer unrelated to the bus can be pre-allocated
-      with <constant>SNDRV_DMA_TYPE_CONTINUOUS</constant> type and the
-      <function>snd_dma_continuous_data(GFP_KERNEL)</function> device pointer,
-      where <constant>GFP_KERNEL</constant> is the kernel allocation flag to
-      use.
-      For the PCI scatter-gather buffers, use
-      <constant>SNDRV_DMA_TYPE_DEV_SG</constant> with
-      <function>snd_dma_pci_data(pci)</function>
-      (see the 
-          <link linkend="buffer-and-memory-non-contiguous"><citetitle>Non-Contiguous Buffers
-          </citetitle></link> section).
-      </para>
-
-      <para>
-        Once the buffer is pre-allocated, you can use the
-        allocator in the <structfield>hw_params</structfield> callback: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_lib_malloc_pages(substream, size);
-]]>
-          </programlisting>
-        </informalexample>
-
-        Note that you have to pre-allocate to use this function.
-      </para>
-    </section>
-
-    <section id="buffer-and-memory-external-hardware">
-      <title>External Hardware Buffers</title>
-      <para>
-        Some chips have their own hardware buffers and the DMA
-      transfer from the host memory is not available. In such a case,
-      you need to either 1) copy/set the audio data directly to the
-      external hardware buffer, or 2) make an intermediate buffer and
-      copy/set the data from it to the external hardware buffer in
-      interrupts (or in tasklets, preferably).
-      </para>
-
-      <para>
-        The first case works fine if the external hardware buffer is large
-      enough.  This method doesn't need any extra buffers and thus is
-      more effective. You need to define the
-      <structfield>copy</structfield> and
-      <structfield>silence</structfield> callbacks for 
-      the data transfer. However, there is a drawback: it cannot
-      be mmapped. The examples are GUS's GF1 PCM or emu8000's
-      wavetable PCM. 
-      </para>
-
-      <para>
-        The second case allows for mmap on the buffer, although you have
-      to handle an interrupt or a tasklet to transfer the data
-      from the intermediate buffer to the hardware buffer. You can find an
-      example in the vxpocket driver. 
-      </para>
-
-      <para>
-        Another case is when the chip uses a PCI memory-map
-      region for the buffer instead of the host memory. In this case,
-      mmap is available only on certain architectures like the Intel one.
-      In non-mmap mode, the data cannot be transferred as in the normal
-      way. Thus you need to define the <structfield>copy</structfield> and
-      <structfield>silence</structfield> callbacks as well, 
-      as in the cases above. The examples are found in
-      <filename>rme32.c</filename> and <filename>rme96.c</filename>. 
-      </para>
-
-      <para>
-        The implementation of the <structfield>copy</structfield> and
-        <structfield>silence</structfield> callbacks depends upon 
-        whether the hardware supports interleaved or non-interleaved
-        samples. The <structfield>copy</structfield> callback is
-        defined like below, a bit 
-        differently depending whether the direction is playback or
-        capture: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int playback_copy(struct snd_pcm_substream *substream, int channel,
-               snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
-  static int capture_copy(struct snd_pcm_substream *substream, int channel,
-               snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        In the case of interleaved samples, the second argument
-      (<parameter>channel</parameter>) is not used. The third argument
-      (<parameter>pos</parameter>) points the 
-      current position offset in frames. 
-      </para>
-
-      <para>
-        The meaning of the fourth argument is different between
-      playback and capture. For playback, it holds the source data
-      pointer, and for capture, it's the destination data pointer. 
-      </para>
-
-      <para>
-        The last argument is the number of frames to be copied.
-      </para>
-
-      <para>
-        What you have to do in this callback is again different
-        between playback and capture directions. In the
-        playback case, you copy the given amount of data
-        (<parameter>count</parameter>) at the specified pointer
-        (<parameter>src</parameter>) to the specified offset
-        (<parameter>pos</parameter>) on the hardware buffer. When
-        coded like memcpy-like way, the copy would be like: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
-            frames_to_bytes(runtime, count));
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        For the capture direction, you copy the given amount of
-        data (<parameter>count</parameter>) at the specified offset
-        (<parameter>pos</parameter>) on the hardware buffer to the
-        specified pointer (<parameter>dst</parameter>). 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
-            frames_to_bytes(runtime, count));
-]]>
-          </programlisting>
-        </informalexample>
-
-        Note that both the position and the amount of data are given
-      in frames. 
-      </para>
-
-      <para>
-        In the case of non-interleaved samples, the implementation
-      will be a bit more complicated. 
-      </para>
-
-      <para>
-        You need to check the channel argument, and if it's -1, copy
-      the whole channels. Otherwise, you have to copy only the
-      specified channel. Please check
-      <filename>isa/gus/gus_pcm.c</filename> as an example. 
-      </para>
-
-      <para>
-        The <structfield>silence</structfield> callback is also
-        implemented in a similar way. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int silence(struct snd_pcm_substream *substream, int channel,
-                     snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The meanings of arguments are the same as in the
-      <structfield>copy</structfield> 
-      callback, although there is no <parameter>src/dst</parameter>
-      argument. In the case of interleaved samples, the channel
-      argument has no meaning, as well as on
-      <structfield>copy</structfield> callback.  
-      </para>
-
-      <para>
-        The role of <structfield>silence</structfield> callback is to
-        set the given amount 
-        (<parameter>count</parameter>) of silence data at the
-        specified offset (<parameter>pos</parameter>) on the hardware
-        buffer. Suppose that the data format is signed (that is, the
-        silent-data is 0), and the implementation using a memset-like
-        function would be like: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0,
-            frames_to_bytes(runtime, count));
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        In the case of non-interleaved samples, again, the
-      implementation becomes a bit more complicated. See, for example,
-      <filename>isa/gus/gus_pcm.c</filename>. 
-      </para>
-    </section>
-
-    <section id="buffer-and-memory-non-contiguous">
-      <title>Non-Contiguous Buffers</title>
-      <para>
-        If your hardware supports the page table as in emu10k1 or the
-      buffer descriptors as in via82xx, you can use the scatter-gather
-      (SG) DMA. ALSA provides an interface for handling SG-buffers.
-      The API is provided in <filename>&lt;sound/pcm.h&gt;</filename>. 
-      </para>
-
-      <para>
-        For creating the SG-buffer handler, call
-        <function>snd_pcm_lib_preallocate_pages()</function> or
-        <function>snd_pcm_lib_preallocate_pages_for_all()</function>
-        with <constant>SNDRV_DMA_TYPE_DEV_SG</constant>
-	in the PCM constructor like other PCI pre-allocator.
-        You need to pass <function>snd_dma_pci_data(pci)</function>,
-        where pci is the struct <structname>pci_dev</structname> pointer
-        of the chip as well.
-        The <type>struct snd_sg_buf</type> instance is created as
-        substream-&gt;dma_private. You can cast
-        the pointer like: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Then call <function>snd_pcm_lib_malloc_pages()</function>
-      in the <structfield>hw_params</structfield> callback
-      as well as in the case of normal PCI buffer.
-      The SG-buffer handler will allocate the non-contiguous kernel
-      pages of the given size and map them onto the virtually contiguous
-      memory.  The virtual pointer is addressed in runtime-&gt;dma_area.
-      The physical address (runtime-&gt;dma_addr) is set to zero,
-      because the buffer is physically non-contigous.
-      The physical address table is set up in sgbuf-&gt;table.
-      You can get the physical address at a certain offset via
-      <function>snd_pcm_sgbuf_get_addr()</function>. 
-      </para>
-
-      <para>
-        When a SG-handler is used, you need to set
-      <function>snd_pcm_sgbuf_ops_page</function> as
-      the <structfield>page</structfield> callback.
-      (See <link linkend="pcm-interface-operators-page-callback">
-      <citetitle>page callback section</citetitle></link>.)
-      </para>
-
-      <para>
-        To release the data, call
-      <function>snd_pcm_lib_free_pages()</function> in the
-      <structfield>hw_free</structfield> callback as usual.
-      </para>
-    </section>
-
-    <section id="buffer-and-memory-vmalloced">
-      <title>Vmalloc'ed Buffers</title>
-      <para>
-        It's possible to use a buffer allocated via
-      <function>vmalloc</function>, for example, for an intermediate
-      buffer. Since the allocated pages are not contiguous, you need
-      to set the <structfield>page</structfield> callback to obtain
-      the physical address at every offset. 
-      </para>
-
-      <para>
-        The implementation of <structfield>page</structfield> callback
-        would be like this: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  #include <linux/vmalloc.h>
-
-  /* get the physical page pointer on the given offset */
-  static struct page *mychip_page(struct snd_pcm_substream *substream,
-                                  unsigned long offset)
-  {
-          void *pageptr = substream->runtime->dma_area + offset;
-          return vmalloc_to_page(pageptr);
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Proc Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="proc-interface">
-    <title>Proc Interface</title>
-    <para>
-      ALSA provides an easy interface for procfs. The proc files are
-      very useful for debugging. I recommend you set up proc files if
-      you write a driver and want to get a running status or register
-      dumps. The API is found in
-      <filename>&lt;sound/info.h&gt;</filename>. 
-    </para>
-
-    <para>
-      To create a proc file, call
-      <function>snd_card_proc_new()</function>. 
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  struct snd_info_entry *entry;
-  int err = snd_card_proc_new(card, "my-file", &entry);
-]]>
-        </programlisting>
-      </informalexample>
-
-      where the second argument specifies the name of the proc file to be
-    created. The above example will create a file
-    <filename>my-file</filename> under the card directory,
-    e.g. <filename>/proc/asound/card0/my-file</filename>. 
-    </para>
-
-    <para>
-    Like other components, the proc entry created via
-    <function>snd_card_proc_new()</function> will be registered and
-    released automatically in the card registration and release
-    functions.
-    </para>
-
-    <para>
-      When the creation is successful, the function stores a new
-    instance in the pointer given in the third argument.
-    It is initialized as a text proc file for read only.  To use
-    this proc file as a read-only text file as it is, set the read
-    callback with a private data via 
-     <function>snd_info_set_text_ops()</function>.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  snd_info_set_text_ops(entry, chip, my_proc_read);
-]]>
-        </programlisting>
-      </informalexample>
-    
-    where the second argument (<parameter>chip</parameter>) is the
-    private data to be used in the callbacks. The third parameter
-    specifies the read buffer size and the fourth
-    (<parameter>my_proc_read</parameter>) is the callback function, which
-    is defined like
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static void my_proc_read(struct snd_info_entry *entry,
-                           struct snd_info_buffer *buffer);
-]]>
-        </programlisting>
-      </informalexample>
-    
-    </para>
-
-    <para>
-    In the read callback, use <function>snd_iprintf()</function> for
-    output strings, which works just like normal
-    <function>printf()</function>.  For example,
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static void my_proc_read(struct snd_info_entry *entry,
-                           struct snd_info_buffer *buffer)
-  {
-          struct my_chip *chip = entry->private_data;
-
-          snd_iprintf(buffer, "This is my chip!\n");
-          snd_iprintf(buffer, "Port = %ld\n", chip->port);
-  }
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-    The file permissions can be changed afterwards.  As default, it's
-    set as read only for all users.  If you want to add write
-    permission for the user (root as default), do as follows:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-]]>
-        </programlisting>
-      </informalexample>
-
-    and set the write buffer size and the callback
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  entry->c.text.write = my_proc_write;
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      For the write callback, you can use
-    <function>snd_info_get_line()</function> to get a text line, and
-    <function>snd_info_get_str()</function> to retrieve a string from
-    the line. Some examples are found in
-    <filename>core/oss/mixer_oss.c</filename>, core/oss/and
-    <filename>pcm_oss.c</filename>. 
-    </para>
-
-    <para>
-      For a raw-data proc-file, set the attributes as follows:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static struct snd_info_entry_ops my_file_io_ops = {
-          .read = my_file_io_read,
-  };
-
-  entry->content = SNDRV_INFO_CONTENT_DATA;
-  entry->private_data = chip;
-  entry->c.ops = &my_file_io_ops;
-  entry->size = 4096;
-  entry->mode = S_IFREG | S_IRUGO;
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      The callback is much more complicated than the text-file
-      version. You need to use a low-level I/O functions such as
-      <function>copy_from/to_user()</function> to transfer the
-      data.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static long my_file_io_read(struct snd_info_entry *entry,
-                              void *file_private_data,
-                              struct file *file,
-                              char *buf,
-                              unsigned long count,
-                              unsigned long pos)
-  {
-          long size = count;
-          if (pos + size > local_max_size)
-                  size = local_max_size - pos;
-          if (copy_to_user(buf, local_data + pos, size))
-                  return -EFAULT;
-          return size;
-  }
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Power Management  -->
-<!-- ****************************************************** -->
-  <chapter id="power-management">
-    <title>Power Management</title>
-    <para>
-      If the chip is supposed to work with suspend/resume
-      functions, you need to add power-management code to the
-      driver. The additional code for power-management should be
-      <function>ifdef</function>'ed with
-      <constant>CONFIG_PM</constant>. 
-    </para>
-
-	<para>
-	If the driver <emphasis>fully</emphasis> supports suspend/resume
-	that is, the device can be
-	properly resumed to its state when suspend was called,
-	you can set the <constant>SNDRV_PCM_INFO_RESUME</constant> flag
-	in the pcm info field.  Usually, this is possible when the
-	registers of the chip can be safely saved and restored to
-	RAM. If this is set, the trigger callback is called with
-	<constant>SNDRV_PCM_TRIGGER_RESUME</constant> after the resume
-	callback completes. 
-	</para>
-
-	<para>
-	Even if the driver doesn't support PM fully but 
-	partial suspend/resume is still possible, it's still worthy to
-	implement suspend/resume callbacks. In such a case, applications
-	would reset the status by calling
-	<function>snd_pcm_prepare()</function> and restart the stream
-	appropriately.  Hence, you can define suspend/resume callbacks
-	below but don't set <constant>SNDRV_PCM_INFO_RESUME</constant>
-	info flag to the PCM.
-	</para>
-	
-	<para>
-	Note that the trigger with SUSPEND can always be called when
-	<function>snd_pcm_suspend_all</function> is called,
-	regardless of the <constant>SNDRV_PCM_INFO_RESUME</constant> flag.
-	The <constant>RESUME</constant> flag affects only the behavior
-	of <function>snd_pcm_resume()</function>.
-	(Thus, in theory,
-	<constant>SNDRV_PCM_TRIGGER_RESUME</constant> isn't needed
-	to be handled in the trigger callback when no
-	<constant>SNDRV_PCM_INFO_RESUME</constant> flag is set.  But,
-	it's better to keep it for compatibility reasons.)
-	</para>
-    <para>
-      In the earlier version of ALSA drivers, a common
-      power-management layer was provided, but it has been removed.
-      The driver needs to define the suspend/resume hooks according to
-      the bus the device is connected to.  In the case of PCI drivers, the
-      callbacks look like below:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  #ifdef CONFIG_PM
-  static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
-  {
-          .... /* do things for suspend */
-          return 0;
-  }
-  static int snd_my_resume(struct pci_dev *pci)
-  {
-          .... /* do things for suspend */
-          return 0;
-  }
-  #endif
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      The scheme of the real suspend job is as follows.
-
-      <orderedlist>
-        <listitem><para>Retrieve the card and the chip data.</para></listitem>
-        <listitem><para>Call <function>snd_power_change_state()</function> with
-	  <constant>SNDRV_CTL_POWER_D3hot</constant> to change the
-	  power status.</para></listitem>
-        <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem>
-	<listitem><para>If AC97 codecs are used, call
-	<function>snd_ac97_suspend()</function> for each codec.</para></listitem>
-        <listitem><para>Save the register values if necessary.</para></listitem>
-        <listitem><para>Stop the hardware if necessary.</para></listitem>
-        <listitem><para>Disable the PCI device by calling
-	  <function>pci_disable_device()</function>.  Then, call
-          <function>pci_save_state()</function> at last.</para></listitem>
-      </orderedlist>
-    </para>
-
-    <para>
-      A typical code would be like:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int mychip_suspend(struct pci_dev *pci, pm_message_t state)
-  {
-          /* (1) */
-          struct snd_card *card = pci_get_drvdata(pci);
-          struct mychip *chip = card->private_data;
-          /* (2) */
-          snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-          /* (3) */
-          snd_pcm_suspend_all(chip->pcm);
-          /* (4) */
-          snd_ac97_suspend(chip->ac97);
-          /* (5) */
-          snd_mychip_save_registers(chip);
-          /* (6) */
-          snd_mychip_stop_hardware(chip);
-          /* (7) */
-          pci_disable_device(pci);
-          pci_save_state(pci);
-          return 0;
-  }
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-    The scheme of the real resume job is as follows.
-
-    <orderedlist>
-    <listitem><para>Retrieve the card and the chip data.</para></listitem>
-    <listitem><para>Set up PCI. First, call <function>pci_restore_state()</function>.
-    	Then enable the pci device again by calling <function>pci_enable_device()</function>.
-	Call <function>pci_set_master()</function> if necessary, too.</para></listitem>
-    <listitem><para>Re-initialize the chip.</para></listitem>
-    <listitem><para>Restore the saved registers if necessary.</para></listitem>
-    <listitem><para>Resume the mixer, e.g. calling
-    <function>snd_ac97_resume()</function>.</para></listitem>
-    <listitem><para>Restart the hardware (if any).</para></listitem>
-    <listitem><para>Call <function>snd_power_change_state()</function> with
-	<constant>SNDRV_CTL_POWER_D0</constant> to notify the processes.</para></listitem>
-    </orderedlist>
-    </para>
-
-    <para>
-    A typical code would be like:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int mychip_resume(struct pci_dev *pci)
-  {
-          /* (1) */
-          struct snd_card *card = pci_get_drvdata(pci);
-          struct mychip *chip = card->private_data;
-          /* (2) */
-          pci_restore_state(pci);
-          pci_enable_device(pci);
-          pci_set_master(pci);
-          /* (3) */
-          snd_mychip_reinit_chip(chip);
-          /* (4) */
-          snd_mychip_restore_registers(chip);
-          /* (5) */
-          snd_ac97_resume(chip->ac97);
-          /* (6) */
-          snd_mychip_restart_chip(chip);
-          /* (7) */
-          snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-          return 0;
-  }
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-	As shown in the above, it's better to save registers after
-	suspending the PCM operations via
-	<function>snd_pcm_suspend_all()</function> or
-	<function>snd_pcm_suspend()</function>.  It means that the PCM
-	streams are already stoppped when the register snapshot is
-	taken.  But, remember that you don't have to restart the PCM
-	stream in the resume callback. It'll be restarted via 
-	trigger call with <constant>SNDRV_PCM_TRIGGER_RESUME</constant>
-	when necessary.
-    </para>
-
-    <para>
-      OK, we have all callbacks now. Let's set them up. In the
-      initialization of the card, make sure that you can get the chip
-      data from the card instance, typically via
-      <structfield>private_data</structfield> field, in case you
-      created the chip data individually.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int __devinit snd_mychip_probe(struct pci_dev *pci,
-                               const struct pci_device_id *pci_id)
-  {
-          ....
-          struct snd_card *card;
-          struct mychip *chip;
-          int err;
-          ....
-          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
-          ....
-          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-          ....
-          card->private_data = chip;
-          ....
-  }
-]]>
-        </programlisting>
-      </informalexample>
-
-	When you created the chip data with
-	<function>snd_card_create()</function>, it's anyway accessible
-	via <structfield>private_data</structfield> field.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int __devinit snd_mychip_probe(struct pci_dev *pci,
-                               const struct pci_device_id *pci_id)
-  {
-          ....
-          struct snd_card *card;
-          struct mychip *chip;
-          int err;
-          ....
-          err = snd_card_create(index[dev], id[dev], THIS_MODULE,
-                                sizeof(struct mychip), &card);
-          ....
-          chip = card->private_data;
-          ....
-  }
-]]>
-        </programlisting>
-      </informalexample>
-
-    </para>
-
-    <para>
-      If you need a space to save the registers, allocate the
-	buffer for it here, too, since it would be fatal
-    if you cannot allocate a memory in the suspend phase.
-    The allocated buffer should be released in the corresponding
-    destructor.
-    </para>
-
-    <para>
-      And next, set suspend/resume callbacks to the pci_driver.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static struct pci_driver driver = {
-          .name = "My Chip",
-          .id_table = snd_my_ids,
-          .probe = snd_my_probe,
-          .remove = __devexit_p(snd_my_remove),
-  #ifdef CONFIG_PM
-          .suspend = snd_my_suspend,
-          .resume = snd_my_resume,
-  #endif
-  };
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Module Parameters  -->
-<!-- ****************************************************** -->
-  <chapter id="module-parameters">
-    <title>Module Parameters</title>
-    <para>
-      There are standard module options for ALSA. At least, each
-      module should have the <parameter>index</parameter>,
-      <parameter>id</parameter> and <parameter>enable</parameter>
-      options. 
-    </para>
-
-    <para>
-      If the module supports multiple cards (usually up to
-      8 = <constant>SNDRV_CARDS</constant> cards), they should be
-      arrays. The default initial values are defined already as
-      constants for easier programming:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-  static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      If the module supports only a single card, they could be single
-    variables, instead.  <parameter>enable</parameter> option is not
-    always necessary in this case, but it would be better to have a
-    dummy option for compatibility.
-    </para>
-
-    <para>
-      The module parameters must be declared with the standard
-    <function>module_param()()</function>,
-    <function>module_param_array()()</function> and
-    <function>MODULE_PARM_DESC()</function> macros.
-    </para>
-
-    <para>
-      The typical coding would be like below:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  #define CARD_NAME "My Chip"
-
-  module_param_array(index, int, NULL, 0444);
-  MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-  module_param_array(id, charp, NULL, 0444);
-  MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-  module_param_array(enable, bool, NULL, 0444);
-  MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      Also, don't forget to define the module description, classes,
-      license and devices. Especially, the recent modprobe requires to
-      define the module license as GPL, etc., otherwise the system is
-      shown as <quote>tainted</quote>. 
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  MODULE_DESCRIPTION("My Chip");
-  MODULE_LICENSE("GPL");
-  MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- How To Put Your Driver  -->
-<!-- ****************************************************** -->
-  <chapter id="how-to-put-your-driver">
-    <title>How To Put Your Driver Into ALSA Tree</title>
-	<section>
-	<title>General</title>
-	<para>
-	So far, you've learned how to write the driver codes.
-	And you might have a question now: how to put my own
-	driver into the ALSA driver tree?
-	Here (finally :) the standard procedure is described briefly.
-	</para>
-
-	<para>
-	Suppose that you create a new PCI driver for the card
-	<quote>xyz</quote>.  The card module name would be
-	snd-xyz.  The new driver is usually put into the alsa-driver
-	tree, <filename>alsa-driver/pci</filename> directory in
-	the case of PCI cards.
-	Then the driver is evaluated, audited and tested
-	by developers and users.  After a certain time, the driver
-	will go to the alsa-kernel tree (to the corresponding directory,
-	such as <filename>alsa-kernel/pci</filename>) and eventually
- 	will be integrated into the Linux 2.6 tree (the directory would be
-	<filename>linux/sound/pci</filename>).
-	</para>
-
-	<para>
-	In the following sections, the driver code is supposed
-	to be put into alsa-driver tree. The two cases are covered:
-	a driver consisting of a single source file and one consisting
-	of several source files.
-	</para>
-	</section>
-
-	<section>
-	<title>Driver with A Single Source File</title>
-	<para>
-	<orderedlist>
-	<listitem>
-	<para>
-	Modify alsa-driver/pci/Makefile
-	</para>
-
-	<para>
-	Suppose you have a file xyz.c.  Add the following
-	two lines
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  snd-xyz-objs := xyz.o
-  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
-]]>
-        </programlisting>
-      </informalexample>
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Create the Kconfig entry
-	</para>
-
-	<para>
-	Add the new entry of Kconfig for your xyz driver.
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  config SND_XYZ
-          tristate "Foobar XYZ"
-          depends on SND
-          select SND_PCM
-          help
-            Say Y here to include support for Foobar XYZ soundcard.
-
-            To compile this driver as a module, choose M here: the module
-            will be called snd-xyz.
-]]>
-        </programlisting>
-      </informalexample>
-
-	the line, select SND_PCM, specifies that the driver xyz supports
-	PCM.  In addition to SND_PCM, the following components are
-	supported for select command:
-	SND_RAWMIDI, SND_TIMER, SND_HWDEP, SND_MPU401_UART,
-	SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB, SND_AC97_CODEC.
-	Add the select command for each supported component.
-	</para>
-
-	<para>
-	Note that some selections imply the lowlevel selections.
-	For example, PCM includes TIMER, MPU401_UART includes RAWMIDI,
-	AC97_CODEC includes PCM, and OPL3_LIB includes HWDEP.
-	You don't need to give the lowlevel selections again.
-	</para>
-
-	<para>
-	For the details of Kconfig script, refer to the kbuild
-	documentation.
-	</para>
-
-	</listitem>
-
-	<listitem>
-	<para>
-	Run cvscompile script to re-generate the configure script and
-	build the whole stuff again.
-	</para>
-	</listitem>
-	</orderedlist>
-	</para>
-	</section>
-
-	<section>
-	<title>Drivers with Several Source Files</title>
-	<para>
-	Suppose that the driver snd-xyz have several source files.
-	They are located in the new subdirectory,
-	pci/xyz.
-
-	<orderedlist>
-	<listitem>
-	<para>
-	Add a new directory (<filename>xyz</filename>) in
-	<filename>alsa-driver/pci/Makefile</filename> as below
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  obj-$(CONFIG_SND) += xyz/
-]]>
-        </programlisting>
-      </informalexample>
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Under the directory <filename>xyz</filename>, create a Makefile
-
-      <example>
-	<title>Sample Makefile for a driver xyz</title>
-        <programlisting>
-<![CDATA[
-  ifndef SND_TOPDIR
-  SND_TOPDIR=../..
-  endif
-
-  include $(SND_TOPDIR)/toplevel.config
-  include $(SND_TOPDIR)/Makefile.conf
-
-  snd-xyz-objs := xyz.o abc.o def.o
-
-  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
-
-  include $(SND_TOPDIR)/Rules.make
-]]>
-        </programlisting>
-      </example>
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Create the Kconfig entry
-	</para>
-
-	<para>
-	This procedure is as same as in the last section.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Run cvscompile script to re-generate the configure script and
-	build the whole stuff again.
-	</para>
-	</listitem>
-	</orderedlist>
-	</para>
-	</section>
-
-  </chapter>
-
-<!-- ****************************************************** -->
-<!-- Useful Functions  -->
-<!-- ****************************************************** -->
-  <chapter id="useful-functions">
-    <title>Useful Functions</title>
-
-    <section id="useful-functions-snd-printk">
-      <title><function>snd_printk()</function> and friends</title>
-      <para>
-        ALSA provides a verbose version of the
-      <function>printk()</function> function. If a kernel config
-      <constant>CONFIG_SND_VERBOSE_PRINTK</constant> is set, this
-      function prints the given message together with the file name
-      and the line of the caller. The <constant>KERN_XXX</constant>
-      prefix is processed as 
-      well as the original <function>printk()</function> does, so it's
-      recommended to add this prefix, e.g. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\n");
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        There are also <function>printk()</function>'s for
-      debugging. <function>snd_printd()</function> can be used for
-      general debugging purposes. If
-      <constant>CONFIG_SND_DEBUG</constant> is set, this function is
-      compiled, and works just like
-      <function>snd_printk()</function>. If the ALSA is compiled
-      without the debugging flag, it's ignored. 
-      </para>
-
-      <para>
-        <function>snd_printdd()</function> is compiled in only when
-      <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is set. Please note
-      that <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is not set as default
-      even if you configure the alsa-driver with
-      <option>--with-debug=full</option> option. You need to give
-      explicitly <option>--with-debug=detect</option> option instead. 
-      </para>
-    </section>
-
-    <section id="useful-functions-snd-bug">
-      <title><function>snd_BUG()</function></title>
-      <para>
-        It shows the <computeroutput>BUG?</computeroutput> message and
-      stack trace as well as <function>snd_BUG_ON</function> at the point.
-      It's useful to show that a fatal error happens there. 
-      </para>
-      <para>
-	 When no debug flag is set, this macro is ignored. 
-      </para>
-    </section>
-
-    <section id="useful-functions-snd-bug-on">
-      <title><function>snd_BUG_ON()</function></title>
-      <para>
-        <function>snd_BUG_ON()</function> macro is similar with
-	<function>WARN_ON()</function> macro. For example,  
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_BUG_ON(!pointer);
-]]>
-          </programlisting>
-        </informalexample>
-
-	or it can be used as the condition,
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (snd_BUG_ON(non_zero_is_bug))
-          return -EINVAL;
-]]>
-          </programlisting>
-        </informalexample>
-
-      </para>
-
-      <para>
-        The macro takes an conditional expression to evaluate.
-	When <constant>CONFIG_SND_DEBUG</constant>, is set, the
-	expression is actually evaluated. If it's non-zero, it shows
-	the warning message such as
-	<computeroutput>BUG? (xxx)</computeroutput>
-	normally followed by stack trace.  It returns the evaluated
-	value.
-	When no <constant>CONFIG_SND_DEBUG</constant> is set, this
-	macro always returns zero.
-      </para>
-
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Acknowledgments  -->
-<!-- ****************************************************** -->
-  <chapter id="acknowledgments">
-    <title>Acknowledgments</title>
-    <para>
-      I would like to thank Phil Kerr for his help for improvement and
-      corrections of this document. 
-    </para>
-    <para>
-    Kevin Conder reformatted the original plain-text to the
-    DocBook format.
-    </para>
-    <para>
-    Giuliano Pochini corrected typos and contributed the example codes
-    in the hardware constraints section.
-    </para>
-  </chapter>
-</book>
-- 
cgit v1.2.3-70-g09d2


From 6dfc0d2c4b9a5455c60e0b9ee95bbf22fc516cef Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Tue, 10 Mar 2009 07:54:20 +0100
Subject: ALSA: hda - Add missing models to documentation

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 80b796e4a80..f9253ea3c19 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -344,7 +344,9 @@ STAC92HD71B*
   dell-m4-1	Dell desktops
   dell-m4-2	Dell desktops
   dell-m4-3	Dell desktops
-  hp-m4		HP dv laptops
+  hp-m4		HP mini 1000
+  hp-dv5	HP dv series
+  hp-hdx	HP HDX series
   auto		BIOS setup (default)
 
 STAC92HD73*
@@ -361,6 +363,7 @@ STAC92HD83*
 ===========
   ref		Reference board
   mic-ref	Reference board with power managment for ports
+  dell-s14	Dell laptop
   auto		BIOS setup (default)
 
 STAC9872
-- 
cgit v1.2.3-70-g09d2


From 307282c8990c5658604b9fda8a64a9a07079b850 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 12 Mar 2009 18:17:58 +0100
Subject: ALSA: hda - Add model=vaio for STAC9872

Add the default pin config for model=vaio (in case of broken BIOS).

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa/HD-Audio-Models.txt |  3 ++-
 sound/pci/hda/patch_sigmatel.c               | 33 ++++++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 3 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index f9253ea3c19..8eec05bc079 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -368,4 +368,5 @@ STAC92HD83*
 
 STAC9872
 ========
-  N/A
+  vaio		VAIO laptop without SPDIF
+  auto		BIOS setup (default)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 72c87aa20bd..e06fc7decd3 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -155,6 +155,12 @@ enum {
 	STAC_927X_MODELS
 };
 
+enum {
+	STAC_9872_AUTO,
+	STAC_9872_VAIO,
+	STAC_9872_MODELS
+};
+
 struct sigmatel_event {
 	hda_nid_t nid;
 	unsigned char type;
@@ -5588,6 +5594,25 @@ static hda_nid_t stac9872_mux_nids[] = {
 	0x15
 };
 
+static unsigned int stac9872_vaio_pin_configs[9] = {
+	0x03211020, 0x411111f0, 0x411111f0, 0x03a15030,
+	0x411111f0, 0x90170110, 0x411111f0, 0x411111f0,
+	0x90a7013e
+};
+
+static const char *stac9872_models[STAC_9872_MODELS] = {
+	[STAC_9872_AUTO] = "auto",
+	[STAC_9872_VAIO] = "vaio",
+};
+
+static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = {
+	[STAC_9872_VAIO] = stac9872_vaio_pin_configs,
+};
+
+static struct snd_pci_quirk stac9872_cfg_tbl[] = {
+	{} /* terminator */
+};
+
 static int patch_stac9872(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec;
@@ -5598,11 +5623,15 @@ static int patch_stac9872(struct hda_codec *codec)
 		return -ENOMEM;
 	codec->spec = spec;
 
-#if 0 /* no model right now */
 	spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
 							stac9872_models,
 							stac9872_cfg_tbl);
-#endif
+	if (spec->board_config < 0)
+		snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, "
+			    "using BIOS defaults\n");
+	else
+		stac92xx_set_config_regs(codec,
+					 stac9872_brd_tbl[spec->board_config]);
 
 	spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
 	spec->pin_nids = stac9872_pin_nids;
-- 
cgit v1.2.3-70-g09d2


From 71969fd9e2c523d22bf1742eb31f1562247710eb Mon Sep 17 00:00:00 2001
From: Boaz Harrosh <bharrosh@panasas.com>
Date: Sun, 25 Jan 2009 16:50:02 +0200
Subject: [SCSI] major.h: char-major number for OSD device driver

Allocate major 260 for osd.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Torben Mathiasen <device@lanana.org>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 Documentation/devices.txt | 6 ++++++
 include/linux/major.h     | 1 +
 2 files changed, 7 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 2be08240ee8..62254d4510c 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -3145,6 +3145,12 @@ Your cooperation is appreciated.
 		  1 = /dev/blockrom1	Second ROM card's translation layer interface
 		  ...
 
+260 char	OSD (Object-based-device) SCSI Device
+		  0 = /dev/osd0		First OSD Device
+		  1 = /dev/osd1		Second OSD Device
+		  ...
+		  255 = /dev/osd255	256th OSD Device
+
  ****	ADDITIONAL /dev DIRECTORY ENTRIES
 
 This section details additional entries that should or may exist in
diff --git a/include/linux/major.h b/include/linux/major.h
index 88249452b93..058ec15dd06 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -171,5 +171,6 @@
 #define VIOTAPE_MAJOR		230
 
 #define BLOCK_EXT_MAJOR		259
+#define SCSI_OSD_MAJOR		260	/* open-osd's OSD scsi device */
 
 #endif
-- 
cgit v1.2.3-70-g09d2


From 78e0c621deca08e5f802383dbe75fd20b258ea4e Mon Sep 17 00:00:00 2001
From: Boaz Harrosh <bharrosh@panasas.com>
Date: Sun, 25 Jan 2009 17:21:40 +0200
Subject: [SCSI] osd: Documentation for OSD library

Add osd.txt to Documentation/scsi/

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Reviewed-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 Documentation/scsi/osd.txt | 198 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 198 insertions(+)
 create mode 100644 Documentation/scsi/osd.txt

(limited to 'Documentation')

diff --git a/Documentation/scsi/osd.txt b/Documentation/scsi/osd.txt
new file mode 100644
index 00000000000..da162f7fd5f
--- /dev/null
+++ b/Documentation/scsi/osd.txt
@@ -0,0 +1,198 @@
+The OSD Standard
+================
+OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
+to provide efficient operation of input/output logical units that manage the
+allocation, placement, and accessing of variable-size data-storage containers,
+called objects. Objects are intended to contain operating system and application
+constructs. Each object has associated attributes attached to it, which are
+integral part of the object and provide metadata about the object. The standard
+defines some common obligatory attributes, but user attributes can be added as
+needed.
+
+See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
+or search the web for "OSD SCSI"
+
+OSD in the Linux Kernel
+=======================
+osd-initiator:
+  The main component of OSD in Kernel is the osd-initiator library. Its main
+user is intended to be the pNFS-over-objects layout driver, which uses objects
+as its back-end data storage. Other clients are the other osd parts listed below.
+
+osd-uld:
+  This is a SCSI ULD that registers for OSD type devices and provides a testing
+platform, both for the in-kernel initiator as well as connected targets. It
+currently has no useful user-mode API, though it could have if need be.
+
+exofs:
+  Is an OSD based Linux file system. It uses the osd-initiator and osd-uld,
+to export a usable file system for users.
+See Documentation/filesystems/exofs.txt for more details
+
+osd target:
+  There are no current plans for an OSD target implementation in kernel. For all
+needs, a user-mode target that is based on the scsi tgt target framework is
+available from Ohio Supercomputer Center (OSC) at:
+http://www.open-osd.org/bin/view/Main/OscOsdProject
+There are several other target implementations. See http://open-osd.org for more
+links.
+
+Files and Folders
+=================
+This is the complete list of files included in this work:
+include/scsi/
+	osd_initiator.h   Main API for the initiator library
+	osd_types.h	  Common OSD types
+	osd_sec.h	  Security Manager API
+	osd_protocol.h	  Wire definitions of the OSD standard protocol
+	osd_attributes.h  Wire definitions of OSD attributes
+
+drivers/scsi/osd/
+	osd_initiator.c   OSD-Initiator library implementation
+	osd_uld.c	  The OSD scsi ULD
+	osd_ktest.{h,c}	  In-kernel test suite (called by osd_uld)
+	osd_debug.h	  Some printk macros
+	Makefile	  For both in-tree and out-of-tree compilation
+	Kconfig		  Enables inclusion of the different pieces
+	osd_test.c	  User-mode application to call the kernel tests
+
+The OSD-Initiator Library
+=========================
+osd_initiator is a low level implementation of an osd initiator encoder.
+But even though, it should be intuitive and easy to use. Perhaps over time an
+higher lever will form that automates some of the more common recipes.
+
+init/fini:
+- osd_dev_init() associates a scsi_device with an osd_dev structure
+  and initializes some global pools. This should be done once per scsi_device
+  (OSD LUN). The osd_dev structure is needed for calling osd_start_request().
+
+- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
+
+OSD commands encoding, execution, and decoding of results:
+
+struct osd_request's is used to iteratively encode an OSD command and carry
+its state throughout execution. Each request goes through these stages:
+
+a. osd_start_request() allocates the request.
+
+b. Any of the osd_req_* methods is used to encode a request of the specified
+   type.
+
+c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
+   CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
+   can be called multiple times on the same request. However, only one
+   attribute-page can be read, as mandated by the OSD standard.
+
+d. osd_finalize_request() computes offsets into the data-in and data-out buffers
+   and signs the request using the provided capability key and integrity-
+   check parameters.
+
+e. osd_execute_request() may be called to execute the request via the block
+   layer and wait for its completion.  The request can be executed
+   asynchronously by calling the block layer API directly.
+
+f. After execution, osd_req_decode_sense() can be called to decode the request's
+   sense information.
+
+g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
+   values.
+
+h. osd_end_request() must be called to deallocate the request and any resource
+   associated with it. Note that osd_end_request cleans up the request at any
+   stage and it must always be called after a successful osd_start_request().
+
+osd_request's structure:
+
+The OSD standard defines a complex structure of IO segments pointed to by
+members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
+4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
+associated get+set of attributes-lists. Other combinations very on the same
+basic theme. From no-segments-used up to all-segments-used.
+
+|________OSD-CDB__________|
+|                         |
+|read_len (offset=0)     -|---------\
+|                         |         |
+|get_attrs_list_length    |         |
+|get_attrs_list_offset   -|----\    |
+|                         |    |    |
+|retrieved_attrs_alloc_len|    |    |
+|retrieved_attrs_offset  -|----|----|-\
+|                         |    |    | |
+|set_attrs_list_length    |    |    | |
+|set_attrs_list_offset   -|-\  |    | |
+|                         | |  |    | |
+|in_data_integ_offset    -|-|--|----|-|-\
+|out_data_integ_offset   -|-|--|--\ | | |
+\_________________________/ |  |  | | | |
+                            |  |  | | | |
+|_______OUT-BUFFER________| |  |  | | | |
+|      Set attr list      |</  |  | | | |
+|                         |    |  | | | |
+|-------------------------|    |  | | | |
+|   Get attr descriptors  |<---/  | | | |
+|                         |       | | | |
+|-------------------------|       | | | |
+|    Out-data integrity   |<------/ | | |
+|                         |         | | |
+\_________________________/         | | |
+                                    | | |
+|________IN-BUFFER________|         | | |
+|      In-Data read       |<--------/ | |
+|                         |           | |
+|-------------------------|           | |
+|      Get attr list      |<----------/ |
+|                         |             |
+|-------------------------|             |
+|    In-data integrity    |<------------/
+|                         |
+\_________________________/
+
+A block device request can carry bidirectional payload by means of associating
+a bidi_read request with a main write-request. Each in/out request is described
+by a chain of BIOs associated with each request.
+The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
+The OSD standard also mandates alignment restrictions at start of each segment.
+
+In the code, in struct osd_request, there are two _osd_io_info structures to
+describe the IN/OUT buffers above, two BIOs for the data payload and up to five
+_osd_req_data_segment structures to hold the different segments allocation and
+information.
+
+Important: We have chosen to disregard the assumption that a BIO-chain (and
+the resulting sg-list) describes a linear memory buffer. Meaning only first and
+last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
+For us, a scatter-gather-list, as its name implies and as used by the Networking
+layer, is to describe a vector of buffers that will be transferred to/from the
+wire. It works very well with current iSCSI transport. iSCSI is currently the
+only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
+devices as well.
+
+The OSD Testing ULD
+===================
+TODO: More user-mode control on tests.
+
+Authors, Mailing list
+=====================
+Please communicate with us on any deployment of osd, whether using this code
+or not.
+
+Any problems, questions, bug reports, lonely OSD nights, please email:
+   OSD Dev List <osd-dev@open-osd.org>
+
+More up-to-date information can be found on:
+http://open-osd.org
+
+Boaz Harrosh <bharrosh@panasas.com>
+Benny Halevy <bhalevy@panasas.com>
+
+References
+==========
+Weber, R., "SCSI Object-Based Storage Device Commands",
+T10/1355-D ANSI/INCITS 400-2004,
+http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
+
+Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
+T10/1729-D, Working Draft, rev. 3
+http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf
-- 
cgit v1.2.3-70-g09d2


From a9d0a1a38352c4fb8946e73b3e42ba4ada29e733 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Tue, 3 Mar 2009 16:58:16 +0100
Subject: genirq: add doc to struct irqaction

Impact: documentation

struct irqaction is not documented. Add kernel doc comments and add
interrupt.h to the genirq docbook.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 Documentation/DocBook/genericirq.tmpl |  1 +
 include/linux/interrupt.h             | 11 +++++++++++
 2 files changed, 12 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl
index 3a882d9a90a..c671a016809 100644
--- a/Documentation/DocBook/genericirq.tmpl
+++ b/Documentation/DocBook/genericirq.tmpl
@@ -440,6 +440,7 @@ desc->chip->end();
      used in the generic IRQ layer.
      </para>
 !Iinclude/linux/irq.h
+!Iinclude/linux/interrupt.h
   </chapter>
 
   <chapter id="pubfunctions">
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 468e3a25a4a..91658d07659 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -61,6 +61,17 @@
 
 typedef irqreturn_t (*irq_handler_t)(int, void *);
 
+/**
+ * struct irqaction - per interrupt action descriptor
+ * @handler:	interrupt handler function
+ * @flags:	flags (see IRQF_* above)
+ * @mask:	no comment as it is useless and about to be removed
+ * @name:	name of the device
+ * @dev_id:	cookie to identify the device
+ * @next:	pointer to the next irqaction for shared interrupts
+ * @irq:	interrupt number
+ * @dir:	pointer to the proc/irq/NN/name entry
+ */
 struct irqaction {
 	irq_handler_t handler;
 	unsigned long flags;
-- 
cgit v1.2.3-70-g09d2


From 0e57aa11abb15b70db53d1f95ae70b3c980ac885 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Fri, 13 Mar 2009 14:34:05 +0100
Subject: genirq: deprecate __do_IRQ

Two years migration time is enough. Remove the compability cruft.

Add the deprecated warning in kernel/irq/handle.c because marking
__do_IRQ itself is way too noisy.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 Documentation/feature-removal-schedule.txt | 8 ++++++++
 kernel/irq/handle.c                        | 5 +++++
 2 files changed, 13 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 20d3b94703a..63b4550411b 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -344,3 +344,11 @@ Why:	See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
 	Removal is subject to fixing any remaining bugs in ACPI which may
 	cause the thermal throttling not to happen at the right time.
 Who:	Dave Jones <davej@redhat.com>, Matthew Garrett <mjg@redhat.com>
+
+-----------------------------
+
+What:	__do_IRQ all in one fits nothing interrupt handler
+When:	2.6.32
+Why:	__do_IRQ was kept for easy migration to the type flow handlers.
+	More than two years of migration time is enough.
+Who:	Thomas Gleixner <tglx@linutronix.de>
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index a2ee682bca2..6661704140c 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -349,6 +349,11 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
 }
 
 #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
+
+#ifdef CONFIG_ENABLE_WARN_DEPRECATED
+# warning __do_IRQ is deprecated. Please convert to proper flow handlers
+#endif
+
 /**
  * __do_IRQ - original all in one highlevel IRQ handler
  * @irq:	the interrupt number
-- 
cgit v1.2.3-70-g09d2


From cb065c06b6cc615a58860d619d7fa7952cd6a18b Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Fri, 13 Mar 2009 14:40:27 +0100
Subject: genirq: deprecate obsolete typedefs and defines

More than two years is enough migration time. Remove the compability cruft.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 Documentation/feature-removal-schedule.txt | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'Documentation')

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 63b4550411b..9aa1dda5d38 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -352,3 +352,12 @@ When:	2.6.32
 Why:	__do_IRQ was kept for easy migration to the type flow handlers.
 	More than two years of migration time is enough.
 Who:	Thomas Gleixner <tglx@linutronix.de>
+
+-----------------------------
+
+What:	obsolete generic irq defines and typedefs
+When:	2.6.30
+Why:	The defines and typedefs (hw_interrupt_type, no_irq_type, irq_desc_t)
+	have been kept around for migration reasons. After more than two years
+	it's time to remove them finally
+Who:	Thomas Gleixner <tglx@linutronix.de>
-- 
cgit v1.2.3-70-g09d2


From 09e1c061484005aa26264c3f82f2c83a273c4094 Mon Sep 17 00:00:00 2001
From: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
Date: Fri, 13 Mar 2009 22:15:54 +0000
Subject: ixgbe: Add documentation for the driver

Documentation for the ixgbe driver in the kernel docs area is missing.
This adds that documentation.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/ixgbe.txt | 199 +++++++++++++++++++++++++++++++++++++
 1 file changed, 199 insertions(+)
 create mode 100644 Documentation/networking/ixgbe.txt

(limited to 'Documentation')

diff --git a/Documentation/networking/ixgbe.txt b/Documentation/networking/ixgbe.txt
new file mode 100644
index 00000000000..eeb68685c78
--- /dev/null
+++ b/Documentation/networking/ixgbe.txt
@@ -0,0 +1,199 @@
+Linux Base Driver for 10 Gigabit PCI Express Intel(R) Network Connection
+========================================================================
+
+March 10, 2009
+
+
+Contents
+========
+
+- In This Release
+- Identifying Your Adapter
+- Building and Installation
+- Additional Configurations
+- Support
+
+
+
+In This Release
+===============
+
+This file describes the ixgbe Linux Base Driver for the 10 Gigabit PCI
+Express Intel(R) Network Connection.  This driver includes support for
+Itanium(R)2-based systems.
+
+For questions related to hardware requirements, refer to the documentation
+supplied with your 10 Gigabit adapter.  All hardware requirements listed apply
+to use with Linux.
+
+The following features are available in this kernel:
+ - Native VLANs
+ - Channel Bonding (teaming)
+ - SNMP
+ - Generic Receive Offload
+ - Data Center Bridging
+
+Channel Bonding documentation can be found in the Linux kernel source:
+/Documentation/networking/bonding.txt
+
+Ethtool, lspci, and ifconfig can be used to display device and driver
+specific information.
+
+
+Identifying Your Adapter
+========================
+
+This driver supports devices based on the 82598 controller and the 82599
+controller.
+
+For specific information on identifying which adapter you have, please visit:
+
+    http://support.intel.com/support/network/sb/CS-008441.htm
+
+
+Building and Installation
+=========================
+
+select m for "Intel(R) 10GbE PCI Express adapters support" located at:
+      Location:
+        -> Device Drivers
+          -> Network device support (NETDEVICES [=y])
+            -> Ethernet (10000 Mbit) (NETDEV_10000 [=y])
+
+1. make modules & make modules_install
+
+2. Load the module:
+
+# modprobe ixgbe
+
+   The insmod command can be used if the full
+   path to the driver module is specified.  For example:
+
+     insmod /lib/modules/<KERNEL VERSION>/kernel/drivers/net/ixgbe/ixgbe.ko
+
+   With 2.6 based kernels also make sure that older ixgbe drivers are
+   removed from the kernel, before loading the new module:
+
+     rmmod ixgbe; modprobe ixgbe
+
+3. Assign an IP address to the interface by entering the following, where
+   x is the interface number:
+
+     ifconfig ethx <IP_address>
+
+4. Verify that the interface works. Enter the following, where <IP_address>
+   is the IP address for another machine on the same subnet as the interface
+   that is being tested:
+
+     ping  <IP_address>
+
+
+Additional Configurations
+=========================
+
+  Viewing Link Messages
+  ---------------------
+  Link messages will not be displayed to the console if the distribution is
+  restricting system messages. In order to see network driver link messages on
+  your console, set dmesg to eight by entering the following:
+
+       dmesg -n 8
+
+  NOTE: This setting is not saved across reboots.
+
+
+  Jumbo Frames
+  ------------
+  The driver supports Jumbo Frames for all adapters. Jumbo Frames support is
+  enabled by changing the MTU to a value larger than the default of 1500.
+  The maximum value for the MTU is 16110.  Use the ifconfig command to
+  increase the MTU size.  For example:
+
+        ifconfig ethx mtu 9000 up
+
+  The maximum MTU setting for Jumbo Frames is 16110.  This value coincides
+  with the maximum Jumbo Frames size of 16128.
+
+  Generic Receive Offload, aka GRO
+  --------------------------------
+  The driver supports the in-kernel software implementation of GRO.  GRO has
+  shown that by coalescing Rx traffic into larger chunks of data, CPU
+  utilization can be significantly reduced when under large Rx load.  GRO is an
+  evolution of the previously-used LRO interface.  GRO is able to coalesce
+  other protocols besides TCP.  It's also safe to use with configurations that
+  are problematic for LRO, namely bridging and iSCSI.
+
+  GRO is enabled by default in the driver.  Future versions of ethtool will
+  support disabling and re-enabling GRO on the fly.
+
+
+  Data Center Bridging, aka DCB
+  -----------------------------
+
+  DCB is a configuration Quality of Service implementation in hardware.
+  It uses the VLAN priority tag (802.1p) to filter traffic.  That means
+  that there are 8 different priorities that traffic can be filtered into.
+  It also enables priority flow control which can limit or eliminate the
+  number of dropped packets during network stress.  Bandwidth can be
+  allocated to each of these priorities, which is enforced at the hardware
+  level.
+
+  To enable DCB support in ixgbe, you must enable the DCB netlink layer to
+  allow the userspace tools (see below) to communicate with the driver.
+  This can be found in the kernel configuration here:
+
+        -> Networking support
+          -> Networking options
+            -> Data Center Bridging support
+
+  Once this is selected, DCB support must be selected for ixgbe.  This can
+  be found here:
+
+        -> Device Drivers
+          -> Network device support (NETDEVICES [=y])
+            -> Ethernet (10000 Mbit) (NETDEV_10000 [=y])
+              -> Intel(R) 10GbE PCI Express adapters support
+                -> Data Center Bridging (DCB) Support
+
+  After these options are selected, you must rebuild your kernel and your
+  modules.
+
+  In order to use DCB, userspace tools must be downloaded and installed.
+  The dcbd tools can be found at:
+
+        http://e1000.sf.net
+
+
+  Ethtool
+  -------
+  The driver utilizes the ethtool interface for driver configuration and
+  diagnostics, as well as displaying statistical information.  Ethtool
+  version 3.0 or later is required for this functionality.
+
+  The latest release of ethtool can be found from
+  http://sourceforge.net/projects/gkernel.
+
+
+  NAPI
+  ----
+
+  NAPI (Rx polling mode) is supported in the ixgbe driver.  NAPI is enabled
+  by default in the driver.
+
+  See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
+
+
+Support
+=======
+
+For general information, go to the Intel support website at:
+
+    http://support.intel.com
+
+or the Intel Wired Networking project hosted by Sourceforge at:
+
+    http://e1000.sourceforge.net
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related
+to the issue to e1000-devel@lists.sf.net
-- 
cgit v1.2.3-70-g09d2


From 5f0fbf9ecaf354fa4bbf266fffdea2ea3d14a0ed Mon Sep 17 00:00:00 2001
From: Nicolas Pitre <nico@cam.org>
Date: Tue, 16 Sep 2008 13:05:53 -0400
Subject: [ARM] fixmap support

This is the minimum fixmap interface expected to be implemented by
architectures supporting highmem.

We have a second level page table already allocated and covering
0xfff00000-0xffffffff because the exception vector page is located
at 0xffff0000, and various cache tricks already use some entries above
0xffff0000.  Therefore the PTEs covering 0xfff00000-0xfffeffff are free
to be used.

However the XScale cache flushing code already uses virtual addresses
between 0xfffe0000 and 0xfffeffff.

So this reserves the 0xfff00000-0xfffdffff range for fixmap stuff.

The Documentation/arm/memory.txt information is updated accordingly,
including the information about the actual top of DMA memory mapping
region which didn't match the code.

Signed-off-by: Nicolas Pitre <nico@marvell.com>
---
 Documentation/arm/memory.txt  |  9 ++++++++-
 arch/arm/include/asm/fixmap.h | 41 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/mm.h              |  3 +--
 3 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/include/asm/fixmap.h

(limited to 'Documentation')

diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt
index dc6045577a8..43cb1004d35 100644
--- a/Documentation/arm/memory.txt
+++ b/Documentation/arm/memory.txt
@@ -29,7 +29,14 @@ ffff0000	ffff0fff	CPU vector page.
 				CPU supports vector relocation (control
 				register V bit.)
 
-ffc00000	fffeffff	DMA memory mapping region.  Memory returned
+fffe0000	fffeffff	XScale cache flush area.  This is used
+				in proc-xscale.S to flush the whole data
+				cache.  Free for other usage on non-XScale.
+
+fff00000	fffdffff	Fixmap mapping region.  Addresses provided
+				by fix_to_virt() will be located here.
+
+ffc00000	ffefffff	DMA memory mapping region.  Memory returned
 				by the dma_alloc_xxx functions will be
 				dynamically mapped here.
 
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
new file mode 100644
index 00000000000..bbae919bceb
--- /dev/null
+++ b/arch/arm/include/asm/fixmap.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+/*
+ * Nothing too fancy for now.
+ *
+ * On ARM we already have well known fixed virtual addresses imposed by
+ * the architecture such as the vector page which is located at 0xffff0000,
+ * therefore a second level page table is already allocated covering
+ * 0xfff00000 upwards.
+ *
+ * The cache flushing code in proc-xscale.S uses the virtual area between
+ * 0xfffe0000 and 0xfffeffff.
+ */
+
+#define FIXADDR_START		0xfff00000UL
+#define FIXADDR_TOP		0xfffe0000UL
+#define FIXADDR_SIZE		(FIXADDR_TOP - FIXADDR_START)
+
+#define FIX_KMAP_BEGIN		0
+#define FIX_KMAP_END		(FIXADDR_SIZE >> PAGE_SHIFT)
+
+#define __fix_to_virt(x)	(FIXADDR_START + ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x)	(((x) - FIXADDR_START) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+static inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	if (idx >= FIX_KMAP_END)
+		__this_fixmap_does_not_exist();
+	return __fix_to_virt(idx);
+}
+
+static inline unsigned int virt_to_fix(const unsigned long vaddr)
+{
+	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+	return __virt_to_fix(vaddr);
+}
+
+#endif
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 95bbe112965..c4f6f05198e 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -1,7 +1,6 @@
-/* the upper-most page table pointer */
-
 #ifdef CONFIG_MMU
 
+/* the upper-most page table pointer */
 extern pmd_t *top_pmd;
 
 #define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
-- 
cgit v1.2.3-70-g09d2


From 76398425bb06b07cc3a3b1ce169c67dc9d6874ed Mon Sep 17 00:00:00 2001
From: Jonathan Corbet <corbet@lwn.net>
Date: Sun, 1 Feb 2009 14:26:59 -0700
Subject: Move FASYNC bit handling to f_op->fasync()

Removing the BKL from FASYNC handling ran into the challenge of keeping the
setting of the FASYNC bit in filp->f_flags atomic with regard to calls to
the underlying fasync() function.  Andi Kleen suggested moving the handling
of that bit into fasync(); this patch does exactly that.  As a result, we
have a couple of internal API changes: fasync() must now manage the FASYNC
bit, and it will be called without the BKL held.

As it happens, every fasync() implementation in the kernel with one
exception calls fasync_helper().  So, if we make fasync_helper() set the
FASYNC bit, we can avoid making any changes to the other fasync()
functions - as long as those functions, themselves, have proper locking.
Most fasync() implementations do nothing but call fasync_helper() - which
has its own lock - so they are easily verified as correct.  The BKL had
already been pushed down into the rest.

The networking code has its own version of fasync_helper(), so that code
has been augmented with explicit FASYNC bit handling.

Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: David Miller <davem@davemloft.net>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
 Documentation/filesystems/Locking |  7 +++++--
 fs/fcntl.c                        | 29 ++++++++++++++++-------------
 fs/ioctl.c                        | 13 +------------
 net/socket.c                      |  7 +++++++
 4 files changed, 29 insertions(+), 27 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index ec6a9392a17..4e78ce67784 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -437,8 +437,11 @@ grab BKL for cases when we close a file that had been opened r/w, but that
 can and should be done using the internal locking with smaller critical areas).
 Current worst offender is ext2_get_block()...
 
-->fasync() is a mess. This area needs a big cleanup and that will probably
-affect locking.
+->fasync() is called without BKL protection, and is responsible for
+maintaining the FASYNC bit in filp->f_flags.  Most instances call
+fasync_helper(), which does that maintenance, so it's not normally
+something one needs to worry about.  Return values > 0 will be mapped to
+zero in the VFS layer.
 
 ->readdir() and ->ioctl() on directories must be changed. Ideally we would
 move ->readdir() to inode_operations and use a separate method for directory
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 04df8570a2d..431bb645927 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -141,7 +141,7 @@ SYSCALL_DEFINE1(dup, unsigned int, fildes)
 	return ret;
 }
 
-#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME)
+#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
 
 static int setfl(int fd, struct file * filp, unsigned long arg)
 {
@@ -177,23 +177,19 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
 		return error;
 
 	/*
-	 * We still need a lock here for now to keep multiple FASYNC calls
-	 * from racing with each other.
+	 * ->fasync() is responsible for setting the FASYNC bit.
 	 */
-	lock_kernel();
-	if ((arg ^ filp->f_flags) & FASYNC) {
-		if (filp->f_op && filp->f_op->fasync) {
-			error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
-			if (error < 0)
-				goto out;
-		}
+	if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op &&
+			filp->f_op->fasync) {
+		error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
+		if (error < 0)
+			goto out;
 	}
-
 	spin_lock(&filp->f_lock);
 	filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
 	spin_unlock(&filp->f_lock);
+
  out:
-	unlock_kernel();
 	return error;
 }
 
@@ -518,7 +514,7 @@ static DEFINE_RWLOCK(fasync_lock);
 static struct kmem_cache *fasync_cache __read_mostly;
 
 /*
- * fasync_helper() is used by some character device drivers (mainly mice)
+ * fasync_helper() is used by almost all character device drivers
  * to set up the fasync queue. It returns negative on error, 0 if it did
  * no changes and positive if it added/deleted the entry.
  */
@@ -557,6 +553,13 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap
 		result = 1;
 	}
 out:
+	/* Fix up FASYNC bit while still holding fasync_lock */
+	spin_lock(&filp->f_lock);
+	if (on)
+		filp->f_flags |= FASYNC;
+	else
+		filp->f_flags &= ~FASYNC;
+	spin_unlock(&filp->f_lock);
 	write_unlock_irq(&fasync_lock);
 	return result;
 }
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 421aab465da..e8e89edba57 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -427,19 +427,11 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp,
 	/* Did FASYNC state change ? */
 	if ((flag ^ filp->f_flags) & FASYNC) {
 		if (filp->f_op && filp->f_op->fasync)
+			/* fasync() adjusts filp->f_flags */
 			error = filp->f_op->fasync(fd, filp, on);
 		else
 			error = -ENOTTY;
 	}
-	if (error)
-		return error;
-
-	spin_lock(&filp->f_lock);
-	if (on)
-		filp->f_flags |= FASYNC;
-	else
-		filp->f_flags &= ~FASYNC;
-	spin_unlock(&filp->f_lock);
 	return error;
 }
 
@@ -507,10 +499,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
 		break;
 
 	case FIOASYNC:
-		/* BKL needed to avoid races tweaking f_flags */
-		lock_kernel();
 		error = ioctl_fioasync(fd, filp, argp);
-		unlock_kernel();
 		break;
 
 	case FIOQSIZE:
diff --git a/net/socket.c b/net/socket.c
index 35dd7371752..0f75746ab06 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1030,6 +1030,13 @@ static int sock_fasync(int fd, struct file *filp, int on)
 
 	lock_sock(sk);
 
+	spin_lock(&filp->f_lock);
+	if (on)
+		filp->f_flags |= FASYNC;
+	else
+		filp->f_flags &= ~FASYNC;
+	spin_unlock(&filp->f_lock);
+
 	prev = &(sock->fasync_list);
 
 	for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
-- 
cgit v1.2.3-70-g09d2


From 9bdd8d40c8c59435664af6049dabe24b7779b203 Mon Sep 17 00:00:00 2001
From: Brian Haley <brian.haley@hp.com>
Date: Wed, 18 Mar 2009 18:22:48 -0700
Subject: ipv6: Fix incorrect disable_ipv6 behavior

Fix the behavior of allowing both sysctl and addrconf_dad_failure()
to set the disable_ipv6 parameter without any bad side-effects.
If DAD fails and accept_dad > 1, we will still set disable_ipv6=1,
but then instead of allowing an RA to add an address then
immediately fail DAD, we simply don't allow the address to be
added in the first place.  This also lets the user set this flag
and disable all IPv6 addresses on the interface, or on the entire
system.

Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 Documentation/networking/ip-sysctl.txt |  4 +++-
 net/ipv6/addrconf.c                    | 21 ++++++++++++++-------
 2 files changed, 17 insertions(+), 8 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 7185e4c41e5..ec5de02f543 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1043,7 +1043,9 @@ max_addresses - INTEGER
 	Default: 16
 
 disable_ipv6 - BOOLEAN
-	Disable IPv6 operation.
+	Disable IPv6 operation.  If accept_dad is set to 2, this value
+	will be dynamically set to TRUE if DAD fails for the link-local
+	address.
 	Default: FALSE (enable IPv6 operation)
 
 accept_dad - INTEGER
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e83852ab4dc..717584bad02 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -590,6 +590,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 {
 	struct inet6_ifaddr *ifa = NULL;
 	struct rt6_info *rt;
+	struct net *net = dev_net(idev->dev);
 	int hash;
 	int err = 0;
 	int addr_type = ipv6_addr_type(addr);
@@ -606,6 +607,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 		goto out2;
 	}
 
+	if (idev->cnf.disable_ipv6 || net->ipv6.devconf_all->disable_ipv6) {
+		err = -EACCES;
+		goto out2;
+	}
+
 	write_lock(&addrconf_hash_lock);
 
 	/* Ignore adding duplicate addresses on an interface */
@@ -1433,6 +1439,11 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
 void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 {
 	struct inet6_dev *idev = ifp->idev;
+
+	if (net_ratelimit())
+		printk(KERN_INFO "%s: IPv6 duplicate address detected!\n",
+			ifp->idev->dev->name);
+
 	if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
 		struct in6_addr addr;
 
@@ -1443,11 +1454,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 		    ipv6_addr_equal(&ifp->addr, &addr)) {
 			/* DAD failed for link-local based on MAC address */
 			idev->cnf.disable_ipv6 = 1;
+
+			printk(KERN_INFO "%s: IPv6 being disabled!\n",
+				ifp->idev->dev->name);
 		}
 	}
 
-	if (net_ratelimit())
-		printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
 	addrconf_dad_stop(ifp);
 }
 
@@ -2823,11 +2835,6 @@ static void addrconf_dad_timer(unsigned long data)
 		read_unlock_bh(&idev->lock);
 		goto out;
 	}
-	if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) {
-		read_unlock_bh(&idev->lock);
-		addrconf_dad_failure(ifp);
-		return;
-	}
 	spin_lock_bh(&ifp->lock);
 	if (ifp->probes == 0) {
 		/*
-- 
cgit v1.2.3-70-g09d2


From 3a853fb933ddf9c5ea8c9f7c665dd8def26bceae Mon Sep 17 00:00:00 2001
From: Jarkko Nikula <jarkko.nikula@nokia.com>
Date: Mon, 23 Mar 2009 18:07:47 -0700
Subject: ARM: OMAP: Add command line option for I2C bus speed, v2

This patch adds a new command line option "i2c_bus=bus_id,clkrate" into
I2C bus registration helper. Purpose of the option is to override the
default board specific bus speed which is supplied by the
omap_register_i2c_bus.

The default bus speed is typically set to speed of slowest I2C chip on the
bus and overriding allow to use some experimental configurations or updated
chip versions without any kernel modifications.

Cc: linux-i2c@vger.kernel.org
Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 Documentation/kernel-parameters.txt |  4 +++
 arch/arm/plat-omap/i2c.c            | 54 ++++++++++++++++++++++++++++++-------
 2 files changed, 48 insertions(+), 10 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 54f21a5c262..d775076d156 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -830,6 +830,10 @@ and is between 256 and 4096 characters. It is defined in the file
 	hvc_iucv=	[S390] Number of z/VM IUCV hypervisor console (HVC)
 			       terminal devices. Valid values: 0..8
 
+	i2c_bus=	[HW] Override the default board specific I2C bus speed
+			     Format:
+			     <bus_id>,<clkrate>
+
 	i8042.debug	[HW] Toggle i8042 debug mode
 	i8042.direct	[HW] Put keyboard port into non-translated mode
 	i8042.dumbkbd	[HW] Pretend that controller can only read data from
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 3e95954e2a8..aa70e435fa7 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -119,6 +119,46 @@ static void __init omap_i2c_mux_pins(int bus)
 	omap_cfg_reg(scl);
 }
 
+static int __init omap_i2c_nr_ports(void)
+{
+	int ports = 0;
+
+	if (cpu_class_is_omap1())
+		ports = 1;
+	else if (cpu_is_omap24xx())
+		ports = 2;
+	else if (cpu_is_omap34xx())
+		ports = 3;
+
+	return ports;
+}
+
+/**
+ * omap_i2c_bus_setup - Process command line options for the I2C bus speed
+ * @str: String of options
+ *
+ * This function allow to override the default I2C bus speed for given I2C
+ * bus with a command line option.
+ *
+ * Format: i2c_bus=bus_id,clkrate (in kHz)
+ *
+ * Returns 1 on success, 0 otherwise.
+ */
+static int __init omap_i2c_bus_setup(char *str)
+{
+	int ports;
+	int ints[3];
+
+	ports = omap_i2c_nr_ports();
+	get_options(str, 3, ints);
+	if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports)
+		return 0;
+	i2c_rate[ints[1] - 1] = ints[2];
+
+	return 1;
+}
+__setup("i2c_bus=", omap_i2c_bus_setup);
+
 /**
  * omap_register_i2c_bus - register I2C bus with device descriptors
  * @bus_id: bus id counting from number 1
@@ -132,19 +172,12 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 			  struct i2c_board_info const *info,
 			  unsigned len)
 {
-	int ports, err;
+	int err;
 	struct platform_device *pdev;
 	struct resource *res;
 	resource_size_t base, irq;
 
-	if (cpu_class_is_omap1())
-		ports = 1;
-	else if (cpu_is_omap24xx())
-		ports = 2;
-	else if (cpu_is_omap34xx())
-		ports = 3;
-
-	BUG_ON(bus_id < 1 || bus_id > ports);
+	BUG_ON(bus_id < 1 || bus_id > omap_i2c_nr_ports());
 
 	if (info) {
 		err = i2c_register_board_info(bus_id, info, len);
@@ -153,7 +186,8 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 	}
 
 	pdev = &omap_i2c_devices[bus_id - 1];
-	*(u32 *)pdev->dev.platform_data = clkrate;
+	if (i2c_rate[bus_id - 1] == 0)
+		i2c_rate[bus_id - 1] = clkrate;
 
 	if (bus_id == 1) {
 		res = pdev->resource;
-- 
cgit v1.2.3-70-g09d2


From 7954763bb95fd484a76d1151b40956fe331d23b9 Mon Sep 17 00:00:00 2001
From: Jarkko Nikula <jarkko.nikula@nokia.com>
Date: Mon, 23 Mar 2009 18:07:48 -0700
Subject: ARM: OMAP: Add method to register additional I2C busses on the
 command line, v2

This patch extends command line option "i2c_bus=bus_id,clkrate" so that
it allow to register additional I2C busses that are not registered with
omap_register_i2c_bus from board initialization code.

Purpose of this is to register additional board busses which are routed
to external connectors only without any on board I2C devices.

Cc: linux-i2c@vger.kernel.org
Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 Documentation/kernel-parameters.txt |  2 +
 arch/arm/plat-omap/i2c.c            | 73 ++++++++++++++++++++++++++-----------
 2 files changed, 54 insertions(+), 21 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d775076d156..ef9827f7c84 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -831,6 +831,8 @@ and is between 256 and 4096 characters. It is defined in the file
 			       terminal devices. Valid values: 0..8
 
 	i2c_bus=	[HW] Override the default board specific I2C bus speed
+			     or register an additional I2C bus that is not
+			     registered from board initialization code.
 			     Format:
 			     <bus_id>,<clkrate>
 
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index aa70e435fa7..a303071d5e3 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -98,6 +98,8 @@ static const int omap34xx_pins[][2] = {
 static const int omap34xx_pins[][2] = {};
 #endif
 
+#define OMAP_I2C_CMDLINE_SETUP	(BIT(31))
+
 static void __init omap_i2c_mux_pins(int bus)
 {
 	int scl, sda;
@@ -133,6 +135,31 @@ static int __init omap_i2c_nr_ports(void)
 	return ports;
 }
 
+static int __init omap_i2c_add_bus(int bus_id)
+{
+	struct platform_device *pdev;
+	struct resource *res;
+	resource_size_t base, irq;
+
+	pdev = &omap_i2c_devices[bus_id - 1];
+	if (bus_id == 1) {
+		res = pdev->resource;
+		if (cpu_class_is_omap1()) {
+			base = OMAP1_I2C_BASE;
+			irq = INT_I2C;
+		} else {
+			base = OMAP2_I2C_BASE1;
+			irq = INT_24XX_I2C1_IRQ;
+		}
+		res[0].start = base;
+		res[0].end = base + OMAP_I2C_SIZE;
+		res[1].start = irq;
+	}
+
+	omap_i2c_mux_pins(bus_id - 1);
+	return platform_device_register(pdev);
+}
+
 /**
  * omap_i2c_bus_setup - Process command line options for the I2C bus speed
  * @str: String of options
@@ -154,11 +181,33 @@ static int __init omap_i2c_bus_setup(char *str)
 	if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports)
 		return 0;
 	i2c_rate[ints[1] - 1] = ints[2];
+	i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP;
 
 	return 1;
 }
 __setup("i2c_bus=", omap_i2c_bus_setup);
 
+/*
+ * Register busses defined in command line but that are not registered with
+ * omap_register_i2c_bus from board initialization code.
+ */
+static int __init omap_register_i2c_bus_cmdline(void)
+{
+	int i, err = 0;
+
+	for (i = 0; i < ARRAY_SIZE(i2c_rate); i++)
+		if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) {
+			i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP;
+			err = omap_i2c_add_bus(i + 1);
+			if (err)
+				goto out;
+		}
+
+out:
+	return err;
+}
+subsys_initcall(omap_register_i2c_bus_cmdline);
+
 /**
  * omap_register_i2c_bus - register I2C bus with device descriptors
  * @bus_id: bus id counting from number 1
@@ -173,9 +222,6 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 			  unsigned len)
 {
 	int err;
-	struct platform_device *pdev;
-	struct resource *res;
-	resource_size_t base, irq;
 
 	BUG_ON(bus_id < 1 || bus_id > omap_i2c_nr_ports());
 
@@ -185,24 +231,9 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 			return err;
 	}
 
-	pdev = &omap_i2c_devices[bus_id - 1];
-	if (i2c_rate[bus_id - 1] == 0)
+	if (!i2c_rate[bus_id - 1])
 		i2c_rate[bus_id - 1] = clkrate;
+	i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP;
 
-	if (bus_id == 1) {
-		res = pdev->resource;
-		if (cpu_class_is_omap1()) {
-			base = OMAP1_I2C_BASE;
-			irq = INT_I2C;
-		} else {
-			base = OMAP2_I2C_BASE1;
-			irq = INT_24XX_I2C1_IRQ;
-		}
-		res[0].start = base;
-		res[0].end = base + OMAP_I2C_SIZE;
-		res[1].start = irq;
-	}
-
-	omap_i2c_mux_pins(bus_id - 1);
-	return platform_device_register(pdev);
+	return omap_i2c_add_bus(bus_id);
 }
-- 
cgit v1.2.3-70-g09d2


From 471c604daf73ff549d374ee54f9e6bfd5a54d4e8 Mon Sep 17 00:00:00 2001
From: Pete Zaitcev <zaitcev@redhat.com>
Date: Thu, 19 Feb 2009 22:54:45 -0700
Subject: USB: usbmon: Add binary API v1

This patch adds an extension to the binary API so it reaches parity with
existing text API (so-called "1u"). The extension delivers additional data,
such as ISO descriptors and the interrupt interval.

Signed-Off-By: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 Documentation/usb/usbmon.txt |  27 +++++---
 drivers/usb/mon/mon_bin.c    | 142 +++++++++++++++++++++++++++++++++++--------
 2 files changed, 136 insertions(+), 33 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index 270481906dc..6c3c625b7f3 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -229,16 +229,26 @@ struct usbmon_packet {
 	int status;		/* 28: */
 	unsigned int length;	/* 32: Length of data (submitted or actual) */
 	unsigned int len_cap;	/* 36: Delivered length */
-	unsigned char setup[8];	/* 40: Only for Control 'S' */
-};				/* 48 bytes total */
+	union {			/* 40: */
+		unsigned char setup[SETUP_LEN];	/* Only for Control S-type */
+		struct iso_rec {		/* Only for ISO */
+			int error_count;
+			int numdesc;
+		} iso;
+	} s;
+	int interval;		/* 48: Only for Interrupt and ISO */
+	int start_frame;	/* 52: For ISO */
+	unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */
+	unsigned int ndesc;	/* 60: Actual number of ISO descriptors */
+};				/* 64 total length */
 
 These events can be received from a character device by reading with read(2),
-with an ioctl(2), or by accessing the buffer with mmap.
+with an ioctl(2), or by accessing the buffer with mmap. However, read(2)
+only returns first 48 bytes for compatibility reasons.
 
 The character device is usually called /dev/usbmonN, where N is the USB bus
 number. Number zero (/dev/usbmon0) is special and means "all buses".
-However, this feature is not implemented yet. Note that specific naming
-policy is set by your Linux distribution.
+Note that specific naming policy is set by your Linux distribution.
 
 If you create /dev/usbmon0 by hand, make sure that it is owned by root
 and has mode 0600. Otherwise, unpriviledged users will be able to snoop
@@ -279,9 +289,10 @@ size is out of [unspecified] bounds for this kernel, the call fails with
 This call returns the current size of the buffer in bytes.
 
  MON_IOCX_GET, defined as _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)
+ MON_IOCX_GETX, defined as _IOW(MON_IOC_MAGIC, 10, struct mon_get_arg)
 
-This call waits for events to arrive if none were in the kernel buffer,
-then returns the first event. Its argument is a pointer to the following
+These calls wait for events to arrive if none were in the kernel buffer,
+then return the first event. The argument is a pointer to the following
 structure:
 
 struct mon_get_arg {
@@ -294,6 +305,8 @@ Before the call, hdr, data, and alloc should be filled. Upon return, the area
 pointed by hdr contains the next event structure, and the data buffer contains
 the data, if any. The event is removed from the kernel buffer.
 
+The MON_IOCX_GET copies 48 bytes, MON_IOCX_GETX copies 64 bytes.
+
  MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg)
 
 This ioctl is primarily used when the application accesses the buffer
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 4cf27c72423..f8d9045d668 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -37,10 +37,13 @@
 #define MON_IOCX_GET   _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
 #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
 #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
+/* #9 was MON_IOCT_SETAPI */
+#define MON_IOCX_GETX   _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get)
 
 #ifdef CONFIG_COMPAT
 #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32)
 #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32)
+#define MON_IOCX_GETX32   _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32)
 #endif
 
 /*
@@ -92,7 +95,29 @@ struct mon_bin_hdr {
 	int status;
 	unsigned int len_urb;	/* Length of data (submitted or actual) */
 	unsigned int len_cap;	/* Delivered length */
-	unsigned char setup[SETUP_LEN];	/* Only for Control S-type */
+	union {
+		unsigned char setup[SETUP_LEN];	/* Only for Control S-type */
+		struct iso_rec {
+			int error_count;
+			int numdesc;
+		} iso;
+	} s;
+	int interval;
+	int start_frame;
+	unsigned int xfer_flags;
+	unsigned int ndesc;	/* Actual number of ISO descriptors */
+};
+
+/*
+ * ISO vector, packed into the head of data stream.
+ * This has to take 16 bytes to make sure that the end of buffer
+ * wrap is not happening in the middle of a descriptor.
+ */
+struct mon_bin_isodesc {
+	int          iso_status;
+	unsigned int iso_off;
+	unsigned int iso_len;
+	u32 _pad;
 };
 
 /* per file statistic */
@@ -102,7 +127,7 @@ struct mon_bin_stats {
 };
 
 struct mon_bin_get {
-	struct mon_bin_hdr __user *hdr;	/* Only 48 bytes, not 64. */
+	struct mon_bin_hdr __user *hdr;	/* Can be 48 bytes or 64. */
 	void __user *data;
 	size_t alloc;		/* Length of data (can be zero) */
 };
@@ -131,6 +156,11 @@ struct mon_bin_mfetch32 {
 #define PKT_ALIGN   64
 #define PKT_SIZE    64
 
+#define PKT_SZ_API0 48	/* API 0 (2.6.20) size */
+#define PKT_SZ_API1 64	/* API 1 size: extra fields */
+
+#define ISODESC_MAX   128	/* Same number as usbfs allows, 2048 bytes. */
+
 /* max number of USB bus supported */
 #define MON_BIN_MAX_MINOR 128
 
@@ -360,12 +390,8 @@ static inline char mon_bin_get_setup(unsigned char *setupb,
     const struct urb *urb, char ev_type)
 {
 
-	if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S')
-		return '-';
-
 	if (urb->setup_packet == NULL)
 		return 'Z';
-
 	memcpy(setupb, urb->setup_packet, SETUP_LEN);
 	return 0;
 }
@@ -387,6 +413,26 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp,
 	return 0;
 }
 
+static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
+    unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
+{
+	struct mon_bin_isodesc *dp;
+	struct usb_iso_packet_descriptor *fp;
+
+	fp = urb->iso_frame_desc;
+	while (ndesc-- != 0) {
+		dp = (struct mon_bin_isodesc *)
+		    (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
+		dp->iso_status = fp->status;
+		dp->iso_off = fp->offset;
+		dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length;
+		dp->_pad = 0;
+		if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size)
+			offset = 0;
+		fp++;
+	}
+}
+
 static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
     char ev_type, int status)
 {
@@ -396,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
 	unsigned int urb_length;
 	unsigned int offset;
 	unsigned int length;
+	unsigned int ndesc, lendesc;
 	unsigned char dir;
 	struct mon_bin_hdr *ep;
 	char data_tag = 0;
@@ -407,6 +454,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
 	/*
 	 * Find the maximum allowable length, then allocate space.
 	 */
+	if (usb_endpoint_xfer_isoc(epd)) {
+		if (urb->number_of_packets < 0) {
+			ndesc = 0;
+		} else if (urb->number_of_packets >= ISODESC_MAX) {
+			ndesc = ISODESC_MAX;
+		} else {
+			ndesc = urb->number_of_packets;
+		}
+	} else {
+		ndesc = 0;
+	}
+	lendesc = ndesc*sizeof(struct mon_bin_isodesc);
+
 	urb_length = (ev_type == 'S') ?
 	    urb->transfer_buffer_length : urb->actual_length;
 	length = urb_length;
@@ -429,10 +489,12 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
 		dir = 0;
 	}
 
-	if (rp->mmap_active)
-		offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE);
-	else
-		offset = mon_buff_area_alloc(rp, length + PKT_SIZE);
+	if (rp->mmap_active) {
+		offset = mon_buff_area_alloc_contiguous(rp,
+						 length + PKT_SIZE + lendesc);
+	} else {
+		offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc);
+	}
 	if (offset == ~0) {
 		rp->cnt_lost++;
 		spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -456,9 +518,31 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
 	ep->ts_usec = ts.tv_usec;
 	ep->status = status;
 	ep->len_urb = urb_length;
-	ep->len_cap = length;
+	ep->len_cap = length + lendesc;
+	ep->xfer_flags = urb->transfer_flags;
+
+	if (usb_endpoint_xfer_int(epd)) {
+		ep->interval = urb->interval;
+	} else if (usb_endpoint_xfer_isoc(epd)) {
+		ep->interval = urb->interval;
+		ep->start_frame = urb->start_frame;
+		ep->s.iso.error_count = urb->error_count;
+		ep->s.iso.numdesc = urb->number_of_packets;
+	}
+
+	if (usb_endpoint_xfer_control(epd) && ev_type == 'S') {
+		ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type);
+	} else {
+		ep->flag_setup = '-';
+	}
+
+	if (ndesc != 0) {
+		ep->ndesc = ndesc;
+		mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc);
+		if ((offset += lendesc) >= rp->b_size)
+			offset -= rp->b_size;
+	}
 
-	ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type);
 	if (length != 0) {
 		ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
 		if (ep->flag_data != 0) {	/* Yes, it's 0x00, not '0' */
@@ -592,7 +676,8 @@ err_alloc:
  * Returns zero or error.
  */
 static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
-    struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes)
+    struct mon_bin_hdr __user *hdr, unsigned int hdrbytes,
+    void __user *data, unsigned int nbytes)
 {
 	unsigned long flags;
 	struct mon_bin_hdr *ep;
@@ -609,7 +694,7 @@ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
 
 	ep = MON_OFF2HDR(rp, rp->b_out);
 
-	if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) {
+	if (copy_to_user(hdr, ep, hdrbytes)) {
 		mutex_unlock(&rp->fetch_lock);
 		return -EFAULT;
 	}
@@ -657,6 +742,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
     size_t nbytes, loff_t *ppos)
 {
 	struct mon_reader_bin *rp = file->private_data;
+	unsigned int hdrbytes = PKT_SZ_API0;
 	unsigned long flags;
 	struct mon_bin_hdr *ep;
 	unsigned int offset;
@@ -674,8 +760,8 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
 
 	ep = MON_OFF2HDR(rp, rp->b_out);
 
-	if (rp->b_read < sizeof(struct mon_bin_hdr)) {
-		step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read);
+	if (rp->b_read < hdrbytes) {
+		step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
 		ptr = ((char *)ep) + rp->b_read;
 		if (step_len && copy_to_user(buf, ptr, step_len)) {
 			mutex_unlock(&rp->fetch_lock);
@@ -687,13 +773,13 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
 		done += step_len;
 	}
 
-	if (rp->b_read >= sizeof(struct mon_bin_hdr)) {
+	if (rp->b_read >= hdrbytes) {
 		step_len = ep->len_cap;
-		step_len -= rp->b_read - sizeof(struct mon_bin_hdr);
+		step_len -= rp->b_read - hdrbytes;
 		if (step_len > nbytes)
 			step_len = nbytes;
 		offset = rp->b_out + PKT_SIZE;
-		offset += rp->b_read - sizeof(struct mon_bin_hdr);
+		offset += rp->b_read - hdrbytes;
 		if (offset >= rp->b_size)
 			offset -= rp->b_size;
 		if (copy_from_buf(rp, offset, buf, step_len)) {
@@ -709,7 +795,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
 	/*
 	 * Check if whole packet was read, and if so, jump to the next one.
 	 */
-	if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) {
+	if (rp->b_read >= hdrbytes + ep->len_cap) {
 		spin_lock_irqsave(&rp->b_lock, flags);
 		mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
 		spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -908,6 +994,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
 		break;
 
 	case MON_IOCX_GET:
+	case MON_IOCX_GETX:
 		{
 		struct mon_bin_get getb;
 
@@ -917,8 +1004,9 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
 
 		if (getb.alloc > 0x10000000)	/* Want to cast to u32 */
 			return -EINVAL;
-		ret = mon_bin_get_event(file, rp,
-			  getb.hdr, getb.data, (unsigned int)getb.alloc);
+		ret = mon_bin_get_event(file, rp, getb.hdr,
+		    (cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1,
+		    getb.data, (unsigned int)getb.alloc);
 		}
 		break;
 
@@ -984,16 +1072,18 @@ static long mon_bin_compat_ioctl(struct file *file,
 
 	switch (cmd) {
 
-	case MON_IOCX_GET32: {
+	case MON_IOCX_GET32:
+	case MON_IOCX_GETX32:
+		{
 		struct mon_bin_get32 getb;
 
 		if (copy_from_user(&getb, (void __user *)arg,
 					    sizeof(struct mon_bin_get32)))
 			return -EFAULT;
 
-		ret = mon_bin_get_event(file, rp,
-		    compat_ptr(getb.hdr32), compat_ptr(getb.data32),
-		    getb.alloc32);
+		ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32),
+		    (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1,
+		    compat_ptr(getb.data32), getb.alloc32);
 		if (ret < 0)
 			return ret;
 		}
-- 
cgit v1.2.3-70-g09d2


From 8205779114e8f612549d191f8e151526a74ab9f2 Mon Sep 17 00:00:00 2001
From: "Hans J. Koch" <hjk@linutronix.de>
Date: Wed, 7 Jan 2009 00:15:39 +0100
Subject: UIO: Add name attributes for mappings and port regions

If a UIO device has several memory mappings, it can be difficult for userspace
to find the right one. The situation becomes even worse if the UIO driver can
handle different versions of a card that have different numbers of mappings.
Benedikt Spranger has such cards and pointed this out to me. Thanks, Bene!

To address this problem, this patch adds "name" sysfs attributes for each
mapping. Userspace can use these to clearly identify each mapping. The name
string is optional. If a driver doesn't set it, an empty string will be
returned, so this patch won't break existing drivers.

The same problem exists for port region information, so a "name" attribute is
added there, too.

Signed-off-by: Hans J. Koch <hjk@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 Documentation/DocBook/uio-howto.tmpl | 29 +++++++++++++++++++++++++----
 drivers/uio/uio.c                    | 22 ++++++++++++++++++++++
 include/linux/uio_driver.h           |  4 ++++
 3 files changed, 51 insertions(+), 4 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index 52e1b79ce0e..8f6e3b2403c 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -41,6 +41,13 @@ GPL version 2.
 </abstract>
 
 <revhistory>
+	<revision>
+	<revnumber>0.8</revnumber>
+	<date>2008-12-24</date>
+	<authorinitials>hjk</authorinitials>
+	<revremark>Added name attributes in mem and portio sysfs directories.
+		</revremark>
+	</revision>
 	<revision>
 	<revnumber>0.7</revnumber>
 	<date>2008-12-23</date>
@@ -303,10 +310,17 @@ interested in translating it, please email me
 	appear if the size of the mapping is not 0.
 </para>
 <para>
-	Each <filename>mapX/</filename> directory contains two read-only files
-	that show start address and size of the memory:
+	Each <filename>mapX/</filename> directory contains four read-only files
+	that show attributes of the memory:
 </para>
 <itemizedlist>
+<listitem>
+	<para>
+	<filename>name</filename>: A string identifier for this mapping. This
+	is optional, the string can be empty. Drivers can set this to make it
+	easier for userspace to find the correct mapping.
+	</para>
+</listitem>
 <listitem>
 	<para>
 	<filename>addr</filename>: The address of memory that can be mapped.
@@ -366,10 +380,17 @@ offset = N * getpagesize();
 	<filename>/sys/class/uio/uioX/portio/</filename>.
 </para>
 <para>
-	Each <filename>portX/</filename> directory contains three read-only
-	files that show start, size, and type of the port region:
+	Each <filename>portX/</filename> directory contains four read-only
+	files that show name, start, size, and type of the port region:
 </para>
 <itemizedlist>
+<listitem>
+	<para>
+	<filename>name</filename>: A string identifier for this port region.
+	The string is optional and can be empty. Drivers can set it to make it
+	easier for userspace to find a certain port region.
+	</para>
+</listitem>
 <listitem>
 	<para>
 	<filename>start</filename>: The first port of this region.
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 4ca85a113aa..68a49655778 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -61,6 +61,14 @@ struct uio_map {
 };
 #define to_map(map) container_of(map, struct uio_map, kobj)
 
+static ssize_t map_name_show(struct uio_mem *mem, char *buf)
+{
+	if (unlikely(!mem->name))
+		mem->name = "";
+
+	return sprintf(buf, "%s\n", mem->name);
+}
+
 static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
 {
 	return sprintf(buf, "0x%lx\n", mem->addr);
@@ -82,6 +90,8 @@ struct map_sysfs_entry {
 	ssize_t (*store)(struct uio_mem *, const char *, size_t);
 };
 
+static struct map_sysfs_entry name_attribute =
+	__ATTR(name, S_IRUGO, map_name_show, NULL);
 static struct map_sysfs_entry addr_attribute =
 	__ATTR(addr, S_IRUGO, map_addr_show, NULL);
 static struct map_sysfs_entry size_attribute =
@@ -90,6 +100,7 @@ static struct map_sysfs_entry offset_attribute =
 	__ATTR(offset, S_IRUGO, map_offset_show, NULL);
 
 static struct attribute *attrs[] = {
+	&name_attribute.attr,
 	&addr_attribute.attr,
 	&size_attribute.attr,
 	&offset_attribute.attr,
@@ -133,6 +144,14 @@ struct uio_portio {
 };
 #define to_portio(portio) container_of(portio, struct uio_portio, kobj)
 
+static ssize_t portio_name_show(struct uio_port *port, char *buf)
+{
+	if (unlikely(!port->name))
+		port->name = "";
+
+	return sprintf(buf, "%s\n", port->name);
+}
+
 static ssize_t portio_start_show(struct uio_port *port, char *buf)
 {
 	return sprintf(buf, "0x%lx\n", port->start);
@@ -159,6 +178,8 @@ struct portio_sysfs_entry {
 	ssize_t (*store)(struct uio_port *, const char *, size_t);
 };
 
+static struct portio_sysfs_entry portio_name_attribute =
+	__ATTR(name, S_IRUGO, portio_name_show, NULL);
 static struct portio_sysfs_entry portio_start_attribute =
 	__ATTR(start, S_IRUGO, portio_start_show, NULL);
 static struct portio_sysfs_entry portio_size_attribute =
@@ -167,6 +188,7 @@ static struct portio_sysfs_entry portio_porttype_attribute =
 	__ATTR(porttype, S_IRUGO, portio_porttype_show, NULL);
 
 static struct attribute *portio_attrs[] = {
+	&portio_name_attribute.attr,
 	&portio_start_attribute.attr,
 	&portio_size_attribute.attr,
 	&portio_porttype_attribute.attr,
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index a0bb6bd2e5c..5dcc9ff72f6 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -22,6 +22,7 @@ struct uio_map;
 
 /**
  * struct uio_mem - description of a UIO memory region
+ * @name:		name of the memory region for identification
  * @addr:		address of the device's memory
  * @size:		size of IO
  * @memtype:		type of memory addr points to
@@ -29,6 +30,7 @@ struct uio_map;
  * @map:		for use by the UIO core only.
  */
 struct uio_mem {
+	const char		*name;
 	unsigned long		addr;
 	unsigned long		size;
 	int			memtype;
@@ -42,12 +44,14 @@ struct uio_portio;
 
 /**
  * struct uio_port - description of a UIO port region
+ * @name:		name of the port region for identification
  * @start:		start of port region
  * @size:		size of port region
  * @porttype:		type of port (see UIO_PORT_* below)
  * @portio:		for use by the UIO core only.
  */
 struct uio_port {
+	const char		*name;
 	unsigned long		start;
 	unsigned long		size;
 	int			porttype;
-- 
cgit v1.2.3-70-g09d2


From e9d376f0fa66bd630fe27403669c6ae6c22a868f Mon Sep 17 00:00:00 2001
From: Jason Baron <jbaron@redhat.com>
Date: Thu, 5 Feb 2009 11:51:38 -0500
Subject: dynamic debug: combine dprintk and dynamic printk

This patch combines Greg Bank's dprintk() work with the existing dynamic
printk patchset, we are now calling it 'dynamic debug'.

The new feature of this patchset is a richer /debugfs control file interface,
(an example output from my system is at the bottom), which allows fined grained
control over the the debug output. The output can be controlled by function,
file, module, format string, and line number.

for example, enabled all debug messages in module 'nf_conntrack':

echo -n 'module nf_conntrack +p' > /mnt/debugfs/dynamic_debug/control

to disable them:

echo -n 'module nf_conntrack -p' > /mnt/debugfs/dynamic_debug/control

A further explanation can be found in the documentation patch.

Signed-off-by: Greg Banks <gnb@sgi.com>
Signed-off-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 Documentation/kernel-parameters.txt |   5 -
 include/asm-generic/vmlinux.lds.h   |  15 +-
 include/linux/device.h              |   2 +-
 include/linux/dynamic_debug.h       |  88 +++++
 include/linux/dynamic_printk.h      |  93 -----
 include/linux/kernel.h              |   4 +-
 kernel/module.c                     |  25 +-
 lib/Kconfig.debug                   |   2 +-
 lib/Makefile                        |   2 +-
 lib/dynamic_debug.c                 | 756 ++++++++++++++++++++++++++++++++++++
 lib/dynamic_printk.c                | 414 --------------------
 net/netfilter/nf_conntrack_pptp.c   |   2 +-
 scripts/Makefile.lib                |   2 +-
 13 files changed, 867 insertions(+), 543 deletions(-)
 create mode 100644 include/linux/dynamic_debug.h
 delete mode 100644 include/linux/dynamic_printk.h
 create mode 100644 lib/dynamic_debug.c
 delete mode 100644 lib/dynamic_printk.c

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 54f21a5c262..3a1aa8a4aff 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1816,11 +1816,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			autoconfiguration.
 			Ranges are in pairs (memory base and size).
 
-	dynamic_printk	Enables pr_debug()/dev_dbg() calls if
-			CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled.
-			These can also be switched on/off via
-			<debugfs>/dynamic_printk/modules
-
 	print-fatal-signals=
 			[KNL] debug: print fatal signals
 			print-fatal-signals=1: print segfault info to
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index c61fab1dd2f..aca40b93bd2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -80,6 +80,11 @@
 	VMLINUX_SYMBOL(__start___tracepoints) = .;			\
 	*(__tracepoints)						\
 	VMLINUX_SYMBOL(__stop___tracepoints) = .;			\
+	/* implement dynamic printk debug */				\
+	. = ALIGN(8);							\
+	VMLINUX_SYMBOL(__start___verbose) = .;                          \
+	*(__verbose)                                                    \
+	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()
 
@@ -309,15 +314,7 @@
 	CPU_DISCARD(init.data)						\
 	CPU_DISCARD(init.rodata)					\
 	MEM_DISCARD(init.data)						\
-	MEM_DISCARD(init.rodata)					\
-	/* implement dynamic printk debug */				\
-	VMLINUX_SYMBOL(__start___verbose_strings) = .;                  \
-	*(__verbose_strings)                                            \
-	VMLINUX_SYMBOL(__stop___verbose_strings) = .;                   \
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	*(__verbose)                                                    \
-	VMLINUX_SYMBOL(__stop___verbose) = .;
+	MEM_DISCARD(init.rodata)
 
 #define INIT_TEXT							\
 	*(.init.text)							\
diff --git a/include/linux/device.h b/include/linux/device.h
index f98d0cfb4f8..2918c0e8fdf 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -582,7 +582,7 @@ extern const char *dev_driver_string(const struct device *dev);
 #if defined(DEBUG)
 #define dev_dbg(dev, format, arg...)		\
 	dev_printk(KERN_DEBUG , dev , format , ## arg)
-#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
 #define dev_dbg(dev, format, ...) do { \
 	dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
 	} while (0)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
new file mode 100644
index 00000000000..07781aaa116
--- /dev/null
+++ b/include/linux/dynamic_debug.h
@@ -0,0 +1,88 @@
+#ifndef _DYNAMIC_DEBUG_H
+#define _DYNAMIC_DEBUG_H
+
+/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+extern long long dynamic_debug_enabled;
+extern long long dynamic_debug_enabled2;
+
+/*
+ * An instance of this structure is created in a special
+ * ELF section at every dynamic debug callsite.  At runtime,
+ * the special section is treated as an array of these.
+ */
+struct _ddebug {
+	/*
+	 * These fields are used to drive the user interface
+	 * for selecting and displaying debug callsites.
+	 */
+	const char *modname;
+	const char *function;
+	const char *filename;
+	const char *format;
+	char primary_hash;
+	char secondary_hash;
+	unsigned int lineno:24;
+	/*
+ 	 * The flags field controls the behaviour at the callsite.
+ 	 * The bits here are changed dynamically when the user
+ 	 * writes commands to <debugfs>/dynamic_debug/ddebug
+	 */
+#define _DPRINTK_FLAGS_PRINT   (1<<0)  /* printk() a message using the format */
+#define _DPRINTK_FLAGS_DEFAULT 0
+	unsigned int flags:8;
+} __attribute__((aligned(8)));
+
+
+int ddebug_add_module(struct _ddebug *tab, unsigned int n,
+				const char *modname);
+
+#if defined(CONFIG_DYNAMIC_DEBUG)
+extern int ddebug_remove_module(char *mod_name);
+
+#define __dynamic_dbg_enabled(dd)  ({	     \
+	int __ret = 0;							     \
+	if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) &&	     \
+			(dynamic_debug_enabled2 & (1LL << DEBUG_HASH2))))   \
+				if (unlikely(dd.flags))			     \
+					__ret = 1;			     \
+	__ret; })
+
+#define dynamic_pr_debug(fmt, ...) do {					\
+	static struct _ddebug descriptor				\
+	__used								\
+	__attribute__((section("__verbose"), aligned(8))) =		\
+	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\
+		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\
+	if (__dynamic_dbg_enabled(descriptor))				\
+		printk(KERN_DEBUG KBUILD_MODNAME ":" fmt,		\
+				##__VA_ARGS__);				\
+	} while (0)
+
+
+#define dynamic_dev_dbg(dev, fmt, ...) do {				\
+	static struct _ddebug descriptor				\
+	__used								\
+	__attribute__((section("__verbose"), aligned(8))) =		\
+	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\
+		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\
+	if (__dynamic_dbg_enabled(descriptor))				\
+			dev_printk(KERN_DEBUG, dev,			\
+					KBUILD_MODNAME ": " fmt,	\
+					##__VA_ARGS__);			\
+	} while (0)
+
+#else
+
+static inline int ddebug_remove_module(char *mod)
+{
+	return 0;
+}
+
+#define dynamic_pr_debug(fmt, ...)  do { } while (0)
+#define dynamic_dev_dbg(dev, format, ...)  do { } while (0)
+#endif
+
+#endif
diff --git a/include/linux/dynamic_printk.h b/include/linux/dynamic_printk.h
deleted file mode 100644
index 2d528d00907..00000000000
--- a/include/linux/dynamic_printk.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef _DYNAMIC_PRINTK_H
-#define _DYNAMIC_PRINTK_H
-
-#define DYNAMIC_DEBUG_HASH_BITS 6
-#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS)
-
-#define TYPE_BOOLEAN 1
-
-#define DYNAMIC_ENABLED_ALL 0
-#define DYNAMIC_ENABLED_NONE 1
-#define DYNAMIC_ENABLED_SOME 2
-
-extern int dynamic_enabled;
-
-/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
- * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
- * use independent hash functions, to reduce the chance of false positives.
- */
-extern long long dynamic_printk_enabled;
-extern long long dynamic_printk_enabled2;
-
-struct mod_debug {
-	char *modname;
-	char *logical_modname;
-	char *flag_names;
-	int type;
-	int hash;
-	int hash2;
-} __attribute__((aligned(8)));
-
-int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
-					char *flags, int hash, int hash2);
-
-#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
-extern int unregister_dynamic_debug_module(char *mod_name);
-extern int __dynamic_dbg_enabled_helper(char *modname, int type,
-					int value, int hash);
-
-#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({	     \
-	int __ret = 0;							     \
-	if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) &&	     \
-			(dynamic_printk_enabled2 & (1LL << DEBUG_HASH2))))   \
-			__ret = __dynamic_dbg_enabled_helper(module, type,   \
-								value, hash);\
-	__ret; })
-
-#define dynamic_pr_debug(fmt, ...) do {					    \
-	static char mod_name[]						    \
-	__attribute__((section("__verbose_strings")))			    \
-	 = KBUILD_MODNAME;						    \
-	static struct mod_debug descriptor				    \
-	__used								    \
-	__attribute__((section("__verbose"), aligned(8))) =		    \
-	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
-	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \
-						0, 0, DEBUG_HASH))	    \
-		printk(KERN_DEBUG KBUILD_MODNAME ":" fmt,		    \
-				##__VA_ARGS__);				    \
-	} while (0)
-
-#define dynamic_dev_dbg(dev, format, ...) do {				    \
-	static char mod_name[]						    \
-	__attribute__((section("__verbose_strings")))			    \
-	 = KBUILD_MODNAME;						    \
-	static struct mod_debug descriptor				    \
-	__used								    \
-	__attribute__((section("__verbose"), aligned(8))) =		    \
-	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
-	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \
-						0, 0, DEBUG_HASH))	    \
-			dev_printk(KERN_DEBUG, dev,			    \
-					KBUILD_MODNAME ": " format,	    \
-					##__VA_ARGS__);			    \
-	} while (0)
-
-#else
-
-static inline int unregister_dynamic_debug_module(const char *mod_name)
-{
-	return 0;
-}
-static inline int __dynamic_dbg_enabled_helper(char *modname, int type,
-						int value, int hash)
-{
-	return 0;
-}
-
-#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({ 0; })
-#define dynamic_pr_debug(fmt, ...)  do { } while (0)
-#define dynamic_dev_dbg(dev, format, ...)  do { } while (0)
-#endif
-
-#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 7fa371898e3..b5496ecbec7 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -16,7 +16,7 @@
 #include <linux/log2.h>
 #include <linux/typecheck.h>
 #include <linux/ratelimit.h>
-#include <linux/dynamic_printk.h>
+#include <linux/dynamic_debug.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -358,7 +358,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 #if defined(DEBUG)
 #define pr_debug(fmt, ...) \
 	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
 #define pr_debug(fmt, ...) do { \
 	dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
 	} while (0)
diff --git a/kernel/module.c b/kernel/module.c
index 1196f5d1170..77672233387 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -822,7 +822,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 	mutex_lock(&module_mutex);
 	/* Store the name of the last unloaded module for diagnostic purposes */
 	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
-	unregister_dynamic_debug_module(mod->name);
+	ddebug_remove_module(mod->name);
 	free_module(mod);
 
  out:
@@ -1827,19 +1827,13 @@ static inline void add_kallsyms(struct module *mod,
 }
 #endif /* CONFIG_KALLSYMS */
 
-static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num)
+static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
 {
-#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
-	unsigned int i;
-
-	for (i = 0; i < num; i++) {
-		register_dynamic_debug_module(debug[i].modname,
-					      debug[i].type,
-					      debug[i].logical_modname,
-					      debug[i].flag_names,
-					      debug[i].hash, debug[i].hash2);
-	}
-#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
+#ifdef CONFIG_DYNAMIC_DEBUG
+	if (ddebug_add_module(debug, num, debug->modname))
+		printk(KERN_ERR "dynamic debug error adding module: %s\n",
+					debug->modname);
+#endif
 }
 
 static void *module_alloc_update_bounds(unsigned long size)
@@ -2213,12 +2207,13 @@ static noinline struct module *load_module(void __user *umod,
 	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
 
 	if (!mod->taints) {
-		struct mod_debug *debug;
+		struct _ddebug *debug;
 		unsigned int num_debug;
 
 		debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
 				     sizeof(*debug), &num_debug);
-		dynamic_printk_setup(debug, num_debug);
+		if (debug)
+			dynamic_debug_setup(debug, num_debug);
 	}
 
 	/* sechdrs[0].sh_size is always zero */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1bcf9cd4baa..0dd1c04c732 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -847,7 +847,7 @@ config BUILD_DOCSRC
 
 	  Say N if you are unsure.
 
-config DYNAMIC_PRINTK_DEBUG
+config DYNAMIC_DEBUG
 	bool "Enable dynamic printk() call support"
 	default n
 	depends on PRINTK
diff --git a/lib/Makefile b/lib/Makefile
index 32b0e64ded2..8633d6be9d2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -82,7 +82,7 @@ obj-$(CONFIG_HAVE_LMB) += lmb.o
 
 obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
 
-obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o
+obj-$(CONFIG_DYNAMIC_DEBUG) += dynamic_debug.o
 
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
new file mode 100644
index 00000000000..9e123ae326b
--- /dev/null
+++ b/lib/dynamic_debug.c
@@ -0,0 +1,756 @@
+/*
+ * lib/dynamic_debug.c
+ *
+ * make pr_debug()/dev_dbg() calls runtime configurable based upon their
+ * source module.
+ *
+ * Copyright (C) 2008 Jason Baron <jbaron@redhat.com>
+ * By Greg Banks <gnb@melbourne.sgi.com>
+ * Copyright (c) 2008 Silicon Graphics Inc.  All Rights Reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kallsyms.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/list.h>
+#include <linux/sysctl.h>
+#include <linux/ctype.h>
+#include <linux/uaccess.h>
+#include <linux/dynamic_debug.h>
+#include <linux/debugfs.h>
+
+extern struct _ddebug __start___verbose[];
+extern struct _ddebug __stop___verbose[];
+
+/* dynamic_debug_enabled, and dynamic_debug_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+long long dynamic_debug_enabled;
+EXPORT_SYMBOL_GPL(dynamic_debug_enabled);
+long long dynamic_debug_enabled2;
+EXPORT_SYMBOL_GPL(dynamic_debug_enabled2);
+
+struct ddebug_table {
+	struct list_head link;
+	char *mod_name;
+	unsigned int num_ddebugs;
+	unsigned int num_enabled;
+	struct _ddebug *ddebugs;
+};
+
+struct ddebug_query {
+	const char *filename;
+	const char *module;
+	const char *function;
+	const char *format;
+	unsigned int first_lineno, last_lineno;
+};
+
+struct ddebug_iter {
+	struct ddebug_table *table;
+	unsigned int idx;
+};
+
+static DEFINE_MUTEX(ddebug_lock);
+static LIST_HEAD(ddebug_tables);
+static int verbose = 0;
+
+/* Return the last part of a pathname */
+static inline const char *basename(const char *path)
+{
+	const char *tail = strrchr(path, '/');
+	return tail ? tail+1 : path;
+}
+
+/* format a string into buf[] which describes the _ddebug's flags */
+static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
+				    size_t maxlen)
+{
+	char *p = buf;
+
+	BUG_ON(maxlen < 4);
+	if (dp->flags & _DPRINTK_FLAGS_PRINT)
+		*p++ = 'p';
+	if (p == buf)
+		*p++ = '-';
+	*p = '\0';
+
+	return buf;
+}
+
+/*
+ * must be called with ddebug_lock held
+ */
+
+static int disabled_hash(char hash, bool first_table)
+{
+	struct ddebug_table *dt;
+	char table_hash_value;
+
+	list_for_each_entry(dt, &ddebug_tables, link) {
+		if (first_table)
+			table_hash_value = dt->ddebugs->primary_hash;
+		else
+			table_hash_value = dt->ddebugs->secondary_hash;
+		if (dt->num_enabled && (hash == table_hash_value))
+			return 0;
+	}
+	return 1;
+}
+
+/*
+ * Search the tables for _ddebug's which match the given
+ * `query' and apply the `flags' and `mask' to them.  Tells
+ * the user which ddebug's were changed, or whether none
+ * were matched.
+ */
+static void ddebug_change(const struct ddebug_query *query,
+			   unsigned int flags, unsigned int mask)
+{
+	int i;
+	struct ddebug_table *dt;
+	unsigned int newflags;
+	unsigned int nfound = 0;
+	char flagbuf[8];
+
+	/* search for matching ddebugs */
+	mutex_lock(&ddebug_lock);
+	list_for_each_entry(dt, &ddebug_tables, link) {
+
+		/* match against the module name */
+		if (query->module != NULL &&
+		    strcmp(query->module, dt->mod_name))
+			continue;
+
+		for (i = 0 ; i < dt->num_ddebugs ; i++) {
+			struct _ddebug *dp = &dt->ddebugs[i];
+
+			/* match against the source filename */
+			if (query->filename != NULL &&
+			    strcmp(query->filename, dp->filename) &&
+			    strcmp(query->filename, basename(dp->filename)))
+				continue;
+
+			/* match against the function */
+			if (query->function != NULL &&
+			    strcmp(query->function, dp->function))
+				continue;
+
+			/* match against the format */
+			if (query->format != NULL &&
+			    strstr(dp->format, query->format) == NULL)
+				continue;
+
+			/* match against the line number range */
+			if (query->first_lineno &&
+			    dp->lineno < query->first_lineno)
+				continue;
+			if (query->last_lineno &&
+			    dp->lineno > query->last_lineno)
+				continue;
+
+			nfound++;
+
+			newflags = (dp->flags & mask) | flags;
+			if (newflags == dp->flags)
+				continue;
+
+			if (!newflags)
+				dt->num_enabled--;
+			else if (!dp-flags)
+				dt->num_enabled++;
+			dp->flags = newflags;
+			if (newflags) {
+				dynamic_debug_enabled |=
+						(1LL << dp->primary_hash);
+				dynamic_debug_enabled2 |=
+						(1LL << dp->secondary_hash);
+			} else {
+				if (disabled_hash(dp->primary_hash, true))
+					dynamic_debug_enabled &=
+						~(1LL << dp->primary_hash);
+				if (disabled_hash(dp->secondary_hash, false))
+					dynamic_debug_enabled2 &=
+						~(1LL << dp->secondary_hash);
+			}
+			if (verbose)
+				printk(KERN_INFO
+					"ddebug: changed %s:%d [%s]%s %s\n",
+					dp->filename, dp->lineno,
+					dt->mod_name, dp->function,
+					ddebug_describe_flags(dp, flagbuf,
+							sizeof(flagbuf)));
+		}
+	}
+	mutex_unlock(&ddebug_lock);
+
+	if (!nfound && verbose)
+		printk(KERN_INFO "ddebug: no matches for query\n");
+}
+
+/*
+ * Wrapper around strsep() to collapse the multiple empty tokens
+ * that it returns when fed sequences of separator characters.
+ * Now, if we had strtok_r()...
+ */
+static inline char *nearly_strtok_r(char **p, const char *sep)
+{
+	char *r;
+
+	while ((r = strsep(p, sep)) != NULL && *r == '\0')
+		;
+	return r;
+}
+
+/*
+ * Split the buffer `buf' into space-separated words.
+ * Return the number of such words or <0 on error.
+ */
+static int ddebug_tokenize(char *buf, char *words[], int maxwords)
+{
+	int nwords = 0;
+
+	while (nwords < maxwords &&
+	       (words[nwords] = nearly_strtok_r(&buf, " \t\r\n")) != NULL)
+		nwords++;
+	if (buf)
+		return -EINVAL;	/* ran out of words[] before bytes */
+
+	if (verbose) {
+		int i;
+		printk(KERN_INFO "%s: split into words:", __func__);
+		for (i = 0 ; i < nwords ; i++)
+			printk(" \"%s\"", words[i]);
+		printk("\n");
+	}
+
+	return nwords;
+}
+
+/*
+ * Parse a single line number.  Note that the empty string ""
+ * is treated as a special case and converted to zero, which
+ * is later treated as a "don't care" value.
+ */
+static inline int parse_lineno(const char *str, unsigned int *val)
+{
+	char *end = NULL;
+	BUG_ON(str == NULL);
+	if (*str == '\0') {
+		*val = 0;
+		return 0;
+	}
+	*val = simple_strtoul(str, &end, 10);
+	return end == NULL || end == str || *end != '\0' ? -EINVAL : 0;
+}
+
+/*
+ * Undo octal escaping in a string, inplace.  This is useful to
+ * allow the user to express a query which matches a format
+ * containing embedded spaces.
+ */
+#define isodigit(c)		((c) >= '0' && (c) <= '7')
+static char *unescape(char *str)
+{
+	char *in = str;
+	char *out = str;
+
+	while (*in) {
+		if (*in == '\\') {
+			if (in[1] == '\\') {
+				*out++ = '\\';
+				in += 2;
+				continue;
+			} else if (in[1] == 't') {
+				*out++ = '\t';
+				in += 2;
+				continue;
+			} else if (in[1] == 'n') {
+				*out++ = '\n';
+				in += 2;
+				continue;
+			} else if (isodigit(in[1]) &&
+			         isodigit(in[2]) &&
+			         isodigit(in[3])) {
+				*out++ = ((in[1] - '0')<<6) |
+				          ((in[2] - '0')<<3) |
+				          (in[3] - '0');
+				in += 4;
+				continue;
+			}
+		}
+		*out++ = *in++;
+	}
+	*out = '\0';
+
+	return str;
+}
+
+/*
+ * Parse words[] as a ddebug query specification, which is a series
+ * of (keyword, value) pairs chosen from these possibilities:
+ *
+ * func <function-name>
+ * file <full-pathname>
+ * file <base-filename>
+ * module <module-name>
+ * format <escaped-string-to-find-in-format>
+ * line <lineno>
+ * line <first-lineno>-<last-lineno> // where either may be empty
+ */
+static int ddebug_parse_query(char *words[], int nwords,
+			       struct ddebug_query *query)
+{
+	unsigned int i;
+
+	/* check we have an even number of words */
+	if (nwords % 2 != 0)
+		return -EINVAL;
+	memset(query, 0, sizeof(*query));
+
+	for (i = 0 ; i < nwords ; i += 2) {
+		if (!strcmp(words[i], "func"))
+			query->function = words[i+1];
+		else if (!strcmp(words[i], "file"))
+			query->filename = words[i+1];
+		else if (!strcmp(words[i], "module"))
+			query->module = words[i+1];
+		else if (!strcmp(words[i], "format"))
+			query->format = unescape(words[i+1]);
+		else if (!strcmp(words[i], "line")) {
+			char *first = words[i+1];
+			char *last = strchr(first, '-');
+			if (last)
+				*last++ = '\0';
+			if (parse_lineno(first, &query->first_lineno) < 0)
+				return -EINVAL;
+			if (last != NULL) {
+				/* range <first>-<last> */
+				if (parse_lineno(last, &query->last_lineno) < 0)
+					return -EINVAL;
+			} else {
+				query->last_lineno = query->first_lineno;
+			}
+		} else {
+			if (verbose)
+				printk(KERN_ERR "%s: unknown keyword \"%s\"\n",
+					__func__, words[i]);
+			return -EINVAL;
+		}
+	}
+
+	if (verbose)
+		printk(KERN_INFO "%s: q->function=\"%s\" q->filename=\"%s\" "
+		       "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n",
+			__func__, query->function, query->filename,
+			query->module, query->format, query->first_lineno,
+			query->last_lineno);
+
+	return 0;
+}
+
+/*
+ * Parse `str' as a flags specification, format [-+=][p]+.
+ * Sets up *maskp and *flagsp to be used when changing the
+ * flags fields of matched _ddebug's.  Returns 0 on success
+ * or <0 on error.
+ */
+static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
+			       unsigned int *maskp)
+{
+	unsigned flags = 0;
+	int op = '=';
+
+	switch (*str) {
+	case '+':
+	case '-':
+	case '=':
+		op = *str++;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (verbose)
+		printk(KERN_INFO "%s: op='%c'\n", __func__, op);
+
+	for ( ; *str ; ++str) {
+		switch (*str) {
+		case 'p':
+			flags |= _DPRINTK_FLAGS_PRINT;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	if (flags == 0)
+		return -EINVAL;
+	if (verbose)
+		printk(KERN_INFO "%s: flags=0x%x\n", __func__, flags);
+
+	/* calculate final *flagsp, *maskp according to mask and op */
+	switch (op) {
+	case '=':
+		*maskp = 0;
+		*flagsp = flags;
+		break;
+	case '+':
+		*maskp = ~0U;
+		*flagsp = flags;
+		break;
+	case '-':
+		*maskp = ~flags;
+		*flagsp = 0;
+		break;
+	}
+	if (verbose)
+		printk(KERN_INFO "%s: *flagsp=0x%x *maskp=0x%x\n",
+			__func__, *flagsp, *maskp);
+	return 0;
+}
+
+/*
+ * File_ops->write method for <debugfs>/dynamic_debug/conrol.  Gathers the
+ * command text from userspace, parses and executes it.
+ */
+static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
+				  size_t len, loff_t *offp)
+{
+	unsigned int flags = 0, mask = 0;
+	struct ddebug_query query;
+#define MAXWORDS 9
+	int nwords;
+	char *words[MAXWORDS];
+	char tmpbuf[256];
+
+	if (len == 0)
+		return 0;
+	/* we don't check *offp -- multiple writes() are allowed */
+	if (len > sizeof(tmpbuf)-1)
+		return -E2BIG;
+	if (copy_from_user(tmpbuf, ubuf, len))
+		return -EFAULT;
+	tmpbuf[len] = '\0';
+	if (verbose)
+		printk(KERN_INFO "%s: read %d bytes from userspace\n",
+			__func__, (int)len);
+
+	nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS);
+	if (nwords < 0)
+		return -EINVAL;
+	if (ddebug_parse_query(words, nwords-1, &query))
+		return -EINVAL;
+	if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
+		return -EINVAL;
+
+	/* actually go and implement the change */
+	ddebug_change(&query, flags, mask);
+
+	*offp += len;
+	return len;
+}
+
+/*
+ * Set the iterator to point to the first _ddebug object
+ * and return a pointer to that first object.  Returns
+ * NULL if there are no _ddebugs at all.
+ */
+static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
+{
+	if (list_empty(&ddebug_tables)) {
+		iter->table = NULL;
+		iter->idx = 0;
+		return NULL;
+	}
+	iter->table = list_entry(ddebug_tables.next,
+				 struct ddebug_table, link);
+	iter->idx = 0;
+	return &iter->table->ddebugs[iter->idx];
+}
+
+/*
+ * Advance the iterator to point to the next _ddebug
+ * object from the one the iterator currently points at,
+ * and returns a pointer to the new _ddebug.  Returns
+ * NULL if the iterator has seen all the _ddebugs.
+ */
+static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
+{
+	if (iter->table == NULL)
+		return NULL;
+	if (++iter->idx == iter->table->num_ddebugs) {
+		/* iterate to next table */
+		iter->idx = 0;
+		if (list_is_last(&iter->table->link, &ddebug_tables)) {
+			iter->table = NULL;
+			return NULL;
+		}
+		iter->table = list_entry(iter->table->link.next,
+					 struct ddebug_table, link);
+	}
+	return &iter->table->ddebugs[iter->idx];
+}
+
+/*
+ * Seq_ops start method.  Called at the start of every
+ * read() call from userspace.  Takes the ddebug_lock and
+ * seeks the seq_file's iterator to the given position.
+ */
+static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
+{
+	struct ddebug_iter *iter = m->private;
+	struct _ddebug *dp;
+	int n = *pos;
+
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p *pos=%lld\n",
+			__func__, m, (unsigned long long)*pos);
+
+	mutex_lock(&ddebug_lock);
+
+	if (!n)
+		return SEQ_START_TOKEN;
+	if (n < 0)
+		return NULL;
+	dp = ddebug_iter_first(iter);
+	while (dp != NULL && --n > 0)
+		dp = ddebug_iter_next(iter);
+	return dp;
+}
+
+/*
+ * Seq_ops next method.  Called several times within a read()
+ * call from userspace, with ddebug_lock held.  Walks to the
+ * next _ddebug object with a special case for the header line.
+ */
+static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	struct ddebug_iter *iter = m->private;
+	struct _ddebug *dp;
+
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p p=%p *pos=%lld\n",
+			__func__, m, p, (unsigned long long)*pos);
+
+	if (p == SEQ_START_TOKEN)
+		dp = ddebug_iter_first(iter);
+	else
+		dp = ddebug_iter_next(iter);
+	++*pos;
+	return dp;
+}
+
+/*
+ * Seq_ops show method.  Called several times within a read()
+ * call from userspace, with ddebug_lock held.  Formats the
+ * current _ddebug as a single human-readable line, with a
+ * special case for the header line.
+ */
+static int ddebug_proc_show(struct seq_file *m, void *p)
+{
+	struct ddebug_iter *iter = m->private;
+	struct _ddebug *dp = p;
+	char flagsbuf[8];
+
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p p=%p\n",
+			__func__, m, p);
+
+	if (p == SEQ_START_TOKEN) {
+		seq_puts(m,
+			"# filename:lineno [module]function flags format\n");
+		return 0;
+	}
+
+	seq_printf(m, "%s:%u [%s]%s %s \"",
+		   dp->filename, dp->lineno,
+		   iter->table->mod_name, dp->function,
+		   ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
+	seq_escape(m, dp->format, "\t\r\n\"");
+	seq_puts(m, "\"\n");
+
+	return 0;
+}
+
+/*
+ * Seq_ops stop method.  Called at the end of each read()
+ * call from userspace.  Drops ddebug_lock.
+ */
+static void ddebug_proc_stop(struct seq_file *m, void *p)
+{
+	if (verbose)
+		printk(KERN_INFO "%s: called m=%p p=%p\n",
+			__func__, m, p);
+	mutex_unlock(&ddebug_lock);
+}
+
+static const struct seq_operations ddebug_proc_seqops = {
+	.start = ddebug_proc_start,
+	.next = ddebug_proc_next,
+	.show = ddebug_proc_show,
+	.stop = ddebug_proc_stop
+};
+
+/*
+ * File_ops->open method for <debugfs>/dynamic_debug/control.  Does the seq_file
+ * setup dance, and also creates an iterator to walk the _ddebugs.
+ * Note that we create a seq_file always, even for O_WRONLY files
+ * where it's not needed, as doing so simplifies the ->release method.
+ */
+static int ddebug_proc_open(struct inode *inode, struct file *file)
+{
+	struct ddebug_iter *iter;
+	int err;
+
+	if (verbose)
+		printk(KERN_INFO "%s: called\n", __func__);
+
+	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+	if (iter == NULL)
+		return -ENOMEM;
+
+	err = seq_open(file, &ddebug_proc_seqops);
+	if (err) {
+		kfree(iter);
+		return err;
+	}
+	((struct seq_file *) file->private_data)->private = iter;
+	return 0;
+}
+
+static const struct file_operations ddebug_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = ddebug_proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release_private,
+	.write = ddebug_proc_write
+};
+
+/*
+ * Allocate a new ddebug_table for the given module
+ * and add it to the global list.
+ */
+int ddebug_add_module(struct _ddebug *tab, unsigned int n,
+			     const char *name)
+{
+	struct ddebug_table *dt;
+	char *new_name;
+
+	dt = kzalloc(sizeof(*dt), GFP_KERNEL);
+	if (dt == NULL)
+		return -ENOMEM;
+	new_name = kstrdup(name, GFP_KERNEL);
+	if (new_name == NULL) {
+		kfree(dt);
+		return -ENOMEM;
+	}
+	dt->mod_name = new_name;
+	dt->num_ddebugs = n;
+	dt->num_enabled = 0;
+	dt->ddebugs = tab;
+
+	mutex_lock(&ddebug_lock);
+	list_add_tail(&dt->link, &ddebug_tables);
+	mutex_unlock(&ddebug_lock);
+
+	if (verbose)
+		printk(KERN_INFO "%u debug prints in module %s\n",
+				 n, dt->mod_name);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ddebug_add_module);
+
+static void ddebug_table_free(struct ddebug_table *dt)
+{
+	list_del_init(&dt->link);
+	kfree(dt->mod_name);
+	kfree(dt);
+}
+
+/*
+ * Called in response to a module being unloaded.  Removes
+ * any ddebug_table's which point at the module.
+ */
+int ddebug_remove_module(char *mod_name)
+{
+	struct ddebug_table *dt, *nextdt;
+	int ret = -ENOENT;
+
+	if (verbose)
+		printk(KERN_INFO "%s: removing module \"%s\"\n",
+				__func__, mod_name);
+
+	mutex_lock(&ddebug_lock);
+	list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
+		if (!strcmp(dt->mod_name, mod_name)) {
+			ddebug_table_free(dt);
+			ret = 0;
+		}
+	}
+	mutex_unlock(&ddebug_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ddebug_remove_module);
+
+static void ddebug_remove_all_tables(void)
+{
+	mutex_lock(&ddebug_lock);
+	while (!list_empty(&ddebug_tables)) {
+		struct ddebug_table *dt = list_entry(ddebug_tables.next,
+						      struct ddebug_table,
+						      link);
+		ddebug_table_free(dt);
+	}
+	mutex_unlock(&ddebug_lock);
+}
+
+static int __init dynamic_debug_init(void)
+{
+	struct dentry *dir, *file;
+	struct _ddebug *iter, *iter_start;
+	const char *modname = NULL;
+	int ret = 0;
+	int n = 0;
+
+	dir = debugfs_create_dir("dynamic_debug", NULL);
+	if (!dir)
+		return -ENOMEM;
+	file = debugfs_create_file("control", 0644, dir, NULL,
+					&ddebug_proc_fops);
+	if (!file) {
+		debugfs_remove(dir);
+		return -ENOMEM;
+	}
+	if (__start___verbose != __stop___verbose) {
+		iter = __start___verbose;
+		modname = iter->modname;
+		iter_start = iter;
+		for (; iter < __stop___verbose; iter++) {
+			if (strcmp(modname, iter->modname)) {
+				ret = ddebug_add_module(iter_start, n, modname);
+				if (ret)
+					goto out_free;
+				n = 0;
+				modname = iter->modname;
+				iter_start = iter;
+			}
+			n++;
+		}
+		ret = ddebug_add_module(iter_start, n, modname);
+	}
+out_free:
+	if (ret) {
+		ddebug_remove_all_tables();
+		debugfs_remove(dir);
+		debugfs_remove(file);
+	}
+	return 0;
+}
+module_init(dynamic_debug_init);
diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c
deleted file mode 100644
index 165a19763dc..00000000000
--- a/lib/dynamic_printk.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * lib/dynamic_printk.c
- *
- * make pr_debug()/dev_dbg() calls runtime configurable based upon their
- * their source module.
- *
- * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/seq_file.h>
-#include <linux/debugfs.h>
-#include <linux/fs.h>
-
-extern struct mod_debug __start___verbose[];
-extern struct mod_debug __stop___verbose[];
-
-struct debug_name {
-	struct hlist_node hlist;
-	struct hlist_node hlist2;
-	int hash1;
-	int hash2;
-	char *name;
-	int enable;
-	int type;
-};
-
-static int nr_entries;
-static int num_enabled;
-int dynamic_enabled = DYNAMIC_ENABLED_NONE;
-static struct hlist_head module_table[DEBUG_HASH_TABLE_SIZE] =
-	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
-static struct hlist_head module_table2[DEBUG_HASH_TABLE_SIZE] =
-	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
-static DECLARE_MUTEX(debug_list_mutex);
-
-/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
- * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
- * use independent hash functions, to reduce the chance of false positives.
- */
-long long dynamic_printk_enabled;
-EXPORT_SYMBOL_GPL(dynamic_printk_enabled);
-long long dynamic_printk_enabled2;
-EXPORT_SYMBOL_GPL(dynamic_printk_enabled2);
-
-/* returns the debug module pointer. */
-static struct debug_name *find_debug_module(char *module_name)
-{
-	int i;
-	struct hlist_head *head;
-	struct hlist_node *node;
-	struct debug_name *element;
-
-	element = NULL;
-	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
-		head = &module_table[i];
-		hlist_for_each_entry_rcu(element, node, head, hlist)
-			if (!strcmp(element->name, module_name))
-				return element;
-	}
-	return NULL;
-}
-
-/* returns the debug module pointer. */
-static struct debug_name *find_debug_module_hash(char *module_name, int hash)
-{
-	struct hlist_head *head;
-	struct hlist_node *node;
-	struct debug_name *element;
-
-	element = NULL;
-	head = &module_table[hash];
-	hlist_for_each_entry_rcu(element, node, head, hlist)
-		if (!strcmp(element->name, module_name))
-			return element;
-	return NULL;
-}
-
-/* caller must hold mutex*/
-static int __add_debug_module(char *mod_name, int hash, int hash2)
-{
-	struct debug_name *new;
-	char *module_name;
-	int ret = 0;
-
-	if (find_debug_module(mod_name)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	module_name = kmalloc(strlen(mod_name) + 1, GFP_KERNEL);
-	if (!module_name) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	module_name = strcpy(module_name, mod_name);
-	module_name[strlen(mod_name)] = '\0';
-	new = kzalloc(sizeof(struct debug_name), GFP_KERNEL);
-	if (!new) {
-		kfree(module_name);
-		ret = -ENOMEM;
-		goto out;
-	}
-	INIT_HLIST_NODE(&new->hlist);
-	INIT_HLIST_NODE(&new->hlist2);
-	new->name = module_name;
-	new->hash1 = hash;
-	new->hash2 = hash2;
-	hlist_add_head_rcu(&new->hlist, &module_table[hash]);
-	hlist_add_head_rcu(&new->hlist2, &module_table2[hash2]);
-	nr_entries++;
-out:
-	return ret;
-}
-
-int unregister_dynamic_debug_module(char *mod_name)
-{
-	struct debug_name *element;
-	int ret = 0;
-
-	down(&debug_list_mutex);
-	element = find_debug_module(mod_name);
-	if (!element) {
-		ret = -EINVAL;
-		goto out;
-	}
-	hlist_del_rcu(&element->hlist);
-	hlist_del_rcu(&element->hlist2);
-	synchronize_rcu();
-	kfree(element->name);
-	if (element->enable)
-		num_enabled--;
-	kfree(element);
-	nr_entries--;
-out:
-	up(&debug_list_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module);
-
-int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
-					char *flags, int hash, int hash2)
-{
-	struct debug_name *elem;
-	int ret = 0;
-
-	down(&debug_list_mutex);
-	elem = find_debug_module(mod_name);
-	if (!elem) {
-		if (__add_debug_module(mod_name, hash, hash2))
-			goto out;
-		elem = find_debug_module(mod_name);
-		if (dynamic_enabled == DYNAMIC_ENABLED_ALL &&
-				!strcmp(mod_name, share_name)) {
-			elem->enable = true;
-			num_enabled++;
-		}
-	}
-	elem->type |= type;
-out:
-	up(&debug_list_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(register_dynamic_debug_module);
-
-int __dynamic_dbg_enabled_helper(char *mod_name, int type, int value, int hash)
-{
-	struct debug_name *elem;
-	int ret = 0;
-
-	if (dynamic_enabled == DYNAMIC_ENABLED_ALL)
-		return 1;
-	rcu_read_lock();
-	elem = find_debug_module_hash(mod_name, hash);
-	if (elem && elem->enable)
-		ret = 1;
-	rcu_read_unlock();
-	return ret;
-}
-EXPORT_SYMBOL_GPL(__dynamic_dbg_enabled_helper);
-
-static void set_all(bool enable)
-{
-	struct debug_name *e;
-	struct hlist_node *node;
-	int i;
-	long long enable_mask;
-
-	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
-		if (module_table[i].first != NULL) {
-			hlist_for_each_entry(e, node, &module_table[i], hlist) {
-				e->enable = enable;
-			}
-		}
-	}
-	if (enable)
-		enable_mask = ULLONG_MAX;
-	else
-		enable_mask = 0;
-	dynamic_printk_enabled = enable_mask;
-	dynamic_printk_enabled2 = enable_mask;
-}
-
-static int disabled_hash(int i, bool first_table)
-{
-	struct debug_name *e;
-	struct hlist_node *node;
-
-	if (first_table) {
-		hlist_for_each_entry(e, node, &module_table[i], hlist) {
-			if (e->enable)
-				return 0;
-		}
-	} else {
-		hlist_for_each_entry(e, node, &module_table2[i], hlist2) {
-			if (e->enable)
-				return 0;
-		}
-	}
-	return 1;
-}
-
-static ssize_t pr_debug_write(struct file *file, const char __user *buf,
-				size_t length, loff_t *ppos)
-{
-	char *buffer, *s, *value_str, *setting_str;
-	int err, value;
-	struct debug_name *elem = NULL;
-	int all = 0;
-
-	if (length > PAGE_SIZE || length < 0)
-		return -EINVAL;
-
-	buffer = (char *)__get_free_page(GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	err = -EFAULT;
-	if (copy_from_user(buffer, buf, length))
-		goto out;
-
-	err = -EINVAL;
-	if (length < PAGE_SIZE)
-		buffer[length] = '\0';
-	else if (buffer[PAGE_SIZE-1])
-		goto out;
-
-	err = -EINVAL;
-	down(&debug_list_mutex);
-
-	if (strncmp("set", buffer, 3))
-		goto out_up;
-	s = buffer + 3;
-	setting_str = strsep(&s, "=");
-	if (s == NULL)
-		goto out_up;
-	setting_str = strstrip(setting_str);
-	value_str = strsep(&s, " ");
-	if (s == NULL)
-		goto out_up;
-	s = strstrip(s);
-	if (!strncmp(s, "all", 3))
-		all = 1;
-	else
-		elem = find_debug_module(s);
-	if (!strncmp(setting_str, "enable", 6)) {
-		value = !!simple_strtol(value_str, NULL, 10);
-		if (all) {
-			if (value) {
-				set_all(true);
-				num_enabled = nr_entries;
-				dynamic_enabled = DYNAMIC_ENABLED_ALL;
-			} else {
-				set_all(false);
-				num_enabled = 0;
-				dynamic_enabled = DYNAMIC_ENABLED_NONE;
-			}
-			err = 0;
-		} else if (elem) {
-			if (value && (elem->enable == 0)) {
-				dynamic_printk_enabled |= (1LL << elem->hash1);
-				dynamic_printk_enabled2 |= (1LL << elem->hash2);
-				elem->enable = 1;
-				num_enabled++;
-				dynamic_enabled = DYNAMIC_ENABLED_SOME;
-				err = 0;
-				printk(KERN_DEBUG
-					"debugging enabled for module %s\n",
-					elem->name);
-			} else if (!value && (elem->enable == 1)) {
-				elem->enable = 0;
-				num_enabled--;
-				if (disabled_hash(elem->hash1, true))
-					dynamic_printk_enabled &=
-							~(1LL << elem->hash1);
-				if (disabled_hash(elem->hash2, false))
-					dynamic_printk_enabled2 &=
-							~(1LL << elem->hash2);
-				if (num_enabled)
-					dynamic_enabled = DYNAMIC_ENABLED_SOME;
-				else
-					dynamic_enabled = DYNAMIC_ENABLED_NONE;
-				err = 0;
-				printk(KERN_DEBUG
-					"debugging disabled for module %s\n",
-					elem->name);
-			}
-		}
-	}
-	if (!err)
-		err = length;
-out_up:
-	up(&debug_list_mutex);
-out:
-	free_page((unsigned long)buffer);
-	return err;
-}
-
-static void *pr_debug_seq_start(struct seq_file *f, loff_t *pos)
-{
-	return (*pos < DEBUG_HASH_TABLE_SIZE) ? pos : NULL;
-}
-
-static void *pr_debug_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-	(*pos)++;
-	if (*pos >= DEBUG_HASH_TABLE_SIZE)
-		return NULL;
-	return pos;
-}
-
-static void pr_debug_seq_stop(struct seq_file *s, void *v)
-{
-	/* Nothing to do */
-}
-
-static int pr_debug_seq_show(struct seq_file *s, void *v)
-{
-	struct hlist_head *head;
-	struct hlist_node *node;
-	struct debug_name *elem;
-	unsigned int i = *(loff_t *) v;
-
-	rcu_read_lock();
-	head = &module_table[i];
-	hlist_for_each_entry_rcu(elem, node, head, hlist) {
-		seq_printf(s, "%s enabled=%d", elem->name, elem->enable);
-		seq_printf(s, "\n");
-	}
-	rcu_read_unlock();
-	return 0;
-}
-
-static struct seq_operations pr_debug_seq_ops = {
-	.start = pr_debug_seq_start,
-	.next  = pr_debug_seq_next,
-	.stop  = pr_debug_seq_stop,
-	.show  = pr_debug_seq_show
-};
-
-static int pr_debug_open(struct inode *inode, struct file *filp)
-{
-	return seq_open(filp, &pr_debug_seq_ops);
-}
-
-static const struct file_operations pr_debug_operations = {
-	.open		= pr_debug_open,
-	.read		= seq_read,
-	.write		= pr_debug_write,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-static int __init dynamic_printk_init(void)
-{
-	struct dentry *dir, *file;
-	struct mod_debug *iter;
-	unsigned long value;
-
-	dir = debugfs_create_dir("dynamic_printk", NULL);
-	if (!dir)
-		return -ENOMEM;
-	file = debugfs_create_file("modules", 0644, dir, NULL,
-					&pr_debug_operations);
-	if (!file) {
-		debugfs_remove(dir);
-		return -ENOMEM;
-	}
-	for (value = (unsigned long)__start___verbose;
-		value < (unsigned long)__stop___verbose;
-		value += sizeof(struct mod_debug)) {
-			iter = (struct mod_debug *)value;
-			register_dynamic_debug_module(iter->modname,
-				iter->type,
-				iter->logical_modname,
-				iter->flag_names, iter->hash, iter->hash2);
-	}
-	if (dynamic_enabled == DYNAMIC_ENABLED_ALL)
-		set_all(true);
-	return 0;
-}
-module_init(dynamic_printk_init);
-/* may want to move this earlier so we can get traces as early as possible */
-
-static int __init dynamic_printk_setup(char *str)
-{
-	if (str)
-		return -ENOENT;
-	dynamic_enabled = DYNAMIC_ENABLED_ALL;
-	return 0;
-}
-/* Use early_param(), so we can get debug output as early as possible */
-early_param("dynamic_printk", dynamic_printk_setup);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 9e169ef2e85..12bd09dbd36 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -66,7 +66,7 @@ void
 			     struct nf_conntrack_expect *exp) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
 
-#if defined(DEBUG) || defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
 /* PptpControlMessageType names */
 const char *const pptp_msg_name[] = {
 	"UNKNOWN_MESSAGE",
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index e06365775bd..c18fa150b6f 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -97,7 +97,7 @@ modname_flags  = $(if $(filter 1,$(words $(modname))),\
                  -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
 
 #hash values
-ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
+ifdef CONFIG_DYNAMIC_DEBUG
 debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
               -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
 else
-- 
cgit v1.2.3-70-g09d2


From 86151fdf38b3795f292b39defbff39d2684b9c8c Mon Sep 17 00:00:00 2001
From: Jason Baron <jbaron@redhat.com>
Date: Thu, 5 Feb 2009 11:53:15 -0500
Subject: dynamic debug: update docs

updates the documentation for 'dynamic debug' feature.

Signed-off-by: Greg Banks <gnb@sgi.com>
Signed-off-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 Documentation/dynamic-debug-howto.txt | 232 ++++++++++++++++++++++++++++++++++
 lib/Kconfig.debug                     |  72 ++++++-----
 2 files changed, 273 insertions(+), 31 deletions(-)
 create mode 100644 Documentation/dynamic-debug-howto.txt

(limited to 'Documentation')

diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
new file mode 100644
index 00000000000..68394825e86
--- /dev/null
+++ b/Documentation/dynamic-debug-howto.txt
@@ -0,0 +1,232 @@
+
+Introduction
+============
+
+This document describes how to use the dynamic debug (ddebug) feature.
+
+Dynamic debug is designed to allow you to dynamically enable/disable kernel
+code to obtain additional kernel information. Currently, if
+CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_debug() calls can be
+dynamically enabled per-callsite.
+
+Dynamic debug has even more useful features:
+
+ * Simple query language allows turning on and off debugging statements by
+   matching any combination of:
+
+   - source filename
+   - function name
+   - line number (including ranges of line numbers)
+   - module name
+   - format string
+
+ * Provides a debugfs control file: <debugfs>/dynamic_debug/control which can be
+   read to display the complete list of known debug statements, to help guide you
+
+Controlling dynamic debug Behaviour
+===============================
+
+The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
+control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
+filesystem, in order to make use of this feature. Subsequently, we refer to the
+control file as: <debugfs>/dynamic_debug/control. For example, if you want to
+enable printing from source file 'svcsock.c', line 1603 you simply do:
+
+nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+If you make a mistake with the syntax, the write will fail thus:
+
+nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
+				<debugfs>/dynamic_debug/control
+-bash: echo: write error: Invalid argument
+
+Viewing Dynamic Debug Behaviour
+===========================
+
+You can view the currently configured behaviour of all the debug statements
+via:
+
+nullarbor:~ # cat <debugfs>/dynamic_debug/control
+# filename:lineno [module]function flags format
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA\040Module\040Removed,\040deregister\040RPC\040RDMA\040transport\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline\040\040\040\040\040\040\040:\040%d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth\040\040\040\040\040\040\040\040\040:\040%d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests\040\040\040\040\040:\040%d\012"
+...
+
+
+You can also apply standard Unix text manipulation filters to this
+data, e.g.
+
+nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control  | wc -l
+62
+
+nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
+42
+
+Note in particular that the third column shows the enabled behaviour
+flags for each debug statement callsite (see below for definitions of the
+flags).  The default value, no extra behaviour enabled, is "-".  So
+you can view all the debug statement callsites with any non-default flags:
+
+nullarbor:~ # awk '$3 != "-"' <debugfs>/dynamic_debug/control
+# filename:lineno [module]function flags format
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process:\040st_sendto\040returned\040%d\012"
+
+
+Command Language Reference
+==========================
+
+At the lexical level, a command comprises a sequence of words separated
+by whitespace characters.  Note that newlines are treated as word
+separators and do *not* end a command or allow multiple commands to
+be done together.  So these are all equivalent:
+
+nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+nullarbor:~ # echo -c '  file   svcsock.c     line  1603 +p  ' >
+				<debugfs>/dynamic_debug/control
+nullarbor:~ # echo -c 'file svcsock.c\nline 1603 +p' >
+				<debugfs>/dynamic_debug/control
+nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+Commands are bounded by a write() system call.  If you want to do
+multiple commands you need to do a separate "echo" for each, like:
+
+nullarbor:~ # echo 'file svcsock.c line 1603 +p' > /proc/dprintk ;\
+> echo 'file svcsock.c line 1563 +p' > /proc/dprintk
+
+or even like:
+
+nullarbor:~ # (
+> echo 'file svcsock.c line 1603 +p' ;\
+> echo 'file svcsock.c line 1563 +p' ;\
+> ) > /proc/dprintk
+
+At the syntactical level, a command comprises a sequence of match
+specifications, followed by a flags change specification.
+
+command ::= match-spec* flags-spec
+
+The match-spec's are used to choose a subset of the known dprintk()
+callsites to which to apply the flags-spec.  Think of them as a query
+with implicit ANDs between each pair.  Note that an empty list of
+match-specs is possible, but is not very useful because it will not
+match any debug statement callsites.
+
+A match specification comprises a keyword, which controls the attribute
+of the callsite to be compared, and a value to compare against.  Possible
+keywords are:
+
+match-spec ::= 'func' string |
+	       'file' string |
+	       'module' string |
+	       'format' string |
+	       'line' line-range
+
+line-range ::= lineno |
+	       '-'lineno |
+	       lineno'-' |
+	       lineno'-'lineno
+// Note: line-range cannot contain space, e.g.
+// "1-30" is valid range but "1 - 30" is not.
+
+lineno ::= unsigned-int
+
+The meanings of each keyword are:
+
+func
+    The given string is compared against the function name
+    of each callsite.  Example:
+
+    func svc_tcp_accept
+
+file
+    The given string is compared against either the full
+    pathname or the basename of the source file of each
+    callsite.  Examples:
+
+    file svcsock.c
+    file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c
+
+module
+    The given string is compared against the module name
+    of each callsite.  The module name is the string as
+    seen in "lsmod", i.e. without the directory or the .ko
+    suffix and with '-' changed to '_'.  Examples:
+
+    module sunrpc
+    module nfsd
+
+format
+    The given string is searched for in the dynamic debug format
+    string.  Note that the string does not need to match the
+    entire format, only some part.  Whitespace and other
+    special characters can be escaped using C octal character
+    escape \ooo notation, e.g. the space character is \040.
+    Examples:
+
+    format svcrdma:	    // many of the NFS/RDMA server dprintks
+    format readahead	    // some dprintks in the readahead cache
+    format nfsd:\040SETATTR // how to match a format with whitespace
+
+line
+    The given line number or range of line numbers is compared
+    against the line number of each dprintk() callsite.  A single
+    line number matches the callsite line number exactly.  A
+    range of line numbers matches any callsite between the first
+    and last line number inclusive.  An empty first number means
+    the first line in the file, an empty line number means the
+    last number in the file.  Examples:
+
+    line 1603	    // exactly line 1603
+    line 1600-1605  // the six lines from line 1600 to line 1605
+    line -1605	    // the 1605 lines from line 1 to line 1605
+    line 1600-	    // all lines from line 1600 to the end of the file
+
+The flags specification comprises a change operation followed
+by one or more flag characters.  The change operation is one
+of the characters:
+
+-
+    remove the given flags
+
++
+    add the given flags
+
+=
+    set the flags to the given flags
+
+The flags are:
+
+p
+    Causes a printk() message to be emitted to dmesg
+
+Note the regexp ^[-+=][scp]+$ matches a flags specification.
+Note also that there is no convenient syntax to remove all
+the flags at once, you need to use "-psc".
+
+Examples
+========
+
+// enable the message at line 1603 of file svcsock.c
+nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+// enable all the messages in file svcsock.c
+nullarbor:~ # echo -n 'file svcsock.c +p' >
+				<debugfs>/dynamic_debug/control
+
+// enable all the messages in the NFS server module
+nullarbor:~ # echo -n 'module nfsd +p' >
+				<debugfs>/dynamic_debug/control
+
+// enable all 12 messages in the function svc_process()
+nullarbor:~ # echo -n 'func svc_process +p' >
+				<debugfs>/dynamic_debug/control
+
+// disable all 12 messages in the function svc_process()
+nullarbor:~ # echo -n 'func svc_process -p' >
+				<debugfs>/dynamic_debug/control
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 0dd1c04c732..8fee0a13ac5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -848,59 +848,69 @@ config BUILD_DOCSRC
 	  Say N if you are unsure.
 
 config DYNAMIC_DEBUG
-	bool "Enable dynamic printk() call support"
+	bool "Enable dynamic printk() support"
 	default n
 	depends on PRINTK
+	depends on DEBUG_FS
 	select PRINTK_DEBUG
 	help
 
 	  Compiles debug level messages into the kernel, which would not
 	  otherwise be available at runtime. These messages can then be
-	  enabled/disabled on a per module basis. This mechanism implicitly
-	  enables all pr_debug() and dev_dbg() calls. The impact of this
-	  compile option is a larger kernel text size of about 2%.
+	  enabled/disabled based on various levels of scope - per source file,
+	  function, module, format string, and line number. This mechanism
+	  implicitly enables all pr_debug() and dev_dbg() calls. The impact of
+	  this compile option is a larger kernel text size of about 2%.
 
 	  Usage:
 
-	  Dynamic debugging is controlled by the debugfs file,
-	  dynamic_printk/modules. This file contains a list of the modules that
-	  can be enabled. The format of the file is the module name, followed
-	  by a set of flags that can be enabled. The first flag is always the
-	  'enabled' flag. For example:
+	  Dynamic debugging is controlled via the 'dynamic_debug/ddebug' file,
+	  which is contained in the 'debugfs' filesystem. Thus, the debugfs
+	  filesystem must first be mounted before making use of this feature.
+	  We refer the control file as: <debugfs>/dynamic_debug/ddebug. This
+	  file contains a list of the debug statements that can be enabled. The
+	  format for each line of the file is:
 
-		<module_name> <enabled=0/1>
-				.
-				.
-				.
+		filename:lineno [module]function flags format
 
-	  <module_name> : Name of the module in which the debug call resides
-	  <enabled=0/1> : whether the messages are enabled or not
+	  filename : source file of the debug statement
+	  lineno : line number of the debug statement
+	  module : module that contains the debug statement
+	  function : function that contains the debug statement
+          flags : 'p' means the line is turned 'on' for printing
+          format : the format used for the debug statement
 
 	  From a live system:
 
-		snd_hda_intel enabled=0
-		fixup enabled=0
-		driver enabled=0
+		nullarbor:~ # cat <debugfs>/dynamic_debug/ddebug
+		# filename:lineno [module]function flags format
+		fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012"
+		fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012"
+		fs/aio.c:1770 [aio]sys_io_cancel - "calling\040cancel\012"
 
-	  Enable a module:
+	  Example usage:
 
-	  	$echo "set enabled=1 <module_name>" > dynamic_printk/modules
+		// enable the message at line 1603 of file svcsock.c
+		nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  Disable a module:
+		// enable all the messages in file svcsock.c
+		nullarbor:~ # echo -n 'file svcsock.c +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  	$echo "set enabled=0 <module_name>" > dynamic_printk/modules
+		// enable all the messages in the NFS server module
+		nullarbor:~ # echo -n 'module nfsd +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  Enable all modules:
+		// enable all 12 messages in the function svc_process()
+		nullarbor:~ # echo -n 'func svc_process +p' >
+						<debugfs>/dynamic_debug/ddebug
 
-		$echo "set enabled=1 all" > dynamic_printk/modules
+		// disable all 12 messages in the function svc_process()
+		nullarbor:~ # echo -n 'func svc_process -p' >
+						<debugfs>/dynamic_debug/ddebug
 
-	  Disable all modules:
-
-		$echo "set enabled=0 all" > dynamic_printk/modules
-
-	  Finally, passing "dynamic_printk" at the command line enables
-	  debugging for all modules. This mode can be turned off via the above
-	  disable command.
+	  See Documentation/dynamic-debug-howto.txt for additional information.
 
 source "samples/Kconfig"
 
-- 
cgit v1.2.3-70-g09d2


From 9898abb3d23311fa227a7f46bf4e40fd2954057f Mon Sep 17 00:00:00 2001
From: Greg Banks <gnb@melbourne.sgi.com>
Date: Fri, 6 Feb 2009 12:54:26 +1100
Subject: Dynamic debug: allow simple quoting of words

Allow simple quoting of words in the dynamic debug control language.

This allows more natural specification when using the control language
to match against printk formats, e.g

#echo -n 'format "Setting node for non-present cpu" +p' >
	/mnt/debugfs/dynamic_debug/control

instead of

#echo -n 'format Setting\040node\040for\040non-present\040cpu +p' >
	/mnt/debugfs/dynamic_debug/control

Adjust the dynamic debug documention to describe that and provide a
new example.  Adjust the existing examples in the documentation to
reflect the current whitespace escaping behaviour when reading the
control file.  Fix some minor documentation trailing whitespace.

Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 Documentation/dynamic-debug-howto.txt | 20 +++++++++----
 lib/dynamic_debug.c                   | 53 ++++++++++++++++++++++-------------
 2 files changed, 47 insertions(+), 26 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
index 68394825e86..674c5663d34 100644
--- a/Documentation/dynamic-debug-howto.txt
+++ b/Documentation/dynamic-debug-howto.txt
@@ -49,10 +49,10 @@ via:
 
 nullarbor:~ # cat <debugfs>/dynamic_debug/control
 # filename:lineno [module]function flags format
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA\040Module\040Removed,\040deregister\040RPC\040RDMA\040transport\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline\040\040\040\040\040\040\040:\040%d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth\040\040\040\040\040\040\040\040\040:\040%d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests\040\040\040\040\040:\040%d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup - "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init - "\011max_inline       : %d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init - "\011sq_depth         : %d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init - "\011max_requests     : %d\012"
 ...
 
 
@@ -72,7 +72,7 @@ you can view all the debug statement callsites with any non-default flags:
 
 nullarbor:~ # awk '$3 != "-"' <debugfs>/dynamic_debug/control
 # filename:lineno [module]function flags format
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process:\040st_sendto\040returned\040%d\012"
+/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
 
 
 Command Language Reference
@@ -166,11 +166,15 @@ format
     entire format, only some part.  Whitespace and other
     special characters can be escaped using C octal character
     escape \ooo notation, e.g. the space character is \040.
+    Alternatively, the string can be enclosed in double quote
+    characters (") or single quote characters (').
     Examples:
 
     format svcrdma:	    // many of the NFS/RDMA server dprintks
     format readahead	    // some dprintks in the readahead cache
-    format nfsd:\040SETATTR // how to match a format with whitespace
+    format nfsd:\040SETATTR // one way to match a format with whitespace
+    format "nfsd: SETATTR"  // a neater way to match a format with whitespace
+    format 'nfsd: SETATTR'  // yet another way to match a format with whitespace
 
 line
     The given line number or range of line numbers is compared
@@ -230,3 +234,7 @@ nullarbor:~ # echo -n 'func svc_process +p' >
 // disable all 12 messages in the function svc_process()
 nullarbor:~ # echo -n 'func svc_process -p' >
 				<debugfs>/dynamic_debug/control
+
+// enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
+nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
+				<debugfs>/dynamic_debug/control
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 9e123ae326b..833139ce1e2 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -195,33 +195,46 @@ static void ddebug_change(const struct ddebug_query *query,
 		printk(KERN_INFO "ddebug: no matches for query\n");
 }
 
-/*
- * Wrapper around strsep() to collapse the multiple empty tokens
- * that it returns when fed sequences of separator characters.
- * Now, if we had strtok_r()...
- */
-static inline char *nearly_strtok_r(char **p, const char *sep)
-{
-	char *r;
-
-	while ((r = strsep(p, sep)) != NULL && *r == '\0')
-		;
-	return r;
-}
-
 /*
  * Split the buffer `buf' into space-separated words.
- * Return the number of such words or <0 on error.
+ * Handles simple " and ' quoting, i.e. without nested,
+ * embedded or escaped \".  Return the number of words
+ * or <0 on error.
  */
 static int ddebug_tokenize(char *buf, char *words[], int maxwords)
 {
 	int nwords = 0;
 
-	while (nwords < maxwords &&
-	       (words[nwords] = nearly_strtok_r(&buf, " \t\r\n")) != NULL)
-		nwords++;
-	if (buf)
-		return -EINVAL;	/* ran out of words[] before bytes */
+	while (*buf) {
+		char *end;
+
+		/* Skip leading whitespace */
+		while (*buf && isspace(*buf))
+			buf++;
+		if (!*buf)
+			break;	/* oh, it was trailing whitespace */
+
+		/* Run `end' over a word, either whitespace separated or quoted */
+		if (*buf == '"' || *buf == '\'') {
+			int quote = *buf++;
+			for (end = buf ; *end && *end != quote ; end++)
+				;
+			if (!*end)
+				return -EINVAL;	/* unclosed quote */
+		} else {
+			for (end = buf ; *end && !isspace(*end) ; end++)
+				;
+			BUG_ON(end == buf);
+		}
+		/* Here `buf' is the start of the word, `end' is one past the end */
+
+		if (nwords == maxwords)
+			return -EINVAL;	/* ran out of words[] before bytes */
+		if (*end)
+			*end++ = '\0';	/* terminate the word */
+		words[nwords++] = buf;
+		buf = end;
+	}
 
 	if (verbose) {
 		int i;
-- 
cgit v1.2.3-70-g09d2


From 07e86f405addc6436eb969b8279bb14a6dcacce4 Mon Sep 17 00:00:00 2001
From: Avishay Traeger <avishay@il.ibm.com>
Date: Tue, 24 Mar 2009 12:40:18 +0100
Subject: block: Repeated lines in switching-sched.txt

These lines appear in this file twice - removed one occurrence.

Signed-off-by: Avishay Traeger <avishay@il.ibm.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
---
 Documentation/block/switching-sched.txt | 6 ------
 1 file changed, 6 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
index 634c952e196..d5af3f63081 100644
--- a/Documentation/block/switching-sched.txt
+++ b/Documentation/block/switching-sched.txt
@@ -35,9 +35,3 @@ noop anticipatory deadline [cfq]
 # echo anticipatory > /sys/block/hda/queue/scheduler
 # cat /sys/block/hda/queue/scheduler
 noop [anticipatory] deadline cfq
-
-Each io queue has a set of io scheduler tunables associated with it. These
-tunables control how the io scheduler works. You can find these entries
-in:
-
-/sys/block/<device>/queue/iosched
-- 
cgit v1.2.3-70-g09d2


From 431429ff788598a19c1a193b9fca3961b7f55916 Mon Sep 17 00:00:00 2001
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Date: Thu, 26 Mar 2009 15:23:55 +0100
Subject: [S390] hvc_iucv: Provide IUCV z/VM user ID filtering

This patch introduces the kernel parameter hvc_iucv_allow= that specifies
a comma-separated list of z/VM user IDs.
If specified, the z/VM IUCV hypervisor console device driver accepts IUCV
connections from listed z/VM user IDs only.

Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
 Documentation/kernel-parameters.txt |   3 +
 drivers/char/hvc_iucv.c             | 254 ++++++++++++++++++++++++++++++++++--
 2 files changed, 249 insertions(+), 8 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 54f21a5c262..9f932a76a94 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -829,6 +829,9 @@ and is between 256 and 4096 characters. It is defined in the file
 
 	hvc_iucv=	[S390] Number of z/VM IUCV hypervisor console (HVC)
 			       terminal devices. Valid values: 0..8
+	hvc_iucv_allow=	[S390] Comma-separated list of z/VM user IDs.
+			       If specified, z/VM IUCV HVC accepts connections
+			       from listed z/VM user IDs only.
 
 	i8042.debug	[HW] Toggle i8042 debug mode
 	i8042.direct	[HW] Put keyboard port into non-translated mode
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c
index 146be5a6094..54481a88776 100644
--- a/drivers/char/hvc_iucv.c
+++ b/drivers/char/hvc_iucv.c
@@ -13,10 +13,11 @@
 
 #include <linux/types.h>
 #include <asm/ebcdic.h>
+#include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/mempool.h>
-#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/tty.h>
 #include <linux/wait.h>
 #include <net/iucv/iucv.h>
@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1;
 /* Array of allocated hvc iucv tty lines... */
 static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES];
 #define IUCV_HVC_CON_IDX	(0)
+/* List of z/VM user ID filter entries (struct iucv_vmid_filter) */
+#define MAX_VMID_FILTER		(500)
+static size_t hvc_iucv_filter_size;
+static void *hvc_iucv_filter;
+static const char *hvc_iucv_filter_string;
+static DEFINE_RWLOCK(hvc_iucv_filter_lock);
 
 /* Kmem cache and mempool for iucv_tty_buffer elements */
 static struct kmem_cache *hvc_iucv_buffer_cache;
@@ -617,6 +624,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
 	}
 }
 
+/**
+ * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID
+ * @ipvmid:	Originating z/VM user ID (right padded with blanks)
+ *
+ * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise
+ * non-zero.
+ */
+static int hvc_iucv_filter_connreq(u8 ipvmid[8])
+{
+	size_t i;
+
+	/* Note: default policy is ACCEPT if no filter is set */
+	if (!hvc_iucv_filter_size)
+		return 0;
+
+	for (i = 0; i < hvc_iucv_filter_size; i++)
+		if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8))
+			return 0;
+	return 1;
+}
+
 /**
  * hvc_iucv_path_pending() - IUCV handler to process a connection request.
  * @path:	Pending path (struct iucv_path)
@@ -641,6 +669,7 @@ static	int hvc_iucv_path_pending(struct iucv_path *path,
 {
 	struct hvc_iucv_private *priv;
 	u8 nuser_data[16];
+	u8 vm_user_id[9];
 	int i, rc;
 
 	priv = NULL;
@@ -653,6 +682,20 @@ static	int hvc_iucv_path_pending(struct iucv_path *path,
 	if (!priv)
 		return -ENODEV;
 
+	/* Enforce that ipvmid is allowed to connect to us */
+	read_lock(&hvc_iucv_filter_lock);
+	rc = hvc_iucv_filter_connreq(ipvmid);
+	read_unlock(&hvc_iucv_filter_lock);
+	if (rc) {
+		iucv_path_sever(path, ipuser);
+		iucv_path_free(path);
+		memcpy(vm_user_id, ipvmid, 8);
+		vm_user_id[8] = 0;
+		pr_info("A connection request from z/VM user ID %s "
+			"was refused\n", vm_user_id);
+		return 0;
+	}
+
 	spin_lock(&priv->lock);
 
 	/* If the terminal is already connected or being severed, then sever
@@ -876,6 +919,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
 	return 0;
 }
 
+/**
+ * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID
+ * @filter:	String containing a comma-separated list of z/VM user IDs
+ */
+static const char *hvc_iucv_parse_filter(const char *filter, char *dest)
+{
+	const char *nextdelim, *residual;
+	size_t len;
+
+	nextdelim = strchr(filter, ',');
+	if (nextdelim) {
+		len = nextdelim - filter;
+		residual = nextdelim + 1;
+	} else {
+		len = strlen(filter);
+		residual = filter + len;
+	}
+
+	if (len == 0)
+		return ERR_PTR(-EINVAL);
+
+	/* check for '\n' (if called from sysfs) */
+	if (filter[len - 1] == '\n')
+		len--;
+
+	if (len > 8)
+		return ERR_PTR(-EINVAL);
+
+	/* pad with blanks and save upper case version of user ID */
+	memset(dest, ' ', 8);
+	while (len--)
+		dest[len] = toupper(filter[len]);
+	return residual;
+}
+
+/**
+ * hvc_iucv_setup_filter() - Set up z/VM user ID filter
+ * @filter:	String consisting of a comma-separated list of z/VM user IDs
+ *
+ * The function parses the @filter string and creates an array containing
+ * the list of z/VM user ID filter entries.
+ * Return code 0 means success, -EINVAL if the filter is syntactically
+ * incorrect, -ENOMEM if there was not enough memory to allocate the
+ * filter list array, or -ENOSPC if too many z/VM user IDs have been specified.
+ */
+static int hvc_iucv_setup_filter(const char *val)
+{
+	const char *residual;
+	int err;
+	size_t size, count;
+	void *array, *old_filter;
+
+	count = strlen(val);
+	if (count == 0 || (count == 1 && val[0] == '\n')) {
+		size  = 0;
+		array = NULL;
+		goto out_replace_filter;	/* clear filter */
+	}
+
+	/* count user IDs in order to allocate sufficient memory */
+	size = 1;
+	residual = val;
+	while ((residual = strchr(residual, ',')) != NULL) {
+		residual++;
+		size++;
+	}
+
+	/* check if the specified list exceeds the filter limit */
+	if (size > MAX_VMID_FILTER)
+		return -ENOSPC;
+
+	array = kzalloc(size * 8, GFP_KERNEL);
+	if (!array)
+		return -ENOMEM;
+
+	count = size;
+	residual = val;
+	while (*residual && count) {
+		residual = hvc_iucv_parse_filter(residual,
+						 array + ((size - count) * 8));
+		if (IS_ERR(residual)) {
+			err = PTR_ERR(residual);
+			kfree(array);
+			goto out_err;
+		}
+		count--;
+	}
+
+out_replace_filter:
+	write_lock_bh(&hvc_iucv_filter_lock);
+	old_filter = hvc_iucv_filter;
+	hvc_iucv_filter_size = size;
+	hvc_iucv_filter = array;
+	write_unlock_bh(&hvc_iucv_filter_lock);
+	kfree(old_filter);
+
+	err = 0;
+out_err:
+	return err;
+}
+
+/**
+ * param_set_vmidfilter() - Set z/VM user ID filter parameter
+ * @val:	String consisting of a comma-separated list of z/VM user IDs
+ * @kp:		Kernel parameter pointing to hvc_iucv_filter array
+ *
+ * The function sets up the z/VM user ID filter specified as comma-separated
+ * list of user IDs in @val.
+ * Note: If it is called early in the boot process, @val is stored and
+ *	 parsed later in hvc_iucv_init().
+ */
+static int param_set_vmidfilter(const char *val, struct kernel_param *kp)
+{
+	int rc;
+
+	if (!MACHINE_IS_VM || !hvc_iucv_devices)
+		return -ENODEV;
+
+	if (!val)
+		return -EINVAL;
+
+	rc = 0;
+	if (slab_is_available())
+		rc = hvc_iucv_setup_filter(val);
+	else
+		hvc_iucv_filter_string = val;	/* defer... */
+	return rc;
+}
+
+/**
+ * param_get_vmidfilter() - Get z/VM user ID filter
+ * @buffer:	Buffer to store z/VM user ID filter,
+ *		(buffer size assumption PAGE_SIZE)
+ * @kp:		Kernel parameter pointing to the hvc_iucv_filter array
+ *
+ * The function stores the filter as a comma-separated list of z/VM user IDs
+ * in @buffer. Typically, sysfs routines call this function for attr show.
+ */
+static int param_get_vmidfilter(char *buffer, struct kernel_param *kp)
+{
+	int rc;
+	size_t index, len;
+	void *start, *end;
+
+	if (!MACHINE_IS_VM || !hvc_iucv_devices)
+		return -ENODEV;
+
+	rc = 0;
+	read_lock_bh(&hvc_iucv_filter_lock);
+	for (index = 0; index < hvc_iucv_filter_size; index++) {
+		start = hvc_iucv_filter + (8 * index);
+		end   = memchr(start, ' ', 8);
+		len   = (end) ? end - start : 8;
+		memcpy(buffer + rc, start, len);
+		rc += len;
+		buffer[rc++] = ',';
+	}
+	read_unlock_bh(&hvc_iucv_filter_lock);
+	if (rc)
+		buffer[--rc] = '\0';	/* replace last comma and update rc */
+	return rc;
+}
+
+#define param_check_vmidfilter(name, p) __param_check(name, p, void)
+
 /**
  * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
  */
@@ -884,19 +1092,44 @@ static int __init hvc_iucv_init(void)
 	int rc;
 	unsigned int i;
 
+	if (!hvc_iucv_devices)
+		return -ENODEV;
+
 	if (!MACHINE_IS_VM) {
 		pr_notice("The z/VM IUCV HVC device driver cannot "
 			   "be used without z/VM\n");
-		return -ENODEV;
+		rc = -ENODEV;
+		goto out_error;
 	}
 
-	if (!hvc_iucv_devices)
-		return -ENODEV;
-
 	if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) {
 		pr_err("%lu is not a valid value for the hvc_iucv= "
 			"kernel parameter\n", hvc_iucv_devices);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_error;
+	}
+
+	/* parse hvc_iucv_allow string and create z/VM user ID filter list */
+	if (hvc_iucv_filter_string) {
+		rc = hvc_iucv_setup_filter(hvc_iucv_filter_string);
+		switch (rc) {
+		case 0:
+			break;
+		case -ENOMEM:
+			pr_err("Allocating memory failed with "
+				"reason code=%d\n", 3);
+			goto out_error;
+		case -EINVAL:
+			pr_err("hvc_iucv_allow= does not specify a valid "
+				"z/VM user ID list\n");
+			goto out_error;
+		case -ENOSPC:
+			pr_err("hvc_iucv_allow= specifies too many "
+				"z/VM user IDs\n");
+			goto out_error;
+		default:
+			goto out_error;
+		}
 	}
 
 	hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT,
@@ -904,7 +1137,8 @@ static int __init hvc_iucv_init(void)
 					   0, 0, NULL);
 	if (!hvc_iucv_buffer_cache) {
 		pr_err("Allocating memory failed with reason code=%d\n", 1);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_error;
 	}
 
 	hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR,
@@ -912,7 +1146,8 @@ static int __init hvc_iucv_init(void)
 	if (!hvc_iucv_mempool) {
 		pr_err("Allocating memory failed with reason code=%d\n", 2);
 		kmem_cache_destroy(hvc_iucv_buffer_cache);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_error;
 	}
 
 	/* register the first terminal device as console
@@ -956,6 +1191,8 @@ out_error_hvc:
 out_error_memory:
 	mempool_destroy(hvc_iucv_mempool);
 	kmem_cache_destroy(hvc_iucv_buffer_cache);
+out_error:
+	hvc_iucv_devices = 0; /* ensure that we do not provide any device */
 	return rc;
 }
 
@@ -971,3 +1208,4 @@ static	int __init hvc_iucv_config(char *val)
 
 device_initcall(hvc_iucv_init);
 __setup("hvc_iucv=", hvc_iucv_config);
+core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640);
-- 
cgit v1.2.3-70-g09d2


From 7676b8fd701beb47cc1b4cc291acaa07287ea69a Mon Sep 17 00:00:00 2001
From: Alan Cox <alan@lxorguk.ukuu.org.uk>
Date: Thu, 26 Mar 2009 20:47:00 +0000
Subject: dontdiff: Fix asm exclude

Now that the headers are in arch/foo/include/asm we don't want to exclude
them when preparing diff files.

Closes-bug: 12921

Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
 Documentation/dontdiff | 1 -
 1 file changed, 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 1e89a51ea49..88519daab6e 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -62,7 +62,6 @@ aic7*reg_print.c*
 aic7*seq.h*
 aicasm
 aicdb.h*
-asm
 asm-offsets.h
 asm_offsets.h
 autoconf.h*
-- 
cgit v1.2.3-70-g09d2


From 6ee7d33056f6e6fc7437d980dcc741816deedd0f Mon Sep 17 00:00:00 2001
From: "Luis R. Rodriguez" <lrodriguez@atheros.com>
Date: Fri, 20 Mar 2009 23:53:06 -0400
Subject: cfg80211: make regdom module parameter available oustide of OLD_REG

It seems a few users are using this module parameter although its not
recommended. People are finding it useful despite there being utilities
for setting this in userspace. I'm not aware of any distribution using
this though.

Until userspace and distributions catch up with a default userspace
automatic replacement (GeoClue integration would be nirvana) we copy
the ieee80211_regdom module parameter from OLD_REG to the new reg
code to help these users migrate.

Users who are using the non-valid ISO / IEC 3166 alpha "EU" in their
ieee80211_regdom module parameter and migrate to non-OLD_REG enabled
system will world roam.

This also schedules removal of this same ieee80211_regdom module
parameter circa March 2010. Hope is by then nirvana is reached and
users will abandoned the module parameter completely.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 Documentation/feature-removal-schedule.txt | 30 ++++++++++++++++++++++++++----
 net/wireless/reg.c                         |  7 ++++++-
 2 files changed, 32 insertions(+), 5 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index e47c0ff8ba7..8365f52a354 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -6,7 +6,31 @@ be removed from this file.
 
 ---------------------------
 
-What:	old static regulatory information and ieee80211_regdom module parameter
+What:	The ieee80211_regdom module parameter
+When:	March 2010
+
+Why:	This was inherited by the CONFIG_WIRELESS_OLD_REGULATORY code,
+	and currently serves as an option for users to define an
+	ISO / IEC 3166 alpha2 code for the country they are currently
+	present in. Although there are userspace API replacements for this
+	through nl80211 distributions haven't yet caught up with implementing
+	decent alternatives through standard GUIs. Although available as an
+	option through iw or wpa_supplicant its just a matter of time before
+	distributions pick up good GUI options for this. The ideal solution
+	would actually consist of intelligent designs which would do this for
+	the user automatically even when travelling through different countries.
+	Until then we leave this module parameter as a compromise.
+
+	When userspace improves with reasonable widely-available alternatives for
+	this we will no longer need this module parameter. This entry hopes that
+	by the super-futuristically looking date of "March 2010" we will have
+	such replacements widely available.
+
+Who:	Luis R. Rodriguez <lrodriguez@atheros.com>
+
+---------------------------
+
+What:	old static regulatory information
 When:	2.6.29
 Why:	The old regulatory infrastructure has been replaced with a new one
 	which does not require statically defined regulatory domains. We do
@@ -17,9 +41,7 @@ Why:	The old regulatory infrastructure has been replaced with a new one
 		* JP
 		* EU
 	and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was
-	set. We also kept around the ieee80211_regdom module parameter in case
-	some applications were relying on it. Changing regulatory domains
-	can now be done instead by using nl80211, as is done with iw.
+	set.
 Who:	Luis R. Rodriguez <lrodriguez@atheros.com>
 
 ---------------------------
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 9afc9168748..ac048a158d8 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -122,9 +122,14 @@ static const struct ieee80211_regdomain *cfg80211_world_regdom =
 
 #ifdef CONFIG_WIRELESS_OLD_REGULATORY
 static char *ieee80211_regdom = "US";
+#else
+static char *ieee80211_regdom = "00";
+#endif
+
 module_param(ieee80211_regdom, charp, 0444);
 MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
 
+#ifdef CONFIG_WIRELESS_OLD_REGULATORY
 /*
  * We assume 40 MHz bandwidth for the old regulatory work.
  * We make emphasis we are using the exact same frequencies
@@ -2152,7 +2157,7 @@ int regulatory_init(void)
 #else
 	cfg80211_regdomain = cfg80211_world_regdom;
 
-	err = regulatory_hint_core("00");
+	err = regulatory_hint_core(ieee80211_regdom);
 #endif
 	if (err) {
 		if (err == -ENOMEM)
-- 
cgit v1.2.3-70-g09d2


From 04de83815993714a7ba2618f637fa1092a5f664b Mon Sep 17 00:00:00 2001
From: Kalle Valo <kalle.valo@nokia.com>
Date: Sun, 22 Mar 2009 21:57:35 +0200
Subject: mac80211: add beacon filtering support

Add IEEE80211_HW_BEACON_FILTERING flag so that driver inform that it supports
beacon filtering. Drivers need to call the new function
ieee80211_beacon_loss() to notify about beacon loss.

Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 Documentation/DocBook/mac80211.tmpl |  6 +++++
 include/net/mac80211.h              | 33 +++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h          |  2 ++
 net/mac80211/iface.c                |  3 +++
 net/mac80211/mlme.c                 | 49 ++++++++++++++++++++++++++++++++++++-
 5 files changed, 92 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
index 8af6d962687..fbeaffc1dcc 100644
--- a/Documentation/DocBook/mac80211.tmpl
+++ b/Documentation/DocBook/mac80211.tmpl
@@ -227,6 +227,12 @@ usage should require reading the full document.
 !Pinclude/net/mac80211.h Powersave support
     </chapter>
 
+    <chapter id="beacon-filter">
+      <title>Beacon filter support</title>
+!Pinclude/net/mac80211.h Beacon filter support
+!Finclude/net/mac80211.h ieee80211_beacon_loss
+    </chapter>
+
     <chapter id="qos">
       <title>Multiple queues and QoS support</title>
       <para>TBD</para>
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 174dc1d7526..d881ed8ad2c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -882,6 +882,10 @@ enum ieee80211_tkip_key_type {
  *
  * @IEEE80211_HW_MFP_CAPABLE:
  *	Hardware supports management frame protection (MFP, IEEE 802.11w).
+ *
+ * @IEEE80211_HW_BEACON_FILTER:
+ *	Hardware supports dropping of irrelevant beacon frames to
+ *	avoid waking up cpu.
  */
 enum ieee80211_hw_flags {
 	IEEE80211_HW_RX_INCLUDES_FCS			= 1<<1,
@@ -897,6 +901,7 @@ enum ieee80211_hw_flags {
 	IEEE80211_HW_PS_NULLFUNC_STACK			= 1<<11,
 	IEEE80211_HW_SUPPORTS_DYNAMIC_PS		= 1<<12,
 	IEEE80211_HW_MFP_CAPABLE			= 1<<13,
+	IEEE80211_HW_BEACON_FILTER			= 1<<14,
 };
 
 /**
@@ -1120,6 +1125,24 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  * value, or by the stack if all nullfunc handling is in the stack.
  */
 
+/**
+ * DOC: Beacon filter support
+ *
+ * Some hardware have beacon filter support to reduce host cpu wakeups
+ * which will reduce system power consumption. It usuallly works so that
+ * the firmware creates a checksum of the beacon but omits all constantly
+ * changing elements (TSF, TIM etc). Whenever the checksum changes the
+ * beacon is forwarded to the host, otherwise it will be just dropped. That
+ * way the host will only receive beacons where some relevant information
+ * (for example ERP protection or WMM settings) have changed.
+ *
+ * Beacon filter support is informed with %IEEE80211_HW_BEACON_FILTER flag.
+ * The driver needs to enable beacon filter support whenever power save is
+ * enabled, that is %IEEE80211_CONF_PS is set. When power save is enabled,
+ * the stack will not check for beacon miss at all and the driver needs to
+ * notify about complete loss of beacons with ieee80211_beacon_loss().
+ */
+
 /**
  * DOC: Frame filtering
  *
@@ -1970,6 +1993,16 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
 struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
 					 const u8 *addr);
 
+/**
+ * ieee80211_beacon_loss - inform hardware does not receive beacons
+ *
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
+ *
+ * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and
+ * IEEE80211_CONF_PS is set, the driver needs to inform whenever the
+ * hardware is not receiving beacons with this function.
+ */
+void ieee80211_beacon_loss(struct ieee80211_vif *vif);
 
 /* Rate control API */
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8a617a7fc09..acba78e1a5c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -275,6 +275,7 @@ struct ieee80211_if_managed {
 	struct timer_list chswitch_timer;
 	struct work_struct work;
 	struct work_struct chswitch_work;
+	struct work_struct beacon_loss_work;
 
 	u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
 
@@ -1086,6 +1087,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
 			     int powersave);
 void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
 			     struct ieee80211_hdr *hdr);
+void ieee80211_beacon_loss_work(struct work_struct *work);
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 				     enum queue_stop_reason reason);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index dd2a276fa8c..91e8e1bacaa 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -477,6 +477,9 @@ static int ieee80211_stop(struct net_device *dev)
 		 */
 		cancel_work_sync(&sdata->u.mgd.work);
 		cancel_work_sync(&sdata->u.mgd.chswitch_work);
+
+		cancel_work_sync(&sdata->u.mgd.beacon_loss_work);
+
 		/*
 		 * When we get here, the interface is marked down.
 		 * Call synchronize_rcu() to wait for the RX path
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 8f30f4d19da..7ecda9d59d8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -610,6 +610,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 		bss_info_changed |= ieee80211_handle_bss_capability(sdata,
 			bss->cbss.capability, bss->has_erp_value, bss->erp_value);
 
+		cfg80211_hold_bss(&bss->cbss);
+
 		ieee80211_rx_bss_put(local, bss);
 	}
 
@@ -751,6 +753,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
+	struct ieee80211_bss *bss;
 	struct sta_info *sta;
 	u32 changed = 0, config_changed = 0;
 
@@ -774,6 +778,15 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
 	ieee80211_sta_tear_down_BA_sessions(sta);
 
+	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
+				   conf->channel->center_freq,
+				   ifmgd->ssid, ifmgd->ssid_len);
+
+	if (bss) {
+		cfg80211_unhold_bss(&bss->cbss);
+		ieee80211_rx_bss_put(local, bss);
+	}
+
 	if (self_disconnected) {
 		if (deauth)
 			ieee80211_send_deauth_disassoc(sdata,
@@ -925,6 +938,33 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
 			  jiffies + IEEE80211_MONITORING_INTERVAL);
 }
 
+void ieee80211_beacon_loss_work(struct work_struct *work)
+{
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data,
+			     u.mgd.beacon_loss_work);
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+	printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
+	       "- sending probe request\n", sdata->dev->name,
+	       sdata->u.mgd.bssid);
+
+	ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
+	ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
+				 ifmgd->ssid_len, NULL, 0);
+
+	mod_timer(&ifmgd->timer, jiffies + IEEE80211_MONITORING_INTERVAL);
+}
+
+void ieee80211_beacon_loss(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+	queue_work(sdata->local->hw.workqueue,
+		   &sdata->u.mgd.beacon_loss_work);
+}
+EXPORT_SYMBOL(ieee80211_beacon_loss);
+
 static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -959,7 +999,13 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
 		goto unlock;
 	}
 
-	if (time_after(jiffies,
+	/*
+	 * Beacon filtering is only enabled with power save and then the
+	 * stack should not check for beacon loss.
+	 */
+	if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
+	      (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
+	    time_after(jiffies,
 		       ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
 		printk(KERN_DEBUG "%s: beacon loss from AP %pM "
 		       "- sending probe request\n",
@@ -1869,6 +1915,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 	ifmgd = &sdata->u.mgd;
 	INIT_WORK(&ifmgd->work, ieee80211_sta_work);
 	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
+	INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
 	setup_timer(&ifmgd->timer, ieee80211_sta_timer,
 		    (unsigned long) sdata);
 	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
-- 
cgit v1.2.3-70-g09d2


From 8a5117d80fe93de5df5b56480054f7df1fd20755 Mon Sep 17 00:00:00 2001
From: "Luis R. Rodriguez" <lrodriguez@atheros.com>
Date: Tue, 24 Mar 2009 21:21:07 -0400
Subject: cfg80211: default CONFIG_WIRELESS_OLD_REGULATORY to n

And update description and feature-removal schedule according
to the new plan.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 Documentation/feature-removal-schedule.txt | 13 +++++++----
 net/wireless/Kconfig                       | 37 ++++++++----------------------
 2 files changed, 18 insertions(+), 32 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 8365f52a354..02ea3773535 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -7,7 +7,7 @@ be removed from this file.
 ---------------------------
 
 What:	The ieee80211_regdom module parameter
-When:	March 2010
+When:	March 2010 / desktop catchup
 
 Why:	This was inherited by the CONFIG_WIRELESS_OLD_REGULATORY code,
 	and currently serves as an option for users to define an
@@ -30,18 +30,23 @@ Who:	Luis R. Rodriguez <lrodriguez@atheros.com>
 
 ---------------------------
 
-What:	old static regulatory information
-When:	2.6.29
+What:	CONFIG_WIRELESS_OLD_REGULATORY - old static regulatory information
+When:	March 2010 / desktop catchup
+
 Why:	The old regulatory infrastructure has been replaced with a new one
 	which does not require statically defined regulatory domains. We do
 	not want to keep static regulatory domains in the kernel due to the
 	the dynamic nature of regulatory law and localization. We kept around
 	the old static definitions for the regulatory domains of:
+
 		* US
 		* JP
 		* EU
+
 	and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was
-	set.
+	set. We will remove this option once the standard Linux desktop catches
+	up with the new userspace APIs we have implemented.
+
 Who:	Luis R. Rodriguez <lrodriguez@atheros.com>
 
 ---------------------------
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index d1d18f34d27..3c3bc9e579e 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -12,36 +12,17 @@ config CFG80211_REG_DEBUG
 
 config WIRELESS_OLD_REGULATORY
 	bool "Old wireless static regulatory definitions"
-	default y
+	default n
 	---help---
 	  This option enables the old static regulatory information
-	  and uses it within the new framework. This is available
-	  temporarily as an option to help prevent immediate issues
-	  due to the switch to the new regulatory framework which
-	  does require a new userspace application which has the
-	  database of regulatory information (CRDA) and another for
-	  setting regulatory domains (iw).
-
-	  For more information see:
-
-	  http://wireless.kernel.org/en/developers/Regulatory/CRDA
-	  http://wireless.kernel.org/en/users/Documentation/iw
-
-	  It is important to note though that if you *do* have CRDA present
-	  and if this option is enabled CRDA *will* be called to update the
-	  regulatory domain (for US and JP only). Support for letting the user
-	  set the regulatory domain through iw is also supported. This option
-	  mainly exists to leave around for a kernel release some old static
-	  regulatory domains that were defined and to keep around the old
-	  ieee80211_regdom module parameter. This is being phased out and you
-	  should stop using them ASAP.
-
-	  Note: You will need CRDA if you want 802.11d support
-
-	  Say Y unless you have installed a new userspace application.
-	  Also say Y if have one currently depending on the ieee80211_regdom
-	  module parameter and cannot port it to use the new userspace
-	  interfaces.
+	  and uses it within the new framework. This option is available
+	  for historical reasons and it is advised to leave it off.
+
+	  For details see:
+
+	  http://wireless.kernel.org/en/developers/Regulatory
+
+	  Say N and if you say Y, please tell us why. The default is N.
 
 config WIRELESS_EXT
 	bool "Wireless extensions"
-- 
cgit v1.2.3-70-g09d2


From 58bfbb51ff2b0fdc6c732ff3d72f50aa632b67a2 Mon Sep 17 00:00:00 2001
From: Paul Moore <paul.moore@hp.com>
Date: Fri, 27 Mar 2009 17:10:41 -0400
Subject: selinux: Remove the "compat_net" compatibility code

The SELinux "compat_net" is marked as deprecated, the time has come to
finally remove it from the kernel.  Further code simplifications are
likely in the future, but this patch was intended to be a simple,
straight-up removal of the compat_net code.

Signed-off-by: Paul Moore <paul.moore@hp.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 Documentation/feature-removal-schedule.txt |  11 ---
 Documentation/kernel-parameters.txt        |   9 --
 security/selinux/hooks.c                   | 153 ++---------------------------
 security/selinux/selinuxfs.c               |  68 -------------
 4 files changed, 7 insertions(+), 234 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 02ea3773535..049a96247f5 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -355,17 +355,6 @@ Who:	Hans de Goede <hdegoede@redhat.com>
 
 ---------------------------
 
-What:	SELinux "compat_net" functionality
-When:	2.6.30 at the earliest
-Why:	In 2.6.18 the Secmark concept was introduced to replace the "compat_net"
-	network access control functionality of SELinux.  Secmark offers both
-	better performance and greater flexibility than the "compat_net"
-	mechanism.  Now that the major Linux distributions have moved to
-	Secmark, it is time to deprecate the older mechanism and start the
-	process of removing the old code.
-Who:	Paul Moore <paul.moore@hp.com>
----------------------------
-
 What:	sysfs ui for changing p4-clockmod parameters
 When:	September 2009
 Why:	See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index fa4e1239a8f..d1b082772e3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2019,15 +2019,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			If enabled at boot time, /selinux/disable can be used
 			later to disable prior to initial policy load.
 
-	selinux_compat_net =
-			[SELINUX] Set initial selinux_compat_net flag value.
-                        Format: { "0" | "1" }
-                        0 -- use new secmark-based packet controls
-                        1 -- use legacy packet controls
-                        Default value is 0 (preferred).
-                        Value can be changed at runtime via
-                        /selinux/compat_net.
-
 	serialnumber	[BUGS=X86-32]
 
 	shapers=	[NET]
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ee2e781d11d..ba808ef6bab 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -93,7 +93,6 @@
 
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
-extern int selinux_compat_net;
 extern struct security_operations *security_ops;
 
 /* SECMARK reference count */
@@ -4019,72 +4018,6 @@ static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
 			    SECCLASS_NODE, NODE__RECVFROM, ad);
 }
 
-static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
-						struct sk_buff *skb,
-						struct avc_audit_data *ad,
-						u16 family,
-						char *addrp)
-{
-	int err;
-	struct sk_security_struct *sksec = sk->sk_security;
-	u16 sk_class;
-	u32 netif_perm, node_perm, recv_perm;
-	u32 port_sid, node_sid, if_sid, sk_sid;
-
-	sk_sid = sksec->sid;
-	sk_class = sksec->sclass;
-
-	switch (sk_class) {
-	case SECCLASS_UDP_SOCKET:
-		netif_perm = NETIF__UDP_RECV;
-		node_perm = NODE__UDP_RECV;
-		recv_perm = UDP_SOCKET__RECV_MSG;
-		break;
-	case SECCLASS_TCP_SOCKET:
-		netif_perm = NETIF__TCP_RECV;
-		node_perm = NODE__TCP_RECV;
-		recv_perm = TCP_SOCKET__RECV_MSG;
-		break;
-	case SECCLASS_DCCP_SOCKET:
-		netif_perm = NETIF__DCCP_RECV;
-		node_perm = NODE__DCCP_RECV;
-		recv_perm = DCCP_SOCKET__RECV_MSG;
-		break;
-	default:
-		netif_perm = NETIF__RAWIP_RECV;
-		node_perm = NODE__RAWIP_RECV;
-		recv_perm = 0;
-		break;
-	}
-
-	err = sel_netif_sid(skb->iif, &if_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
-	if (err)
-		return err;
-
-	err = sel_netnode_sid(addrp, family, &node_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
-	if (err)
-		return err;
-
-	if (!recv_perm)
-		return 0;
-	err = sel_netport_sid(sk->sk_protocol,
-			      ntohs(ad->u.net.sport), &port_sid);
-	if (unlikely(err)) {
-		printk(KERN_WARNING
-		       "SELinux: failure in"
-		       " selinux_sock_rcv_skb_iptables_compat(),"
-		       " network port label not found\n");
-		return err;
-	}
-	return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
-}
-
 static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
 				       u16 family)
 {
@@ -4102,14 +4035,12 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
 	if (err)
 		return err;
 
-	if (selinux_compat_net)
-		err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
-							   family, addrp);
-	else if (selinux_secmark_enabled())
+	if (selinux_secmark_enabled()) {
 		err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
 				   PACKET__RECV, &ad);
-	if (err)
-		return err;
+		if (err)
+			return err;
+	}
 
 	if (selinux_policycap_netpeer) {
 		err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4151,7 +4082,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	 * to the selinux_sock_rcv_skb_compat() function to deal with the
 	 * special handling.  We do this in an attempt to keep this function
 	 * as fast and as clean as possible. */
-	if (selinux_compat_net || !selinux_policycap_netpeer)
+	if (!selinux_policycap_netpeer)
 		return selinux_sock_rcv_skb_compat(sk, skb, family);
 
 	secmark_active = selinux_secmark_enabled();
@@ -4516,71 +4447,6 @@ static unsigned int selinux_ipv4_output(unsigned int hooknum,
 	return selinux_ip_output(skb, PF_INET);
 }
 
-static int selinux_ip_postroute_iptables_compat(struct sock *sk,
-						int ifindex,
-						struct avc_audit_data *ad,
-						u16 family, char *addrp)
-{
-	int err;
-	struct sk_security_struct *sksec = sk->sk_security;
-	u16 sk_class;
-	u32 netif_perm, node_perm, send_perm;
-	u32 port_sid, node_sid, if_sid, sk_sid;
-
-	sk_sid = sksec->sid;
-	sk_class = sksec->sclass;
-
-	switch (sk_class) {
-	case SECCLASS_UDP_SOCKET:
-		netif_perm = NETIF__UDP_SEND;
-		node_perm = NODE__UDP_SEND;
-		send_perm = UDP_SOCKET__SEND_MSG;
-		break;
-	case SECCLASS_TCP_SOCKET:
-		netif_perm = NETIF__TCP_SEND;
-		node_perm = NODE__TCP_SEND;
-		send_perm = TCP_SOCKET__SEND_MSG;
-		break;
-	case SECCLASS_DCCP_SOCKET:
-		netif_perm = NETIF__DCCP_SEND;
-		node_perm = NODE__DCCP_SEND;
-		send_perm = DCCP_SOCKET__SEND_MSG;
-		break;
-	default:
-		netif_perm = NETIF__RAWIP_SEND;
-		node_perm = NODE__RAWIP_SEND;
-		send_perm = 0;
-		break;
-	}
-
-	err = sel_netif_sid(ifindex, &if_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
-		return err;
-
-	err = sel_netnode_sid(addrp, family, &node_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
-	if (err)
-		return err;
-
-	if (send_perm != 0)
-		return 0;
-
-	err = sel_netport_sid(sk->sk_protocol,
-			      ntohs(ad->u.net.dport), &port_sid);
-	if (unlikely(err)) {
-		printk(KERN_WARNING
-		       "SELinux: failure in"
-		       " selinux_ip_postroute_iptables_compat(),"
-		       " network port label not found\n");
-		return err;
-	}
-	return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
-}
-
 static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 						int ifindex,
 						u16 family)
@@ -4601,15 +4467,10 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 	if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
 		return NF_DROP;
 
-	if (selinux_compat_net) {
-		if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
-							 &ad, family, addrp))
-			return NF_DROP;
-	} else if (selinux_secmark_enabled()) {
+	if (selinux_secmark_enabled())
 		if (avc_has_perm(sksec->sid, skb->secmark,
 				 SECCLASS_PACKET, PACKET__SEND, &ad))
 			return NF_DROP;
-	}
 
 	if (selinux_policycap_netpeer)
 		if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
@@ -4633,7 +4494,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
 	 * to the selinux_ip_postroute_compat() function to deal with the
 	 * special handling.  We do this in an attempt to keep this function
 	 * as fast and as clean as possible. */
-	if (selinux_compat_net || !selinux_policycap_netpeer)
+	if (!selinux_policycap_netpeer)
 		return selinux_ip_postroute_compat(skb, ifindex, family);
 #ifdef CONFIG_XFRM
 	/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index d3c8b982cfb..2d5136ec3d5 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -47,8 +47,6 @@ static char *policycap_names[] = {
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
-int selinux_compat_net = 0;
-
 static int __init checkreqprot_setup(char *str)
 {
 	unsigned long checkreqprot;
@@ -58,16 +56,6 @@ static int __init checkreqprot_setup(char *str)
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
-static int __init selinux_compat_net_setup(char *str)
-{
-	unsigned long compat_net;
-	if (!strict_strtoul(str, 0, &compat_net))
-		selinux_compat_net = compat_net ? 1 : 0;
-	return 1;
-}
-__setup("selinux_compat_net=", selinux_compat_net_setup);
-
-
 static DEFINE_MUTEX(sel_mutex);
 
 /* global data for booleans */
@@ -450,61 +438,6 @@ static const struct file_operations sel_checkreqprot_ops = {
 	.write		= sel_write_checkreqprot,
 };
 
-static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
-				   size_t count, loff_t *ppos)
-{
-	char tmpbuf[TMPBUFLEN];
-	ssize_t length;
-
-	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
-	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
-}
-
-static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
-				    size_t count, loff_t *ppos)
-{
-	char *page;
-	ssize_t length;
-	int new_value;
-
-	length = task_has_security(current, SECURITY__LOAD_POLICY);
-	if (length)
-		return length;
-
-	if (count >= PAGE_SIZE)
-		return -ENOMEM;
-	if (*ppos != 0) {
-		/* No partial writes. */
-		return -EINVAL;
-	}
-	page = (char *)get_zeroed_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-	length = -EFAULT;
-	if (copy_from_user(page, buf, count))
-		goto out;
-
-	length = -EINVAL;
-	if (sscanf(page, "%d", &new_value) != 1)
-		goto out;
-
-	if (new_value) {
-		printk(KERN_NOTICE
-		       "SELinux: compat_net is deprecated, please use secmark"
-		       " instead\n");
-		selinux_compat_net = 1;
-	} else
-		selinux_compat_net = 0;
-	length = count;
-out:
-	free_page((unsigned long) page);
-	return length;
-}
-static const struct file_operations sel_compat_net_ops = {
-	.read		= sel_read_compat_net,
-	.write		= sel_write_compat_net,
-};
-
 /*
  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
  */
@@ -1665,7 +1598,6 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
 		[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
 		[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
 		[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
-		[SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
 		[SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
 		[SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
 		/* last one */ {""}
-- 
cgit v1.2.3-70-g09d2


From 4303154e86597885bc3cbc178a48ccbc8213875f Mon Sep 17 00:00:00 2001
From: Etienne Basset <etienne.basset@numericable.fr>
Date: Fri, 27 Mar 2009 17:11:01 -0400
Subject: smack: Add a new '-CIPSO' option to the network address label
 configuration

This patch adds a new special option '-CIPSO' to the Smack subsystem. When used
in the netlabel list, it means "use CIPSO networking". A use case is when your
local network speaks CIPSO and you want also to connect to the unlabeled
Internet. This patch also add some documentation describing that. The patch
also corrects an oops when setting a '' SMACK64 xattr to a file.

Signed-off-by: Etienne Basset <etienne.basset@numericable.fr>
Signed-off-by: Paul Moore <paul.moore@hp.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 Documentation/Smack.txt       | 42 +++++++++++++++++++++++++++++++++++++-----
 security/smack/smack.h        |  3 +++
 security/smack/smack_access.c |  3 +++
 security/smack/smack_lsm.c    | 11 +++++++++--
 security/smack/smackfs.c      | 38 ++++++++++++++++++++++++++++++--------
 5 files changed, 82 insertions(+), 15 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/Smack.txt b/Documentation/Smack.txt
index 989c2fcd811..629c92e9978 100644
--- a/Documentation/Smack.txt
+++ b/Documentation/Smack.txt
@@ -184,14 +184,16 @@ length. Single character labels using special characters, that being anything
 other than a letter or digit, are reserved for use by the Smack development
 team. Smack labels are unstructured, case sensitive, and the only operation
 ever performed on them is comparison for equality. Smack labels cannot
-contain unprintable characters or the "/" (slash) character.
+contain unprintable characters or the "/" (slash) character. Smack labels
+cannot begin with a '-', which is reserved for special options.
 
 There are some predefined labels:
 
-	_ Pronounced "floor", a single underscore character.
-	^ Pronounced "hat", a single circumflex character.
-	* Pronounced "star", a single asterisk character.
-	? Pronounced "huh", a single question mark character.
+	_ 	Pronounced "floor", a single underscore character.
+	^ 	Pronounced "hat", a single circumflex character.
+	* 	Pronounced "star", a single asterisk character.
+	? 	Pronounced "huh", a single question mark character.
+	@ 	Pronounced "Internet", a single at sign character.
 
 Every task on a Smack system is assigned a label. System tasks, such as
 init(8) and systems daemons, are run with the floor ("_") label. User tasks
@@ -412,6 +414,36 @@ sockets.
 	A privileged program may set this to match the label of another
 	task with which it hopes to communicate.
 
+Smack Netlabel Exceptions
+
+You will often find that your labeled application has to talk to the outside,
+unlabeled world. To do this there's a special file /smack/netlabel where you can
+add some exceptions in the form of :
+@IP1	   LABEL1 or
+@IP2/MASK  LABEL2
+
+It means that your application will have unlabeled access to @IP1 if it has
+write access on LABEL1, and access to the subnet @IP2/MASK if it has write
+access on LABEL2.
+
+Entries in the /smack/netlabel file are matched by longest mask first, like in
+classless IPv4 routing.
+
+A special label '@' and an option '-CIPSO' can be used there :
+@      means Internet, any application with any label has access to it
+-CIPSO means standard CIPSO networking
+
+If you don't know what CIPSO is and don't plan to use it, you can just do :
+echo 127.0.0.1 -CIPSO > /smack/netlabel
+echo 0.0.0.0/0 @      > /smack/netlabel
+
+If you use CIPSO on your 192.168.0.0/16 local network and need also unlabeled
+Internet access, you can have :
+echo 127.0.0.1      -CIPSO > /smack/netlabel
+echo 192.168.0.0/16 -CIPSO > /smack/netlabel
+echo 0.0.0.0/0      @      > /smack/netlabel
+
+
 Writing Applications for Smack
 
 There are three sorts of applications that will run on a Smack system. How an
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 5e5a3bcb599..42ef313f985 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -132,6 +132,8 @@ struct smack_known {
 #define XATTR_NAME_SMACKIPIN	XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
 #define XATTR_NAME_SMACKIPOUT	XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
 
+#define SMACK_CIPSO_OPTION 	"-CIPSO"
+
 /*
  * How communications on this socket are treated.
  * Usually it's determined by the underlying netlabel code
@@ -199,6 +201,7 @@ u32 smack_to_secid(const char *);
 extern int smack_cipso_direct;
 extern char *smack_net_ambient;
 extern char *smack_onlycap;
+extern const char *smack_cipso_option;
 
 extern struct smack_known smack_known_floor;
 extern struct smack_known smack_known_hat;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 58564195bb0..ac0a2707f6d 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -261,6 +261,9 @@ char *smk_import(const char *string, int len)
 {
 	struct smack_known *skp;
 
+	/* labels cannot begin with a '-' */
+	if (string[0] == '-')
+		return NULL;
 	skp = smk_import_entry(string, len);
 	if (skp == NULL)
 		return NULL;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 8ed502c2ad4..921514902ec 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -609,6 +609,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
 	    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
 		if (!capable(CAP_MAC_ADMIN))
 			rc = -EPERM;
+		/* a label cannot be void and cannot begin with '-' */
+		if (size == 0 || (size > 0 && ((char *)value)[0] == '-'))
+			rc = -EINVAL;
 	} else
 		rc = cap_inode_setxattr(dentry, name, value, size, flags);
 
@@ -1323,8 +1326,12 @@ static char *smack_host_label(struct sockaddr_in *sip)
 		* so we have found the most specific match
 		*/
 		if ((&snp->smk_host.sin_addr)->s_addr ==
-		    (siap->s_addr & (&snp->smk_mask)->s_addr))
+		    (siap->s_addr & (&snp->smk_mask)->s_addr)) {
+			/* we have found the special CIPSO option */
+			if (snp->smk_label == smack_cipso_option)
+				return NULL;
 			return snp->smk_label;
+		}
 
 	return NULL;
 }
@@ -1486,7 +1493,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
 	struct socket *sock;
 	int rc = 0;
 
-	if (value == NULL || size > SMK_LABELLEN)
+	if (value == NULL || size > SMK_LABELLEN || size == 0)
 		return -EACCES;
 
 	sp = smk_import(value, size);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 856c8a28752..e03a7e19c73 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -86,6 +86,9 @@ LIST_HEAD(smack_rule_list);
 
 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 
+const char *smack_cipso_option = SMACK_CIPSO_OPTION;
+
+
 #define	SEQ_READ_FINISHED	1
 
 /*
@@ -565,6 +568,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
 		goto unlockedout;
 	}
 
+	/* labels cannot begin with a '-' */
+	if (data[0] == '-') {
+		rc = -EINVAL;
+		goto unlockedout;
+	}
 	data[count] = '\0';
 	rule = data;
 	/*
@@ -808,9 +816,18 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 	if (m > BEBITS)
 		return -EINVAL;
 
-	sp = smk_import(smack, 0);
-	if (sp == NULL)
-		return -EINVAL;
+	/* if smack begins with '-', its an option, don't import it */
+	if (smack[0] != '-') {
+		sp = smk_import(smack, 0);
+		if (sp == NULL)
+			return -EINVAL;
+	} else {
+		/* check known options */
+		if (strcmp(smack, smack_cipso_option) == 0)
+			sp = (char *)smack_cipso_option;
+		else
+			return -EINVAL;
+	}
 
 	for (temp_mask = 0; m > 0; m--) {
 		temp_mask |= mask_bits;
@@ -849,18 +866,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 			smk_netlbladdr_insert(skp);
 		}
 	} else {
-		rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
-			&skp->smk_host.sin_addr, &skp->smk_mask,
-			PF_INET, &audit_info);
+		/* we delete the unlabeled entry, only if the previous label
+		 * wasnt the special CIPSO option */
+		if (skp->smk_label != smack_cipso_option)
+			rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
+					&skp->smk_host.sin_addr, &skp->smk_mask,
+					PF_INET, &audit_info);
+		else
+			rc = 0;
 		skp->smk_label = sp;
 	}
 
 	/*
 	 * Now tell netlabel about the single label nature of
 	 * this host so that incoming packets get labeled.
+	 * but only if we didn't get the special CIPSO option
 	 */
-
-	if (rc == 0)
+	if (rc == 0 && sp != smack_cipso_option)
 		rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
 			&skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
 			smack_to_secid(skp->smk_label), &audit_info);
-- 
cgit v1.2.3-70-g09d2


From 764c16918fb2347b3cbc8f6030b2b6561911bc32 Mon Sep 17 00:00:00 2001
From: Jean Delvare <khali@linux-fr.org>
Date: Sat, 28 Mar 2009 21:34:40 +0100
Subject: i2c: Document the different ways to instantiate i2c devices

On popular demand, here comes some documentation about how to
instantiate i2c devices in the new (standard) i2c device driver
binding model.

I have also clarified how the class bitfield lets driver authors
control which buses are probed in the auto-detect case, and warned
more loudly against the abuse of this method.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Michael Lawnick <nospam_lawnick@gmx.de>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
---
 Documentation/i2c/instantiating-devices | 167 ++++++++++++++++++++++++++++++++
 Documentation/i2c/writing-clients       |  19 +++-
 2 files changed, 182 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/i2c/instantiating-devices

(limited to 'Documentation')

diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices
new file mode 100644
index 00000000000..b55ce57a84d
--- /dev/null
+++ b/Documentation/i2c/instantiating-devices
@@ -0,0 +1,167 @@
+How to instantiate I2C devices
+==============================
+
+Unlike PCI or USB devices, I2C devices are not enumerated at the hardware
+level. Instead, the software must know which devices are connected on each
+I2C bus segment, and what address these devices are using. For this
+reason, the kernel code must instantiate I2C devices explicitly. There are
+several ways to achieve this, depending on the context and requirements.
+
+
+Method 1: Declare the I2C devices by bus number
+-----------------------------------------------
+
+This method is appropriate when the I2C bus is a system bus as is the case
+for many embedded systems. On such systems, each I2C bus has a number
+which is known in advance. It is thus possible to pre-declare the I2C
+devices which live on this bus. This is done with an array of struct
+i2c_board_info which is registered by calling i2c_register_board_info().
+
+Example (from omap2 h4):
+
+static struct i2c_board_info __initdata h4_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("isp1301_omap", 0x2d),
+		.irq		= OMAP_GPIO_IRQ(125),
+	},
+	{	/* EEPROM on mainboard */
+		I2C_BOARD_INFO("24c01", 0x52),
+		.platform_data	= &m24c01,
+	},
+	{	/* EEPROM on cpu card */
+		I2C_BOARD_INFO("24c01", 0x57),
+		.platform_data	= &m24c01,
+	},
+};
+
+static void __init omap_h4_init(void)
+{
+	(...)
+	i2c_register_board_info(1, h4_i2c_board_info,
+			ARRAY_SIZE(h4_i2c_board_info));
+	(...)
+}
+
+The above code declares 3 devices on I2C bus 1, including their respective
+addresses and custom data needed by their drivers. When the I2C bus in
+question is registered, the I2C devices will be instantiated automatically
+by i2c-core.
+
+The devices will be automatically unbound and destroyed when the I2C bus
+they sit on goes away (if ever.)
+
+
+Method 2: Instantiate the devices explicitly
+--------------------------------------------
+
+This method is appropriate when a larger device uses an I2C bus for
+internal communication. A typical case is TV adapters. These can have a
+tuner, a video decoder, an audio decoder, etc. usually connected to the
+main chip by the means of an I2C bus. You won't know the number of the I2C
+bus in advance, so the method 1 described above can't be used. Instead,
+you can instantiate your I2C devices explicitly. This is done by filling
+a struct i2c_board_info and calling i2c_new_device().
+
+Example (from the sfe4001 network driver):
+
+static struct i2c_board_info sfe4001_hwmon_info = {
+	I2C_BOARD_INFO("max6647", 0x4e),
+};
+
+int sfe4001_init(struct efx_nic *efx)
+{
+	(...)
+	efx->board_info.hwmon_client =
+		i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);
+
+	(...)
+}
+
+The above code instantiates 1 I2C device on the I2C bus which is on the
+network adapter in question.
+
+A variant of this is when you don't know for sure if an I2C device is
+present or not (for example for an optional feature which is not present
+on cheap variants of a board but you have no way to tell them apart), or
+it may have different addresses from one board to the next (manufacturer
+changing its design without notice). In this case, you can call
+i2c_new_probed_device() instead of i2c_new_device().
+
+Example (from the pnx4008 OHCI driver):
+
+static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
+
+static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
+{
+	(...)
+	struct i2c_adapter *i2c_adap;
+	struct i2c_board_info i2c_info;
+
+	(...)
+	i2c_adap = i2c_get_adapter(2);
+	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
+	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
+						   normal_i2c);
+	i2c_put_adapter(i2c_adap);
+	(...)
+}
+
+The above code instantiates up to 1 I2C device on the I2C bus which is on
+the OHCI adapter in question. It first tries at address 0x2c, if nothing
+is found there it tries address 0x2d, and if still nothing is found, it
+simply gives up.
+
+The driver which instantiated the I2C device is responsible for destroying
+it on cleanup. This is done by calling i2c_unregister_device() on the
+pointer that was earlier returned by i2c_new_device() or
+i2c_new_probed_device().
+
+
+Method 3: Probe an I2C bus for certain devices
+----------------------------------------------
+
+Sometimes you do not have enough information about an I2C device, not even
+to call i2c_new_probed_device(). The typical case is hardware monitoring
+chips on PC mainboards. There are several dozen models, which can live
+at 25 different addresses. Given the huge number of mainboards out there,
+it is next to impossible to build an exhaustive list of the hardware
+monitoring chips being used. Fortunately, most of these chips have
+manufacturer and device ID registers, so they can be identified by
+probing.
+
+In that case, I2C devices are neither declared nor instantiated
+explicitly. Instead, i2c-core will probe for such devices as soon as their
+drivers are loaded, and if any is found, an I2C device will be
+instantiated automatically. In order to prevent any misbehavior of this
+mechanism, the following restrictions apply:
+* The I2C device driver must implement the detect() method, which
+  identifies a supported device by reading from arbitrary registers.
+* Only buses which are likely to have a supported device and agree to be
+  probed, will be probed. For example this avoids probing for hardware
+  monitoring chips on a TV adapter.
+
+Example:
+See lm90_driver and lm90_detect() in drivers/hwmon/lm90.c
+
+I2C devices instantiated as a result of such a successful probe will be
+destroyed automatically when the driver which detected them is removed,
+or when the underlying I2C bus is itself destroyed, whichever happens
+first.
+
+Those of you familiar with the i2c subsystem of 2.4 kernels and early 2.6
+kernels will find out that this method 3 is essentially similar to what
+was done there. Two significant differences are:
+* Probing is only one way to instantiate I2C devices now, while it was the
+  only way back then. Where possible, methods 1 and 2 should be preferred.
+  Method 3 should only be used when there is no other way, as it can have
+  undesirable side effects.
+* I2C buses must now explicitly say which I2C driver classes can probe
+  them (by the means of the class bitfield), while all I2C buses were
+  probed by default back then. The default is an empty class which means
+  that no probing happens. The purpose of the class bitfield is to limit
+  the aforementioned undesirable side effects.
+
+Once again, method 3 should be avoided wherever possible. Explicit device
+instantiation (methods 1 and 2) is much preferred for it is safer and
+faster.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 6b9af7d479c..c1a06f989cf 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -207,15 +207,26 @@ You simply have to define a detect callback which will attempt to
 identify supported devices (returning 0 for supported ones and -ENODEV
 for unsupported ones), a list of addresses to probe, and a device type
 (or class) so that only I2C buses which may have that type of device
-connected (and not otherwise enumerated) will be probed.  The i2c
-core will then call you back as needed and will instantiate a device
-for you for every successful detection.
+connected (and not otherwise enumerated) will be probed.  For example,
+a driver for a hardware monitoring chip for which auto-detection is
+needed would set its class to I2C_CLASS_HWMON, and only I2C adapters
+with a class including I2C_CLASS_HWMON would be probed by this driver.
+Note that the absence of matching classes does not prevent the use of
+a device of that type on the given I2C adapter.  All it prevents is
+auto-detection; explicit instantiation of devices is still possible.
 
 Note that this mechanism is purely optional and not suitable for all
 devices.  You need some reliable way to identify the supported devices
 (typically using device-specific, dedicated identification registers),
 otherwise misdetections are likely to occur and things can get wrong
-quickly.
+quickly.  Keep in mind that the I2C protocol doesn't include any
+standard way to detect the presence of a chip at a given address, let
+alone a standard way to identify devices.  Even worse is the lack of
+semantics associated to bus transfers, which means that the same
+transfer can be seen as a read operation by a chip and as a write
+operation by another chip.  For these reasons, explicit device
+instantiation should always be preferred to auto-detection where
+possible.
 
 
 Device Deletion
-- 
cgit v1.2.3-70-g09d2


From f02e3d74e9f89e3d49284e7c99217993b657f5b7 Mon Sep 17 00:00:00 2001
From: Jean Delvare <khali@linux-fr.org>
Date: Sat, 28 Mar 2009 21:34:40 +0100
Subject: i2c: Let checkpatch shout on users of the legacy model

As suggested by Mauro Carvalho Chehab.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
---
 Documentation/feature-removal-schedule.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'Documentation')

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 02ea3773535..7907586c6e0 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -340,7 +340,8 @@ Who:  Krzysztof Piotr Oledzki <ole@ans.pl>
 ---------------------------
 
 What:	i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client()
-When:	2.6.29 (ideally) or 2.6.30 (more likely)
+When:	2.6.30
+Check:	i2c_attach_client i2c_detach_client
 Why:	Deprecated by the new (standard) device driver binding model. Use
 	i2c_driver->probe() and ->remove() instead.
 Who:	Jean Delvare <khali@linux-fr.org>
-- 
cgit v1.2.3-70-g09d2


From d2dd14ac1847082d4bb955619e86ed315c0ecd20 Mon Sep 17 00:00:00 2001
From: Jean Delvare <khali@linux-fr.org>
Date: Sat, 28 Mar 2009 21:34:41 +0100
Subject: i2c-nforce2: Add support for MCP67, MCP73, MCP78S and MCP79

The MCP78S and MCP79 appear to be compatible with the previous nForce
chips as far as the SMBus controller is concerned. The MCP67 and MCP73
were not tested yet but I'd be very surprised if they weren't
compatible too.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Oleg Ryjkov <olegr@olegr.ca>
Cc: Malcolm Lalkaka <mlalkaka@gmail.com>
Cc: Zbigniew Luszpinski <zbiggy@o2.pl>
---
 Documentation/i2c/busses/i2c-nforce2 | 12 ++++++++----
 drivers/i2c/busses/i2c-nforce2.c     | 12 ++++++++++--
 include/linux/pci_ids.h              |  4 ++++
 3 files changed, 22 insertions(+), 6 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
index fae3495bcba..9698c396b83 100644
--- a/Documentation/i2c/busses/i2c-nforce2
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -7,10 +7,14 @@ Supported adapters:
   * nForce3 250Gb MCP          10de:00E4 
   * nForce4 MCP                10de:0052
   * nForce4 MCP-04             10de:0034
-  * nForce4 MCP51              10de:0264
-  * nForce4 MCP55              10de:0368
-  * nForce4 MCP61              10de:03EB
-  * nForce4 MCP65              10de:0446
+  * nForce MCP51               10de:0264
+  * nForce MCP55               10de:0368
+  * nForce MCP61               10de:03EB
+  * nForce MCP65               10de:0446
+  * nForce MCP67               10de:0542
+  * nForce MCP73               10de:07D8
+  * nForce MCP78S              10de:0752
+  * nForce MCP79               10de:0AA2
 
 Datasheet: not publicly available, but seems to be similar to the
            AMD-8111 SMBus 2.0 adapter.
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 05af6cd7f27..2ff4683703a 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -31,10 +31,14 @@
     nForce3 250Gb MCP		00E4
     nForce4 MCP			0052
     nForce4 MCP-04		0034
-    nForce4 MCP51		0264
-    nForce4 MCP55		0368
+    nForce MCP51		0264
+    nForce MCP55		0368
     nForce MCP61		03EB
     nForce MCP65		0446
+    nForce MCP67		0542
+    nForce MCP73		07D8
+    nForce MCP78S		0752
+    nForce MCP79		0AA2
 
     This driver supports the 2 SMBuses that are included in the MCP of the
     nForce2/3/4/5xx chipsets.
@@ -315,6 +319,10 @@ static struct pci_device_id nforce2_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS) },
 	{ 0 }
 };
 
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 05dfa7c4fb6..5109fecde28 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1237,6 +1237,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
 #define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
 #define PCI_DEVICE_ID_NVIDIA_NVENET_23              0x0453
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS     0x0542
 #define PCI_DEVICE_ID_NVIDIA_NVENET_24              0x054C
 #define PCI_DEVICE_ID_NVIDIA_NVENET_25              0x054D
 #define PCI_DEVICE_ID_NVIDIA_NVENET_26              0x054E
@@ -1247,11 +1248,14 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_31              0x07DF
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE       0x0560
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE       0x056C
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS    0x0752
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
 #define PCI_DEVICE_ID_NVIDIA_NVENET_32              0x0760
 #define PCI_DEVICE_ID_NVIDIA_NVENET_33              0x0761
 #define PCI_DEVICE_ID_NVIDIA_NVENET_34              0x0762
 #define PCI_DEVICE_ID_NVIDIA_NVENET_35              0x0763
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS     0x07D8
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS     0x0AA2
 #define PCI_DEVICE_ID_NVIDIA_NVENET_36              0x0AB0
 #define PCI_DEVICE_ID_NVIDIA_NVENET_37              0x0AB1
 #define PCI_DEVICE_ID_NVIDIA_NVENET_38              0x0AB2
-- 
cgit v1.2.3-70-g09d2


From 506a8b6c27cb08998dc13069fbdf6eb7ec748b99 Mon Sep 17 00:00:00 2001
From: Flavio Leitner <fbl@sysclose.org>
Date: Sat, 28 Mar 2009 21:34:46 +0100
Subject: i2c-piix4: Add support for the Broadcom HT1100 chipset

Add support for the Broadcom HT1100 LD chipset (SMBus function.)

Signed-off-by: Flavio Leitner <fbl@redhat.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
---
 Documentation/i2c/busses/i2c-piix4 | 2 +-
 drivers/i2c/busses/Kconfig         | 1 +
 drivers/i2c/busses/i2c-piix4.c     | 4 +++-
 include/linux/pci_ids.h            | 1 +
 4 files changed, 6 insertions(+), 2 deletions(-)

(limited to 'Documentation')

diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
index ef1efa79b1d..f889481762b 100644
--- a/Documentation/i2c/busses/i2c-piix4
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -4,7 +4,7 @@ Supported adapters:
   * Intel 82371AB PIIX4 and PIIX4E
   * Intel 82443MX (440MX)
     Datasheet: Publicly available at the Intel website
-  * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
+  * ServerWorks OSB4, CSB5, CSB6, HT-1000 and HT-1100 southbridges
     Datasheet: Only available via NDA from ServerWorks
   * ATI IXP200, IXP300, IXP400, SB600, SB700 and SB800 southbridges
     Datasheet: Not publicly available
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 68650643d11..da809ad0996 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -132,6 +132,7 @@ config I2C_PIIX4
 	    Serverworks CSB5
 	    Serverworks CSB6
 	    Serverworks HT-1000
+	    Serverworks HT-1100
 	    SMSC Victory66
 
 	  This driver can also be built as a module.  If so, the module
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 63d5e597804..0249a7d762b 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -20,7 +20,7 @@
 /*
    Supports:
 	Intel PIIX4, 440MX
-	Serverworks OSB4, CSB5, CSB6, HT-1000
+	Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
 	ATI IXP200, IXP300, IXP400, SB600, SB700, SB800
 	SMSC Victory66
 
@@ -487,6 +487,8 @@ static struct pci_device_id piix4_ids[] = {
 		     PCI_DEVICE_ID_SERVERWORKS_CSB6) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
 		     PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+		     PCI_DEVICE_ID_SERVERWORKS_HT1100LD) },
 	{ 0, }
 };
 
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 5109fecde28..2c9e8080da5 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1479,6 +1479,7 @@
 #define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
+#define PCI_DEVICE_ID_SERVERWORKS_HT1100LD 0x0408
 
 #define PCI_VENDOR_ID_SBE		0x1176
 #define PCI_DEVICE_ID_SBE_WANXL100	0x0301
-- 
cgit v1.2.3-70-g09d2