All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: Does dom0 see all physical processors? (RE:[Xen-ia64-devel] SAL INFO virtualization)
From: Ian Pratt @ 2006-04-05 14:32 UTC (permalink / raw)
  To: Magenheimer, Dan (HP Labs Fort Collins), Keir Fraser, Tian, Kevin
  Cc: Jimi Xenidis, xen-devel, okrieg, Tristan Gingold, xen-ia64-devel


> I believe ppc has "paravirtualized spinlocks" in their Linux 
> kernel, though even this won't necessarily help with a poorly 
> written SMP application.

We have an equivalent of this ("bad pre-emption mitigation"), along with
an alternative ("bad pre-emption avoidance"). Both have various pros and
cons, and can be shown to offer significant benefits in various
contrived benchmarks.

We have benchmark code that records when these bad pre-emptions happen,
and the workloads we've looked at we haven't been moved to check either
scheme in.

That's not to say that we won't have to at some point in the future, but
the limits to scalability are currently elsewhere. 

> > > So on a 16-processor system, every time dom0 needs to run 
> (e.g. to 
> > > handle backend I/O for any one of perhaps hundreds of domains), 
> > > *every* domain gets descheduled so that dom0 can be 
> (gang-)scheduled 
> > > on all 16 processors?
> > > 
> > > If true, this sounds like a _horrible_ performance hit, so I hope 
> > > I'm misunderstanding something...
> > 
> > This isn't an issue.
> > 
> > After booting you probably want dom0 to give up all but 1 
> vCPU anyway.
> 
> Unless of course the PCPU's have data that change over time, 
> such as variable cycle rate (for power management) or 
> hot-plug memory...

Such events don't happen very often -- dom0 is still free to run
something on a given CPU whenever it wants to.

Ian

^ permalink raw reply

* Anybody applied the patch "Add 85xx CDS to arch/powerpc" on the 2.6.16. I failed to apply it:-(
From: fengcheng lu @ 2006-04-05 14:32 UTC (permalink / raw)
  To: linuxppc-dev, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 964 bytes --]

Hello all

    I downloaded this patch from
http://patchwork.ozlabs.org/linuxppc/patch?id=4910. But I failed to apply
it. The following is the output:
debian:/usr/src/linux-2.6.16# patch -p1 <powerpc.patch
patching file arch/powerpc/config/mpc85xx_cds_deconfig
patching file arch/powerpc/platforms/85xx/Kconfig
Hunk #1 FAILED at 11
1 out of 1 hunk FAILED -- saving rejects to file
arch/powerpc/platforms/85xx/Kconfig.rej
patching file arch/powerpc/platforms/85xx/Makefile
Hunk #1 FAILED at 3
1 out of 1 hunk FAILED -- saving rejects to file
arch/powerpc/platforms/85xx/Makefile.rej
patching file arch/powerpc/platforms/85xx/mpc85xx_cds.c
patching file arch/powerpc/platforms/85xx/mpc85xx_cds.h
patching file include/asm-ppc/mpc85xx.h

It looks seem the Makefile and Kconfig don't match yours.

Who have the successful patch experience. Thank you to tell me the right
procedure!

BTW: the patch command version is 2.5.4

Best Regards
Lu

[-- Attachment #2: Type: text/html, Size: 1178 bytes --]

^ permalink raw reply

* Re: [PATCHl] localtime basis for paravirtualized guests
From: Bruce Rogers @ 2006-04-05 14:30 UTC (permalink / raw)
  To: Keir Fraser; +Cc: Ian Pratt, xen-devel
In-Reply-To: <268cbf4ac7bb43efa0994df4a124a19d@cl.cam.ac.uk>

Thanks.  I'll resend then.  I did notice a few issues with my original
patch, so it good that it's getting looked at in greater detail.

- Bruce

>>> Keir Fraser <Keir.Fraser@cl.cam.ac.uk> 4/5/2006 7:03:50 am >>>

On 31 Mar 2006, at 21:22, Bruce Rogers wrote:

> This patch allows the localtime parameter to be used for 
> para-virtualized guests.
> Some paravirtualized guests may need to start with a local time basis

> instead of UTC.
> This patch provides for that need.  Please review and apply.

I've just checked in a patch to provide a clean wallclock update 
interface from common Xen code. Please re-send based on that patch. 
Your dom0_op implementation should modify d->time_offset_seconds 
directly and then call update_domain_wallclock_time(d).

Apart from that, the time_offset_seconds field in dom0_op.h should be 
type int32_t (we don't use s32 in public headers).

  -- Keir


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com 
http://lists.xensource.com/xen-devel

^ permalink raw reply

* Re: [PATCH] ip_conntrack section mismatch warning fix
From: Patrick McHardy @ 2006-04-05 14:30 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netfilter-devel
In-Reply-To: <20060404113233.4de507d3@dxpl.pdx.osdl.net>

Stephen Hemminger wrote:
> This is a bit of a hack. It eliminates the section mismatch warning from
> latest linker. What happens is the init_or_cleanup code gets called
> from cleanup() hook and the linker thinks it will reference __initdata
> because of it's limited static analysis.  By asking compiler to
> inline, it can eliminate that dead code. It does the __init text
> section to grow, but then the space can be reclaimed.

I think this might still fail without forced inlining. Our init
functions look like crap anyway, and the reason mostly seems to
be mass-registration of hooks, so I guess I'll clean that up
with a small helper function and then just split them.

^ permalink raw reply

* [U-Boot-Users] Re: [DNX#2006040542000046] [patch] mkconfig crates bad symlink
From: DENX Support System @ 2006-04-05 14:30 UTC (permalink / raw)
  To: u-boot

Hello list,

inside the automatic U-Boot patch tracking system a new ticket
[DNX#2006040542000046] was created:

<snip>
> Hello
> 
> mkconfig creates include/asm-*/arch.
> but some board this symbolic link is broken and not necessary.
> with this patch, mkconfig wil create a sym-link when there is a
> directory to link.
> 
> Signed-off-by: Hiroshi Ito <ito@mlb.co.jp>
> 
> CHANGELOG:
> 
> * mkconfig will not create broken symlink.
>   Patch by Hiroshi Ito, 5 Apr 2006
> 
> --------
> Hiroshi Ito
> Media Lab. Inc.,
> URL http://www.mlb.co.jp ( Sorry, Japanese only. )
> TEL +81-3-5294-7255  FAX +81-3-5294-7256
</snip>

Your U-Boot support team

^ permalink raw reply

* [U-Boot-Users] Re: [DNX#2006040542000046] [patch] mkconfig cra [...]
From: U-Boot patch tracking system @ 2006-04-05 14:30 UTC (permalink / raw)
  To: u-boot

Dear Mr. U. Boot,

thank you for your contribution to the U-Boot project.

Your e-mail was registered at our system under the ticket
number [DNX#2006040542000046].

Your U-Boot support team

Powered by OTRS (http://otrs.org/)

^ permalink raw reply

* [U-Boot-Users] Re: [patch] add .gitignore
From: ito at mlb.co.jp @ 2006-04-05 14:30 UTC (permalink / raw)
  To: u-boot

Hello
 
add .gitignore

Signed-off-by: Hiroshi Ito <ito@mlb.co.jp>

CHANGELOG:

* add .gitignore
  Patch by Hiroshi Ito, 5 Apr 2006

--------
Hiroshi Ito
Media Lab. Inc.,
URL http://www.mlb.co.jp ( Sorry, Japanese only. )
TEL +81-3-5294-7255  FAX +81-3-5294-7256

-------------- next part --------------
diff -x .git -uNr u-boot.git.org/.gitignore u-boot.git/.gitignore
--- u-boot.git.org/.gitignore	1970-01-01 09:00:00.000000000 +0900
+++ u-boot.git/.gitignore	2006-03-31 17:04:43.000000000 +0900
@@ -0,0 +1,16 @@
+# Normal rules
+*.o
+*.a
+.depend
+*.bin
+*.srec
+*.map
+
+# auto generated files
+u-boot
+TAGS
+tags
+include/config.h
+include/config.mk
+include/asm
+include/version_autogenerated.h
diff -x .git -uNr u-boot.git.org/examples/.gitignore u-boot.git/examples/.gitignore
--- u-boot.git.org/examples/.gitignore	1970-01-01 09:00:00.000000000 +0900
+++ u-boot.git/examples/.gitignore	2006-03-31 17:03:07.000000000 +0900
@@ -0,0 +1 @@
+hello_world
diff -x .git -uNr u-boot.git.org/tools/.gitignore u-boot.git/tools/.gitignore
--- u-boot.git.org/tools/.gitignore	1970-01-01 09:00:00.000000000 +0900
+++ u-boot.git/tools/.gitignore	2006-03-30 19:33:33.000000000 +0900
@@ -0,0 +1,8 @@
+bmp_logo
+crc32.c
+envcrc
+environment.c
+gen_eth_addr
+img2srec
+inca-swap-bytes
+mkimage

^ permalink raw reply

* Re: [PATCH 00/15] powerpc: move some header files
From: Kumar Gala @ 2006-04-05 14:28 UTC (permalink / raw)
  To: sfr; +Cc: linuxppc-dev, paulus
In-Reply-To: <11442138494042-git-send-email-sfr@canb.auug.org.au>


On Apr 5, 2006, at 12:10 AM, sfr@canb.auug.org.au wrote:

> This patch set moves sufficient include files from include/asm-ppc
> to include/asm-powerpc to allow us to remove the include hack in the
> arch/powerpc/Makefile.
>
>  b/arch/powerpc/Makefile           |   21 ++------------
>  b/include/asm-powerpc/amigappc.h  |    9 ++----
>  b/include/asm-powerpc/bootinfo.h  |    8 ++---
>  b/include/asm-powerpc/highmem.h   |   11 +++----
>  b/include/asm-powerpc/hydra.h     |    8 ++---
>  b/include/asm-powerpc/mpc83xx.h   |    7 ++--
>  b/include/asm-powerpc/mpc85xx.h   |    9 ++----
>  b/include/asm-powerpc/mpc8xx.h    |   10 +++---
>  b/include/asm-powerpc/ocp.h       |    7 ++--
>  b/include/asm-powerpc/ocp_ids.h   |    6 ++--
>  b/include/asm-powerpc/open_pic.h  |   10 +++---
>  b/include/asm-powerpc/pnp.h       |    8 ++---
>  b/include/asm-powerpc/reg_booke.h |   55 ++++++++++++++++++ 
> +-------------------
>  b/include/asm-powerpc/residual.h  |    6 ++--
>  b/include/asm-powerpc/suspend.h   |   17 +++++++++++
>  include/asm-ppc/suspend.h         |   12 --------
>  16 files changed, 95 insertions(+), 109 deletions(-)

How about we do the following to remove the include hack:

don't move the following (determine what needs them to build and  
fixup, I dont believe any of these need to exist at this point in  
arch/powerpc for it to build any supported arch/powerpc platform:

  b/include/asm-powerpc/amigappc.h  |    9 ++----
  b/include/asm-powerpc/bootinfo.h  |    8 ++---
  b/include/asm-powerpc/mpc8xx.h    |   10 +++---
  b/include/asm-powerpc/ocp.h       |    7 ++--
  b/include/asm-powerpc/ocp_ids.h   |    6 ++--
  b/include/asm-powerpc/open_pic.h  |   10 +++---

Duplicate these headers (then I'll go through and clean them up,  
removing arch/ppc'ism):

  b/include/asm-powerpc/mpc83xx.h   |    7 ++--
  b/include/asm-powerpc/mpc85xx.h   |    9 ++----

- kumar

^ permalink raw reply

* [U-Boot-Users] [patch] mkconfig crates bad symlink
From: ito at mlb.co.jp @ 2006-04-05 14:27 UTC (permalink / raw)
  To: u-boot

Hello

mkconfig creates include/asm-*/arch.
but some board this symbolic link is broken and not necessary.
with this patch, mkconfig wil create a sym-link when there is a
directory to link.

Signed-off-by: Hiroshi Ito <ito@mlb.co.jp>

CHANGELOG:

* mkconfig will not create broken symlink.
  Patch by Hiroshi Ito, 5 Apr 2006

--------
Hiroshi Ito
Media Lab. Inc.,
URL http://www.mlb.co.jp ( Sorry, Japanese only. )
TEL +81-3-5294-7255  FAX +81-3-5294-7256
-------------- next part --------------
diff -x .git -uNr u-boot.git.org/mkconfig u-boot.git/mkconfig
--- u-boot.git.org/mkconfig	2006-04-05 06:49:16.000000000 +0900
+++ u-boot.git/mkconfig	2006-04-04 07:18:43.000000000 +0900
@@ -33,7 +33,9 @@
 rm -f asm-$2/arch
 
 if [ -z "$6" -o "$6" = "NULL" ] ; then
-	ln -s arch-$3 asm-$2/arch
+	if [ -d arch-$3 ]; then
+		ln -s arch-$3 asm-$2/arch
+	fi
 else
 	ln -s arch-$6 asm-$2/arch
 fi

^ permalink raw reply

* Re: [PATCH] add support for XCHG instruction accessing APIC
From: Boris Ostrovsky @ 2006-04-05 14:26 UTC (permalink / raw)
  To: Keir Fraser; +Cc: xen-devel
In-Reply-To: <f9aeb15a23cbcea6f79cae17ae7c0b60@cl.cam.ac.uk>

[-- Attachment #1: Type: text/plain, Size: 1147 bytes --]

Keir Fraser wrote:

>>
>> My only argument in favor of using the lock would be for completeness 
>> of the emulation. You are
>> absolutely right in that for Linux there seems to be no need to hold 
>> the lock. My concern is that
>> other OSs  may treat this differently. And if we don't have sources, 
>> it may be somewhat difficult
>> to  figure out that the atomicity (or lack of it) was the cause of a 
>> problem.
>>
>> If, however, there is a strong feeling that we don't need the lock, I 
>> am happy to drop it.
>> I guess you are mostly unhappy about adding a new field to 
>> hvm_domain, not about performance
>> impact?
>
>
> Yes, also my second argument was that there is *no way* for two VCPUs 
> to conflict on a local APIC access, since LAPIC accesses are always to 
> the VCPU's own LAPIC. So there is no potential concurrency that needs 
> to be serialised, regardless of the guest OS.


OK, that's fair. Here is updated patch with lock removed.

I don't think I then understand why Linux is using atomic accesses to
local APICs. It's interesting though that 64-bit code doesn't do it ---
they use vanilla apic_write().

-boris

[-- Attachment #2: xchg.patch --]
[-- Type: text/x-patch, Size: 4256 bytes --]

#
# Add support for XCHG instruction accessing APIC
#

Signed-off-by: Boris Ostrovsky <bostrovsky@virtualiron.com>


diff -r d0d3fef37685 xen/Rules.mk
--- a/xen/Rules.mk	Mon Apr  3 14:34:20 2006 +0100
+++ b/xen/Rules.mk	Wed Apr  5 10:18:35 2006 -0400
@@ -31,6 +31,9 @@ HDRS    += $(wildcard $(BASEDIR)/include
 HDRS    += $(wildcard $(BASEDIR)/include/public/*.h)
 HDRS    += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h)
 HDRS    += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/$(TARGET_SUBARCH)/*.h)
+HDRS    += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/*.h)
+HDRS    += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/svm/*.h)
+HDRS    += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/vmx/*.h)
 # Do not depend on auto-generated header files.
 HDRS    := $(subst $(BASEDIR)/include/asm-$(TARGET_ARCH)/asm-offsets.h,,$(HDRS))
 HDRS    := $(subst $(BASEDIR)/include/xen/banner.h,,$(HDRS))
diff -r d0d3fef37685 xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c	Mon Apr  3 14:34:20 2006 +0100
+++ b/xen/arch/x86/hvm/intercept.c	Wed Apr  5 10:18:35 2006 -0400
@@ -123,6 +123,16 @@ static inline void hvm_mmio_access(struc
         req->u.data = tmp1;
         break;
 
+    case IOREQ_TYPE_XCHG:
+        /* 
+         * Note that we don't need to be atomic here since VCPU is accessing
+         * its own local APIC.
+         */
+        tmp1 = read_handler(v, req->addr, req->size);
+        write_handler(v, req->addr, req->size, (unsigned long) req->u.data);
+        req->u.data = tmp1;
+        break;
+
     default:
         printk("error ioreq type for local APIC %x\n", req->type);
         domain_crash_synchronous();
@@ -143,7 +153,7 @@ int hvm_mmio_intercept(ioreq_t *p)
         if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) ) {
             hvm_mmio_access(v, p,
                             hvm_mmio_handlers[i]->read_handler,
-	                    hvm_mmio_handlers[i]->write_handler);
+                            hvm_mmio_handlers[i]->write_handler);
             return 1;
         }
     }
diff -r d0d3fef37685 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c	Mon Apr  3 14:34:20 2006 +0100
+++ b/xen/arch/x86/hvm/platform.c	Wed Apr  5 10:18:35 2006 -0400
@@ -439,6 +439,14 @@ static int hvm_decode(int realmode, unsi
         GET_OP_SIZE_FOR_BYTE(size_reg);
         return mem_reg(size_reg, opcode, instr, rex);
 
+    case 0x87:  /* xchg {r/m16|r/m32}, {m/r16|m/r32} */
+        instr->instr = INSTR_XCHG;
+        GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+        if (((*(opcode+1)) & 0xc7) == 5)
+            return reg_mem(instr->op_size, opcode, instr, rex);
+        else
+            return mem_reg(instr->op_size, opcode, instr, rex);
+
     case 0x88: /* mov r8, m8 */
         instr->instr = INSTR_MOV;
         instr->op_size = BYTE;
@@ -936,6 +944,17 @@ void handle_mmio(unsigned long va, unsig
             break;
         }
 
+    case INSTR_XCHG:
+        mmio_opp->flags = mmio_inst.flags;
+        mmio_opp->instr = mmio_inst.instr;
+        mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */
+        mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */
+
+        /* send the request and wait for the value */
+        send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
+                      mmio_inst.op_size, 0, IOREQ_WRITE, 0);
+        break;
+
     default:
         printf("Unhandled MMIO instruction\n");
         domain_crash_synchronous();
diff -r d0d3fef37685 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h	Mon Apr  3 14:34:20 2006 +0100
+++ b/xen/include/asm-x86/hvm/io.h	Wed Apr  5 10:18:35 2006 -0400
@@ -66,6 +66,7 @@
 #define INSTR_STOS  10
 #define INSTR_TEST  11
 #define INSTR_BT    12
+#define INSTR_XCHG  13
 
 struct instruction {
     __s8    instr;        /* instruction type */
diff -r d0d3fef37685 xen/include/public/hvm/ioreq.h
--- a/xen/include/public/hvm/ioreq.h	Mon Apr  3 14:34:20 2006 +0100
+++ b/xen/include/public/hvm/ioreq.h	Wed Apr  5 10:18:35 2006 -0400
@@ -34,6 +34,7 @@
 #define IOREQ_TYPE_AND          2
 #define IOREQ_TYPE_OR           3
 #define IOREQ_TYPE_XOR          4
+#define IOREQ_TYPE_XCHG         5
 
 /*
  * VMExit dispatcher should cooperate with instruction decoder to

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply

* [PATCH] Fix compile with expat, but an old curl version
From: Johannes Schindelin @ 2006-04-05 14:22 UTC (permalink / raw)
  To: git, junkio


With an old curl version, git-http-push is not compiled. But git-http-fetch
still needs to be linked with expat if NO_EXPAT is not defined.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

---

 Makefile |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

57918780ecdff0c767a22b7589ff1025de6cb40f
diff --git a/Makefile b/Makefile
index 3596445..557d322 100644
--- a/Makefile
+++ b/Makefile
@@ -333,9 +333,11 @@ ifndef NO_CURL
 	curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
 	ifeq "$(curl_check)" "070908"
 		ifndef NO_EXPAT
-			EXPAT_LIBEXPAT = -lexpat
 			PROGRAMS += git-http-push$X
 		endif
+	endif
+	ifndef NO_EXPAT
+		EXPAT_LIBEXPAT = -lexpat
 	endif
 endif
 
-- 
1.3.0.rc2.g4a16-dirty

^ permalink raw reply related

* Re: Does dom0 see all physical processors? (RE:[Xen-ia64-devel] SAL INFO virtualization)
From: Keir Fraser @ 2006-04-05 14:20 UTC (permalink / raw)
  To: Magenheimer, Dan (HP Labs Fort Collins)
  Cc: Jimi Xenidis, Ian Pratt, Tian, Kevin, xen-devel, Tristan Gingold,
	okrieg, xen-ia64-devel
In-Reply-To: <516F50407E01324991DD6D07B0531AD51BCF50@cacexc12.americas.cpqcorp.net>


On 5 Apr 2006, at 15:07, Magenheimer, Dan (HP Labs Fort Collins) wrote:

> I believe ppc has "paravirtualized spinlocks" in their Linux
> kernel, though even this won't necessarily help with a poorly
> written SMP application.
>
> No data, admittedly, but perhaps our good buddies at
> Watson could comment?

IBM did some investigation into this a while back. The conclusion then 
was that, even in a microbenchmark somewhat contrived to try and 
indicate 'worst case' spinlock behaviour, the benefit of smarter 
spinlocks was negligible. Maybe the benchmark was bad, maybe there are 
other pathological worst cases out there that the benchmark did not 
represent, or maybe the smart spinlocks should have been smarter. 
Whatever: the numbers we have so far do not indicate that there's a 
problem to be solved, and these potential multi-processor optimisations 
have to be empirically driven because intuition is so frequently off 
the mark.

  -- Keir

^ permalink raw reply

* Re: VMX status report 9532:5baf152d63ef
From: Mark Williamson @ 2006-04-05 14:19 UTC (permalink / raw)
  To: Dave Feustel; +Cc: xen-devel
In-Reply-To: <200604051027.22382.dfeustel@mindspring.com>

> > Yes, IBM publish them for Linux and Windows XP guests (with other Windows
> > OSes to follow once the tests are automated.  I forget who's responsible,
> > though, sorry.
>
> Are  IBM's test results published to this list? I don't remember having
> seen them.

Oops, actually I think the results I was thinking of were for x460s, which are 
Xeon-based.

Sorry, got my wires crossed.  In that case, I don't know of any published 
results regarding the Pacifica testing. :-(

Cheers,
Mark

-- 
Dave: Just a question. What use is a unicyle with no seat?  And no pedals!
Mark: To answer a question with a question: What use is a skateboard?
Dave: Skateboards have wheels.
Mark: My wheel has a wheel!

^ permalink raw reply

* Re: Q on audit, audit-syscall
From: Kyle Moffett @ 2006-04-05 14:17 UTC (permalink / raw)
  To: Herbert Rosmanith; +Cc: Robin Holt, linux-kernel
In-Reply-To: <200604051350.k35DoIXF009872@wildsau.enemy.org>

On Apr 5, 2006, at 09:50:17, Herbert Rosmanith wrote:
>> On Apr 5, 2006, at 08:06:30, Herbert Rosmanith wrote:
>>> as I said, "ptrace" is not an option.
>>
>> Why not, exactly?  (No, we don't know why).
>
> according to the man-page:
>
> RETURN VALUES
>      EPERM   The specified process [...] is already being traced.
>
> this makes it unusable for me.

Please stop being unclear and describe _exactly_ what you want to do;  
otherwise it's impossible to help you.  You want to trace and  
intercept syscalls, no?  It implicitly doesn't make any sense to try  
to trace and intercept syscalls from one process in more than one other.

>> ptrace is _the_ Linux  mechanism to trace and intercept syscalls.   
>> There is no other way.
> "there is no other way": [1,2,3,4]
>
> [1] http://www.uniforum.chi.il.us/slides/HardeningLinux/LAuS- 
> Design.pdf
> [2] http://www.usenix.org/publications/library/proceedings/als01/ 
> full_papers/edwards/edwards.pdf
> [3] http://www.citi.umich.edu/u/provos/papers/systrace.pdf
> [4] http://www.nsa.gov/selinux/papers/freenix01.pdf

It looks like you solved your own problem, then!  Feel free to use  
any one of those.  The only commonly-available mainline mechanism to  
_trace_ and _intercept_ syscalls is ptrace.  If you happen to be  
looking for how to implement extra process security checks, might I  
suggest looking at Linux Security Modules?  On the other hand, I  
think LSMs may never even see some requests if they fail access- 
restrictions before calling into the LSM.  I believe there's  
documentation on them in the linux/Documentation dir of your copies  
of the linux sources.

Cheers,
Kyle Moffett


^ permalink raw reply

* Re: [PATCH 14/15] powerpc: move asm/mpc85xx.h
From: Kumar Gala @ 2006-04-05 14:17 UTC (permalink / raw)
  To: sfr; +Cc: linuxppc-dev, paulus
In-Reply-To: <11442138813940-git-send-email-sfr@canb.auug.org.au>

Nack.  I was avoiding moving this header since it introduces a number  
things that should only exist in arch/ppc.

- k

On Apr 5, 2006, at 12:10 AM, sfr@canb.auug.org.au wrote:

> From: Stephen Rothwell <sfr@canb.auug.org.au>
>
> Since the ARCH=powerpc build depends on this file, move it to
> include/asm-powerpc.
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
>
> ---
>
>  include/asm-powerpc/mpc85xx.h |  195 ++++++++++++++++++++++++++++++ 
> ++++++++++
>  include/asm-ppc/mpc85xx.h     |  198  
> -----------------------------------------
>  2 files changed, 195 insertions(+), 198 deletions(-)
>  create mode 100644 include/asm-powerpc/mpc85xx.h
>  delete mode 100644 include/asm-ppc/mpc85xx.h
>
> 4fc7b6e78d24e11e704ef7b5a1ceb659d3a03cc2
> diff --git a/include/asm-powerpc/mpc85xx.h b/include/asm-powerpc/ 
> mpc85xx.h
> new file mode 100644
> index 0000000..4113165
> --- /dev/null
> +++ b/include/asm-powerpc/mpc85xx.h
> @@ -0,0 +1,195 @@
> +#ifndef _ASM_POWERPC_MPC85XX_H
> +#define _ASM_POWERPC_MPC85XX_H
> +/*
> + * MPC85xx definitions
> + *
> + * Maintainer: Kumar Gala <galak@kernel.crashing.org>
> + *
> + * Copyright 2004 Freescale Semiconductor, Inc
> + *
> + * 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;  either version 2 of the  License, or  
> (at your
> + * option) any later version.
> + */
> +
> +#ifdef __KERNEL__
> +
> +#include <asm/mmu.h>
> +
> +#ifdef CONFIG_85xx
> +
> +#ifdef CONFIG_MPC8540_ADS
> +#include <platforms/85xx/mpc8540_ads.h>
> +#endif
> +#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
> +#include <platforms/85xx/mpc8555_cds.h>
> +#endif
> +#ifdef CONFIG_MPC8560_ADS
> +#include <platforms/85xx/mpc8560_ads.h>
> +#endif
> +#ifdef CONFIG_SBC8560
> +#include <platforms/85xx/sbc8560.h>
> +#endif
> +#ifdef CONFIG_STX_GP3
> +#include <platforms/85xx/stx_gp3.h>
> +#endif
> +#if defined(CONFIG_TQM8540) || defined(CONFIG_TQM8541) || \
> +	defined(CONFIG_TQM8555) || defined(CONFIG_TQM8560)
> +#include <platforms/85xx/tqm85xx.h>
> +#endif
> +
> +#define _IO_BASE        isa_io_base
> +#define _ISA_MEM_BASE   isa_mem_base
> +#ifdef CONFIG_PCI
> +#define PCI_DRAM_OFFSET pci_dram_offset
> +#else
> +#define PCI_DRAM_OFFSET 0
> +#endif
> +
> +/*
> + * The "residual" board information structure the boot loader passes
> + * into the kernel.
> + */
> +extern unsigned char __res[];
> +
> +/* Offset from CCSRBAR */
> +#define MPC85xx_CPM_OFFSET	(0x80000)
> +#define MPC85xx_CPM_SIZE	(0x40000)
> +#define MPC85xx_DMA_OFFSET	(0x21000)
> +#define MPC85xx_DMA_SIZE	(0x01000)
> +#define MPC85xx_DMA0_OFFSET	(0x21100)
> +#define MPC85xx_DMA0_SIZE	(0x00080)
> +#define MPC85xx_DMA1_OFFSET	(0x21180)
> +#define MPC85xx_DMA1_SIZE	(0x00080)
> +#define MPC85xx_DMA2_OFFSET	(0x21200)
> +#define MPC85xx_DMA2_SIZE	(0x00080)
> +#define MPC85xx_DMA3_OFFSET	(0x21280)
> +#define MPC85xx_DMA3_SIZE	(0x00080)
> +#define MPC85xx_ENET1_OFFSET	(0x24000)
> +#define MPC85xx_ENET1_SIZE	(0x01000)
> +#define MPC85xx_MIIM_OFFSET	(0x24520)
> +#define MPC85xx_MIIM_SIZE	(0x00018)
> +#define MPC85xx_ENET2_OFFSET	(0x25000)
> +#define MPC85xx_ENET2_SIZE	(0x01000)
> +#define MPC85xx_ENET3_OFFSET	(0x26000)
> +#define MPC85xx_ENET3_SIZE	(0x01000)
> +#define MPC85xx_GUTS_OFFSET	(0xe0000)
> +#define MPC85xx_GUTS_SIZE	(0x01000)
> +#define MPC85xx_IIC1_OFFSET	(0x03000)
> +#define MPC85xx_IIC1_SIZE	(0x00100)
> +#define MPC85xx_OPENPIC_OFFSET	(0x40000)
> +#define MPC85xx_OPENPIC_SIZE	(0x40000)
> +#define MPC85xx_PCI1_OFFSET	(0x08000)
> +#define MPC85xx_PCI1_SIZE	(0x01000)
> +#define MPC85xx_PCI2_OFFSET	(0x09000)
> +#define MPC85xx_PCI2_SIZE	(0x01000)
> +#define MPC85xx_PERFMON_OFFSET	(0xe1000)
> +#define MPC85xx_PERFMON_SIZE	(0x01000)
> +#define MPC85xx_SEC2_OFFSET	(0x30000)
> +#define MPC85xx_SEC2_SIZE	(0x10000)
> +#define MPC85xx_UART0_OFFSET	(0x04500)
> +#define MPC85xx_UART0_SIZE	(0x00100)
> +#define MPC85xx_UART1_OFFSET	(0x04600)
> +#define MPC85xx_UART1_SIZE	(0x00100)
> +
> +#define MPC85xx_CCSRBAR_SIZE	(1024*1024)
> +
> +/* Let modules/drivers get at CCSRBAR */
> +extern phys_addr_t get_ccsrbar(void);
> +
> +#ifdef MODULE
> +#define CCSRBAR get_ccsrbar()
> +#else
> +#define CCSRBAR BOARD_CCSRBAR
> +#endif
> +
> +enum ppc_sys_devices {
> +	MPC85xx_TSEC1,
> +	MPC85xx_TSEC2,
> +	MPC85xx_FEC,
> +	MPC85xx_IIC1,
> +	MPC85xx_DMA0,
> +	MPC85xx_DMA1,
> +	MPC85xx_DMA2,
> +	MPC85xx_DMA3,
> +	MPC85xx_DUART,
> +	MPC85xx_PERFMON,
> +	MPC85xx_SEC2,
> +	MPC85xx_CPM_SPI,
> +	MPC85xx_CPM_I2C,
> +	MPC85xx_CPM_USB,
> +	MPC85xx_CPM_SCC1,
> +	MPC85xx_CPM_SCC2,
> +	MPC85xx_CPM_SCC3,
> +	MPC85xx_CPM_SCC4,
> +	MPC85xx_CPM_FCC1,
> +	MPC85xx_CPM_FCC2,
> +	MPC85xx_CPM_FCC3,
> +	MPC85xx_CPM_MCC1,
> +	MPC85xx_CPM_MCC2,
> +	MPC85xx_CPM_SMC1,
> +	MPC85xx_CPM_SMC2,
> +	MPC85xx_eTSEC1,
> +	MPC85xx_eTSEC2,
> +	MPC85xx_eTSEC3,
> +	MPC85xx_eTSEC4,
> +	MPC85xx_IIC2,
> +	MPC85xx_MDIO,
> +	NUM_PPC_SYS_DEVS,
> +};
> +
> +/* Internal interrupts are all Level Sensitive, and Positive  
> Polarity */
> +#define MPC85XX_INTERNAL_IRQ_SENSES \
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46 */	\
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE)	/* Internal 47 */
> +
> +#endif /* CONFIG_85xx */
> +#endif /* __KERNEL__ */
> +#endif /* _ASM_POWERPC_MPC85XX_H */
> diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
> deleted file mode 100644
> index f47002a..0000000
> --- a/include/asm-ppc/mpc85xx.h
> +++ /dev/null
> @@ -1,198 +0,0 @@
> -/*
> - * include/asm-ppc/mpc85xx.h
> - *
> - * MPC85xx definitions
> - *
> - * Maintainer: Kumar Gala <galak@kernel.crashing.org>
> - *
> - * Copyright 2004 Freescale Semiconductor, Inc
> - *
> - * 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;  either version 2 of the  License, or  
> (at your
> - * option) any later version.
> - */
> -
> -#ifdef __KERNEL__
> -#ifndef __ASM_MPC85xx_H__
> -#define __ASM_MPC85xx_H__
> -
> -#include <linux/config.h>
> -#include <asm/mmu.h>
> -
> -#ifdef CONFIG_85xx
> -
> -#ifdef CONFIG_MPC8540_ADS
> -#include <platforms/85xx/mpc8540_ads.h>
> -#endif
> -#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
> -#include <platforms/85xx/mpc8555_cds.h>
> -#endif
> -#ifdef CONFIG_MPC8560_ADS
> -#include <platforms/85xx/mpc8560_ads.h>
> -#endif
> -#ifdef CONFIG_SBC8560
> -#include <platforms/85xx/sbc8560.h>
> -#endif
> -#ifdef CONFIG_STX_GP3
> -#include <platforms/85xx/stx_gp3.h>
> -#endif
> -#if defined(CONFIG_TQM8540) || defined(CONFIG_TQM8541) || \
> -	defined(CONFIG_TQM8555) || defined(CONFIG_TQM8560)
> -#include <platforms/85xx/tqm85xx.h>
> -#endif
> -
> -#define _IO_BASE        isa_io_base
> -#define _ISA_MEM_BASE   isa_mem_base
> -#ifdef CONFIG_PCI
> -#define PCI_DRAM_OFFSET pci_dram_offset
> -#else
> -#define PCI_DRAM_OFFSET 0
> -#endif
> -
> -/*
> - * The "residual" board information structure the boot loader passes
> - * into the kernel.
> - */
> -extern unsigned char __res[];
> -
> -/* Offset from CCSRBAR */
> -#define MPC85xx_CPM_OFFSET	(0x80000)
> -#define MPC85xx_CPM_SIZE	(0x40000)
> -#define MPC85xx_DMA_OFFSET	(0x21000)
> -#define MPC85xx_DMA_SIZE	(0x01000)
> -#define MPC85xx_DMA0_OFFSET	(0x21100)
> -#define MPC85xx_DMA0_SIZE	(0x00080)
> -#define MPC85xx_DMA1_OFFSET	(0x21180)
> -#define MPC85xx_DMA1_SIZE	(0x00080)
> -#define MPC85xx_DMA2_OFFSET	(0x21200)
> -#define MPC85xx_DMA2_SIZE	(0x00080)
> -#define MPC85xx_DMA3_OFFSET	(0x21280)
> -#define MPC85xx_DMA3_SIZE	(0x00080)
> -#define MPC85xx_ENET1_OFFSET	(0x24000)
> -#define MPC85xx_ENET1_SIZE	(0x01000)
> -#define MPC85xx_MIIM_OFFSET	(0x24520)
> -#define MPC85xx_MIIM_SIZE	(0x00018)
> -#define MPC85xx_ENET2_OFFSET	(0x25000)
> -#define MPC85xx_ENET2_SIZE	(0x01000)
> -#define MPC85xx_ENET3_OFFSET	(0x26000)
> -#define MPC85xx_ENET3_SIZE	(0x01000)
> -#define MPC85xx_GUTS_OFFSET	(0xe0000)
> -#define MPC85xx_GUTS_SIZE	(0x01000)
> -#define MPC85xx_IIC1_OFFSET	(0x03000)
> -#define MPC85xx_IIC1_SIZE	(0x00100)
> -#define MPC85xx_OPENPIC_OFFSET	(0x40000)
> -#define MPC85xx_OPENPIC_SIZE	(0x40000)
> -#define MPC85xx_PCI1_OFFSET	(0x08000)
> -#define MPC85xx_PCI1_SIZE	(0x01000)
> -#define MPC85xx_PCI2_OFFSET	(0x09000)
> -#define MPC85xx_PCI2_SIZE	(0x01000)
> -#define MPC85xx_PERFMON_OFFSET	(0xe1000)
> -#define MPC85xx_PERFMON_SIZE	(0x01000)
> -#define MPC85xx_SEC2_OFFSET	(0x30000)
> -#define MPC85xx_SEC2_SIZE	(0x10000)
> -#define MPC85xx_UART0_OFFSET	(0x04500)
> -#define MPC85xx_UART0_SIZE	(0x00100)
> -#define MPC85xx_UART1_OFFSET	(0x04600)
> -#define MPC85xx_UART1_SIZE	(0x00100)
> -
> -#define MPC85xx_CCSRBAR_SIZE	(1024*1024)
> -
> -/* Let modules/drivers get at CCSRBAR */
> -extern phys_addr_t get_ccsrbar(void);
> -
> -#ifdef MODULE
> -#define CCSRBAR get_ccsrbar()
> -#else
> -#define CCSRBAR BOARD_CCSRBAR
> -#endif
> -
> -enum ppc_sys_devices {
> -	MPC85xx_TSEC1,
> -	MPC85xx_TSEC2,
> -	MPC85xx_FEC,
> -	MPC85xx_IIC1,
> -	MPC85xx_DMA0,
> -	MPC85xx_DMA1,
> -	MPC85xx_DMA2,
> -	MPC85xx_DMA3,
> -	MPC85xx_DUART,
> -	MPC85xx_PERFMON,
> -	MPC85xx_SEC2,
> -	MPC85xx_CPM_SPI,
> -	MPC85xx_CPM_I2C,
> -	MPC85xx_CPM_USB,
> -	MPC85xx_CPM_SCC1,
> -	MPC85xx_CPM_SCC2,
> -	MPC85xx_CPM_SCC3,
> -	MPC85xx_CPM_SCC4,
> -	MPC85xx_CPM_FCC1,
> -	MPC85xx_CPM_FCC2,
> -	MPC85xx_CPM_FCC3,
> -	MPC85xx_CPM_MCC1,
> -	MPC85xx_CPM_MCC2,
> -	MPC85xx_CPM_SMC1,
> -	MPC85xx_CPM_SMC2,
> -	MPC85xx_eTSEC1,
> -	MPC85xx_eTSEC2,
> -	MPC85xx_eTSEC3,
> -	MPC85xx_eTSEC4,
> -	MPC85xx_IIC2,
> -	MPC85xx_MDIO,
> -	NUM_PPC_SYS_DEVS,
> -};
> -
> -/* Internal interrupts are all Level Sensitive, and Positive  
> Polarity */
> -#define MPC85XX_INTERNAL_IRQ_SENSES \
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46 */	\
> -	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE)	/* Internal 47 */
> -
> -#endif /* CONFIG_85xx */
> -#endif /* __ASM_MPC85xx_H__ */
> -#endif /* __KERNEL__ */
> -- 
> 1.2.4
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 10/15] powerpc: move asm/mpc83xx.h
From: Kumar Gala @ 2006-04-05 14:17 UTC (permalink / raw)
  To: sfr; +Cc: linuxppc-dev, paulus
In-Reply-To: <11442138673826-git-send-email-sfr@canb.auug.org.au>

Nack.  I was avoiding moving this header since it introduces a number  
things that should only exist in arch/ppc.

- k

On Apr 5, 2006, at 12:10 AM, sfr@canb.auug.org.au wrote:

> From: Stephen Rothwell <sfr@canb.auug.org.au>
>
> Since the ARCH=powerpc build depends on this file, move it to
> include/asm-powerpc.
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
>
> ---
>
>  include/asm-powerpc/mpc83xx.h |  115 ++++++++++++++++++++++++++++++ 
> +++++++++++
>  include/asm-ppc/mpc83xx.h     |  116  
> -----------------------------------------
>  2 files changed, 115 insertions(+), 116 deletions(-)
>  create mode 100644 include/asm-powerpc/mpc83xx.h
>  delete mode 100644 include/asm-ppc/mpc83xx.h
>
> ce28e1e8654ad07cc23573a31f8cea992d41f9cc
> diff --git a/include/asm-powerpc/mpc83xx.h b/include/asm-powerpc/ 
> mpc83xx.h
> new file mode 100644
> index 0000000..da4b0fa
> --- /dev/null
> +++ b/include/asm-powerpc/mpc83xx.h
> @@ -0,0 +1,115 @@
> +#ifndef _ASM_POWERPC_MPC83XX_H
> +#define _ASM_POWERPC_MPC83XX_H
> +/*
> + * include/asm-ppc/mpc83xx.h
> + *
> + * MPC83xx definitions
> + *
> + * Maintainer: Kumar Gala <galak@kernel.crashing.org>
> + *
> + * Copyright 2005 Freescale Semiconductor, Inc
> + *
> + * 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;  either version 2 of the  License, or  
> (at your
> + * option) any later version.
> + */
> +
> +#ifdef __KERNEL__
> +
> +#include <asm/mmu.h>
> +
> +#ifdef CONFIG_83xx
> +
> +#ifdef CONFIG_MPC834x_SYS
> +#include <platforms/83xx/mpc834x_sys.h>
> +#endif
> +
> +#define _IO_BASE        isa_io_base
> +#define _ISA_MEM_BASE   isa_mem_base
> +#ifdef CONFIG_PCI
> +#define PCI_DRAM_OFFSET pci_dram_offset
> +#else
> +#define PCI_DRAM_OFFSET 0
> +#endif
> +
> +/*
> + * The "residual" board information structure the boot loader passes
> + * into the kernel.
> + */
> +extern unsigned char __res[];
> +
> +/* Internal IRQs on MPC83xx OpenPIC */
> +/* Not all of these exist on all MPC83xx implementations */
> +
> +#ifndef MPC83xx_IPIC_IRQ_OFFSET
> +#define MPC83xx_IPIC_IRQ_OFFSET	0
> +#endif
> +
> +#define NR_IPIC_INTS 128
> +
> +#define MPC83xx_IRQ_UART1	( 9 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_UART2	(10 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_SEC2	(11 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_IIC1	(14 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_IIC2	(15 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_SPI		(16 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT1	(17 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT2	(18 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT3	(19 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT4	(20 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT5	(21 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT6	(22 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT7	(23 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_TSEC1_TX	(32 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_TSEC1_RX	(33 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_TSEC1_ERROR	(34 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_TSEC2_TX	(35 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_TSEC2_RX	(36 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_TSEC2_ERROR	(37 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_USB2_DR	(38 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_USB2_MPH	(39 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_EXT0	(48 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_RTC_SEC	(64 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_PIT		(65 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_PCI1	(66 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_PCI2	(67 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_RTC_ALR	(68 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_MU		(69 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_SBA		(70 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_DMA		(71 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM4	(72 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM8	(73 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GPIO1	(74 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GPIO2	(75 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_DDR		(76 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_LBC		(77 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM2	(78 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM6	(79 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_PMC		(80 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM3	(84 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM7	(85 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM1	(90 + MPC83xx_IPIC_IRQ_OFFSET)
> +#define MPC83xx_IRQ_GTM5	(91 + MPC83xx_IPIC_IRQ_OFFSET)
> +
> +#define MPC83xx_CCSRBAR_SIZE	(1024*1024)
> +
> +/* Let modules/drivers get at immrbar (physical) */
> +extern phys_addr_t immrbar;
> +
> +enum ppc_sys_devices {
> +	MPC83xx_TSEC1,
> +	MPC83xx_TSEC2,
> +	MPC83xx_IIC1,
> +	MPC83xx_IIC2,
> +	MPC83xx_DUART,
> +	MPC83xx_SEC2,
> +	MPC83xx_USB2_DR,
> +	MPC83xx_USB2_MPH,
> +	MPC83xx_MDIO,
> +	NUM_PPC_SYS_DEVS,
> +};
> +
> +#endif /* CONFIG_83xx */
> +#endif /* __KERNEL__ */
> +#endif /* _ASM_POWERPC_MPC83XX_H */
> diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
> deleted file mode 100644
> index 3c23fc4..0000000
> --- a/include/asm-ppc/mpc83xx.h
> +++ /dev/null
> @@ -1,116 +0,0 @@
> -/*
> - * include/asm-ppc/mpc83xx.h
> - *
> - * MPC83xx definitions
> - *
> - * Maintainer: Kumar Gala <galak@kernel.crashing.org>
> - *
> - * Copyright 2005 Freescale Semiconductor, Inc
> - *
> - * 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;  either version 2 of the  License, or  
> (at your
> - * option) any later version.
> - */
> -
> -#ifdef __KERNEL__
> -#ifndef __ASM_MPC83xx_H__
> -#define __ASM_MPC83xx_H__
> -
> -#include <linux/config.h>
> -#include <asm/mmu.h>
> -
> -#ifdef CONFIG_83xx
> -
> -#ifdef CONFIG_MPC834x_SYS
> -#include <platforms/83xx/mpc834x_sys.h>
> -#endif
> -
> -#define _IO_BASE        isa_io_base
> -#define _ISA_MEM_BASE   isa_mem_base
> -#ifdef CONFIG_PCI
> -#define PCI_DRAM_OFFSET pci_dram_offset
> -#else
> -#define PCI_DRAM_OFFSET 0
> -#endif
> -
> -/*
> - * The "residual" board information structure the boot loader passes
> - * into the kernel.
> - */
> -extern unsigned char __res[];
> -
> -/* Internal IRQs on MPC83xx OpenPIC */
> -/* Not all of these exist on all MPC83xx implementations */
> -
> -#ifndef MPC83xx_IPIC_IRQ_OFFSET
> -#define MPC83xx_IPIC_IRQ_OFFSET	0
> -#endif
> -
> -#define NR_IPIC_INTS 128
> -
> -#define MPC83xx_IRQ_UART1	( 9 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_UART2	(10 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_SEC2	(11 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_IIC1	(14 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_IIC2	(15 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_SPI		(16 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT1	(17 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT2	(18 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT3	(19 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT4	(20 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT5	(21 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT6	(22 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT7	(23 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_TSEC1_TX	(32 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_TSEC1_RX	(33 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_TSEC1_ERROR	(34 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_TSEC2_TX	(35 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_TSEC2_RX	(36 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_TSEC2_ERROR	(37 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_USB2_DR	(38 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_USB2_MPH	(39 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_EXT0	(48 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_RTC_SEC	(64 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_PIT		(65 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_PCI1	(66 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_PCI2	(67 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_RTC_ALR	(68 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_MU		(69 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_SBA		(70 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_DMA		(71 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM4	(72 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM8	(73 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GPIO1	(74 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GPIO2	(75 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_DDR		(76 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_LBC		(77 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM2	(78 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM6	(79 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_PMC		(80 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM3	(84 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM7	(85 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM1	(90 + MPC83xx_IPIC_IRQ_OFFSET)
> -#define MPC83xx_IRQ_GTM5	(91 + MPC83xx_IPIC_IRQ_OFFSET)
> -
> -#define MPC83xx_CCSRBAR_SIZE	(1024*1024)
> -
> -/* Let modules/drivers get at immrbar (physical) */
> -extern phys_addr_t immrbar;
> -
> -enum ppc_sys_devices {
> -	MPC83xx_TSEC1,
> -	MPC83xx_TSEC2,
> -	MPC83xx_IIC1,
> -	MPC83xx_IIC2,
> -	MPC83xx_DUART,
> -	MPC83xx_SEC2,
> -	MPC83xx_USB2_DR,
> -	MPC83xx_USB2_MPH,
> -	MPC83xx_MDIO,
> -	NUM_PPC_SYS_DEVS,
> -};
> -
> -#endif /* CONFIG_83xx */
> -#endif /* __ASM_MPC83xx_H__ */
> -#endif /* __KERNEL__ */
> -- 
> 1.2.4
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: Cygwin can't handle huge packfiles?
From: Johannes Schindelin @ 2006-04-05 14:14 UTC (permalink / raw)
  To: Kees-Jan Dijkzeul; +Cc: git
In-Reply-To: <fa0b6e200604050624h13ebd8deg241ae98cef1f5a74@mail.gmail.com>

Hi,

On Wed, 5 Apr 2006, Kees-Jan Dijkzeul wrote:

> On 4/3/06, Linus Torvalds <torvalds@osdl.org> wrote:
> [...]
> > That's not hugely fundamental, but I didn't expect people to hit it this
> > quickly. What kind of project has a 1.5GB pack-file _already_? I hope it's
> > fifteen years of history (so that we'll have another fifteen years before
> > we'll have to worry about 4GB pack-files ;)
> 
> I'm trying to get Git to manage my companies source tree. We're
> writing software for digital TV sets. Anyway, the archive is about 5Gb
> in size and contains binaries, zip files, excel sheets meeting minutes
> and whatnot. So it doesn't compress very well. The 1.5Gb pack file
> hardly contains any history at all (five commits or so). On the flip
> side, for now I'll be the only one adding to the archive, so at least
> it will not grow that fast ;-)
> 
> Anyway, to reconstitute the tree, I need very nearly the entire pack,
> so limiting the pack size won't do much good, as git will still try to
> allocate a total of 1.5Gb memory (which, unfortunately, isn't there
> :-)
> 
> Inspired by a patch of Alex Riesen (thanks, Alex), I tried to use the
> regular mmap for mapping pack files, only to discover that I compile
> without defining "NO_MMAP", so I've been using the stock mmap all
> along. So now I'm thinking that the cygwin mmap also does a
> malloc-and-read, just like git does with NO_MMAP. So I'll continue to
> investigate in that direction.

I think cygwin's mmap() is based on the Win32 API equivalent, which could 
mean that it *is* memory mapped, but in a special area (which is smaller 
than 1.5 gigabyte). In this case, it would make sense to limit the pack 
size, thereby having several packs, and mmap() them as they are needed.

Hth,
Dscho

^ permalink raw reply

* RE: [2.6.16 PATCH] Filessytem Events Reporter V2
From: Michael Guo @ 2006-04-05 14:13 UTC (permalink / raw)
  To: Yi Yang, LKML; +Cc: Andrew Morton, Evgeniy Polyakov, Matt Helsley

Hi,
  Now, kernel is growing bigger and bigger continuously and performance is becoming slower. So, if possible, please consider to add a 
common and simple interface which is scalable and flexible to satisfy real requirement of users instead of telling users use this or that like Microsoft. In a word, simple makes application programmers happy!


Guo
 

-----Original Message-----
From: linux-kernel-owner@vger.kernel.org [mailto:linux-kernel-owner@vger.kernel.org]On Behalf Of Yi Yang
Sent: Wednesday, April 05, 2006 9:21 AM
To: LKML
Cc: Andrew Morton; Evgeniy Polyakov; Matt Helsley
Subject: [2.6.16 PATCH] Filessytem Events Reporter V2


Compared with Filesystem Events Reporter v1, the following changes are done:
  - Use workqueue/keventd instead of kfseventd. 
  - fsevent_mask can be set by sysctl and proc
    interface.
  - Add missed spinlock
  - Ensure fsevent sequence number is uniqe

This patch implements a filsystem events report facitily, Filesystem Events
Reporter, the user can monitor filesystem activities via it, currently, it
 can monitor access, attribute change, open, create, modify, delete,
 move and close of any file or directory as well as mount/umount.

Every filesystem event will include tgid, uid and gid of the process
 which triggered this event, process name, file or directory name 
operated by it.

Filesystem Events Reporter is never a duplicate of inotify, inotify
 just concerns change on file or directory, Beagle uses it to watch
 file changes in order to regenerate index for it, inotify can't tell
 us who did that change and what is its process name, but filesystem
 events reporter can do these, moreover inotify's overhead is greater
 than filesystem events reporter, inotify needs compare inode with 
watched file or directories list to decide whether it should generate an
 inotify_event, some locks also increase overhead, filesystem event 
connector hasn't these overhead, it just generates a fsevent and send.

To be important, filesystem event reporter doesn't add any new system 
call, the user space application can make use of it by netlink socket, 
but inotify added several system calls, many events mechanism in kernel
 have used netlink as communication way with user space, for example, 
KOBJECT_UEVENT, PROC_EVENTS, to use netlink will make it more possible
 to unify events interface to netlink, the user space application can use 
it very easy.

Every application using fsevent can set its own fsevent filter list 
without effect in other applications using fsevent, there are three
filter lists, they are pid filter list, uid filetr list and gid 
filter list, respectively, moreover, there is a fsevent mask used to
control those fsevents which fail to match  three filter lists, an 
application using fsevent can listen those fsevents it want to 
monitor and ignore those fsevents it doesn't interest in by set 
series of filters, there is a fsevent mask used to take effects on
all the applications using fsevent, it can be set by sysctl and proc
interface.

 fs/Kconfig               |   10 
 fs/Makefile              |    1 
 fs/fsevent.c             |  598 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/namespace.c           |   12 
 include/linux/fsevent.h  |  131 ++++++++++
 include/linux/fsnotify.h |   37 ++
 include/linux/netlink.h  |    1 
 7 files changed, 790 insertions(+)

Signed-off-by: Yi Yang <yang.y.yi@gmail.com>

--- a/include/linux/netlink.h.orig	2006-03-31 22:58:50.000000000 +0800
+++ b/include/linux/netlink.h	2006-04-05 20:34:23.000000000 +0800
@@ -21,6 +21,7 @@
 #define NETLINK_DNRTMSG		14	/* DECnet routing messages */
 #define NETLINK_KOBJECT_UEVENT	15	/* Kernel messages to userspace */
 #define NETLINK_GENERIC		16
+#define NETLINK_FSEVENT		17	/* File system events to userspace */
 
 #define MAX_LINKS 32		
 
--- a/include/linux/fsnotify.h.orig	2006-01-03 11:21:10.000000000 +0800
+++ b/include/linux/fsnotify.h	2006-04-03 22:12:52.000000000 +0800
@@ -15,6 +15,7 @@
 
 #include <linux/dnotify.h>
 #include <linux/inotify.h>
+#include <linux/fsevent.h>
 
 /*
  * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
@@ -45,6 +46,8 @@ static inline void fsnotify_move(struct 
 	if (source) {
 		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
 	}
+	raise_fsevent_move(old_dir, old_name, new_dir, new_name,
+			   FSEVENT_MOVE | (isdir?FSEVENT_ISDIR:0));
 }
 
 /*
@@ -56,6 +59,8 @@ static inline void fsnotify_nameremove(s
 		isdir = IN_ISDIR;
 	dnotify_parent(dentry, DN_DELETE);
 	inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name);
+	raise_fsevent(dentry,
+		      FSEVENT_DELETE | (isdir?FSEVENT_ISDIR:0));
 }
 
 /*
@@ -74,6 +79,7 @@ static inline void fsnotify_create(struc
 {
 	inode_dir_notify(inode, DN_CREATE);
 	inotify_inode_queue_event(inode, IN_CREATE, 0, name);
+	raise_fsevent_create(inode, name, FSEVENT_CREATE);
 }
 
 /*
@@ -83,6 +89,8 @@ static inline void fsnotify_mkdir(struct
 {
 	inode_dir_notify(inode, DN_CREATE);
 	inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, name);
+	raise_fsevent_create(inode, name,
+			     FSEVENT_CREATE | FSEVENT_ISDIR);
 }
 
 /*
@@ -99,6 +107,8 @@ static inline void fsnotify_access(struc
 	dnotify_parent(dentry, DN_ACCESS);
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
 	inotify_inode_queue_event(inode, mask, 0, NULL);
+	raise_fsevent(dentry, FSEVENT_ACCESS |
+				((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
 }
 
 /*
@@ -115,6 +125,8 @@ static inline void fsnotify_modify(struc
 	dnotify_parent(dentry, DN_MODIFY);
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
 	inotify_inode_queue_event(inode, mask, 0, NULL);
+	raise_fsevent(dentry, FSEVENT_MODIFY |
+				((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
 }
 
 /*
@@ -130,6 +142,9 @@ static inline void fsnotify_open(struct 
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
 	inotify_inode_queue_event(inode, mask, 0, NULL);	
+	raise_fsevent(dentry, FSEVENT_OPEN |
+				((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
+
 }
 
 /*
@@ -148,6 +163,8 @@ static inline void fsnotify_close(struct
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, name);
 	inotify_inode_queue_event(inode, mask, 0, NULL);
+	raise_fsevent(dentry, FSEVENT_CLOSE |
+				((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
 }
 
 /*
@@ -163,6 +180,8 @@ static inline void fsnotify_xattr(struct
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
 	inotify_inode_queue_event(inode, mask, 0, NULL);
+	raise_fsevent(dentry, FSEVENT_MODIFY_ATTRIB |
+				((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
 }
 
 /*
@@ -213,6 +232,24 @@ static inline void fsnotify_change(struc
 		inotify_dentry_parent_queue_event(dentry, in_mask, 0,
 						  dentry->d_name.name);
 	}
+
+#ifdef CONFIG_FS_EVENTS
+	{
+	u32 fsevent_mask = 0;
+	if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE))
+		fsevent_mask |= FSEVENT_MODIFY_ATTRIB;
+	if ((ia_valid & ATTR_ATIME) && (ia_valid & ATTR_MTIME))
+		fsevent_mask |= FSEVENT_MODIFY_ATTRIB;
+	else if (ia_valid & ATTR_ATIME)
+		fsevent_mask |= FSEVENT_ACCESS;
+	else if (ia_valid & ATTR_MTIME)
+		fsevent_mask |= FSEVENT_MODIFY;
+	if (ia_valid & ATTR_SIZE)
+		fsevent_mask |= FSEVENT_MODIFY;
+	if (fsevent_mask)
+		raise_fsevent(dentry, fsevent_mask);
+	}
+#endif /* CONFIG_FS_EVENTS */
 }
 
 #ifdef CONFIG_INOTIFY	/* inotify helpers */
--- a/fs/namespace.c.orig	2006-03-25 23:13:42.000000000 +0800
+++ b/fs/namespace.c	2006-04-03 22:12:52.000000000 +0800
@@ -25,6 +25,7 @@
 #include <linux/mount.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <linux/fsevent.h>
 #include "pnode.h"
 
 extern int __init init_rootfs(void);
@@ -612,6 +613,13 @@ asmlinkage long sys_umount(char __user *
 		goto dput_and_out;
 
 	retval = do_umount(nd.mnt, flags);
+
+	if (retval == 0) {
+		char * tmp = getname(name);
+		raise_fsevent_umount(tmp);
+		putname(tmp);
+	}
+
 dput_and_out:
 	path_release_on_umount(&nd);
 out:
@@ -1459,6 +1467,10 @@ asmlinkage long sys_mount(char __user * 
 	retval = do_mount((char *)dev_page, dir_page, (char *)type_page,
 			  flags, (void *)data_page);
 	unlock_kernel();
+
+	if (retval == 0)
+		raise_fsevent_mount((char *)dev_page, dir_page);
+
 	free_page(data_page);
 
 out3:
--- a/fs/Kconfig.orig	2006-03-31 21:23:20.000000000 +0800
+++ b/fs/Kconfig	2006-04-03 22:12:52.000000000 +0800
@@ -405,6 +405,16 @@ config INOTIFY
 
 	  If unsure, say Y.
 
+config FS_EVENTS
+	tristate "Report filesystem events to userspace"
+	---help---
+	  Provide a facility that reports filesystem events to userspace. The
+	  reported event include access, write, utime, chmod, chown, chgrp,
+	  close, open, create, rename, unlink, mkdir, rmdir, mount, umount.
+
+	  The user can set filesystem events filter to filter its events, so
+	  that he just get those events he concerns.
+
 config QUOTA
 	bool "Quota support"
 	help
--- a/fs/Makefile.orig	2006-03-31 21:23:33.000000000 +0800
+++ b/fs/Makefile	2006-04-03 22:12:52.000000000 +0800
@@ -13,6 +13,7 @@ obj-y :=	open.o read_write.o file_table.
 		ioprio.o pnode.o drop_caches.o
 
 obj-$(CONFIG_INOTIFY)		+= inotify.o
+obj-$(CONFIG_FS_EVENTS)		+= fsevent.o
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
 obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
 
--- /dev/null	2003-01-30 18:24:37.000000000 +0800
+++ b/include/linux/fsevent.h	2006-04-04 23:18:01.000000000 +0800
@@ -0,0 +1,131 @@
+/*
+ * fsevent.h - filesystem events connector
+ *
+ * Copyright (C) 2006 Yi Yang <yang.y.yi@gmail.com>
+ * Based on cn_proc.h by Matt Helsley, IBM Corp
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LINUX_FSEVENT_H
+#define LINUX_FSEVENT_H
+
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/netlink.h>
+
+enum  fsevent_type {
+	FSEVENT_ACCESS = 	0x00000001,	/* File was accessed */
+	FSEVENT_MODIFY = 	0x00000002,	/* File was modified */
+	FSEVENT_MODIFY_ATTRIB = 0x00000004,	/* Metadata changed */
+	FSEVENT_CLOSE = 	0x00000008,	/* File was closed */
+	FSEVENT_OPEN = 		0x00000010,	/* File was opened */
+	FSEVENT_MOVE = 		0x00000020,	/* File was moved */
+	FSEVENT_CREATE = 	0x00000040,	/* File was created */
+	FSEVENT_DELETE =	0x00000080,	/* File was deleted */
+	FSEVENT_MOUNT =		0x00000100,	/* File system is mounted */
+	FSEVENT_UMOUNT =	0x00000200,	/* File system is umounted */
+
+	/* The following definitions are command types for fsevent filter
+	 * or acknowlege types of the corresponding commands
+	 */
+	FSEVENT_FILTER_ALL = 	0x08000000,	/* For all events */
+	FSEVENT_FILTER_PID = 	0x10000000,	/* For some process ID */
+	FSEVENT_FILTER_UID = 	0x20000000,	/* For some user ID */
+	FSEVENT_FILTER_GID =	0x40000000,	/* For some group ID */
+
+	FSEVENT_ISDIR = 	0x80000000	/* It is set for a dir */
+};
+
+#define FSEVENT_MASK 0x800003ff
+
+typedef unsigned long fsevent_mask_t;
+
+enum filter_control {
+	FSEVENT_FILTER_LISTEN = 1,		/* Listen fsevents mask defines*/
+	FSEVENT_FILTER_IGNORE ,		/* Ignore fsevents mask defines*/
+	FSEVENT_FILTER_REMOVE,			/* Remove a given filter */
+};	
+
+struct fsevent_filter {
+	/* filter type, it just is one of them
+	 * FSEVENT_FILTER_ALL
+	 * FSEVENT_FILTER_PID
+	 * FSEVENT_FILTER_UID
+	 * FSEVENT_FILTER_GID
+	 */
+	enum fsevent_type type;	/* filter type */
+
+	/* mask of file system events the user listen or ignore
+	 * if the user need to ignore all the events of some pid
+	 * , gid or uid, he(she) must set mask to FSEVENT_MASK.
+	 */ 
+	fsevent_mask_t mask;
+	union {
+		pid_t pid;
+		uid_t uid;
+		gid_t gid;
+	} id;
+
+	enum filter_control control;
+};
+
+struct fsevent {
+	__u32 type;
+	__u32 cpu;
+	struct timespec timestamp;
+	pid_t pid;
+	uid_t uid;
+	gid_t gid;
+	int err;
+	__u32 len;
+	__u32 pname_len;
+	__u32 fname_len;
+	__u32 new_fname_len;
+	char name[0];
+};
+
+#define FSEVENT_FILTER_MSGSIZE \
+	(sizeof(struct fsevent_filter) + sizeof(struct nlmsghdr))
+
+#ifdef __KERNEL__
+#ifdef CONFIG_FS_EVENTS
+extern void raise_fsevent(struct dentry * dentryp, u32 mask);
+extern void raise_fsevent_move(struct inode * olddir, const char * oldname, 
+		struct inode * newdir, const char * newname, u32 mask);
+extern void raise_fsevent_create(struct inode * inode, 
+		const char * name, u32 mask);
+extern void raise_fsevent_mount(const char * devname, const char * mountpoint);
+extern void raise_fsevent_umount(const char * mountpoint);
+#else
+static void raise_fsevent(struct dentry * dentryp,  u32 mask)
+{}
+
+static void raise_fsevent_move(struct inode * olddir, const char * oldname, 
+		struct inode * newdir, const char * newname, u32 mask)
+{}
+
+static void raise_fsevent_create(struct inode * inode, 
+		const char * name, u32 mask)
+{}
+
+static void raise_fsevent_mount(const char * devname, const char * mountpoint)
+{}
+
+static void raise_fsevent_umount(const char * mountpoint)
+{}
+#endif	/* CONFIG_FS_EVENTS */
+#endif	/* __KERNEL__ */
+#endif	/* LINUX_FSEVENT_H */
--- /dev/null	2003-01-30 18:24:37.000000000 +0800
+++ b/fs/fsevent.c	2006-04-05 20:52:53.000000000 +0800
@@ -0,0 +1,598 @@
+/*
+ * 	fsevent.c
+ * 
+ * 2006 Copyright (c) Yi Yang <yang.y.yi@gmail.com>
+ * All rights reserved.
+ * 
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/moduleparam.h>
+#include <linux/fsevent.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/list.h>
+#include <linux/percpu.h>
+#include <linux/cpu.h>
+#include <linux/kthread.h>
+#include <linux/notifier.h>
+#include <linux/compiler.h>
+#include <linux/workqueue.h>
+#include <linux/sysctl.h>
+
+#define FSEVENT_MASK_CTL_NAME -2
+
+static DEFINE_PER_CPU(struct sk_buff_head, fsevent_send_queue);
+static DEFINE_PER_CPU(struct work_struct, fsevent_work);
+
+typedef struct pid_filter {
+	pid_t pid;
+	u32 mask;
+	struct list_head list;
+} pid_filter;
+
+typedef struct uid_filter {
+	uid_t uid;
+	u32 mask;
+	struct list_head list;
+} uid_filter;
+
+typedef struct gid_filter {
+	gid_t gid;
+	u32 mask;
+	struct list_head list;
+} gid_filter;
+
+typedef struct fsevent_listener {
+	pid_t pid;
+	struct list_head pid_filter_list_head;
+	struct list_head uid_filter_list_head;
+	struct list_head gid_filter_list_head;
+	u32 mask;
+	struct list_head list;
+} listener;
+
+	
+/* The netlink socket. */
+static struct sock * fsevent_sock = NULL;
+static LIST_HEAD(listener_list_head);
+static DEFINE_SPINLOCK(listener_list_lock);
+
+static atomic_t fsevent_count = ATOMIC_INIT(0);
+static int fsevent_burst_limit = 100;
+static int fsevent_ratelimit = 5 * HZ;
+static unsigned long last = 0;
+static int fsevent_sum = 0;
+static u32 fsevents_mask = FSEVENT_MASK;
+static atomic_t fsevent_listener_num = ATOMIC_INIT(0);
+
+static inline void get_seq(__u32 *ts, int *cpu)
+{
+	*ts = atomic_inc_return(&fsevent_count);
+	*cpu = smp_processor_id();
+}
+
+static void append_string(char **dest, const char *src, size_t len)
+{
+	strncpy(*dest, src, len);
+	(*dest)[len] = '\0';
+	*dest += len + 1;
+}
+
+static inline int filter_fsevent(u32 filter_mask, u32 event_mask)
+{
+	event_mask &= FSEVENT_MASK;
+	event_mask &= filter_mask;
+	if (event_mask == 0) {
+		return -1;
+	}
+	return 0;
+}
+
+static int filter_fsevent_all(u32 * mask)
+{
+	int ret = 0;
+
+	(*mask) &= FSEVENT_MASK;
+
+	if ((((*mask) & FSEVENT_ISDIR) == FSEVENT_ISDIR)
+		 && ((fsevents_mask & FSEVENT_ISDIR) == 0)) {
+		ret = -1;
+		goto out;
+	}
+
+	(*mask) &= fsevents_mask;
+	if ((*mask) == 0) {
+		ret = -5;
+	}
+
+out:
+	return ret;
+}
+
+static void fsevent_send(struct sk_buff * skb)
+{
+	struct sk_buff_head * head = &get_cpu_var(fsevent_send_queue);
+	skb_queue_tail(head, skb);
+	schedule_work(&per_cpu(fsevent_work, smp_processor_id()));
+	put_cpu_var(fsevent_send_queue);
+}
+
+int __raise_fsevent(const char * oldname, const char * newname, u32 mask)
+{
+	struct fsevent *event;
+	int namelen = 0;
+	char * nameptr = NULL;
+	unsigned int size;
+	struct nlmsghdr * nlhdr;
+	struct sk_buff * skb = NULL;
+
+	if (filter_fsevent_all(&mask) != 0)
+		return -1;
+
+	if (atomic_read(&fsevent_listener_num) <= 0)
+		return -1;
+
+	if (jiffies - last <= fsevent_ratelimit) {
+		if (fsevent_sum > fsevent_burst_limit)
+			return -2;
+		fsevent_sum++;
+	} else {
+		last = jiffies;
+		fsevent_sum = 0;
+	}
+
+	namelen = strlen(current->comm) + strlen(oldname) + 2;
+	if (newname)
+		namelen += strlen(newname) + 1;
+
+	size = NLMSG_SPACE(sizeof(struct fsevent) + namelen);
+	                                                                                                                                       
+	skb = alloc_skb(size, GFP_KERNEL);
+	if (!skb)
+	        return -ENOMEM;
+	                                                                                                                                       
+	nlhdr = NLMSG_PUT(skb, 0, 0, NLMSG_DONE, size - sizeof(*nlhdr));
+	event = NLMSG_DATA(nlhdr);
+
+	get_seq(&(nlhdr->nlmsg_seq), &event->cpu);
+	ktime_get_ts(&event->timestamp);
+	event->type = mask;
+	event->pid = current->tgid;
+	event->uid = current->uid;
+	event->gid = current->gid;
+	nameptr = event->name;
+	event->pname_len = strlen(current->comm);
+	append_string(&nameptr, current->comm, event->pname_len);
+	event->fname_len = strlen(oldname);
+	append_string(&nameptr, oldname, event->fname_len);
+	event->len = event->pname_len +  event->fname_len + 2;
+	event->new_fname_len = 0;
+	if (newname) {
+		event->new_fname_len = strlen(newname);
+		append_string(&nameptr, newname, event->new_fname_len);
+		event->len += event->new_fname_len + 1;
+	}
+	fsevent_send(skb);
+	return 0;
+
+nlmsg_failure:
+	kfree_skb(skb);
+	return -1;
+}
+
+void raise_fsevent(struct dentry * dentryp, u32 mask)
+{
+	if (dentryp->d_inode && (MAJOR(dentryp->d_inode->i_rdev) == 4))
+		return;
+	__raise_fsevent(dentryp->d_name.name, NULL, mask);
+}
+EXPORT_SYMBOL_GPL(raise_fsevent);
+
+void raise_fsevent_create(struct inode * inode, const char * name, u32 mask)
+{
+	__raise_fsevent(name, NULL, mask);
+}
+EXPORT_SYMBOL_GPL(raise_fsevent_create);
+
+void raise_fsevent_move(struct inode * olddir, const char * oldname, 
+		struct inode * newdir, const char * newname, u32 mask)
+{
+	__raise_fsevent(oldname, newname, mask);
+}
+EXPORT_SYMBOL_GPL(raise_fsevent_move);
+
+void raise_fsevent_mount(const char * devname, const char * mountpoint)
+{
+	__raise_fsevent(devname, mountpoint, FSEVENT_MOUNT);
+}
+
+void raise_fsevent_umount(const char * mountpoint)
+{
+	__raise_fsevent(mountpoint, NULL, FSEVENT_UMOUNT);
+}
+
+static int fsevent_ack(enum fsevent_type type, pid_t pid, u32 seq)
+{
+	struct fsevent *event;
+	unsigned int size;
+	struct sk_buff * skb = NULL;
+	struct nlmsghdr * nlhdr = NULL;
+
+	size = NLMSG_SPACE(sizeof(struct fsevent));
+	                                                                                                                                       
+	skb = alloc_skb(size, GFP_KERNEL);
+	if (!skb)
+	        return -ENOMEM;
+	                                                                                                                                       
+	nlhdr = NLMSG_PUT(skb, 0, seq, NLMSG_DONE, size - sizeof(*nlhdr));
+	event = NLMSG_DATA(nlhdr);
+
+	ktime_get_ts(&event->timestamp);
+	event->cpu = -1;
+	event->type = type; 
+	event->pid = 0;
+	event->uid = 0;
+	event->gid = 0;
+	event->len = 0;
+	event->pname_len = 0;
+	event->fname_len = 0;
+	event->new_fname_len = 0;
+	event->err = 0;
+	                                                                                                                                       
+	NETLINK_CB(skb).dst_group = 0;
+	NETLINK_CB(skb).dst_pid = pid;
+	NETLINK_CB(skb).pid = 0;
+
+	return (netlink_unicast(fsevent_sock, skb, pid, MSG_DONTWAIT));
+
+nlmsg_failure:
+	kfree_skb(skb);
+	return -1;
+}
+
+static void set_fsevent_mask(u32 * to_mask, u32 from_mask, int mode)
+{
+	if (mode == FSEVENT_FILTER_IGNORE)
+		(*to_mask) &= ~(from_mask);
+	else if (mode == FSEVENT_FILTER_LISTEN)
+		(*to_mask) |= from_mask;
+}
+
+#define DEFINE_FILTER_FIND_FUNC(type, key) 				\
+	type * find_##type(struct list_head * head, key##_t id)		\
+	{								\
+		int alloc_flag = 1;					\
+		type * entry = NULL;					\
+									\
+		list_for_each_entry(entry, head, list) {		\
+			if (entry->key == id) {				\
+				alloc_flag = 0;				\
+				break;					\
+			}						\
+		}							\
+									\
+		if (alloc_flag == 1) {					\
+			entry  = (type *)kmalloc(sizeof(type), GFP_ATOMIC); \
+			if (entry == NULL) 				\
+				return NULL;				\
+			memset(entry, 0, sizeof(type));			\
+			entry->key = id;				\
+			list_add_tail(&(entry->list), head);		\
+		}							\
+		return entry;						\
+	}								\
+
+DEFINE_FILTER_FIND_FUNC(pid_filter, pid)
+
+DEFINE_FILTER_FIND_FUNC(uid_filter, uid)
+
+DEFINE_FILTER_FIND_FUNC(gid_filter, gid)
+		
+DEFINE_FILTER_FIND_FUNC(listener, pid)
+
+static void set_fsevent_filter(struct fsevent_filter * filter, pid_t pid)
+{
+	enum fsevent_type type;
+	u32 mask = 0;
+	int control = 0;
+	listener * listenerp = NULL;
+	pid_filter * pfilter = NULL;
+	uid_filter * ufilter = NULL;
+	gid_filter * gfilter = NULL;
+
+
+	mask = filter->mask;
+	control = filter->control;
+	type = filter->type;
+	mask &= FSEVENT_MASK;
+	if (mask == 0)
+		goto out;
+
+	spin_lock(&listener_list_lock);
+	listenerp = find_listener(&listener_list_head, pid);
+	if (unlikely(listenerp == NULL)) {
+		spin_unlock(&listener_list_lock);
+		return;
+	}
+
+	if (!(listenerp->pid_filter_list_head.next)) {
+		INIT_LIST_HEAD(&(listenerp->pid_filter_list_head));
+		INIT_LIST_HEAD(&(listenerp->uid_filter_list_head));
+		INIT_LIST_HEAD(&(listenerp->gid_filter_list_head));
+	}
+
+	if ((type & FSEVENT_FILTER_ALL) == FSEVENT_FILTER_ALL) {
+		if (control == FSEVENT_FILTER_REMOVE) {
+			atomic_dec(&fsevent_listener_num);
+			list_del(&(listenerp->list));
+			kfree(listenerp);
+		} else
+			set_fsevent_mask(&(listenerp->mask), mask, control);
+	} else if ((type & FSEVENT_FILTER_PID) == FSEVENT_FILTER_PID) {
+		pfilter = find_pid_filter(&(listenerp->pid_filter_list_head),
+				filter->id.pid);
+		if (unlikely(pfilter == NULL))
+			return;
+
+		if (control == FSEVENT_FILTER_REMOVE) {
+			list_del(&(pfilter->list));
+			kfree(pfilter);
+		} else
+			set_fsevent_mask(&(pfilter->mask), mask, control);
+	} else if ((type & FSEVENT_FILTER_UID) == FSEVENT_FILTER_UID) {
+		ufilter = find_uid_filter(&(listenerp->uid_filter_list_head),
+						filter->id.uid);
+		if (unlikely(ufilter == NULL))
+			return;
+
+		if (control == FSEVENT_FILTER_REMOVE) {
+			list_del(&(ufilter->list));
+			kfree(ufilter);
+		} else
+			set_fsevent_mask(&(ufilter->mask), mask, control);
+	} else if ((type & FSEVENT_FILTER_GID) == FSEVENT_FILTER_GID) {
+		gfilter = find_gid_filter(&(listenerp->gid_filter_list_head),
+						filter->id.gid);
+		if (unlikely(gfilter == NULL))
+			return;
+
+		if (control == FSEVENT_FILTER_REMOVE) {
+			list_del(&(gfilter->list));
+			kfree(gfilter);
+		} else
+			set_fsevent_mask(&(gfilter->mask), mask, control);
+	}
+	spin_unlock(&listener_list_lock);
+
+out:
+	fsevent_ack(type, pid, 0);
+}
+
+static listener * find_fsevent_listener(pid_t pid)
+{
+	listener * listenerp = NULL;
+	spin_lock(&listener_list_lock);
+	list_for_each_entry(listenerp, &listener_list_head, list) {
+		if (listenerp->pid == pid) {
+			spin_unlock(&listener_list_lock);
+			return listenerp;
+		}
+	}
+	spin_unlock(&listener_list_lock);
+	return NULL;
+}
+
+static void cleanup_dead_listener(listener * x)
+{
+	pid_filter * p = NULL, * pq = NULL;
+	uid_filter * u = NULL, * uq = NULL;
+	gid_filter * g = NULL, * gq = NULL;
+
+	if (p == NULL)
+		return;
+
+	list_del(&(x->list));
+
+	list_for_each_entry_safe(p, pq, &(x->pid_filter_list_head), list) {
+		list_del(&(p->list));
+		kfree(p);
+	}
+
+	list_for_each_entry_safe(u, uq, &(x->uid_filter_list_head), list) {
+		list_del(&(u->list));
+		kfree(u);
+	}
+
+	list_for_each_entry_safe(g, gq, &(x->gid_filter_list_head), list) {
+		list_del(&(g->list));
+		kfree(g);
+	}
+	
+	kfree(x);
+}
+
+static void fsevent_recv(struct sock *sk, int len)
+{
+	struct sk_buff *skb = NULL;
+	struct nlmsghdr *nlhdr = NULL;
+	struct fsevent_filter * filter = NULL;
+	pid_t pid;
+
+	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+		skb_get(skb);
+		if (skb->len >= FSEVENT_FILTER_MSGSIZE) {
+			nlhdr = (struct nlmsghdr *)skb->data;
+			filter = NLMSG_DATA(nlhdr);
+			pid = NETLINK_CREDS(skb)->pid;
+			if (find_fsevent_listener(pid) == NULL)
+				atomic_inc(&fsevent_listener_num);
+			set_fsevent_filter(filter, pid);
+		}
+		kfree_skb(skb);
+	}
+}
+
+#define DEFINE_FILTER_MATCH_FUNC(filtertype, key) 			\
+	static int match_##filtertype(listener * p,			\
+				struct fsevent * event,			\
+				struct sk_buff * skb)			\
+	{								\
+		int ret = 0;						\
+		filtertype * xfilter = NULL;				\
+		struct sk_buff * skb2 = NULL;				\
+		struct list_head *  head = &(p->key##_filter_list_head);  \
+		list_for_each_entry(xfilter, head, list) {		\
+			if (xfilter->key != event->key)			\
+				continue;				\
+			ret = filter_fsevent(xfilter->mask, event->type); \
+			if ( ret != 0)					\
+				return -1;				\
+			skb2 = skb_clone(skb, GFP_KERNEL);		\
+       			if (skb2 == NULL)				\
+				return -ENOMEM;				\
+			NETLINK_CB(skb2).dst_group = 0;			\
+			NETLINK_CB(skb2).dst_pid = p->pid;		\
+			NETLINK_CB(skb2).pid = 0;			\
+			return (netlink_unicast(fsevent_sock, skb2,	\
+					p->pid, MSG_DONTWAIT));		\
+		}							\
+		return -ENODEV;						\
+	}								\
+
+DEFINE_FILTER_MATCH_FUNC(pid_filter, pid)
+
+DEFINE_FILTER_MATCH_FUNC(uid_filter, uid)
+
+DEFINE_FILTER_MATCH_FUNC(gid_filter, gid)
+
+#define MATCH_XID(key, listenerp, event, skb) 			\
+	ret = match_##key##_filter(listenerp, event, skb); 	\
+	if (ret == 0) {					 	\
+		kfree_skb(skb);				 	\
+	        continue;				 	\
+	}						 	\
+	do {} while (0)					 	\
+
+static int fsevent_send_to_process(struct sk_buff * skb)
+{
+	listener * p  = NULL, * q = NULL;
+	struct fsevent * event = NULL;
+	struct sk_buff * skb2 = NULL;
+	int ret = 0;
+
+	event = (struct fsevent *)(skb->data + sizeof(struct nlmsghdr));
+	spin_lock(&listener_list_lock);
+	list_for_each_entry_safe(p, q, &listener_list_head, list) {
+		MATCH_XID(pid, p, event, skb);
+		MATCH_XID(uid, p, event, skb);
+		MATCH_XID(gid, p, event, skb);
+
+		if (filter_fsevent(p->mask, event->type) == 0) {
+			 skb2 = skb_clone(skb, GFP_KERNEL);
+	                 if (skb2 == NULL)
+	                 	return -ENOMEM;
+	                 NETLINK_CB(skb2).dst_group = 0;
+	                 NETLINK_CB(skb2).dst_pid = p->pid;
+	                 NETLINK_CB(skb2).pid = 0;
+	                 ret = netlink_unicast(fsevent_sock, skb2,
+	                                p->pid, MSG_DONTWAIT);
+			if (ret == -ECONNREFUSED) {
+				atomic_dec(&fsevent_listener_num);
+				cleanup_dead_listener(p);
+			}
+		}
+	}
+	spin_unlock(&listener_list_lock);
+	return ret;
+}
+
+static void fsevent_commit(void * unused)
+{
+	struct sk_buff * skb = NULL;
+		
+	while((skb = skb_dequeue(&get_cpu_var(fsevent_send_queue)))
+		!= NULL) {
+		fsevent_send_to_process(skb);
+		put_cpu_var(fsevent_send_queue);
+	}
+}
+
+static struct ctl_table fsevent_mask_sysctl[] = {
+	{
+		.ctl_name = FSEVENT_MASK_CTL_NAME,
+		.procname = "fsevent_mask",
+		.data = &fsevents_mask,
+		.maxlen = sizeof(u32),
+		.mode = 0644,
+		.proc_handler = &proc_dointvec,
+	},
+	{ .ctl_name = 0 }
+};
+
+static struct ctl_table fs_root_sysctl[] = {
+	{
+		.ctl_name = CTL_FS,
+		.procname = "fs",
+		.mode = 0555,
+		.child = fsevent_mask_sysctl,
+	},
+	{ .ctl_name = 0 }
+};
+
+static int __init fsevent_init(void)
+{
+	int cpu;
+	struct sk_buff_head * listptr;
+	struct work_struct * workptr;
+
+	fsevent_sock = netlink_kernel_create(NETLINK_FSEVENT, 0,
+					 fsevent_recv, THIS_MODULE);
+	if (!fsevent_sock)
+		return -EIO;
+	for_each_cpu(cpu) {
+		listptr = &per_cpu(fsevent_send_queue, cpu);
+		skb_queue_head_init(listptr);
+		workptr = &per_cpu(fsevent_work, cpu);
+		INIT_WORK(workptr, fsevent_commit, NULL);
+	}
+
+	if (register_sysctl_table(fs_root_sysctl, 0) == NULL)
+                return -ENOMEM;
+
+	return 0;
+}
+
+static void __exit fsevent_exit(void)
+{
+	listener * p = NULL, * q = NULL;
+	sock_release(fsevent_sock->sk_socket);
+	spin_lock(&listener_list_lock);
+	list_for_each_entry_safe(p, q, &listener_list_head, list) {
+		cleanup_dead_listener(p);
+	}
+	spin_unlock(&listener_list_lock);
+}
+
+module_init(fsevent_init);
+module_exit(fsevent_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yi Yang <yang.y.yi@gmail.com>");
+MODULE_DESCRIPTION("File System Events Reporter");


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: dma_alloc_coherent
From: Kartik Babu @ 2006-04-05 14:12 UTC (permalink / raw)
  To: Robert Hancock; +Cc: linux-kernel
In-Reply-To: <44330535.2070803@shaw.ca>

Its a char device driver Im using to control the SPI port on the PXA255 
processor. I transfer fixed sized packets over this bus, and hence DMA 
is a good option instead of interrupt driven IO.

it seems that the dma_pool_create function explicitly handles both cases 
dev = NULL and dev != NULL.

However, the dma_alloc_coherent function only checks if dev is not NULL, 
and apparently uses the valu in one case without checking it.

My understanding is that the dev pointer is needed only to check the 
mask for accesible DMA locations correct?

Kartik

Robert Hancock wrote:
> Kartik Babu wrote:
>>  I'm trying to replace consistent_alloc in a driver that was written 
>> for the 2.4 kernel with dma_alloc_coherent. My question is that I do 
>> not use a struct device * pointer at all. Browsing through the source 
>> for the 2.6.12
>> on ARM XScale PXA255, I see that this argument may be NULL.
>>
>> Still, I'd like to know if passing NULL has any side effects. If so, 
>> what are they?
>>
>> I do however have a cdev structure taht I use for device 
>> registration, but I do not see how that would help.
>
> What kind of a device is it? If it's a PCI device, the struct device 
> can be accessed with the dev pointer inside the struct pci_dev.
>


^ permalink raw reply

* driver for Native Instruments' audio devices
From: Daniel Mack @ 2006-04-05 14:10 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 314 bytes --]

Hi folks,

here's my first shot of a driver for the new audio devices produced
by Native Instruments such as RigKontrol2 and Kore controller.

The patchset should cleanly apply to the current CVS. I also tried to
keep to the coding style as close as possible ;)

Please let me know what you think.

Best,
Daniel



[-- Attachment #2: caiaq-alsa-cvs.patch --]
[-- Type: application/octet-stream, Size: 2109 bytes --]

Index: alsa-kernel/scripts/ksync
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/scripts/ksync,v
retrieving revision 1.66
diff -u -p -r1.66 ksync
--- alsa-kernel/scripts/ksync	2 Feb 2006 12:56:53 -0000	1.66
+++ alsa-kernel/scripts/ksync	5 Apr 2006 13:38:59 -0000
@@ -261,6 +261,7 @@ COMMENT_MAP_DRIVER = [
 		('/pcmcia/Makefile'	,'PCMCIA'),
 		('/pcmcia'		,'ERROR'),
 		('/usb/usx2y/.*'	,'USB USX2Y'),
+		('/usb/caiaq/'		,'caiaq USB driver'),
 		('/usb/Kconfig'		,'USB'),
 		('/usb/Makefile'	,'USB'),
 		('/usb/usbaudio.(c|h)'	,'USB generic driver'),
Index: alsa-kernel/usb/Kconfig
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/Kconfig,v
retrieving revision 1.9
diff -u -p -r1.9 Kconfig
--- alsa-kernel/usb/Kconfig	8 May 2005 21:22:27 -0000	1.9
+++ alsa-kernel/usb/Kconfig	5 Apr 2006 13:38:59 -0000
@@ -29,5 +29,18 @@ config SND_USB_USX2Y
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-usb-usx2y.
 
+config SND_USB_CAIAQ
+	tristate "caiaq/NativeInstruments USB audio devices"
+	depends on SND && USB && (X86 || PPC || ALPHA)
+	select SND_HWDEP
+	select SND_RAWMIDI
+	select SND_PCM
+	help
+	  Say Y here to include support for caiaq USB audio interfaces
+	  such as NativeInstrument's 'RigKontrol2' and 'Kore controller'.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-usb-caiaq.
+
 endmenu
 
Index: alsa-kernel/usb/Makefile
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/usb/Makefile,v
retrieving revision 1.5
diff -u -p -r1.5 Makefile
--- alsa-kernel/usb/Makefile	3 Aug 2004 14:22:32 -0000	1.5
+++ alsa-kernel/usb/Makefile	5 Apr 2006 13:38:59 -0000
@@ -8,5 +8,6 @@ snd-usb-lib-objs := usbmidi.o
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
 obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
+obj-$(CONFIG_SND_USB_CAIAQ) += snd-usb-lib.o
 
-obj-$(CONFIG_SND) += usx2y/
+obj-$(CONFIG_SND) += usx2y/ caiaq/

[-- Attachment #3: caiaq-alsa.patch --]
[-- Type: application/octet-stream, Size: 41437 bytes --]

diff -Nur -x .svn orig/Makefile alsa-kernel/usb/caiaq/Makefile
--- orig/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ alsa-kernel/usb/caiaq/Makefile	2006-04-05 14:57:48.000000000 +0200
@@ -0,0 +1,3 @@
+snd-usb-caiaq-objs := caiaq-device.o caiaq-audio.o caiaq-midi.o
+
+obj-$(CONFIG_SND_USB_CAIAQ) += snd-usb-caiaq.o
diff -Nur -x .svn orig/caiaq-audio.c alsa-kernel/usb/caiaq/caiaq-audio.c
--- orig/caiaq-audio.c	1970-01-01 01:00:00.000000000 +0100
+++ alsa-kernel/usb/caiaq/caiaq-audio.c	2006-04-05 15:36:17.000000000 +0200
@@ -0,0 +1,727 @@
+/*
+ *   Copyright (c) 2006 Daniel Mack
+ *
+ *   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; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/rawmidi.h>
+
+#include "caiaq-device.h"
+#include "caiaq-audio.h"
+
+#ifndef MAX
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#define CLOCK_DRIFT_TOLERANCE	3
+
+#define N_URBS 			64
+#define FRAMES_PER_URB		8
+#define BYTES_PER_FRAME		512
+#define CHANNELS_PER_STREAM	2
+				 
+#define ENDPOINT_CAPTURE  	2
+#define ENDPOINT_PLAYBACK 	6
+
+#define BYTES_PER_SAMPLE	3
+				 
+static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
+	.info 		= (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER),
+	.formats 	= SNDRV_PCM_FMTBIT_S24_3BE,
+	.rates 		= (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 
+			   SNDRV_PCM_RATE_96000),
+	.rate_min	= 44100,
+	.rate_max	= 96000,
+	.channels_min	= 0, /* will overwrite later */
+	.channels_max	= 0, /* will overwrite later */
+	.buffer_bytes_max = 32768,
+	.period_bytes_min = 4096,
+	.period_bytes_max = 32768,
+	.periods_min	= 1,
+	.periods_max	= 1024,
+};
+	
+/* open callback */
+static int snd_usb_caiaq_playback_open(struct snd_pcm_substream *substream)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	debug("snd_usb_caiaq_playback_open(%p)\n", substream);
+	runtime->hw = dev->pcm_info_playback;
+	dev->pcm_sub_playback = substream;
+	return 0;
+}
+
+/* close callback */
+static int snd_usb_caiaq_playback_close(struct snd_pcm_substream *substream)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+
+	debug("snd_usb_caiaq_playback_close(%p)\n", substream);
+	dev->pcm_sub_playback = NULL;
+	return 0;
+}
+
+/* open callback */
+static int snd_usb_caiaq_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	debug("snd_usb_caiaq_capture_open(%p)\n", substream);
+	runtime->hw = dev->pcm_info_capture;
+	dev->pcm_sub_capture = substream;
+	return 0;
+}
+
+/* close callback */
+static int snd_usb_caiaq_capture_close(struct snd_pcm_substream *substream)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	debug("snd_usb_caiaq_capture_close(%p)\n", substream);
+	dev->pcm_sub_capture = NULL;
+	return 0;
+}
+
+/* hw_params callback */
+static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *hw_params)
+{
+	debug("snd_usb_caiaq_pcm_hw_params(%p)\n", substream);
+	return snd_pcm_lib_malloc_pages(substream,
+				   params_buffer_bytes(hw_params));
+}
+
+/* hw_free callback */
+static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	debug("snd_usb_caiaq_pcm_hw_free(%p)\n", substream);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+/* prepare callback */
+static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	int bytes_per_sample, bpp, ret;
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream);
+
+	if (dev->streaming) {
+		debug("not setting params again, already streaming\n");
+		return 0;
+	}
+
+	down(&dev->mutex);
+	
+	bytes_per_sample = BYTES_PER_SAMPLE;
+	dev->stream_pitch = frames_to_bytes(substream->runtime, 
+					    substream->runtime->buffer_size);
+
+	if (dev->spec.data_alignment == 1)
+		bytes_per_sample++;
+	
+	bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
+			* bytes_per_sample * 2 * dev->n_streams;
+	
+	debug("setting audio params: %d Hz, %d bits, %d bytes/sample\n",
+			runtime->rate, runtime->sample_bits, bytes_per_sample);
+
+	dev->audio_out_buf_pos = BYTES_PER_SAMPLE + 1;
+	dev->audio_in_buf_pos = BYTES_PER_SAMPLE - 1;
+	
+	ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate, runtime->sample_bits, bpp);
+
+	up(&dev->mutex);
+	
+	return ret;
+}
+
+static void stream_start(void *d)
+{
+	int i, ret;
+	struct snd_usb_caiaqdev *dev = (struct snd_usb_caiaqdev *) d;
+
+	debug("stream_start(%p)\n", dev);
+
+	if (dev->streaming)
+		return;
+	
+	down(&dev->mutex);
+	
+	dev->streaming = 1;
+	dev->input_panic = 0;
+	dev->output_panic = 0;
+	dev->first_packet = 1;
+
+	for (i = 0; i < N_URBS; i++) {
+		ret = usb_submit_urb(dev->data_urbs_in[i], GFP_KERNEL);
+		if (ret < 0)
+			log("unable to trigger initial read #%d! (ret = %d)\n", i, ret);
+	}
+
+	up(&dev->mutex);
+}
+
+static void stream_stop(void *d)
+{
+	int i;
+	struct snd_usb_caiaqdev *dev = (struct snd_usb_caiaqdev *) d;
+	
+	debug("stream_stop(%p)\n", dev);
+
+	if (!dev->streaming)
+		return;
+
+	down(&dev->mutex);
+	dev->streaming = 0;
+
+	for (i = 0; i < N_URBS; i++) {
+		usb_kill_urb(dev->data_urbs_in[i]);
+		usb_kill_urb(dev->data_urbs_out[i]);
+	}
+	
+	up(&dev->mutex);
+}
+
+static void stream_restart(void *d)
+{
+	debug("stream_restart()\n");
+	stream_stop(d);
+	stream_start(d);
+}
+
+/* trigger callback */
+static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *substream,
+				 int cmd)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+
+	switch (cmd) {
+		case SNDRV_PCM_TRIGGER_START:
+		case SNDRV_PCM_TRIGGER_RESUME:
+			debug("snd_usb_caiaq_pcm_trigger SNDRV_PCM_TRIGGER_START (%p)\n",
+					substream);
+			schedule_delayed_work(&dev->stream_start_work, 0);
+			break;
+		case SNDRV_PCM_TRIGGER_STOP:
+		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+			debug("snd_usb_caiaq_pcm_trigger SNDRV_PCM_TRIGGER_STOP (%p)\n",
+					substream);
+			schedule_delayed_work(&dev->stream_stop_work, 0);
+	       		break;
+		default:
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* pointer callback */
+static snd_pcm_uframes_t
+snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	
+	if (dev->pcm_sub_playback)
+		return bytes_to_frames(dev->pcm_sub_playback->runtime, dev->audio_out_buf_pos);
+	
+	if (dev->pcm_sub_capture)
+		return bytes_to_frames(dev->pcm_sub_capture->runtime, dev->audio_in_buf_pos);
+
+	return 0;
+}
+
+/* operators */
+static struct snd_pcm_ops snd_usb_caiaq_playback_ops = {
+	.open =		snd_usb_caiaq_playback_open,
+	.close =	snd_usb_caiaq_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_usb_caiaq_pcm_hw_params,
+	.hw_free =	snd_usb_caiaq_pcm_hw_free,
+	.prepare =	snd_usb_caiaq_pcm_prepare,
+	.trigger =	snd_usb_caiaq_pcm_trigger,
+	.pointer =	snd_usb_caiaq_pcm_pointer,
+};
+
+/* operators */
+static struct snd_pcm_ops snd_usb_caiaq_capture_ops = {
+	.open =		snd_usb_caiaq_capture_open,
+	.close =	snd_usb_caiaq_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_usb_caiaq_pcm_hw_params,
+	.hw_free =	snd_usb_caiaq_pcm_hw_free,
+	.prepare =	snd_usb_caiaq_pcm_prepare,
+	.trigger =	snd_usb_caiaq_pcm_trigger,
+	.pointer =	snd_usb_caiaq_pcm_pointer,
+};
+
+static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
+			      struct urb *urb,
+			      const struct usb_iso_packet_descriptor *iso)
+{
+	struct snd_pcm_runtime *runtime;
+	unsigned char *dma_buf;
+	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	int stream, i = 0;
+
+	if (!dev->pcm_sub_capture)
+		return;
+	
+	runtime = dev->pcm_sub_capture->runtime;
+	dma_buf = runtime->dma_area;
+	
+	for (;;) {
+		for (stream = 0; stream < dev->n_streams; stream++)
+			dma_buf[dev->audio_in_buf_pos + (stream * dev->stream_pitch)] = usb_buf[i++];
+
+		dev->audio_in_buf_pos++;
+		dev->audio_in_buf_pos %= frames_to_bytes(runtime, runtime->buffer_size);
+
+		if (i >= iso->actual_length)
+			break;
+	}
+
+	dev->period_in_count += bytes_to_frames(runtime, iso->actual_length);
+}
+
+static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+			      struct urb *urb,
+			      const struct usb_iso_packet_descriptor *iso)
+{
+	struct snd_pcm_runtime *runtime = NULL;
+	unsigned char *dma_buf = NULL;
+	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	int stream, i = 0;
+	
+	if (dev->pcm_sub_capture) {
+		runtime = dev->pcm_sub_capture->runtime;
+		dma_buf = runtime->dma_area;
+	}
+	
+	for (;;) {
+		if ((dev->audio_in_buf_pos % BYTES_PER_SAMPLE) == 2) {
+			for (stream = 0; stream < dev->n_streams; stream++, i++) {
+				if ((!dev->first_packet) && (usb_buf[i] & 0x3f) != 
+					((stream << 1) | (~(dev->audio_in_buf_pos / 
+							   BYTES_PER_SAMPLE) & 1)))
+					dev->input_panic = 1;
+
+				if (usb_buf[i] & 0x80) 
+					dev->output_panic = 1;
+			}
+		
+		}
+		
+		dev->first_packet = 0;
+		
+		dev->audio_in_buf_pos++;
+		dev->audio_in_buf_pos %= dev->stream_pitch;
+	
+		if (runtime)
+			for (stream = 0; stream < dev->n_streams; stream++)
+				dma_buf[dev->audio_in_buf_pos + (stream * dev->stream_pitch)] = usb_buf[i++];
+		else
+			i += dev->n_streams;
+		
+		if (i >= iso->actual_length)
+			break;
+		
+	}
+
+	if (runtime)
+		dev->period_in_count += bytes_to_frames(runtime, (iso->actual_length/4)*3);
+}
+
+static void read_in_urb(struct snd_usb_caiaqdev *dev,
+			struct urb *urb,
+			const struct usb_iso_packet_descriptor *iso)
+{
+	struct snd_pcm_runtime *runtime = NULL;
+	
+	if (dev->pcm_sub_capture)
+		runtime = dev->pcm_sub_capture->runtime;
+	
+	switch (dev->spec.data_alignment) {
+		case 0:
+			read_in_urb_mode0(dev, urb, iso);
+			break;
+		case 2:
+			read_in_urb_mode2(dev, urb, iso);
+			break;
+	}
+
+	if (dev->input_panic || dev->output_panic) {
+		debug("streaming error detected %s %s\n", 
+				dev->input_panic ? "(input)" : "",
+				dev->output_panic ? "(output)" : "");
+		schedule_delayed_work(&dev->stream_restart_work, 0);
+	}
+	
+	if (runtime)
+		if (dev->period_in_count >= runtime->period_size) {
+			snd_pcm_period_elapsed(dev->pcm_sub_capture);
+			dev->period_in_count %= runtime->period_size;
+		}
+}
+
+static void fill_out_urb_mode0(struct snd_usb_caiaqdev *dev, 
+			       struct urb *urb, 
+       			       const struct usb_iso_packet_descriptor *iso)
+{
+	struct snd_pcm_runtime *runtime;
+	unsigned char *dma_buf;
+	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	int stream, i = 0;
+
+	if (!dev->pcm_sub_playback) {
+		memset(usb_buf, 0, iso->length);
+		return;
+	}
+
+	runtime = dev->pcm_sub_playback->runtime;
+	dma_buf = runtime->dma_area;
+
+	for (;;) {
+		for (stream = 0; stream < dev->n_streams; stream++)
+			usb_buf[i++] = dma_buf[dev->audio_out_buf_pos + (stream * dev->stream_pitch)];
+
+		dev->audio_out_buf_pos++;
+		dev->audio_out_buf_pos %= frames_to_bytes(runtime, runtime->buffer_size);
+		
+		if (i >= iso->length)
+			break;
+	}
+
+	dev->period_out_count += bytes_to_frames(runtime, iso->length);
+}
+
+static void fill_out_urb_mode2(struct snd_usb_caiaqdev *dev, 
+			       struct urb *urb, 
+			       const struct usb_iso_packet_descriptor *iso)
+{
+	struct snd_pcm_runtime *runtime = NULL;
+	unsigned char *dma_buf = NULL;
+	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	int stream, i = 0;
+	
+	if (dev->pcm_sub_playback) {
+		runtime = dev->pcm_sub_playback->runtime;
+		dma_buf = runtime->dma_area;
+	}
+	
+	for (;;) {
+		if (runtime) {
+			for (stream = 0; stream < dev->n_streams; stream++)
+				usb_buf[i++] = dma_buf[dev->audio_out_buf_pos + 
+							(stream * dev->stream_pitch)];
+		} else
+			i += dev->n_streams;
+
+		if ((dev->audio_out_buf_pos % BYTES_PER_SAMPLE) == 2)
+			for (stream = 0; stream < dev->n_streams; stream++)
+				usb_buf[i++] = (stream << 1) | 
+					((dev->audio_out_buf_pos / BYTES_PER_SAMPLE) & 1);
+		
+		dev->audio_out_buf_pos++;
+		dev->audio_out_buf_pos %= dev->stream_pitch;
+		
+		if (i >= iso->length)
+			break;
+	}
+
+	if (runtime)
+		dev->period_out_count += bytes_to_frames(runtime, (iso->length/4)*3);
+}
+
+static void fill_out_urb(struct snd_usb_caiaqdev *dev, 
+			 struct urb *urb, 
+			 const struct usb_iso_packet_descriptor *iso)
+{
+	struct snd_pcm_runtime *runtime = NULL;
+
+	if (dev->pcm_sub_playback)
+		runtime = dev->pcm_sub_playback->runtime;
+	
+	switch (dev->spec.data_alignment) {
+		case 0:
+			fill_out_urb_mode0(dev, urb, iso);
+			break;
+		case 2:
+			fill_out_urb_mode2(dev, urb, iso);
+			break;
+	}
+	
+	if (runtime)
+		if (dev->period_out_count >= runtime->period_size) {
+			snd_pcm_period_elapsed(dev->pcm_sub_playback);
+			dev->period_out_count %= runtime->period_size;
+		}
+}
+
+static void read_completed(struct urb *urb, struct pt_regs *regs)
+{
+	struct snd_usb_caiaq_cb_info *info = (struct snd_usb_caiaq_cb_info *) urb->context; 
+	struct snd_usb_caiaqdev *dev = info->dev;
+	struct urb *out = dev->data_urbs_out[info->index];
+	int frame, len, send_it = 0, outframe = 0;
+
+	if (!dev->streaming)
+		return;
+
+	if (urb->status != 0)
+		return;
+
+	for (frame = 0; frame < FRAMES_PER_URB; frame++) {
+		if (urb->iso_frame_desc[frame].status != 0)
+			continue;
+
+		len = urb->iso_frame_desc[outframe].actual_length;
+		out->iso_frame_desc[outframe].length = len;
+		out->iso_frame_desc[outframe].actual_length = 0;
+		out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
+		
+		if (len) {
+			fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
+			send_it = 1;
+		}
+
+		outframe++;
+	}
+
+	if (send_it) {
+		out->number_of_packets = FRAMES_PER_URB;
+		out->transfer_flags = URB_ISO_ASAP;
+		usb_submit_urb(out, GFP_ATOMIC);
+	}
+
+	for (frame = 0; frame < FRAMES_PER_URB; frame++) {
+		if (urb->iso_frame_desc[frame].status != 0)
+			continue;
+
+		if (urb->iso_frame_desc[frame].actual_length > 0)
+			read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
+	}
+	
+	/* prepare urb for re-submission */
+	for (frame = 0; frame < FRAMES_PER_URB; frame++) {
+		urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame;
+		urb->iso_frame_desc[frame].length = BYTES_PER_FRAME;
+		urb->iso_frame_desc[frame].actual_length = 0;
+	}
+	
+	urb->number_of_packets = FRAMES_PER_URB;
+	urb->transfer_flags = URB_ISO_ASAP;
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static void write_completed(struct urb *urb, struct pt_regs *regs)
+{
+}
+
+static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
+{
+	int i, frame;
+	struct urb **urbs;
+	struct usb_device *usb_dev = dev->chip.dev;
+	unsigned int pipe;
+
+	pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? 
+		usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) :
+		usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE);
+
+	urbs = (struct urb **) kmalloc(N_URBS * sizeof(struct urb*), GFP_KERNEL);
+	if (!urbs) {
+		log("unable to kmalloc() urbs, OOM!?\n");
+		*ret = -1;
+		return NULL;
+	}
+
+	for (i = 0; i < N_URBS; i++) {
+		urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL);
+		if (!urbs[i]) {
+			log("unable to usb_alloc_urb(), OOM!?\n");
+			*ret = -1;
+			return urbs;
+		}
+
+		urbs[i]->transfer_buffer = kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL);
+		if (!urbs[i]->transfer_buffer) {
+			log("unable to kmalloc() transfer buffer, OOM!?\n");
+			*ret = -1;
+			return urbs;
+		}
+		
+		for (frame = 0; frame < FRAMES_PER_URB; frame++) {
+			urbs[i]->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame;
+			urbs[i]->iso_frame_desc[frame].length = BYTES_PER_FRAME;
+		}
+		
+		urbs[i]->dev = usb_dev;
+		urbs[i]->pipe = pipe;
+		urbs[i]->transfer_buffer_length = FRAMES_PER_URB * BYTES_PER_FRAME;
+		urbs[i]->context = &dev->data_cb_info[i];
+		urbs[i]->interval = 1;
+		urbs[i]->start_frame = -1;
+		urbs[i]->transfer_flags = URB_ISO_ASAP;
+		urbs[i]->number_of_packets = FRAMES_PER_URB;
+		urbs[i]->complete = (dir == SNDRV_PCM_STREAM_PLAYBACK) ?
+					write_completed : read_completed;
+	}
+
+	*ret = 0;
+	return urbs;
+}
+
+static void free_urbs(struct urb **urbs)
+{
+	int i;
+
+	if (!urbs)
+		return;
+
+	for (i = 0; i < N_URBS; i++) {
+		if (!urbs[i])
+			continue;
+		
+		usb_kill_urb(urbs[i]);
+
+		if (urbs[i]->transfer_buffer) {
+			kfree(urbs[i]->transfer_buffer);
+			urbs[i]->transfer_buffer = NULL;
+		}
+
+		usb_free_urb(urbs[i]);
+		urbs[i] = NULL;
+	}
+
+	kfree(urbs);
+}
+
+
+int __devinit snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
+{
+	int i, ret;
+	struct snd_pcm *pcm;
+
+	dev->n_audio_in  = MAX(dev->spec.num_analog_audio_in, 
+			       dev->spec.num_digital_audio_in) / CHANNELS_PER_STREAM;
+	dev->n_audio_out = MAX(dev->spec.num_analog_audio_out,
+			       dev->spec.num_digital_audio_out) / CHANNELS_PER_STREAM;
+	dev->n_streams   = MAX(dev->n_audio_in, dev->n_audio_out);
+
+	debug("dev->n_audio_in = %d\n", dev->n_audio_in);
+	debug("dev->n_audio_out = %d\n", dev->n_audio_out);
+	debug("dev->n_streams = %d\n", dev->n_streams);
+	
+	ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, 
+			dev->n_streams, dev->n_streams, &pcm);
+
+	if (ret < 0) {
+		log("snd_pcm_new() returned %d\n", ret);
+		return ret;
+	}
+
+	pcm->private_data = dev;
+	strcpy(pcm->name, dev->product_name);
+	dev->pcm = pcm;
+
+	memcpy(&dev->pcm_info_playback, &snd_usb_caiaq_pcm_hardware, sizeof(snd_usb_caiaq_pcm_hardware));
+	memcpy(&dev->pcm_info_capture, &snd_usb_caiaq_pcm_hardware, sizeof(snd_usb_caiaq_pcm_hardware));
+
+	dev->pcm_info_playback.channels_min = CHANNELS_PER_STREAM;
+	dev->pcm_info_playback.channels_max = CHANNELS_PER_STREAM;
+
+	dev->pcm_info_capture.channels_min = CHANNELS_PER_STREAM;
+	dev->pcm_info_capture.channels_max = CHANNELS_PER_STREAM;
+	
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usb_caiaq_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usb_caiaq_capture_ops);
+
+	dev->pcm_sub_playback = NULL;
+	dev->pcm_sub_capture = NULL;
+	
+	snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+				      SNDRV_DMA_TYPE_CONTINUOUS,
+				      snd_dma_continuous_data(GFP_KERNEL),
+				      64*1024, 128*1024);
+
+	snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+				      SNDRV_DMA_TYPE_CONTINUOUS,
+				      snd_dma_continuous_data(GFP_KERNEL),
+				      64*1024, 128*1024);
+
+	dev->data_cb_info = (struct snd_usb_caiaq_cb_info *) 
+		kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, GFP_KERNEL);
+
+	if (!dev->data_cb_info)
+		return -ENOMEM;
+
+	for (i = 0; i < N_URBS; i++) {
+		dev->data_cb_info[i].dev = dev;
+		dev->data_cb_info[i].index = i;
+	}
+	
+	dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret);
+	if (ret < 0) {
+		free_urbs(dev->data_urbs_in);
+		return -ENOMEM;
+	}
+	
+	dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret);
+	if (ret < 0) {
+		free_urbs(dev->data_urbs_in);
+		free_urbs(dev->data_urbs_out);
+		return -ENOMEM;
+	}
+
+	INIT_WORK(&dev->stream_start_work, stream_start, dev);
+	INIT_WORK(&dev->stream_stop_work, stream_stop, dev);
+	INIT_WORK(&dev->stream_restart_work, stream_restart, dev);
+
+	return 0;
+}
+
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
+{
+	up(&dev->mutex);
+
+	cancel_delayed_work(&dev->stream_start_work);
+	cancel_delayed_work(&dev->stream_stop_work);
+	stream_stop(dev);
+
+	free_urbs(dev->data_urbs_in);
+	free_urbs(dev->data_urbs_out);
+
+	dev->data_urbs_in = NULL;
+	dev->data_urbs_out = NULL;
+	
+	if (dev->data_cb_info) {
+		kfree(dev->data_cb_info);
+		dev->data_cb_info = NULL;
+	}
+}
+
diff -Nur -x .svn orig/caiaq-audio.h alsa-kernel/usb/caiaq/caiaq-audio.h
--- orig/caiaq-audio.h	1970-01-01 01:00:00.000000000 +0100
+++ alsa-kernel/usb/caiaq/caiaq-audio.h	2006-04-05 15:36:29.000000000 +0200
@@ -0,0 +1,7 @@
+#ifndef CAIAQ_AUDIO_H
+#define CAIAQ_AUDIO_H
+
+int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev);
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev);
+
+#endif /* CAIAQ_AUDIO_H */
diff -Nur -x .svn orig/caiaq-device.c alsa-kernel/usb/caiaq/caiaq-device.c
--- orig/caiaq-device.c	1970-01-01 01:00:00.000000000 +0100
+++ alsa-kernel/usb/caiaq/caiaq-device.c	2006-04-05 15:35:21.000000000 +0200
@@ -0,0 +1,397 @@
+/*
+ * caiaq.c: ALSA driver for caiaq/NativeInstrument devices
+ *
+ *   Copyright (c) 2006 Daniel Mack
+ *
+ *   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; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/rawmidi.h>
+
+#include "caiaq-device.h"
+#include "caiaq-audio.h"
+#include "caiaq-midi.h"
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.org>");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.0.0");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{NI(0x17cc), (0x1969)(0x4711) }}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
+static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static int snd_card_used[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the caiaq sound device");
+
+enum {
+	SAMPLERATE_44100	= 0,
+	SAMPLERATE_48000	= 1,
+	SAMPLERATE_96000	= 2,
+	SAMPLERATE_192000	= 3,
+	SAMPLERATE_INVALID	= 0xff
+};
+
+enum {
+	DEPTH_NONE	= 0,
+	DEPTH_16	= 1,
+	DEPTH_24	= 2,
+	DEPTH_32	= 3
+};
+
+static struct usb_device_id snd_usb_id_table[] = {
+	{
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =	USB_PID_RIGKONTROL2 
+	},
+	{
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =	USB_PID_KORECONTROLLER
+	},
+	{ /* terminator */ }
+};
+
+static void usb_ep1_command_reply_dispatch (struct urb* urb, struct pt_regs *regs)
+{
+	struct snd_usb_caiaqdev *dev = (struct snd_usb_caiaqdev *) urb->context;
+	char *buf = urb->transfer_buffer;
+
+	if (urb->status != 0)
+		return;
+
+	switch(buf[0]) {
+	case EP1_CMD_GET_DEVICE_INFO:
+	{
+	 	memcpy(&dev->spec, buf+1, sizeof(struct caiaq_device_spec));
+		
+		debug("--- dumping spec ---\n");
+		debug(".............firmware version: 0x%04x\n", dev->spec.fw_version);
+		debug(".............hardware sub-type: %d\n", dev->spec.hw_subtype);
+		debug(".............num of ERP: %d\n", dev->spec.num_erp);
+		debug(".............num of analog inputs: %d\n", dev->spec.num_analog_in);
+		debug(".............num of digital inputs: %d\n", dev->spec.num_digital_in);
+		debug(".............num of digital outputs: %d\n", dev->spec.num_digital_out);
+		debug(".............num of analog audio outputs: %d\n", dev->spec.num_analog_audio_out);
+		debug(".............num of analog audio inputs: %d\n", dev->spec.num_analog_audio_in);
+		debug(".............num of digital audio outputs: %d\n", dev->spec.num_digital_audio_out);
+		debug(".............num of digital audio inputs: %d\n", dev->spec.num_digital_audio_in);
+		debug(".............num of MIDI out: %d\n", dev->spec.num_midi_out);
+		debug(".............num of MIDI in: %d\n", dev->spec.num_midi_in);
+		debug(".............data_alignment: %d\n", dev->spec.data_alignment);
+	
+		schedule_delayed_work(&dev->setup_work, 0);
+		break;
+	}
+	case EP1_CMD_AUDIO_PARAMS:
+		if (buf[1] != 1)
+			debug("unable to set the device's audio params\n");
+		break;
+	case EP1_CMD_MIDI_READ:
+		snd_usb_caiaq_midi_handle_input(dev, buf[1], &buf[3], buf[2]);
+		break;
+	}
+
+	dev->ep1_in_urb->actual_length = 0;
+	usb_submit_urb(dev->ep1_in_urb, GFP_KERNEL);
+}
+
+static int send_command (struct snd_usb_caiaqdev *dev,
+			 unsigned char command, 
+			 const unsigned char *buffer,
+			 int len)
+{
+	int ret, actual_len;
+	struct usb_device *usb_dev = dev->chip.dev;
+	char tmp[EP1_BUFSIZE];
+
+	if (!usb_dev)
+		return -EIO;
+
+	if (len > EP1_BUFSIZE - 1)
+		len = EP1_BUFSIZE - 1;
+
+	if (buffer && len > 0)
+		memcpy(tmp+1, buffer, len);
+	
+	tmp[0] = command;
+
+	ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1),
+			   tmp, len+1, &actual_len, 200);
+	
+	return ret;
+}
+
+int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev,
+		   		    int rate, int depth, int bbp)
+{
+	char tmp[5];
+	
+	switch (rate) {
+		case 44100:	tmp[0] = SAMPLERATE_44100;   break;
+		case 48000:	tmp[0] = SAMPLERATE_48000;   break;
+		case 96000:	tmp[0] = SAMPLERATE_96000;   break;
+		case 192000:	tmp[0] = SAMPLERATE_192000;  break;
+		default:	return -EINVAL;
+	}
+
+	switch (depth) {
+		case 16:	tmp[1] = DEPTH_16;   break;
+		case 24:	tmp[1] = DEPTH_24;   break;
+		default:	return -EINVAL;
+	}
+
+	tmp[2] = cpu_to_le16(bbp) & 0xff;
+	tmp[3] = cpu_to_le16(bbp) >> 8;
+	tmp[4] = 1; /* packets per microframe */
+
+	return send_command(dev, EP1_CMD_AUDIO_PARAMS, tmp, sizeof(tmp));
+}
+
+int snd_usb_caiaq_midi_send (struct snd_usb_caiaqdev *dev,
+			     int port, char *buf, int len)
+{
+	char tmp[EP1_BUFSIZE];
+
+	if (len > EP1_BUFSIZE-2) {
+		debug("warning! MIDI overflow!\n");
+		len = EP1_BUFSIZE-2;
+	}
+
+	tmp[0] = port;
+	memcpy(tmp+1, buf, len);
+	return send_command(dev, EP1_CMD_MIDI_WRITE, tmp, len+1);
+}
+
+static void setup_card(void *data)
+{
+	int ret;
+	struct snd_usb_caiaqdev *dev = (struct snd_usb_caiaqdev *) data;
+	struct usb_device *usb_dev = dev->chip.dev;
+	
+	/* device-specific startup specials: */
+	if (usb_dev->descriptor.idVendor == USB_VID_NATIVEINSTRUMENTS &&
+	    usb_dev->descriptor.idProduct == USB_PID_RIGKONTROL2) {
+		char val[3];
+		
+		/* RigKontrol2 - display centered dash ('-') */
+		val[0] = 0x00;
+		val[1] = 0x00;
+		val[2] = 0x01;
+		send_command(dev, EP1_CMD_WRITE_IO, val, 3);
+	}
+	
+	ret = snd_usb_caiaq_audio_init(dev);
+	if (ret != 0)
+		log("Unable to set up audio system (ret=%d)\n", ret);
+	
+	ret = snd_usb_caiaq_midi_init(dev);
+	if (ret != 0)
+		log("Unable to set up MIDI system (ret=%d)\n", ret);
+
+	/* finally, register the card and all its sub-instances */
+	ret = snd_card_register(dev->chip.card);
+	if (ret < 0) {
+		log("snd_card_register() returned %d\n", ret);
+		snd_card_free(dev->chip.card);
+	}
+}
+
+static struct snd_card* create_card(struct usb_device* usb_dev)
+{
+	int devnum;
+	struct snd_card *card;
+	struct snd_usb_caiaqdev *dev;
+
+	for (devnum = 0; devnum < SNDRV_CARDS; devnum++)
+		if (enable[devnum] && !snd_card_used[devnum])
+			break;
+
+	if (devnum >= SNDRV_CARDS)
+		return NULL;
+
+	card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(struct snd_usb_caiaqdev));
+	if (!card)
+		return NULL;
+
+	dev = caiaqdev(card);
+	
+	dev->chip.dev = usb_dev;
+	dev->chip.card = card;
+	init_MUTEX(&dev->mutex);
+	
+	snd_card_set_dev(card, &usb_dev->dev);
+
+	return card;
+}
+
+static int init_card(struct snd_usb_caiaqdev *dev)
+{
+	char *c;
+	struct usb_device *usb_dev = dev->chip.dev;
+	struct snd_card *card = dev->chip.card;
+	
+	if (usb_set_interface(usb_dev, 0, 1) != 0) {
+		log("can't set alt interface.\n");
+		return -EIO;
+	}
+
+	dev->ep1_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	dev->midi_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+	if (!dev->ep1_in_urb || !dev->midi_out_urb)
+		return -ENOMEM;
+
+	dev->ep1_in_buf = kmalloc(EP1_BUFSIZE, GFP_KERNEL);
+	dev->midi_out_buf = kmalloc(EP1_BUFSIZE, GFP_KERNEL);
+	
+	if (!dev->ep1_in_buf || !dev->midi_out_buf) {
+		usb_free_urb(dev->ep1_in_urb);
+		usb_free_urb(dev->midi_out_urb);
+		return -ENOMEM;
+	}
+
+	usb_fill_bulk_urb(dev->ep1_in_urb, usb_dev, usb_rcvbulkpipe(usb_dev, 0x1),
+			  dev->ep1_in_buf, EP1_BUFSIZE, usb_ep1_command_reply_dispatch, dev);
+
+	usb_fill_bulk_urb(dev->midi_out_urb, usb_dev, usb_sndbulkpipe(usb_dev, 0x1),
+			  dev->midi_out_buf, EP1_BUFSIZE, snd_usb_caiaq_midi_output_done, dev);
+	
+	if (usb_submit_urb(dev->ep1_in_urb, GFP_KERNEL) != 0)
+		return -EIO;
+
+	INIT_WORK(&dev->setup_work, setup_card, dev);
+	send_command(dev, EP1_CMD_GET_DEVICE_INFO, NULL, 0);
+
+	usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
+			dev->vendor_name, CAIAQ_USB_STR_LEN);
+	
+	usb_string(usb_dev, usb_dev->descriptor.iProduct,
+			dev->product_name, CAIAQ_USB_STR_LEN);
+	
+	usb_string(usb_dev, usb_dev->descriptor.iSerialNumber,
+			dev->serial, CAIAQ_USB_STR_LEN);
+
+	/* terminate serial string at first white space occurence */
+	c = strchr(dev->serial, ' ');
+	if (c)
+		*c = '\0';
+	
+	strcpy(card->driver, MODNAME);
+	strcpy(card->shortname, dev->product_name);
+	sprintf(card->longname, "%s %s (USB ID %04x/%04x, serial %s)", 
+			dev->vendor_name, dev->product_name,
+			usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct,
+			dev->serial);
+	
+	return 0;
+}
+
+static int snd_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	int ret;
+	struct snd_card *card;
+	struct usb_device *device = interface_to_usbdev(intf);
+	
+	card = create_card(device);
+	
+	if (!card)
+		return -EIO;
+			
+	dev_set_drvdata(&intf->dev, card);
+
+	ret = init_card(caiaqdev(card));
+	if (ret < 0) {
+		log("unable to init card! (ret=%d)\n", ret);
+		return ret;
+	}
+	
+	return 0;
+}
+
+static void snd_disconnect(struct usb_interface *intf)
+{
+	struct snd_usb_caiaqdev *dev;
+	void *ptr = dev_get_drvdata(&intf->dev);
+
+	debug("snd_disconnect(%p)\n", intf);
+
+	if (!ptr)
+		return;
+
+	dev = caiaqdev((struct snd_card*) ptr);
+
+	snd_usb_caiaq_audio_free(dev);
+	cancel_delayed_work(&dev->setup_work);
+
+	if (dev->ep1_in_urb) {
+		usb_kill_urb(dev->ep1_in_urb);
+		usb_free_urb(dev->ep1_in_urb);
+		dev->ep1_in_urb = NULL;
+	}
+	
+	if (dev->midi_out_urb) {
+		usb_kill_urb(dev->midi_out_urb);
+		usb_free_urb(dev->midi_out_urb);
+		dev->midi_out_urb = NULL;
+	}
+
+	if (dev->ep1_in_buf) {
+		kfree(dev->ep1_in_buf);
+		dev->ep1_in_buf = NULL;
+	}
+
+	if (dev->midi_out_buf) {
+		kfree(dev->midi_out_buf);
+		dev->midi_out_buf = NULL;
+	}
+
+	snd_card_free((struct snd_card*) ptr);
+}
+
+
+MODULE_DEVICE_TABLE(usb, snd_usb_id_table);
+static struct usb_driver snd_usb_driver = {
+ 	.owner 		= THIS_MODULE,
+	.name 		= MODNAME,
+	.probe 		= snd_probe,
+	.disconnect	= snd_disconnect,
+	.id_table 	= snd_usb_id_table,
+};
+
+static int __init snd_module_init(void)
+{
+	return usb_register(&snd_usb_driver);
+}
+
+static void __exit snd_module_exit(void)
+{
+	usb_deregister(&snd_usb_driver);
+}
+
+module_init(snd_module_init)
+module_exit(snd_module_exit)
+
diff -Nur -x .svn orig/caiaq-device.h alsa-kernel/usb/caiaq/caiaq-device.h
--- orig/caiaq-device.h	1970-01-01 01:00:00.000000000 +0100
+++ alsa-kernel/usb/caiaq/caiaq-device.h	2006-04-05 15:25:24.000000000 +0200
@@ -0,0 +1,111 @@
+#ifndef CAIAQ_DEVICE_H
+#define CAIAQ_DEVICE_H
+
+#include "../usbaudio.h"
+
+#define USB_VID_NATIVEINSTRUMENTS 0x17cc
+
+#define USB_PID_RIGKONTROL2	0x1969
+#define USB_PID_KORECONTROLLER 	0x4711
+
+#define EP1_BUFSIZE 64
+#define CAIAQ_USB_STR_LEN 0xff
+
+//#define	SND_USB_CAIAQ_DEBUG
+
+#define MODNAME "snd-usb-caiaq"
+#define log(x...) snd_printk(KERN_WARNING MODNAME" log: " x)
+
+#ifdef SND_USB_CAIAQ_DEBUG
+#define debug(x...) snd_printk(KERN_WARNING MODNAME " debug: " x)
+#else
+#define debug(x...)
+#endif
+
+#define EP1_CMD_GET_DEVICE_INFO	0x1
+#define EP1_CMD_WRITE_IO	0x5
+#define EP1_CMD_MIDI_READ	0x6
+#define EP1_CMD_MIDI_WRITE	0x7
+#define EP1_CMD_AUDIO_PARAMS	0x9
+
+struct caiaq_device_spec {
+	unsigned short fw_version;
+	unsigned char hw_subtype;
+	unsigned char num_erp;
+	unsigned char num_analog_in;
+	unsigned char num_digital_in;
+	unsigned char num_digital_out;
+	unsigned char num_analog_audio_out;
+	unsigned char num_analog_audio_in;
+	unsigned char num_digital_audio_out;
+	unsigned char num_digital_audio_in;
+	unsigned char num_midi_out;
+	unsigned char num_midi_in;
+	unsigned char data_alignment;
+} __attribute__ ((packed));
+
+struct snd_usb_caiaq_cb_info;
+
+struct snd_usb_caiaqdev {
+	struct snd_usb_audio chip;
+
+	struct urb *ep1_in_urb;
+	struct urb *midi_out_urb;
+	struct urb **data_urbs_in;
+	struct urb **data_urbs_out;
+
+	struct snd_usb_caiaq_cb_info *data_cb_info;
+	
+	unsigned char *ep1_in_buf;
+	unsigned char *midi_out_buf;
+
+	struct caiaq_device_spec spec;
+	struct work_struct setup_work;
+	struct work_struct stream_start_work;
+	struct work_struct stream_stop_work;
+	struct work_struct stream_restart_work;
+	struct semaphore mutex;
+	
+	int n_streams;
+	int n_audio_in, n_audio_out;
+	int streaming;
+	int stream_pitch;
+	
+	char vendor_name[CAIAQ_USB_STR_LEN];
+	char product_name[CAIAQ_USB_STR_LEN];
+	char serial[CAIAQ_USB_STR_LEN];
+
+	int audio_in_buf_pos;
+	int audio_out_buf_pos;
+
+	int period_in_count;
+	int period_out_count;
+
+	int input_panic;
+	int output_panic;
+	int first_packet;
+	
+	//ALSA
+	struct snd_pcm *pcm;
+	struct snd_pcm_substream *pcm_sub_playback;
+	struct snd_pcm_substream *pcm_sub_capture;
+	struct snd_pcm_hardware pcm_info_playback, pcm_info_capture;
+
+	struct snd_rawmidi *rmidi;
+	struct snd_rawmidi_substream *midi_receive_substream;
+
+	struct snd_rawmidi_substream *midi_out_substream;
+};
+
+struct snd_usb_caiaq_cb_info {
+	struct snd_usb_caiaqdev *dev;
+	int index;
+};
+
+#define caiaqdev(c) ((struct snd_usb_caiaqdev*)(c)->private_data)
+
+int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, int rate, int depth, int bbp);
+int snd_usb_caiaq_midi_send (struct snd_usb_caiaqdev *dev, int port, char *buf, int len);
+
+
+#endif /* CAIAQ_DEVICE_H */
diff -Nur -x .svn orig/caiaq-midi.c alsa-kernel/usb/caiaq/caiaq-midi.c
--- orig/caiaq-midi.c	1970-01-01 01:00:00.000000000 +0100
+++ alsa-kernel/usb/caiaq/caiaq-midi.c	2006-04-05 15:36:59.000000000 +0200
@@ -0,0 +1,165 @@
+/*
+ *   Copyright (c) 2006 Daniel Mack
+ *
+ *   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; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include <sound/pcm.h>
+
+#include "caiaq-device.h"
+#include "caiaq-midi.h"
+
+
+static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream * substream)
+{
+	return 0;
+}
+
+static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream * substream)
+{
+	return 0;
+}
+
+static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream * substream, int up)
+{
+	struct snd_usb_caiaqdev *dev = (struct snd_usb_caiaqdev *)
+		substream->rmidi->private_data;
+
+	if (!dev)
+		return;
+	
+	dev->midi_receive_substream = up ? substream : NULL;
+}
+
+
+static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream * substream)
+{
+	return 0;
+}
+
+static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream * substream)
+{
+	return 0;
+}
+
+static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream * substream, int up)
+{
+	int len, ret;
+	struct snd_usb_caiaqdev *dev = (struct snd_usb_caiaqdev *) 
+					substream->rmidi->private_data;
+	
+	if (dev->midi_out_substream != NULL)
+		return;
+	
+	if (!up) {
+		dev->midi_out_substream = NULL;
+		return;
+	}
+
+	dev->midi_out_substream = substream;
+	dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
+	dev->midi_out_buf[1] = 0; /* port */
+	len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3);
+	dev->midi_out_buf[2] = len;
+	dev->midi_out_urb->transfer_buffer_length = len+3;
+	
+	ret = usb_submit_urb(dev->midi_out_urb, GFP_ATOMIC);
+	if (ret < 0)
+		log("snd_usb_caiaq_midi_output_trigger(%p): usb_submit_urb() failed, %d\n",
+				substream, ret);
+	
+	debug("snd_usb_caiaq_midi_output_trigger(%p): sent %d bytes\n", substream, len);
+}
+
+
+static struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
+{
+	.open =		snd_usb_caiaq_midi_output_open,
+	.close =	snd_usb_caiaq_midi_output_close,
+	.trigger =      snd_usb_caiaq_midi_output_trigger,
+};
+
+static struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
+{
+	.open =		snd_usb_caiaq_midi_input_open,
+	.close =	snd_usb_caiaq_midi_input_close,
+	.trigger =      snd_usb_caiaq_midi_input_trigger,
+};
+
+void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len)
+{
+	if (!dev->midi_receive_substream)
+		return;
+	
+	snd_rawmidi_receive(dev->midi_receive_substream, buf, len);
+}
+
+int __devinit snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
+{
+	int ret;
+	struct snd_rawmidi *rmidi;
+
+	ret = snd_rawmidi_new(device->chip.card, device->product_name, 0,
+					device->spec.num_midi_out,
+					device->spec.num_midi_in,
+					&rmidi);
+
+	if (ret < 0)
+		return ret;
+
+	strcpy(rmidi->name, device->product_name);
+
+	rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
+	rmidi->private_data = device;
+
+	if (device->spec.num_midi_out > 0) {
+		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
+		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usb_caiaq_midi_output);
+	}
+
+	if (device->spec.num_midi_in > 0) {
+		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
+		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usb_caiaq_midi_input);
+	}
+	
+	device->rmidi = rmidi;
+
+	return 0;
+}
+
+void snd_usb_caiaq_midi_output_done(struct urb* urb, struct pt_regs *regs)
+{
+	struct snd_usb_caiaqdev *dev = (struct snd_usb_caiaqdev *) urb->context;
+      	char *buf = urb->transfer_buffer;
+	
+	if (urb->status != 0)
+		return;
+
+	if (!dev->midi_out_substream)
+		return;
+
+	snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]);
+	dev->midi_out_substream = NULL;
+}
+
diff -Nur -x .svn orig/caiaq-midi.h alsa-kernel/usb/caiaq/caiaq-midi.h
--- orig/caiaq-midi.h	1970-01-01 01:00:00.000000000 +0100
+++ alsa-kernel/usb/caiaq/caiaq-midi.h	2006-04-04 17:44:14.000000000 +0200
@@ -0,0 +1,8 @@
+#ifndef CAIAQ_MIDI_H
+#define CAIAQ_MIDI_H
+
+int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev);
+void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len);
+void snd_usb_caiaq_midi_output_done(struct urb* urb, struct pt_regs *regs);
+
+#endif /* CAIAQ_MIDI_H */
diff -Nur -x .svn orig/.cvsignore alsa-driver/usb/caiaq/.cvsignore
--- orig/.cvsignore	1970-01-01 01:00:00.000000000 +0100
+++ alsa-driver/usb/caiaq/.cvsignore	2006-04-05 14:54:42.000000000 +0200
@@ -0,0 +1,4 @@
+.depend
+.*.cmd
+*.ko
+*.mod.c
diff -Nur -x .svn orig/Makefile alsa-driver/usb/caiaq/Makefile
--- orig/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ alsa-driver/usb/caiaq/Makefile	2006-04-05 15:04:10.000000000 +0200
@@ -0,0 +1,19 @@
+ifndef SND_TOPDIR
+SND_TOPDIR=../..
+endif
+
+include $(SND_TOPDIR)/toplevel.config
+include $(SND_TOPDIR)/Makefile.conf
+
+clean-files := caiaq-device.c caiaq-audio.c caiaq-midi.c
+
+include $(SND_TOPDIR)/alsa-kernel/usb/caiaq/Makefile
+
+EXTRA_CFLAGS += -I$(SND_TOPDIR)/alsa-kernel/usb/caiaq
+
+include $(SND_TOPDIR)/Rules.make
+
+caiaq-device.c: $(SND_TOPDIR)/alsa-kernel/usb/caiaq/caiaq-device.c
+caiaq-audio.c: $(SND_TOPDIR)/alsa-kernel/usb/caiaq/caiaq-audio.c
+caiaq-midi.c: $(SND_TOPDIR)/alsa-kernel/usb/caiaq/caiaq-midi.c
+

^ permalink raw reply

* [U-Boot-Users] Re: [DNX#2006040542000037] [patch] Support IDE secondary disk without primary [...]
From: DENX Support System @ 2006-04-05 14:10 UTC (permalink / raw)
  To: u-boot

Hello list,

inside the automatic U-Boot patch tracking system a new ticket
[DNX#2006040542000037] was created:

<snip>
> Hello
> 
> Current u-boot does not search disks on secondary port if there is no
> disks
> on primary port.
> 
> this patch fixes this problem.
> 
> Signed-off-by: Hiroshi Ito <ito@mlb.co.jp>
> 
> CHANGELOG:
> 
> * Support IDE secondary disk without primary disk.
>   Patch by Hiroshi Ito, 5 Apr 2006
</snip>

Your U-Boot support team

^ permalink raw reply

* [U-Boot-Users] Re: [DNX#2006040542000037] [patch] Support IDE  [...]
From: U-Boot patch tracking system @ 2006-04-05 14:10 UTC (permalink / raw)
  To: u-boot

Dear Mr. U. Boot,

thank you for your contribution to the U-Boot project.

Your e-mail was registered at our system under the ticket
number [DNX#2006040542000037].

Your U-Boot support team

Powered by OTRS (http://otrs.org/)

^ permalink raw reply

* Re: [PATCH 12/15] powerpc: move asm/ocp_ids.h
From: Kumar Gala @ 2006-04-05 14:07 UTC (permalink / raw)
  To: sfr; +Cc: linuxppc-dev, paulus
In-Reply-To: <1144213870220-git-send-email-sfr@canb.auug.org.au>

Nack. OCP should not exist in arch/powerpc so leave this header where  
it is.

- k

On Apr 5, 2006, at 12:10 AM, sfr@canb.auug.org.au wrote:

> From: Stephen Rothwell <sfr@canb.auug.org.au>
>
> Since the ARCH=powerpc build depends on this file, move it to
> include/asm-powerpc.
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
>
> ---
>
>  include/asm-powerpc/ocp_ids.h |   75 ++++++++++++++++++++++++++++++ 
> +++++++++++
>  include/asm-ppc/ocp_ids.h     |   73  
> ----------------------------------------
>  2 files changed, 75 insertions(+), 73 deletions(-)
>  create mode 100644 include/asm-powerpc/ocp_ids.h
>  delete mode 100644 include/asm-ppc/ocp_ids.h
>
> a374f458829d868a3142bff918ef872e0ecff1a8
> diff --git a/include/asm-powerpc/ocp_ids.h b/include/asm-powerpc/ 
> ocp_ids.h
> new file mode 100644
> index 0000000..78e5906
> --- /dev/null
> +++ b/include/asm-powerpc/ocp_ids.h
> @@ -0,0 +1,75 @@
> +#ifndef _ASM_POWERPC_OCP_IDS_H
> +#define _ASM_POWERPC_OCP_IDS_H
> +/*
> + * OCP device ids based on the ideas from PCI
> + *
> + * The numbers below are almost completely arbitrary, and in fact
> + * strings might work better.  -- paulus
> + *
> + * 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;  either version 2 of the  License, or  
> (at your
> + * option) any later version.
> + */
> +
> +/*
> + * Vender  device
> + * [xxxx]  [xxxx]
> + *
> + *  Keep in order, please
> + */
> +
> +/* Vendor IDs 0x0001 - 0xFFFF copied from pci_ids.h */
> +
> +#define	OCP_VENDOR_INVALID	0x0000
> +#define	OCP_VENDOR_ARM		0x0004
> +#define OCP_VENDOR_FREESCALE	0x1057
> +#define OCP_VENDOR_IBM		0x1014
> +#define OCP_VENDOR_MOTOROLA	OCP_VENDOR_FREESCALE
> +#define	OCP_VENDOR_XILINX	0x10ee
> +#define	OCP_VENDOR_UNKNOWN	0xFFFF
> +
> +/* device identification */
> +
> +/* define type */
> +#define OCP_FUNC_INVALID	0x0000
> +
> +/* system 0x0001 - 0x001F */
> +
> +/* Timers 0x0020 - 0x002F */
> +
> +/* Serial 0x0030 - 0x006F*/
> +#define OCP_FUNC_16550		0x0031
> +#define OCP_FUNC_IIC		0x0032
> +#define OCP_FUNC_USB		0x0033
> +#define OCP_FUNC_PSC_UART	0x0034
> +
> +/* Memory devices 0x0090 - 0x009F */
> +#define OCP_FUNC_MAL		0x0090
> +#define OCP_FUNC_DMA		0x0091
> +
> +/* Display 0x00A0 - 0x00AF */
> +
> +/* Sound 0x00B0 - 0x00BF */
> +
> +/* Mass Storage 0x00C0 - 0xxCF */
> +#define OCP_FUNC_IDE		0x00C0
> +
> +/* Misc 0x00D0 - 0x00DF*/
> +#define OCP_FUNC_GPIO		0x00D0
> +#define OCP_FUNC_ZMII		0x00D1
> +#define OCP_FUNC_PERFMON	0x00D2	/* Performance Monitor */
> +#define OCP_FUNC_RGMII		0x00D3
> +#define OCP_FUNC_TAH		0x00D4
> +#define OCP_FUNC_SEC2		0x00D5	/* Crypto/Security 2.0 */
> +
> +/* Network 0x0200 - 0x02FF */
> +#define OCP_FUNC_EMAC		0x0200
> +#define OCP_FUNC_GFAR		0x0201	/* TSEC & FEC */
> +
> +/* Bridge devices 0xE00 - 0xEFF */
> +#define OCP_FUNC_OPB		0x0E00
> +
> +#define OCP_FUNC_UNKNOWN	0xFFFF
> +
> +#endif /* _ASM_POWERPC_OCP_IDS_H */
> diff --git a/include/asm-ppc/ocp_ids.h b/include/asm-ppc/ocp_ids.h
> deleted file mode 100644
> index 8ae4b31..0000000
> --- a/include/asm-ppc/ocp_ids.h
> +++ /dev/null
> @@ -1,73 +0,0 @@
> -/*
> - * ocp_ids.h
> - *
> - * OCP device ids based on the ideas from PCI
> - *
> - * The numbers below are almost completely arbitrary, and in fact
> - * strings might work better.  -- paulus
> - *
> - * 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;  either version 2 of the  License, or  
> (at your
> - * option) any later version.
> - */
> -
> -/*
> - * Vender  device
> - * [xxxx]  [xxxx]
> - *
> - *  Keep in order, please
> - */
> -
> -/* Vendor IDs 0x0001 - 0xFFFF copied from pci_ids.h */
> -
> -#define	OCP_VENDOR_INVALID	0x0000
> -#define	OCP_VENDOR_ARM		0x0004
> -#define OCP_VENDOR_FREESCALE	0x1057
> -#define OCP_VENDOR_IBM		0x1014
> -#define OCP_VENDOR_MOTOROLA	OCP_VENDOR_FREESCALE
> -#define	OCP_VENDOR_XILINX	0x10ee
> -#define	OCP_VENDOR_UNKNOWN	0xFFFF
> -
> -/* device identification */
> -
> -/* define type */
> -#define OCP_FUNC_INVALID	0x0000
> -
> -/* system 0x0001 - 0x001F */
> -
> -/* Timers 0x0020 - 0x002F */
> -
> -/* Serial 0x0030 - 0x006F*/
> -#define OCP_FUNC_16550		0x0031
> -#define OCP_FUNC_IIC		0x0032
> -#define OCP_FUNC_USB		0x0033
> -#define OCP_FUNC_PSC_UART	0x0034
> -
> -/* Memory devices 0x0090 - 0x009F */
> -#define OCP_FUNC_MAL		0x0090
> -#define OCP_FUNC_DMA		0x0091
> -
> -/* Display 0x00A0 - 0x00AF */
> -
> -/* Sound 0x00B0 - 0x00BF */
> -
> -/* Mass Storage 0x00C0 - 0xxCF */
> -#define OCP_FUNC_IDE		0x00C0
> -
> -/* Misc 0x00D0 - 0x00DF*/
> -#define OCP_FUNC_GPIO		0x00D0
> -#define OCP_FUNC_ZMII		0x00D1
> -#define OCP_FUNC_PERFMON	0x00D2	/* Performance Monitor */
> -#define OCP_FUNC_RGMII		0x00D3
> -#define OCP_FUNC_TAH		0x00D4
> -#define OCP_FUNC_SEC2		0x00D5	/* Crypto/Security 2.0 */
> -
> -/* Network 0x0200 - 0x02FF */
> -#define OCP_FUNC_EMAC		0x0200
> -#define OCP_FUNC_GFAR		0x0201	/* TSEC & FEC */
> -
> -/* Bridge devices 0xE00 - 0xEFF */
> -#define OCP_FUNC_OPB		0x0E00
> -
> -#define OCP_FUNC_UNKNOWN	0xFFFF
> -- 
> 1.2.4
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 11/15] powerpc: move asm/ocp.h
From: Kumar Gala @ 2006-04-05 14:07 UTC (permalink / raw)
  To: sfr; +Cc: linuxppc-dev, paulus
In-Reply-To: <1144213868772-git-send-email-sfr@canb.auug.org.au>

Nack. OCP should not exist in arch/powerpc so leave this header where  
it is.

- k

On Apr 5, 2006, at 12:10 AM, sfr@canb.auug.org.au wrote:

> From: Stephen Rothwell <sfr@canb.auug.org.au>
>
> Since the ARCH=powerpc build depends on this file, move it to
> include/asm-powerpc.
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
>
> ---
>
>  include/asm-powerpc/ocp.h |  206 ++++++++++++++++++++++++++++++++++ 
> +++++++++++
>  include/asm-ppc/ocp.h     |  207  
> ---------------------------------------------
>  2 files changed, 206 insertions(+), 207 deletions(-)
>  create mode 100644 include/asm-powerpc/ocp.h
>  delete mode 100644 include/asm-ppc/ocp.h
>
> c7b417812dc2ebece32356c0a5e93966de9ba2cd
> diff --git a/include/asm-powerpc/ocp.h b/include/asm-powerpc/ocp.h
> new file mode 100644
> index 0000000..8916c52
> --- /dev/null
> +++ b/include/asm-powerpc/ocp.h
> @@ -0,0 +1,206 @@
> +#ifndef _ASM_POWERPC_OCP_H
> +#define _ASM_POWERPC_OCP_H
> +/*
> + * ocp.h
> + *
> + *      (c) Benjamin Herrenschmidt (benh@kernel.crashing.org)
> + *          Mipsys - France
> + *
> + *          Derived from work (c) Armin Kuster akuster@pacbell.net
> + *
> + *          Additional support and port to 2.6 LDM/sysfs by
> + *          Matt Porter <mporter@kernel.crashing.org>
> + *          Copyright 2003-2004 MontaVista Software, Inc.
> + *
> + * 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;  either version 2 of the  License, or  
> (at your
> + * option) any later version.
> + *
> + *  TODO: - Add get/put interface & fixup locking to provide same  
> API for
> + *          2.4 and 2.5
> + *	  - Rework PM callbacks
> + */
> +
> +#ifdef __KERNEL__
> +
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/devfs_fs_kernel.h>
> +#include <linux/device.h>
> +
> +#include <asm/mmu.h>
> +#include <asm/ocp_ids.h>
> +#include <asm/rwsem.h>
> +#include <asm/semaphore.h>
> +
> +#ifdef CONFIG_PPC_OCP
> +
> +#define OCP_MAX_IRQS	7
> +#define MAX_EMACS	4
> +#define OCP_IRQ_NA	-1	/* used when ocp device does not have an irq */
> +#define OCP_IRQ_MUL	-2	/* used for ocp devices with multiply irqs */
> +#define OCP_NULL_TYPE	-1	/* used to mark end of list */
> +#define OCP_CPM_NA	0	/* No Clock or Power Management avaliable */
> +#define OCP_PADDR_NA	0	/* No MMIO registers */
> +
> +#define OCP_ANY_ID	(~0)
> +#define OCP_ANY_INDEX	-1
> +
> +extern struct list_head 	ocp_devices;
> +extern struct rw_semaphore	ocp_devices_sem;
> +
> +struct ocp_device_id {
> +	unsigned int	vendor, function;	/* Vendor and function ID or  
> OCP_ANY_ID */
> +	unsigned long	driver_data;		/* Data private to the driver */
> +};
> +
> +
> +/*
> + * Static definition of an OCP device.
> + *
> + * @vendor:    Vendor code. It is _STRONGLY_ discouraged to use
> + *             the vendor code as a way to match a unique device,
> + *             though I kept that possibility open, you should
> + *             really define different function codes for different
> + *             device types
> + * @function:  This is the function code for this device.
> + * @index:     This index is used for mapping the Nth function of a
> + *             given core. This is typically used for cross-driver
> + *             matching, like looking for a given MAL or ZMII from
> + *             an EMAC or for getting to the proper set of DCRs.
> + *             Indices are no longer magically calculated based on
> + *             structure ordering, they have to be actually coded
> + *             into the ocp_def to avoid any possible confusion
> + *             I _STRONGLY_ (again ? wow !) encourage anybody relying
> + *             on index mapping to encode the "target" index in an
> + *             associated structure pointed to by "additions", see
> + *             how it's done for the EMAC driver.
> + * @paddr:     Device physical address (may not mean anything...)
> + * @irq:       Interrupt line for this device (TODO: think about  
> making
> + *             an array with this)
> + * @pm:        Currently, contains the bitmask in CPMFR DCR for  
> the device
> + * @additions: Optionally points to a function specific structure
> + *             providing additional informations for a given device
> + *             instance. It's currently used by the EMAC driver  
> for MAL
> + *             channel & ZMII port mapping among others.
> + * @show:      Optionally points to a function specific structure
> + *             providing a sysfs show routine for additions fields.
> + */
> +struct ocp_def {
> +	unsigned int	vendor;
> +	unsigned int	function;
> +	int		index;
> +	phys_addr_t	paddr;
> +	int	  	irq;
> +	unsigned long	pm;
> +	void		*additions;
> +	void		(*show)(struct device *);
> +};
> +
> +
> +/* Struct for a given device instance */
> +struct ocp_device {
> +	struct list_head	link;
> +	char			name[80];	/* device name */
> +	struct ocp_def		*def;		/* device definition */
> +	void			*drvdata;	/* driver data for this device */
> +	struct ocp_driver	*driver;
> +	u32			current_state;	/* Current operating state. In ACPI-speak,
> +						   this is D0-D3, D0 being fully functional,
> +						   and D3 being off. */
> +	struct			device dev;
> +};
> +
> +struct ocp_driver {
> +	struct list_head node;
> +	char *name;
> +	const struct ocp_device_id *id_table;	/* NULL if wants all  
> devices */
> +	int  (*probe)  (struct ocp_device *dev);	/* New device inserted */
> +	void (*remove) (struct ocp_device *dev);	/* Device removed (NULL  
> if not a hot-plug capable driver) */
> +	int  (*suspend) (struct ocp_device *dev, pm_message_t state);	/*  
> Device suspended */
> +	int  (*resume) (struct ocp_device *dev);	                /*  
> Device woken up */
> +	struct device_driver driver;
> +};
> +
> +#define to_ocp_dev(n) container_of(n, struct ocp_device, dev)
> +#define to_ocp_drv(n) container_of(n, struct ocp_driver, driver)
> +
> +/* Similar to the helpers above, these manipulate per-ocp_dev
> + * driver-specific data.  Currently stored as ocp_dev::ocpdev,
> + * a void pointer, but it is not present on older kernels.
> + */
> +static inline void *
> +ocp_get_drvdata(struct ocp_device *pdev)
> +{
> +	return pdev->drvdata;
> +}
> +
> +static inline void
> +ocp_set_drvdata(struct ocp_device *pdev, void *data)
> +{
> +	pdev->drvdata = data;
> +}
> +
> +#if defined (CONFIG_PM)
> +/*
> + * This is right for the IBM 405 and 440 but will need to be
> + * generalized if the OCP stuff gets used on other processors.
> + */
> +static inline void
> +ocp_force_power_off(struct ocp_device *odev)
> +{
> +	mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | odev->def->pm);
> +}
> +
> +static inline void
> +ocp_force_power_on(struct ocp_device *odev)
> +{
> +	mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~odev->def->pm);
> +}
> +#else
> +#define ocp_force_power_off(x)	(void)(x)
> +#define ocp_force_power_on(x)	(void)(x)
> +#endif
> +
> +/* Register/Unregister an OCP driver */
> +extern int ocp_register_driver(struct ocp_driver *drv);
> +extern void ocp_unregister_driver(struct ocp_driver *drv);
> +
> +/* Build list of devices */
> +extern int ocp_early_init(void) __init;
> +
> +/* Find a device by index */
> +extern struct ocp_device *ocp_find_device(unsigned int vendor,  
> unsigned int function, int index);
> +
> +/* Get a def by index */
> +extern struct ocp_def *ocp_get_one_device(unsigned int vendor,  
> unsigned int function, int index);
> +
> +/* Add a device by index */
> +extern int ocp_add_one_device(struct ocp_def *def);
> +
> +/* Remove a device by index */
> +extern int ocp_remove_one_device(unsigned int vendor, unsigned int  
> function, int index);
> +
> +/* Iterate over devices and execute a routine */
> +extern void ocp_for_each_device(void(*callback)(struct ocp_device  
> *, void *arg), void *arg);
> +
> +/* Sysfs support */
> +#define OCP_SYSFS_ADDTL(type, format, name, field)			\
> +static ssize_t								\
> +show_##name##_##field(struct device *dev, struct device_attribute  
> *attr, char *buf)			\
> +{									\
> +	struct ocp_device *odev = to_ocp_dev(dev);			\
> +	type *add = odev->def->additions;				\
> +									\
> +	return sprintf(buf, format, add->field);			\
> +}									\
> +static DEVICE_ATTR(name##_##field, S_IRUGO, show_##name##_##field,  
> NULL);
> +
> +#ifdef CONFIG_IBM_OCP
> +#include <asm/ibm_ocp.h>
> +#endif
> +
> +#endif				/* CONFIG_PPC_OCP */
> +#endif				/* __KERNEL__ */
> +#endif /* _ASM_POWERPC_OCP_H */
> diff --git a/include/asm-ppc/ocp.h b/include/asm-ppc/ocp.h
> deleted file mode 100644
> index 983116f..0000000
> --- a/include/asm-ppc/ocp.h
> +++ /dev/null
> @@ -1,207 +0,0 @@
> -/*
> - * ocp.h
> - *
> - *      (c) Benjamin Herrenschmidt (benh@kernel.crashing.org)
> - *          Mipsys - France
> - *
> - *          Derived from work (c) Armin Kuster akuster@pacbell.net
> - *
> - *          Additional support and port to 2.6 LDM/sysfs by
> - *          Matt Porter <mporter@kernel.crashing.org>
> - *          Copyright 2003-2004 MontaVista Software, Inc.
> - *
> - * 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;  either version 2 of the  License, or  
> (at your
> - * option) any later version.
> - *
> - *  TODO: - Add get/put interface & fixup locking to provide same  
> API for
> - *          2.4 and 2.5
> - *	  - Rework PM callbacks
> - */
> -
> -#ifdef __KERNEL__
> -#ifndef __OCP_H__
> -#define __OCP_H__
> -
> -#include <linux/init.h>
> -#include <linux/list.h>
> -#include <linux/config.h>
> -#include <linux/devfs_fs_kernel.h>
> -#include <linux/device.h>
> -
> -#include <asm/mmu.h>
> -#include <asm/ocp_ids.h>
> -#include <asm/rwsem.h>
> -#include <asm/semaphore.h>
> -
> -#ifdef CONFIG_PPC_OCP
> -
> -#define OCP_MAX_IRQS	7
> -#define MAX_EMACS	4
> -#define OCP_IRQ_NA	-1	/* used when ocp device does not have an irq */
> -#define OCP_IRQ_MUL	-2	/* used for ocp devices with multiply irqs */
> -#define OCP_NULL_TYPE	-1	/* used to mark end of list */
> -#define OCP_CPM_NA	0	/* No Clock or Power Management avaliable */
> -#define OCP_PADDR_NA	0	/* No MMIO registers */
> -
> -#define OCP_ANY_ID	(~0)
> -#define OCP_ANY_INDEX	-1
> -
> -extern struct list_head 	ocp_devices;
> -extern struct rw_semaphore	ocp_devices_sem;
> -
> -struct ocp_device_id {
> -	unsigned int	vendor, function;	/* Vendor and function ID or  
> OCP_ANY_ID */
> -	unsigned long	driver_data;		/* Data private to the driver */
> -};
> -
> -
> -/*
> - * Static definition of an OCP device.
> - *
> - * @vendor:    Vendor code. It is _STRONGLY_ discouraged to use
> - *             the vendor code as a way to match a unique device,
> - *             though I kept that possibility open, you should
> - *             really define different function codes for different
> - *             device types
> - * @function:  This is the function code for this device.
> - * @index:     This index is used for mapping the Nth function of a
> - *             given core. This is typically used for cross-driver
> - *             matching, like looking for a given MAL or ZMII from
> - *             an EMAC or for getting to the proper set of DCRs.
> - *             Indices are no longer magically calculated based on
> - *             structure ordering, they have to be actually coded
> - *             into the ocp_def to avoid any possible confusion
> - *             I _STRONGLY_ (again ? wow !) encourage anybody relying
> - *             on index mapping to encode the "target" index in an
> - *             associated structure pointed to by "additions", see
> - *             how it's done for the EMAC driver.
> - * @paddr:     Device physical address (may not mean anything...)
> - * @irq:       Interrupt line for this device (TODO: think about  
> making
> - *             an array with this)
> - * @pm:        Currently, contains the bitmask in CPMFR DCR for  
> the device
> - * @additions: Optionally points to a function specific structure
> - *             providing additional informations for a given device
> - *             instance. It's currently used by the EMAC driver  
> for MAL
> - *             channel & ZMII port mapping among others.
> - * @show:      Optionally points to a function specific structure
> - *             providing a sysfs show routine for additions fields.
> - */
> -struct ocp_def {
> -	unsigned int	vendor;
> -	unsigned int	function;
> -	int		index;
> -	phys_addr_t	paddr;
> -	int	  	irq;
> -	unsigned long	pm;
> -	void		*additions;
> -	void		(*show)(struct device *);
> -};
> -
> -
> -/* Struct for a given device instance */
> -struct ocp_device {
> -	struct list_head	link;
> -	char			name[80];	/* device name */
> -	struct ocp_def		*def;		/* device definition */
> -	void			*drvdata;	/* driver data for this device */
> -	struct ocp_driver	*driver;
> -	u32			current_state;	/* Current operating state. In ACPI-speak,
> -						   this is D0-D3, D0 being fully functional,
> -						   and D3 being off. */
> -	struct			device dev;
> -};
> -
> -struct ocp_driver {
> -	struct list_head node;
> -	char *name;
> -	const struct ocp_device_id *id_table;	/* NULL if wants all  
> devices */
> -	int  (*probe)  (struct ocp_device *dev);	/* New device inserted */
> -	void (*remove) (struct ocp_device *dev);	/* Device removed (NULL  
> if not a hot-plug capable driver) */
> -	int  (*suspend) (struct ocp_device *dev, pm_message_t state);	/*  
> Device suspended */
> -	int  (*resume) (struct ocp_device *dev);	                /*  
> Device woken up */
> -	struct device_driver driver;
> -};
> -
> -#define to_ocp_dev(n) container_of(n, struct ocp_device, dev)
> -#define to_ocp_drv(n) container_of(n, struct ocp_driver, driver)
> -
> -/* Similar to the helpers above, these manipulate per-ocp_dev
> - * driver-specific data.  Currently stored as ocp_dev::ocpdev,
> - * a void pointer, but it is not present on older kernels.
> - */
> -static inline void *
> -ocp_get_drvdata(struct ocp_device *pdev)
> -{
> -	return pdev->drvdata;
> -}
> -
> -static inline void
> -ocp_set_drvdata(struct ocp_device *pdev, void *data)
> -{
> -	pdev->drvdata = data;
> -}
> -
> -#if defined (CONFIG_PM)
> -/*
> - * This is right for the IBM 405 and 440 but will need to be
> - * generalized if the OCP stuff gets used on other processors.
> - */
> -static inline void
> -ocp_force_power_off(struct ocp_device *odev)
> -{
> -	mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | odev->def->pm);
> -}
> -
> -static inline void
> -ocp_force_power_on(struct ocp_device *odev)
> -{
> -	mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~odev->def->pm);
> -}
> -#else
> -#define ocp_force_power_off(x)	(void)(x)
> -#define ocp_force_power_on(x)	(void)(x)
> -#endif
> -
> -/* Register/Unregister an OCP driver */
> -extern int ocp_register_driver(struct ocp_driver *drv);
> -extern void ocp_unregister_driver(struct ocp_driver *drv);
> -
> -/* Build list of devices */
> -extern int ocp_early_init(void) __init;
> -
> -/* Find a device by index */
> -extern struct ocp_device *ocp_find_device(unsigned int vendor,  
> unsigned int function, int index);
> -
> -/* Get a def by index */
> -extern struct ocp_def *ocp_get_one_device(unsigned int vendor,  
> unsigned int function, int index);
> -
> -/* Add a device by index */
> -extern int ocp_add_one_device(struct ocp_def *def);
> -
> -/* Remove a device by index */
> -extern int ocp_remove_one_device(unsigned int vendor, unsigned int  
> function, int index);
> -
> -/* Iterate over devices and execute a routine */
> -extern void ocp_for_each_device(void(*callback)(struct ocp_device  
> *, void *arg), void *arg);
> -
> -/* Sysfs support */
> -#define OCP_SYSFS_ADDTL(type, format, name, field)			\
> -static ssize_t								\
> -show_##name##_##field(struct device *dev, struct device_attribute  
> *attr, char *buf)			\
> -{									\
> -	struct ocp_device *odev = to_ocp_dev(dev);			\
> -	type *add = odev->def->additions;				\
> -									\
> -	return sprintf(buf, format, add->field);			\
> -}									\
> -static DEVICE_ATTR(name##_##field, S_IRUGO, show_##name##_##field,  
> NULL);
> -
> -#ifdef CONFIG_IBM_OCP
> -#include <asm/ibm_ocp.h>
> -#endif
> -
> -#endif				/* CONFIG_PPC_OCP */
> -#endif				/* __OCP_H__ */
> -#endif				/* __KERNEL__ */
> -- 
> 1.2.4
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* RE: Does dom0 see all physical processors? (RE:[Xen-ia64-devel] SAL INFO virtualization)
From: Magenheimer, Dan (HP Labs Fort Collins) @ 2006-04-05 14:07 UTC (permalink / raw)
  To: Ian Pratt, Keir Fraser, Tian, Kevin
  Cc: Jimi Xenidis, xen-devel, okrieg, Tristan Gingold, xen-ia64-devel

(Orran/Jimi cc'ed, see question below...)

> > I understand and sympathize with the need for dom0 to 
> > sometimes get and use information from each processor that is 
> > only available if dom0 is running on each processor.
> > 
> > However, AFAIK, SMP guests are always gang-scheduled, correct?
> 
> No, there's no need to strictly gang schedule, and the 
> current scheduler makes no attempt to do so. It may generally 
> be a decent thing to do, though.
> 
> > (If not, aren't there some very knotty research issues 
> > related to locking and forward progress?)
> 
> You could end up preempting a vCPU holding a lock which could 
> lead to daft behaviour of naïve spin locks. A number of 
> possible workarounds have been prototyped, but since it 
> doesn't seem to be much of a problem in practice nothing has 
> been checked in.

I wonder if "not a problem in practice" is more of an indication
of lack of practice than lack of problem.  I can see that the
problem would be unlikely to occur with small numbers of
processors and one SMP guests running a highly scalable SMP app
(such as a web server), but I'll bet a real enterprise load
of home-grown SMP apps running in a IT shop that's had big SMP
boxes for years would see the problem more quickly, especially
after multiple SMP guests are consolidated onto a single box.

I believe ppc has "paravirtualized spinlocks" in their Linux
kernel, though even this won't necessarily help with a poorly
written SMP application.

No data, admittedly, but perhaps our good buddies at
Watson could comment?

> > So on a 16-processor system, every time dom0 needs to run 
> > (e.g. to handle backend I/O for any one of perhaps hundreds 
> > of domains), *every* domain gets descheduled so that dom0 can 
> > be (gang-)scheduled on all 16 processors?
> > 
> > If true, this sounds like a _horrible_ performance hit, so I 
> > hope I'm misunderstanding something...
> 
> This isn't an issue.
> 
> After booting you probably want dom0 to give up all but 1 vCPU anyway.

Unless of course the PCPU's have data that change over time, such
as variable cycle rate (for power management) or hot-plug memory...
 
> Ian
>

Dan

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.