* "lseek/write char driver" versus "usermode iomem access"
From: Josef Angermeier @ 2006-03-29 8:22 UTC (permalink / raw)
To: linuxppc-embedded
Hello,
besides adapting linux to my custom board, i now have to write a driver
for a special device. This device mainly consists of an up to 512 bytes
big IO memory. Because performance matters alot, i wonder if i shall
write a simple char driver offering a write/lseek-interface to access
this memory or if i shall do something new to me, mapping the IO-memory
to the userspace, so that the user-program can directly access the
device memory. Can anyone tell me how performance probably differs
between those two design.
Thanks, you probably save me alot of time to tryout!
Josef
^ permalink raw reply
* Re: linux-2.6-rt patch on ppc and OOM messages
From: Kumar Gala @ 2006-03-29 7:39 UTC (permalink / raw)
To: emre kara; +Cc: linuxppc-dev
In-Reply-To: <20060329064551.29548.qmail@web25913.mail.ukl.yahoo.com>
On Mar 29, 2006, at 12:45 AM, emre kara wrote:
> Dear All,
> Is Ingo Molnar's realtime-preempt patch compatible
> with ppc, or is there any work on a porting effort of
> this patch ? I have made some tests on a 85xx machine
> with this patch, under heavy load on ethernet
> interfaces, thw system prints OOM messages on console
> and hangs..
> Thanks.
Can you try setting the gfar interrupts to SA_INTERRUPT and see what =20
happens.
- k
> --------------------------console output-----
> softirq-net-rx/: page allocation failure. order:0,
> mode:0x20
> Call Trace:
> [C04E3DB0] [C000A60C] show_stack+0x50/0x188
> (unreliable)
> [C04E3DE0] [C004C3EC] __alloc_pages+0x1c8/0x2a4
> [C04E3E30] [C0063C90] cache_alloc_refill+0x35c/0x57c
> [C04E3E80] [C0063FA4] __kmalloc+0xf4/0xfc
> [C04E3EB0] [C012D460] __alloc_skb+0x58/0x118
> [C04E3ED0] [C011AF20] gfar_new_skb+0x40/0xd4
> [C04E3EF0] [C011D320] gfar_clean_rx_ring+0x25c/0x634
> [C04E3F30] [C011D72C] gfar_poll+0x34/0x140
> [C04E3F50] [C013364C] net_rx_action+0x94/0x188
> [C04E3F80] [C0026730] ksoftirqd+0x104/0x1b4
> [C04E3FC0] [C003779C] kthread+0xf8/0x100
> [C04E3FF0] [C0004DB8] kernel_thread+0x44/0x60
> Mem-info:
> DMA per-cpu:
> cpu 0 hot: high 90, batch 15 used:0
> cpu 0 cold: high 30, batch 7 used:0
> DMA32 per-cpu: empty
> Normal per-cpu: empty
> HighMem per-cpu: empty
> Free pages: 768kB (0kB HighMem)
> Active:1650 inactive:2036 dirty:0 writeback:0
> unstable:0 free:192
> slab:60106 mapped:764 pagetables:29
> DMA free:768kB min:2048kB low:2560kB high:3072kB
> active:6600kB
> inactive:8144kB present:262144kB pages_scanned:0
> all_unreclaimab
> le? no
> lowmem_reserve[]: 0 0 0 0
> DMA32 free:0kB min:0kB low:0kB high:0kB active:0kB
> inactive:0kB
> present:0kB pages_scanned:0 all_unreclaimable? no
> lowmem_reserve[]: 0 0 0 0
> Normal free:0kB min:0kB low:0kB high:0kB active:0kB
> inactive:0kB
> present:0kB pages_scanned:0 all_unreclaimable? no
> lowmem_reserve[]: 0 0 0 0
> HighMem free:0kB min:128kB low:128kB high:128kB
> active:0kB
> inactive:0kB present:0kB pages_scanned:0
> all_unreclaimable? no
> lowmem_reserve[]: 0 0 0 0
> DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 1*256kB
> 1*512kB 0*1024kB
> 0*2048kB 0*4096kB =3D 768kB
> DMA32: empty
> Normal: empty
> HighMem: empty
> Swap cache: add 0, delete 0, find 0/0, race 0+0
> Free swap =3D 0kB
> Total swap =3D 0kB
> Free swap: 0kB
> 65536 pages of RAM
> 0 pages of HIGHMEM
> 662 free pages
> 1180 reserved pages
> 1249 pages shared
> 0 pages swap cached
> printk: 2159030 messages suppressed.
>
>
>
> =09
> ___________________________________________________________
> Yahoo! Photos =96 NEW, now offering a quality print service from just =20=
> 8p a photo http://uk.photos.yahoo.com
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* linux-2.6-rt patch on ppc and OOM messages
From: emre kara @ 2006-03-29 6:45 UTC (permalink / raw)
To: linuxppc-dev
Dear All,
Is Ingo Molnar's realtime-preempt patch compatible
with ppc, or is there any work on a porting effort of
this patch ? I have made some tests on a 85xx machine
with this patch, under heavy load on ethernet
interfaces, thw system prints OOM messages on console
and hangs..
Thanks.
--------------------------console output-----
softirq-net-rx/: page allocation failure. order:0,
mode:0x20
Call Trace:
[C04E3DB0] [C000A60C] show_stack+0x50/0x188
(unreliable)
[C04E3DE0] [C004C3EC] __alloc_pages+0x1c8/0x2a4
[C04E3E30] [C0063C90] cache_alloc_refill+0x35c/0x57c
[C04E3E80] [C0063FA4] __kmalloc+0xf4/0xfc
[C04E3EB0] [C012D460] __alloc_skb+0x58/0x118
[C04E3ED0] [C011AF20] gfar_new_skb+0x40/0xd4
[C04E3EF0] [C011D320] gfar_clean_rx_ring+0x25c/0x634
[C04E3F30] [C011D72C] gfar_poll+0x34/0x140
[C04E3F50] [C013364C] net_rx_action+0x94/0x188
[C04E3F80] [C0026730] ksoftirqd+0x104/0x1b4
[C04E3FC0] [C003779C] kthread+0xf8/0x100
[C04E3FF0] [C0004DB8] kernel_thread+0x44/0x60
Mem-info:
DMA per-cpu:
cpu 0 hot: high 90, batch 15 used:0
cpu 0 cold: high 30, batch 7 used:0
DMA32 per-cpu: empty
Normal per-cpu: empty
HighMem per-cpu: empty
Free pages: 768kB (0kB HighMem)
Active:1650 inactive:2036 dirty:0 writeback:0
unstable:0 free:192
slab:60106 mapped:764 pagetables:29
DMA free:768kB min:2048kB low:2560kB high:3072kB
active:6600kB
inactive:8144kB present:262144kB pages_scanned:0
all_unreclaimab
le? no
lowmem_reserve[]: 0 0 0 0
DMA32 free:0kB min:0kB low:0kB high:0kB active:0kB
inactive:0kB
present:0kB pages_scanned:0 all_unreclaimable? no
lowmem_reserve[]: 0 0 0 0
Normal free:0kB min:0kB low:0kB high:0kB active:0kB
inactive:0kB
present:0kB pages_scanned:0 all_unreclaimable? no
lowmem_reserve[]: 0 0 0 0
HighMem free:0kB min:128kB low:128kB high:128kB
active:0kB
inactive:0kB present:0kB pages_scanned:0
all_unreclaimable? no
lowmem_reserve[]: 0 0 0 0
DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 1*256kB
1*512kB 0*1024kB
0*2048kB 0*4096kB = 768kB
DMA32: empty
Normal: empty
HighMem: empty
Swap cache: add 0, delete 0, find 0/0, race 0+0
Free swap = 0kB
Total swap = 0kB
Free swap: 0kB
65536 pages of RAM
0 pages of HIGHMEM
662 free pages
1180 reserved pages
1249 pages shared
0 pages swap cached
printk: 2159030 messages suppressed.
___________________________________________________________
Yahoo! Photos NEW, now offering a quality print service from just 8p a photo http://uk.photos.yahoo.com
^ permalink raw reply
* Re: [OT] ppc64 serialization problem
From: Benjamin Herrenschmidt @ 2006-03-29 4:21 UTC (permalink / raw)
To: Greg Smith; +Cc: linuxppc-dev
In-Reply-To: <1143605294.3075.87.camel@localhost.localdomain>
On Tue, 2006-03-28 at 23:08 -0500, Greg Smith wrote:
> Very fair questions!!
>
> Actually the code was
>
> pthread_mutex_lock(&lock);
> u32 |= bitB;
> TRACE("A", u32, ...);
> TRACE("B", u32, ...);
> pthread_mutex_unlock(&lock);
>
> where TRACE is a function call (entering a trace entry to an in-storage
> wrap-around table). So for the "A" call, u32 could have come directly
> from a register and for "B" from the storage location. I'll have the
> user (actually a fellow developer) send me the assembly listing to make
> sure.
Could you try to make a small program that reproduces the problem
instead ?
> He has tested SLES9 (kernel 2.6.5, glibc 2.3.3, gcc 3.3.3) and Debian
> (kernel 2.6.16, glibc 2.3.6, gcc 4.0.3).
>
> The TRACE occurs while the lock is held.
>
> Now the interesting part.
>
> I suggested he try u64 instead of u32. That works!!
>
> He is suspecting a recent firmware upgrade may have something to do with
> the problem.
I doubt it, but I need more informations.
> Thank you,
> Greg Smith
>
> On Wed, 2006-03-29 at 14:11 +1100, Benjamin Herrenschmidt wrote:
> > On Tue, 2006-03-28 at 20:58 -0500, Greg Smith wrote:
> > > We have a multi-threaded app running on a p520 in 64 bit mode.
> > >
> > > Thread A does
> > >
> > > pthread_mutex_lock(&lock);
> > > u32 &= ~bitA;
> > > pthread_mutex_unlock(&lock);
> > >
> > > and Thread B does
> > >
> > > pthread_mutex_lock(&lock);
> > > u32 |= bitB;
> > > A = u32;
> > > B = u32;
> > > pthread_mutex_unlock(&lock);
> > >
> > > On rare occasions, values A and B will differ! In the examples that I
> > > have seen, there is contention with `lock'. This phenomenon does not
> > > occur on ppc32 or a number of other architectures that we support.
> >
> > How did you actually "look" at A and B ? is that also protected by the
> > lock ?
> >
> > > I confess I do not know the linux version nor the glibc version nor what
> > > pthreads implementation is being used. I'll find that out shortly.
> >
> > That's fairly important to know those yes.
> >
> > > What I am curious about is where the problem might lie
> > > (kernel/lib/pthreads/app) so I can ask the right people.
> > >
> > > Thank you for your patience,
> > > Greg Smith
>
^ permalink raw reply
* please pull powerpc.git
From: Paul Mackerras @ 2006-03-29 4:15 UTC (permalink / raw)
To: torvalds; +Cc: linuxppc-dev
Linus,
Please do a pull from
git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git
to get another batch of powerpc updates.
Thanks,
Paul.
Andrew Morton:
powerpc: hot_add_scn_to_nid() build fix
git-powerpc: WARN was a dumb idea
Anton Blanchard:
powerpc: Allow non zero boot cpuids
powerpc: Consistent printing of node id
powerpc: Compile warning in hvcs driver
powerpc: Remove some ifdefs in oprofile_impl.h
powerpc: export validate_sp for oprofile calltrace
powerpc: Fix some initcall return values
powerpc: Add oprofile calltrace support to all powerpc cpus
powerpc: Remove oprofile spinlock backtrace code
Arnd Bergmann:
powerpc: fix cell iommu setup
powerpc: update cell defconfig
powerpc: work around a cell interrupt HW bug
powerpc: declare arch syscalls in <asm/syscalls.h>
spufs: allow SPU code to do syscalls
spufs: implement mfc access for PPE-side DMA
powerpc: fix spider-pic affinity setting
powerpc: use guarded ioremap for cell on-chip mappings
spufs: Fix endless protection fault on LS writes by SPE.
powerpc: add hvc backend for rtas
spufs: fix __init/__exit annotations
Benjamin Herrenschmidt:
powerpc: Kill _machine and hard-coded platform numbers
Brian Rogan:
powerpc: Add oprofile calltrace support
Dirk Herrendoerfer:
spufs: initialize context correctly
Eugene Surovegin:
lock PTE before updating it in 440/BookE page fault handler
Jens Osterkamp:
powerpc: cell interrupt controller updates
John Rose:
powerpc: dynamic probe - use ppc_md.pci_probe_mode()
KAMEZAWA Hiroyuki:
for_each_possible_cpu: powerpc
for_each_possible_cpu: ppc
Kumar Gala:
ppc: fix strncasecmp prototype
powerpc: use memparse() for mem= command line parsing
powerpc: move math-emu over to arch/powerpc
powerpc: Make uImage default build output for MPC8540 ADS
powerpc: remove OCP references
Laurent MEYER:
powerpc: fix incorrect SA_ONSTACK behaviour for 64-bit processes
Linas Vepstas:
powerpc/pseries: Cleanup device name printing.
Mark Nutter:
spufs: enable SPE problem state MMIO access.
Michael Ellerman:
powerpc: Make BUG_ON & WARN_ON play nice with compile-time optimisations
powerpc: Change firmware_has_feature() to a macro
powerpc: Rename and export ppc64_firmware_features
powerpc: Cope with duplicate node & property names in /proc/device-tree
Michael Neuling:
powerpc: legacy_serial loop cleanup
powerpc: HVC init race
Mike Kravetz:
powerpc: Workaround for pSeries RTAS bug
Olaf Hering:
correct the comment about stackpointer alignment in __boot_from_prom
powerpc: return to OF via trap, not exit
Paul Mackerras:
powerpc: Unify the 32 and 64 bit idle loops
powerpc: Simplify pSeries idle loop
powerpc: Move l2cr.S over to arch/powerpc
powerpc: Move cpu_setup_6xx.S and temp.c over to arch/powerpc
powerpc: Move swsusp.S over to arch/powerpc
powerpc: Move module.c over to arch/powerpc
powerpc: Move perfmon_fsl_booke.c over to arch/powerpc
powerpc: Don't compile in arch/ppc/kernel for 32-bit ARCH=powerpc
ppc: Remove duplicate exports of __down, __up etc.
powerpc: Fix event-scan code for 32-bit CHRP
powerpc: Fix goof in 6xx and POWER4 idle power-save functions
ppc: Remove CHRP, POWER3 and POWER4 support from arch/ppc
ppc: Fix compile error in arch/ppc/lib/strcase.c
Ryan S. Arnold:
powerpc: hvc_console updates
Stephen Rothwell:
powerpc: work around sparse warnings in cputable.h
powerpc: fix various sparse warnings
powerpc: make ISA floppies work again
powerpc: a couple of trivial compile warning fixes
Sylvain Munaut:
ppc32: Adds support for the PCI hostbridge in MPC5200B
ppc32: Adds support for the LITE5200B dev board
ppc32: Reorganize and complete MPC52xx initial cpu setup
Documentation/powerpc/booting-without-of.txt | 5
arch/powerpc/Kconfig | 4
arch/powerpc/Kconfig.debug | 5
arch/powerpc/Makefile | 7
arch/powerpc/configs/cell_defconfig | 133 +-
arch/powerpc/configs/mpc8540_ads_defconfig | 43 -
arch/powerpc/kernel/Makefile | 11
arch/powerpc/kernel/asm-offsets.c | 2
arch/powerpc/kernel/cpu_setup_6xx.S | 0
arch/powerpc/kernel/entry_32.S | 8
arch/powerpc/kernel/entry_64.S | 6
arch/powerpc/kernel/firmware.c | 4
arch/powerpc/kernel/head_64.S | 32
arch/powerpc/kernel/idle.c | 122 ++
arch/powerpc/kernel/idle_64.c | 121 --
arch/powerpc/kernel/idle_6xx.S | 18
arch/powerpc/kernel/idle_power4.S | 38 -
arch/powerpc/kernel/irq.c | 2
arch/powerpc/kernel/l2cr_6xx.S | 0
arch/powerpc/kernel/legacy_serial.c | 42 -
arch/powerpc/kernel/lparcfg.c | 4
arch/powerpc/kernel/module_32.c | 0
arch/powerpc/kernel/nvram_64.c | 7
arch/powerpc/kernel/paca.c | 21
arch/powerpc/kernel/pci_32.c | 4
arch/powerpc/kernel/pci_64.c | 1
arch/powerpc/kernel/perfmon_fsl_booke.c | 0
arch/powerpc/kernel/proc_ppc64.c | 3
arch/powerpc/kernel/process.c | 11
arch/powerpc/kernel/prom.c | 154 +-
arch/powerpc/kernel/prom_init.c | 68 +
arch/powerpc/kernel/rtas-proc.c | 2
arch/powerpc/kernel/rtas.c | 8
arch/powerpc/kernel/setup-common.c | 70 +
arch/powerpc/kernel/setup_32.c | 75 -
arch/powerpc/kernel/setup_64.c | 78 -
arch/powerpc/kernel/signal_32.c | 1
arch/powerpc/kernel/signal_64.c | 3
arch/powerpc/kernel/smp.c | 2
arch/powerpc/kernel/swsusp_32.S | 0
arch/powerpc/kernel/syscalls.c | 1
arch/powerpc/kernel/sysfs.c | 12
arch/powerpc/kernel/tau_6xx.c | 0
arch/powerpc/kernel/time.c | 4
arch/powerpc/kernel/traps.c | 35 -
arch/powerpc/kernel/vdso.c | 9
arch/powerpc/kernel/vmlinux.lds.S | 379 +++--
arch/powerpc/lib/sstep.c | 2
arch/powerpc/math-emu/Makefile | 0
arch/powerpc/math-emu/double.h | 0
arch/powerpc/math-emu/fabs.c | 0
arch/powerpc/math-emu/fadd.c | 0
arch/powerpc/math-emu/fadds.c | 0
arch/powerpc/math-emu/fcmpo.c | 0
arch/powerpc/math-emu/fcmpu.c | 0
arch/powerpc/math-emu/fctiw.c | 0
arch/powerpc/math-emu/fctiwz.c | 0
arch/powerpc/math-emu/fdiv.c | 0
arch/powerpc/math-emu/fdivs.c | 0
arch/powerpc/math-emu/fmadd.c | 0
arch/powerpc/math-emu/fmadds.c | 0
arch/powerpc/math-emu/fmr.c | 0
arch/powerpc/math-emu/fmsub.c | 0
arch/powerpc/math-emu/fmsubs.c | 0
arch/powerpc/math-emu/fmul.c | 0
arch/powerpc/math-emu/fmuls.c | 0
arch/powerpc/math-emu/fnabs.c | 0
arch/powerpc/math-emu/fneg.c | 0
arch/powerpc/math-emu/fnmadd.c | 0
arch/powerpc/math-emu/fnmadds.c | 0
arch/powerpc/math-emu/fnmsub.c | 0
arch/powerpc/math-emu/fnmsubs.c | 0
arch/powerpc/math-emu/fres.c | 0
arch/powerpc/math-emu/frsp.c | 0
arch/powerpc/math-emu/frsqrte.c | 0
arch/powerpc/math-emu/fsel.c | 0
arch/powerpc/math-emu/fsqrt.c | 0
arch/powerpc/math-emu/fsqrts.c | 0
arch/powerpc/math-emu/fsub.c | 0
arch/powerpc/math-emu/fsubs.c | 0
arch/powerpc/math-emu/lfd.c | 0
arch/powerpc/math-emu/lfs.c | 0
arch/powerpc/math-emu/math.c | 0
arch/powerpc/math-emu/mcrfs.c | 0
arch/powerpc/math-emu/mffs.c | 0
arch/powerpc/math-emu/mtfsb0.c | 0
arch/powerpc/math-emu/mtfsb1.c | 0
arch/powerpc/math-emu/mtfsf.c | 0
arch/powerpc/math-emu/mtfsfi.c | 0
arch/powerpc/math-emu/op-1.h | 0
arch/powerpc/math-emu/op-2.h | 0
arch/powerpc/math-emu/op-4.h | 0
arch/powerpc/math-emu/op-common.h | 0
arch/powerpc/math-emu/sfp-machine.h | 0
arch/powerpc/math-emu/single.h | 0
arch/powerpc/math-emu/soft-fp.h | 0
arch/powerpc/math-emu/stfd.c | 0
arch/powerpc/math-emu/stfiwx.c | 0
arch/powerpc/math-emu/stfs.c | 0
arch/powerpc/math-emu/types.c | 0
arch/powerpc/math-emu/udivmodti4.c | 0
arch/powerpc/mm/fault.c | 30
arch/powerpc/mm/hash_utils_64.c | 7
arch/powerpc/mm/mem.c | 2
arch/powerpc/mm/numa.c | 2
arch/powerpc/mm/pgtable_32.c | 6
arch/powerpc/mm/stab.c | 2
arch/powerpc/oprofile/Makefile | 2
arch/powerpc/oprofile/backtrace.c | 126 ++
arch/powerpc/oprofile/common.c | 9
arch/powerpc/oprofile/op_model_7450.c | 4
arch/powerpc/oprofile/op_model_fsl_booke.c | 4
arch/powerpc/oprofile/op_model_power4.c | 45 -
arch/powerpc/oprofile/op_model_rs64.c | 5
arch/powerpc/platforms/85xx/Kconfig | 1
arch/powerpc/platforms/cell/Kconfig | 5
arch/powerpc/platforms/cell/Makefile | 10
arch/powerpc/platforms/cell/interrupt.c | 135 ++
arch/powerpc/platforms/cell/interrupt.h | 2
arch/powerpc/platforms/cell/iommu.c | 16
arch/powerpc/platforms/cell/pervasive.c | 4
arch/powerpc/platforms/cell/setup.c | 11
arch/powerpc/platforms/cell/spider-pic.c | 108 +-
arch/powerpc/platforms/cell/spu_base.c | 17
arch/powerpc/platforms/cell/spu_callbacks.c | 345 +++++
arch/powerpc/platforms/cell/spufs/backing_ops.c | 47 +
arch/powerpc/platforms/cell/spufs/context.c | 24
arch/powerpc/platforms/cell/spufs/file.c | 523 +++++++-
arch/powerpc/platforms/cell/spufs/hw_ops.c | 57 +
arch/powerpc/platforms/cell/spufs/inode.c | 6
arch/powerpc/platforms/cell/spufs/run.c | 91 +
arch/powerpc/platforms/cell/spufs/sched.c | 2
arch/powerpc/platforms/cell/spufs/spufs.h | 28
arch/powerpc/platforms/cell/spufs/switch.c | 3
arch/powerpc/platforms/chrp/chrp.h | 2
arch/powerpc/platforms/chrp/setup.c | 77 +
arch/powerpc/platforms/iseries/setup.c | 13
arch/powerpc/platforms/maple/setup.c | 10
arch/powerpc/platforms/powermac/bootx_init.c | 6
arch/powerpc/platforms/powermac/feature.c | 2
arch/powerpc/platforms/powermac/low_i2c.c | 3
arch/powerpc/platforms/powermac/nvram.c | 14
arch/powerpc/platforms/powermac/pci.c | 5
arch/powerpc/platforms/powermac/pfunc_base.c | 2
arch/powerpc/platforms/powermac/setup.c | 74 +
arch/powerpc/platforms/powermac/time.c | 4
arch/powerpc/platforms/powermac/udbg_scc.c | 2
arch/powerpc/platforms/pseries/eeh.c | 2
arch/powerpc/platforms/pseries/eeh_driver.c | 16
arch/powerpc/platforms/pseries/firmware.c | 2
arch/powerpc/platforms/pseries/hvconsole.c | 5
arch/powerpc/platforms/pseries/pci.c | 2
arch/powerpc/platforms/pseries/pci_dlpar.c | 11
arch/powerpc/platforms/pseries/ras.c | 2
arch/powerpc/platforms/pseries/reconfig.c | 5
arch/powerpc/platforms/pseries/rtasd.c | 3
arch/powerpc/platforms/pseries/setup.c | 223 +--
arch/powerpc/platforms/pseries/xics.c | 4
arch/ppc/Kconfig | 93 -
arch/ppc/Kconfig.debug | 7
arch/ppc/Makefile | 6
arch/ppc/boot/Makefile | 7
arch/ppc/boot/openfirmware/Makefile | 109 --
arch/ppc/boot/openfirmware/chrpmain.c | 101 -
arch/ppc/boot/openfirmware/common.c | 146 --
arch/ppc/boot/openfirmware/dummy.c | 4
arch/ppc/boot/openfirmware/misc.S | 67 -
arch/ppc/boot/openfirmware/start.c | 172 --
arch/ppc/boot/simple/mpc10x_memory.c | 4
arch/ppc/boot/simple/relocate.S | 2
arch/ppc/boot/utils/addnote.c | 175 ---
arch/ppc/boot/utils/hack-coff.c | 84 -
arch/ppc/boot/utils/mknote.c | 44 -
arch/ppc/configs/ibmchrp_defconfig | 875 -------------
arch/ppc/configs/pmac_defconfig | 1591 -----------------------
arch/ppc/configs/power3_defconfig | 1035 ---------------
arch/ppc/configs/prep_defconfig | 0
arch/ppc/kernel/Makefile | 28
arch/ppc/kernel/entry.S | 60 -
arch/ppc/kernel/head.S | 183 ---
arch/ppc/kernel/idle.c | 112 --
arch/ppc/kernel/idle_6xx.S | 233 ---
arch/ppc/kernel/idle_power4.S | 91 -
arch/ppc/kernel/pci.c | 396 ------
arch/ppc/kernel/ppc_htab.c | 8
arch/ppc/kernel/ppc_ksyms.c | 26
arch/ppc/kernel/setup.c | 256 ----
arch/ppc/kernel/smp.c | 2
arch/ppc/lib/strcase.c | 3
arch/ppc/mm/fault.c | 30
arch/ppc/mm/hashtable.S | 34
arch/ppc/mm/init.c | 13
arch/ppc/mm/mmu_context.c | 2
arch/ppc/mm/pgtable.c | 8
arch/ppc/mm/ppc_mmu.c | 28
arch/ppc/platforms/Makefile | 12
arch/ppc/platforms/chrp_nvram.c | 83 -
arch/ppc/platforms/chrp_pci.c | 309 ----
arch/ppc/platforms/chrp_pegasos_eth.c | 211 ---
arch/ppc/platforms/chrp_setup.c | 669 ----------
arch/ppc/platforms/chrp_smp.c | 99 -
arch/ppc/platforms/chrp_time.c | 235 ---
arch/ppc/platforms/lite5200.c | 71 +
arch/ppc/platforms/prep_setup.c | 12
arch/ppc/syslib/Makefile | 2
arch/ppc/syslib/mpc52xx_pci.c | 3
arch/ppc/syslib/mpc52xx_setup.c | 48 +
arch/ppc/syslib/open_pic.c | 2
arch/ppc/syslib/prom.c | 1429 ---------------------
arch/ppc/syslib/prom_init.c | 1011 ---------------
arch/ppc/xmon/start.c | 2
drivers/char/Kconfig | 17
drivers/char/Makefile | 4
drivers/char/generic_nvram.c | 5
drivers/char/hvc_console.c | 101 +
drivers/char/hvc_console.h | 63 +
drivers/char/hvc_rtas.c | 138 ++
drivers/char/hvc_vio.c | 11
drivers/char/hvcs.c | 1
drivers/ide/pci/via82cxxx.c | 2
drivers/ide/ppc/pmac.c | 2
drivers/ieee1394/ohci1394.c | 4
drivers/macintosh/adb.c | 3
drivers/macintosh/adbhid.c | 4
drivers/macintosh/mediabay.c | 4
drivers/media/video/planb.c | 2
drivers/net/tulip/de4x5.c | 2
drivers/scsi/mesh.c | 2
drivers/usb/core/hcd-pci.c | 4
drivers/video/aty/aty128fb.c | 7
drivers/video/aty/atyfb_base.c | 7
drivers/video/aty/radeon_pm.c | 4
drivers/video/cirrusfb.c | 4
drivers/video/matrox/matroxfb_base.c | 3
drivers/video/nvidia/nvidia.c | 5
drivers/video/radeonfb.c | 2
drivers/video/riva/fbdev.c | 9
fs/partitions/mac.c | 3
fs/proc/proc_devtree.c | 103 +
include/asm-powerpc/bug.h | 36 -
include/asm-powerpc/cputable.h | 299 ++--
include/asm-powerpc/firmware.h | 10
include/asm-powerpc/floppy.h | 5
include/asm-powerpc/hvcall.h | 1
include/asm-powerpc/hvconsole.h | 26
include/asm-powerpc/machdep.h | 43 -
include/asm-powerpc/oprofile_impl.h | 17
include/asm-powerpc/paca.h | 2
include/asm-powerpc/percpu.h | 2
include/asm-powerpc/pmac_feature.h | 2
include/asm-powerpc/processor.h | 43 -
include/asm-powerpc/prom.h | 14
include/asm-powerpc/reg.h | 4
include/asm-powerpc/smp.h | 2
include/asm-powerpc/spu.h | 11
include/asm-powerpc/syscalls.h | 58 +
include/asm-powerpc/unistd.h | 35 -
include/asm-powerpc/vdso_datapage.h | 3
include/asm-ppc/machdep.h | 17
include/asm-ppc/mpc52xx.h | 4
include/asm-ppc/pgtable.h | 3
include/asm-ppc/prom.h | 156 --
include/asm-ppc/serial.h | 7
include/linux/pci_ids.h | 1
sound/oss/dmasound/dmasound_awacs.c | 2
sound/ppc/pmac.c | 2
266 files changed, 3450 insertions(+), 11829 deletions(-)
rename arch/{ppc/kernel/cpu_setup_6xx.S => powerpc/kernel/cpu_setup_6xx.S} (100%)
create mode 100644 arch/powerpc/kernel/idle.c
delete mode 100644 arch/powerpc/kernel/idle_64.c
rename arch/{ppc/kernel/l2cr.S => powerpc/kernel/l2cr_6xx.S} (100%)
rename arch/{ppc/kernel/module.c => powerpc/kernel/module_32.c} (100%)
rename arch/{ppc/kernel/perfmon_fsl_booke.c => powerpc/kernel/perfmon_fsl_booke.c} (100%)
rename arch/{ppc/kernel/swsusp.S => powerpc/kernel/swsusp_32.S} (100%)
rename arch/{ppc/kernel/temp.c => powerpc/kernel/tau_6xx.c} (100%)
rename arch/{ppc/math-emu/Makefile => powerpc/math-emu/Makefile} (100%)
rename arch/{ppc/math-emu/double.h => powerpc/math-emu/double.h} (100%)
rename arch/{ppc/math-emu/fabs.c => powerpc/math-emu/fabs.c} (100%)
rename arch/{ppc/math-emu/fadd.c => powerpc/math-emu/fadd.c} (100%)
rename arch/{ppc/math-emu/fadds.c => powerpc/math-emu/fadds.c} (100%)
rename arch/{ppc/math-emu/fcmpo.c => powerpc/math-emu/fcmpo.c} (100%)
rename arch/{ppc/math-emu/fcmpu.c => powerpc/math-emu/fcmpu.c} (100%)
rename arch/{ppc/math-emu/fctiw.c => powerpc/math-emu/fctiw.c} (100%)
rename arch/{ppc/math-emu/fctiwz.c => powerpc/math-emu/fctiwz.c} (100%)
rename arch/{ppc/math-emu/fdiv.c => powerpc/math-emu/fdiv.c} (100%)
rename arch/{ppc/math-emu/fdivs.c => powerpc/math-emu/fdivs.c} (100%)
rename arch/{ppc/math-emu/fmadd.c => powerpc/math-emu/fmadd.c} (100%)
rename arch/{ppc/math-emu/fmadds.c => powerpc/math-emu/fmadds.c} (100%)
rename arch/{ppc/math-emu/fmr.c => powerpc/math-emu/fmr.c} (100%)
rename arch/{ppc/math-emu/fmsub.c => powerpc/math-emu/fmsub.c} (100%)
rename arch/{ppc/math-emu/fmsubs.c => powerpc/math-emu/fmsubs.c} (100%)
rename arch/{ppc/math-emu/fmul.c => powerpc/math-emu/fmul.c} (100%)
rename arch/{ppc/math-emu/fmuls.c => powerpc/math-emu/fmuls.c} (100%)
rename arch/{ppc/math-emu/fnabs.c => powerpc/math-emu/fnabs.c} (100%)
rename arch/{ppc/math-emu/fneg.c => powerpc/math-emu/fneg.c} (100%)
rename arch/{ppc/math-emu/fnmadd.c => powerpc/math-emu/fnmadd.c} (100%)
rename arch/{ppc/math-emu/fnmadds.c => powerpc/math-emu/fnmadds.c} (100%)
rename arch/{ppc/math-emu/fnmsub.c => powerpc/math-emu/fnmsub.c} (100%)
rename arch/{ppc/math-emu/fnmsubs.c => powerpc/math-emu/fnmsubs.c} (100%)
rename arch/{ppc/math-emu/fres.c => powerpc/math-emu/fres.c} (100%)
rename arch/{ppc/math-emu/frsp.c => powerpc/math-emu/frsp.c} (100%)
rename arch/{ppc/math-emu/frsqrte.c => powerpc/math-emu/frsqrte.c} (100%)
rename arch/{ppc/math-emu/fsel.c => powerpc/math-emu/fsel.c} (100%)
rename arch/{ppc/math-emu/fsqrt.c => powerpc/math-emu/fsqrt.c} (100%)
rename arch/{ppc/math-emu/fsqrts.c => powerpc/math-emu/fsqrts.c} (100%)
rename arch/{ppc/math-emu/fsub.c => powerpc/math-emu/fsub.c} (100%)
rename arch/{ppc/math-emu/fsubs.c => powerpc/math-emu/fsubs.c} (100%)
rename arch/{ppc/math-emu/lfd.c => powerpc/math-emu/lfd.c} (100%)
rename arch/{ppc/math-emu/lfs.c => powerpc/math-emu/lfs.c} (100%)
rename arch/{ppc/math-emu/math.c => powerpc/math-emu/math.c} (100%)
rename arch/{ppc/math-emu/mcrfs.c => powerpc/math-emu/mcrfs.c} (100%)
rename arch/{ppc/math-emu/mffs.c => powerpc/math-emu/mffs.c} (100%)
rename arch/{ppc/math-emu/mtfsb0.c => powerpc/math-emu/mtfsb0.c} (100%)
rename arch/{ppc/math-emu/mtfsb1.c => powerpc/math-emu/mtfsb1.c} (100%)
rename arch/{ppc/math-emu/mtfsf.c => powerpc/math-emu/mtfsf.c} (100%)
rename arch/{ppc/math-emu/mtfsfi.c => powerpc/math-emu/mtfsfi.c} (100%)
rename arch/{ppc/math-emu/op-1.h => powerpc/math-emu/op-1.h} (100%)
rename arch/{ppc/math-emu/op-2.h => powerpc/math-emu/op-2.h} (100%)
rename arch/{ppc/math-emu/op-4.h => powerpc/math-emu/op-4.h} (100%)
rename arch/{ppc/math-emu/op-common.h => powerpc/math-emu/op-common.h} (100%)
rename arch/{ppc/math-emu/sfp-machine.h => powerpc/math-emu/sfp-machine.h} (100%)
rename arch/{ppc/math-emu/single.h => powerpc/math-emu/single.h} (100%)
rename arch/{ppc/math-emu/soft-fp.h => powerpc/math-emu/soft-fp.h} (100%)
rename arch/{ppc/math-emu/stfd.c => powerpc/math-emu/stfd.c} (100%)
rename arch/{ppc/math-emu/stfiwx.c => powerpc/math-emu/stfiwx.c} (100%)
rename arch/{ppc/math-emu/stfs.c => powerpc/math-emu/stfs.c} (100%)
rename arch/{ppc/math-emu/types.c => powerpc/math-emu/types.c} (100%)
rename arch/{ppc/math-emu/udivmodti4.c => powerpc/math-emu/udivmodti4.c} (100%)
create mode 100644 arch/powerpc/oprofile/backtrace.c
create mode 100644 arch/powerpc/platforms/cell/spu_callbacks.c
delete mode 100644 arch/ppc/boot/openfirmware/Makefile
delete mode 100644 arch/ppc/boot/openfirmware/chrpmain.c
delete mode 100644 arch/ppc/boot/openfirmware/common.c
delete mode 100644 arch/ppc/boot/openfirmware/dummy.c
delete mode 100644 arch/ppc/boot/openfirmware/misc.S
delete mode 100644 arch/ppc/boot/openfirmware/start.c
delete mode 100644 arch/ppc/boot/utils/addnote.c
delete mode 100644 arch/ppc/boot/utils/hack-coff.c
delete mode 100644 arch/ppc/boot/utils/mknote.c
delete mode 100644 arch/ppc/configs/ibmchrp_defconfig
delete mode 100644 arch/ppc/configs/pmac_defconfig
delete mode 100644 arch/ppc/configs/power3_defconfig
rename arch/ppc/configs/{common_defconfig => prep_defconfig} (100%)
delete mode 100644 arch/ppc/kernel/idle.c
delete mode 100644 arch/ppc/kernel/idle_6xx.S
delete mode 100644 arch/ppc/kernel/idle_power4.S
delete mode 100644 arch/ppc/platforms/chrp_nvram.c
delete mode 100644 arch/ppc/platforms/chrp_pci.c
delete mode 100644 arch/ppc/platforms/chrp_pegasos_eth.c
delete mode 100644 arch/ppc/platforms/chrp_setup.c
delete mode 100644 arch/ppc/platforms/chrp_smp.c
delete mode 100644 arch/ppc/platforms/chrp_time.c
delete mode 100644 arch/ppc/syslib/prom.c
delete mode 100644 arch/ppc/syslib/prom_init.c
create mode 100644 drivers/char/hvc_console.h
create mode 100644 drivers/char/hvc_rtas.c
create mode 100644 include/asm-powerpc/syscalls.h
^ permalink raw reply
* Re: [OT] ppc64 serialization problem
From: Greg Smith @ 2006-03-29 4:08 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1143601903.3585.2.camel@localhost.localdomain>
Very fair questions!!
Actually the code was
pthread_mutex_lock(&lock);
u32 |= bitB;
TRACE("A", u32, ...);
TRACE("B", u32, ...);
pthread_mutex_unlock(&lock);
where TRACE is a function call (entering a trace entry to an in-storage
wrap-around table). So for the "A" call, u32 could have come directly
from a register and for "B" from the storage location. I'll have the
user (actually a fellow developer) send me the assembly listing to make
sure.
He has tested SLES9 (kernel 2.6.5, glibc 2.3.3, gcc 3.3.3) and Debian
(kernel 2.6.16, glibc 2.3.6, gcc 4.0.3).
The TRACE occurs while the lock is held.
Now the interesting part.
I suggested he try u64 instead of u32. That works!!
He is suspecting a recent firmware upgrade may have something to do with
the problem.
Thank you,
Greg Smith
On Wed, 2006-03-29 at 14:11 +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2006-03-28 at 20:58 -0500, Greg Smith wrote:
> > We have a multi-threaded app running on a p520 in 64 bit mode.
> >
> > Thread A does
> >
> > pthread_mutex_lock(&lock);
> > u32 &= ~bitA;
> > pthread_mutex_unlock(&lock);
> >
> > and Thread B does
> >
> > pthread_mutex_lock(&lock);
> > u32 |= bitB;
> > A = u32;
> > B = u32;
> > pthread_mutex_unlock(&lock);
> >
> > On rare occasions, values A and B will differ! In the examples that I
> > have seen, there is contention with `lock'. This phenomenon does not
> > occur on ppc32 or a number of other architectures that we support.
>
> How did you actually "look" at A and B ? is that also protected by the
> lock ?
>
> > I confess I do not know the linux version nor the glibc version nor what
> > pthreads implementation is being used. I'll find that out shortly.
>
> That's fairly important to know those yes.
>
> > What I am curious about is where the problem might lie
> > (kernel/lib/pthreads/app) so I can ask the right people.
> >
> > Thank you for your patience,
> > Greg Smith
^ permalink raw reply
* Re: [OT] ppc64 serialization problem
From: Paul Mackerras @ 2006-03-29 4:07 UTC (permalink / raw)
To: Greg Smith; +Cc: linuxppc-dev
In-Reply-To: <1143597506.3075.53.camel@localhost.localdomain>
Greg Smith writes:
> On rare occasions, values A and B will differ! In the examples that I
> have seen, there is contention with `lock'. This phenomenon does not
> occur on ppc32 or a number of other architectures that we support.
I would be interested to see the assembler code being generated for
your code snippets.
Paul.
^ permalink raw reply
* Re: snd-aoa: new apple sound driver
From: Benjamin Herrenschmidt @ 2006-03-29 4:01 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev, debian-powerpc, Alastair Poole
In-Reply-To: <1143547826.13615.24.camel@localhost>
BTW.. with the current stuff, if I install the modules and then do
modprobe i2sbus
I get a registration error in dmesg. If I then try to rmmod it, the
machine blows up. Haven't had time to track that down at this point.
Appart from that, it works and I can play morse with myh SPID output :)
Oh, and jackd seems to be unhappy even if I tell it to ignore the
capture channels, it's probably a problem with setting the sample
formats, I haven't looked in detail (yet).
Ben.
^ permalink raw reply
* Re: [OT] ppc64 serialization problem
From: Benjamin Herrenschmidt @ 2006-03-29 3:11 UTC (permalink / raw)
To: Greg Smith; +Cc: linuxppc-dev
In-Reply-To: <1143597506.3075.53.camel@localhost.localdomain>
On Tue, 2006-03-28 at 20:58 -0500, Greg Smith wrote:
> We have a multi-threaded app running on a p520 in 64 bit mode.
>
> Thread A does
>
> pthread_mutex_lock(&lock);
> u32 &= ~bitA;
> pthread_mutex_unlock(&lock);
>
> and Thread B does
>
> pthread_mutex_lock(&lock);
> u32 |= bitB;
> A = u32;
> B = u32;
> pthread_mutex_unlock(&lock);
>
> On rare occasions, values A and B will differ! In the examples that I
> have seen, there is contention with `lock'. This phenomenon does not
> occur on ppc32 or a number of other architectures that we support.
How did you actually "look" at A and B ? is that also protected by the
lock ?
> I confess I do not know the linux version nor the glibc version nor what
> pthreads implementation is being used. I'll find that out shortly.
That's fairly important to know those yes.
> What I am curious about is where the problem might lie
> (kernel/lib/pthreads/app) so I can ask the right people.
>
> Thank you for your patience,
> Greg Smith
>
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH] DTC - validation by device_type
From: Paul Nasrat @ 2006-03-29 2:33 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <66cc5bfb5a367a814fbace8105572658@penguinppc.org>
On Tue, 2006-03-28 at 20:03 -0600, Hollis Blanchard wrote:
> On Mar 28, 2006, at 4:49 PM, Paul Nasrat wrote:
> >
> > It'd be nice to be able to validate by device_type, to ensure that we
> > don't reinvent the wheel (address vs. local-mac-address) and to give
> > embedded designers an added level of sanity checking.
> >
> > Here is a proposed implementation with an implemented check for
> > "network".
> >
> Unless this is some weird style thing, that close brace seems
> misindented.
No you're not missing anything, both artefacts of how I got there. Take
2.
As above
Signed-off-by: Paul Nasrat <pnasrat@redhat.com>
diff --git a/livetree.c b/livetree.c
index ef54174..bf8bb56 100644
--- a/livetree.c
+++ b/livetree.c
@@ -441,6 +441,51 @@ static int check_structure(struct node *
(propname), (node)->fullpath); \
} while (0)
+static int check_network(struct node *net)
+{
+
+ int ok = 1;
+ struct property *prop;
+
+ CHECK_HAVE(net, "reg");
+ CHECK_HAVE(net, "local-mac-address");
+ CHECK_HAVE(net, "mac-address");
+ CHECK_HAVE(net, "address-bits");
+
+ return ok;
+}
+
+static struct {
+ char *devtype;
+ int (*check_fn)(struct node *node);
+} devtype_checker_table[] = {
+ {"network", check_network},
+};
+
+static int check_devtypes(struct node *root)
+{
+
+ struct node *child;
+ struct property *prop;
+ int ok = 1;
+ int i;
+
+ for_each_child(root, child) {
+ /* check this node */
+ if ((prop = get_property((child), ("device_type"))))
+ for (i = 0; i < ARRAY_SIZE(devtype_checker_table); i++) {
+ if (streq(prop->val.val, devtype_checker_table[i].devtype))
+ if (! devtype_checker_table[i].check_fn(child)) {
+ ok = 0;
+ break;
+ }
+ }
+ ok = check_devtypes(child);
+ }
+
+ return ok;
+}
+
static int check_root(struct node *root)
{
struct property *prop;
@@ -716,6 +761,7 @@ int check_device_tree(struct node *dt)
ok = ok && check_cpus(dt);
ok = ok && check_memory(dt);
ok = ok && check_chosen(dt);
+ ok = ok && check_devtypes(dt);
if (! ok)
return 0;
^ permalink raw reply related
* [PATCH 3/3] altix: msi support
From: Mark Maule @ 2006-03-29 2:31 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
In-Reply-To: <20060329023105.13892.52299.24895@lnx-maule.americas.sgi.com>
MSI callouts for altix. Involves a fair amount of code reorg in sn irq.c
code as well as adding some extensions to the altix PCI provider abstaction.
Signed-off-by: Mark Maule <maule@sgi.com>
Index: linux-2.6/arch/ia64/sn/kernel/io_init.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/io_init.c 2006-03-27 11:10:59.000000000 -0600
+++ linux-2.6/arch/ia64/sn/kernel/io_init.c 2006-03-27 19:03:17.206816884 -0600
@@ -58,7 +58,7 @@
*/
static dma_addr_t
-sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size)
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
{
return 0;
}
@@ -457,13 +457,6 @@
pcidev_info->pdi_sn_irq_info = NULL;
kfree(sn_irq_info);
}
-
- /*
- * MSI currently not supported on altix. Remove this when
- * the MSI abstraction patches are integrated into the kernel
- * (sometime after 2.6.16 releases)
- */
- dev->no_msi = 1;
}
/*
Index: linux-2.6/arch/ia64/sn/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/irq.c 2006-03-27 14:28:49.000000000 -0600
+++ linux-2.6/arch/ia64/sn/kernel/irq.c 2006-03-27 14:33:46.977089283 -0600
@@ -26,11 +26,11 @@
int sn_force_interrupt_flag = 1;
extern int sn_ioif_inited;
-static struct list_head **sn_irq_lh;
+struct list_head **sn_irq_lh;
static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
-static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
- u64 sn_irq_info,
+u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
+ struct sn_irq_info *sn_irq_info,
int req_irq, nasid_t req_nasid,
int req_slice)
{
@@ -40,12 +40,13 @@
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
(u64) SAL_INTR_ALLOC, (u64) local_nasid,
- (u64) local_widget, (u64) sn_irq_info, (u64) req_irq,
+ (u64) local_widget, __pa(sn_irq_info), (u64) req_irq,
(u64) req_nasid, (u64) req_slice);
+
return ret_stuff.status;
}
-static inline void sn_intr_free(nasid_t local_nasid, int local_widget,
+void sn_intr_free(nasid_t local_nasid, int local_widget,
struct sn_irq_info *sn_irq_info)
{
struct ia64_sal_retval ret_stuff;
@@ -112,73 +113,91 @@
static void sn_irq_info_free(struct rcu_head *head);
-static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
+ nasid_t nasid, int slice)
{
- struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
- int cpuid, cpuphys;
+ int vector;
+ int cpuphys;
+ int64_t bridge;
+ int local_widget, status;
+ nasid_t local_nasid;
+ struct sn_irq_info *new_irq_info;
+ struct sn_pcibus_provider *pci_provider;
- cpuid = first_cpu(mask);
- cpuphys = cpu_physical_id(cpuid);
+ new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
+ if (new_irq_info == NULL)
+ return NULL;
+
+ memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
+
+ bridge = (u64) new_irq_info->irq_bridge;
+ if (!bridge) {
+ kfree(new_irq_info);
+ return NULL; /* irq is not a device interrupt */
+ }
- list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
- sn_irq_lh[irq], list) {
- u64 bridge;
- int local_widget, status;
- nasid_t local_nasid;
- struct sn_irq_info *new_irq_info;
- struct sn_pcibus_provider *pci_provider;
-
- new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
- if (new_irq_info == NULL)
- break;
- memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
-
- bridge = (u64) new_irq_info->irq_bridge;
- if (!bridge) {
- kfree(new_irq_info);
- break; /* irq is not a device interrupt */
- }
+ local_nasid = NASID_GET(bridge);
- local_nasid = NASID_GET(bridge);
+ if (local_nasid & 1)
+ local_widget = TIO_SWIN_WIDGETNUM(bridge);
+ else
+ local_widget = SWIN_WIDGETNUM(bridge);
+
+ vector = sn_irq_info->irq_irq;
+ /* Free the old PROM new_irq_info structure */
+ sn_intr_free(local_nasid, local_widget, new_irq_info);
+ /* Update kernels new_irq_info with new target info */
+ unregister_intr_pda(new_irq_info);
+
+ /* allocate a new PROM new_irq_info struct */
+ status = sn_intr_alloc(local_nasid, local_widget,
+ new_irq_info, vector,
+ nasid, slice);
+
+ /* SAL call failed */
+ if (status) {
+ kfree(new_irq_info);
+ return NULL;
+ }
- if (local_nasid & 1)
- local_widget = TIO_SWIN_WIDGETNUM(bridge);
- else
- local_widget = SWIN_WIDGETNUM(bridge);
-
- /* Free the old PROM new_irq_info structure */
- sn_intr_free(local_nasid, local_widget, new_irq_info);
- /* Update kernels new_irq_info with new target info */
- unregister_intr_pda(new_irq_info);
-
- /* allocate a new PROM new_irq_info struct */
- status = sn_intr_alloc(local_nasid, local_widget,
- __pa(new_irq_info), irq,
- cpuid_to_nasid(cpuid),
- cpuid_to_slice(cpuid));
-
- /* SAL call failed */
- if (status) {
- kfree(new_irq_info);
- break;
- }
+ cpuphys = nasid_slice_to_cpuid(nasid, slice);
+ new_irq_info->irq_cpuid = cpuphys;
+ register_intr_pda(new_irq_info);
- new_irq_info->irq_cpuid = cpuid;
- register_intr_pda(new_irq_info);
+ pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
- pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
- if (pci_provider && pci_provider->target_interrupt)
- (pci_provider->target_interrupt)(new_irq_info);
-
- spin_lock(&sn_irq_info_lock);
- list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
- spin_unlock(&sn_irq_info_lock);
- call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+ /*
+ * If this represents a line interrupt, target it. If it's
+ * an msi (irq_int_bit < 0), it's already targeted.
+ */
+ if (new_irq_info->irq_int_bit >= 0 &&
+ pci_provider && pci_provider->target_interrupt)
+ (pci_provider->target_interrupt)(new_irq_info);
+
+ spin_lock(&sn_irq_info_lock);
+ list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
+ spin_unlock(&sn_irq_info_lock);
+ call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
#ifdef CONFIG_SMP
- set_irq_affinity_info((irq & 0xff), cpuphys, 0);
+ set_irq_affinity_info((vector & 0xff), cpuphys, 0);
#endif
- }
+
+ return new_irq_info;
+}
+
+static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+{
+ struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
+ nasid_t nasid;
+ int slice;
+
+ nasid = cpuid_to_nasid(first_cpu(mask));
+ slice = cpuid_to_slice(first_cpu(mask));
+
+ list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
+ sn_irq_lh[irq], list)
+ (void)sn_retarget_vector(sn_irq_info, nasid, slice);
}
struct hw_interrupt_type irq_type_sn = {
Index: linux-2.6/arch/ia64/sn/pci/pci_dma.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/pci/pci_dma.c 2006-03-27 11:10:59.000000000 -0600
+++ linux-2.6/arch/ia64/sn/pci/pci_dma.c 2006-03-27 14:33:46.980018681 -0600
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <asm/dma.h>
-#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/intr.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/sn_sal.h>
@@ -113,7 +113,8 @@
* resources.
*/
- *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size);
+ *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size,
+ SN_DMA_ADDR_PHYS);
if (!*dma_handle) {
printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
free_pages((unsigned long)cpuaddr, get_order(size));
@@ -176,7 +177,7 @@
BUG_ON(dev->bus != &pci_bus_type);
phys_addr = __pa(cpu_addr);
- dma_addr = provider->dma_map(pdev, phys_addr, size);
+ dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
if (!dma_addr) {
printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
return 0;
@@ -260,7 +261,8 @@
for (i = 0; i < nhwentries; i++, sg++) {
phys_addr = SG_ENT_PHYS_ADDRESS(sg);
sg->dma_address = provider->dma_map(pdev,
- phys_addr, sg->length);
+ phys_addr, sg->length,
+ SN_DMA_ADDR_PHYS);
if (!sg->dma_address) {
printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
Index: linux-2.6/arch/ia64/sn/pci/pcibr/pcibr_dma.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/pci/pcibr/pcibr_dma.c 2006-03-27 11:10:59.000000000 -0600
+++ linux-2.6/arch/ia64/sn/pci/pcibr/pcibr_dma.c 2006-03-27 14:33:46.983924544 -0600
@@ -41,7 +41,7 @@
static dma_addr_t
pcibr_dmamap_ate32(struct pcidev_info *info,
- u64 paddr, size_t req_size, u64 flags)
+ u64 paddr, size_t req_size, u64 flags, int dma_flags)
{
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
@@ -81,9 +81,12 @@
if (IS_PCIX(pcibus_info))
ate_flags &= ~(PCI32_ATE_PREF);
- xio_addr =
- IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr);
+ if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS))
+ xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+ PHYS_TO_TIODMA(paddr);
+ else
+ xio_addr = paddr;
+
offset = IOPGOFF(xio_addr);
ate = ate_flags | (xio_addr - offset);
@@ -91,6 +94,13 @@
if (IS_PIC_SOFT(pcibus_info)) {
ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT);
}
+
+ /*
+ * If we're mapping for MSI, set the MSI bit in the ATE
+ */
+ if (dma_flags & SN_DMA_MSI)
+ ate |= PCI32_ATE_MSI;
+
ate_write(pcibus_info, ate_index, ate_count, ate);
/*
@@ -105,20 +115,27 @@
if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR)
ATE_SWAP_ON(pci_addr);
+
return pci_addr;
}
static dma_addr_t
pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
- u64 dma_attributes)
+ u64 dma_attributes, int dma_flags)
{
struct pcibus_info *pcibus_info = (struct pcibus_info *)
((info->pdi_host_pcidev_info)->pdi_pcibus_info);
u64 pci_addr;
/* Translate to Crosstalk View of Physical Address */
- pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr)) | dma_attributes;
+ if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+ pci_addr = IS_PIC_SOFT(pcibus_info) ?
+ PHYS_TO_DMA(paddr) :
+ PHYS_TO_TIODMA(paddr) | dma_attributes;
+ else
+ pci_addr = IS_PIC_SOFT(pcibus_info) ?
+ paddr :
+ paddr | dma_attributes;
/* Handle Bus mode */
if (IS_PCIX(pcibus_info))
@@ -130,7 +147,9 @@
((u64) pcibus_info->
pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT);
} else
- pci_addr |= TIOCP_PCI64_CMDTYPE_MEM;
+ pci_addr |= (dma_flags & SN_DMA_MSI) ?
+ TIOCP_PCI64_CMDTYPE_MSI :
+ TIOCP_PCI64_CMDTYPE_MEM;
/* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */
if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn))
@@ -141,7 +160,7 @@
static dma_addr_t
pcibr_dmatrans_direct32(struct pcidev_info * info,
- u64 paddr, size_t req_size, u64 flags)
+ u64 paddr, size_t req_size, u64 flags, int dma_flags)
{
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
@@ -156,8 +175,14 @@
return 0;
}
- xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr);
+ if (dma_flags & SN_DMA_MSI)
+ return 0;
+
+ if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+ xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+ PHYS_TO_TIODMA(paddr);
+ else
+ xio_addr = paddr;
xio_base = pcibus_info->pbi_dir_xbase;
offset = xio_addr - xio_base;
@@ -327,7 +352,7 @@
*/
dma_addr_t
-pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
+pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags)
{
dma_addr_t dma_handle;
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
@@ -344,11 +369,11 @@
*/
dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
- PCI64_ATTR_PREF);
+ PCI64_ATTR_PREF, dma_flags);
} else {
/* Handle 32-63 bit cards via direct mapping */
dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr,
- size, 0);
+ size, 0, dma_flags);
if (!dma_handle) {
/*
* It is a 32 bit card and we cannot do direct mapping,
@@ -356,7 +381,8 @@
*/
dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr,
- size, PCI32_ATE_PREF);
+ size, PCI32_ATE_PREF,
+ dma_flags);
}
}
@@ -365,18 +391,18 @@
dma_addr_t
pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr,
- size_t size)
+ size_t size, int dma_flags)
{
dma_addr_t dma_handle;
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
if (hwdev->dev.coherent_dma_mask == ~0UL) {
dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
- PCI64_ATTR_BAR);
+ PCI64_ATTR_BAR, dma_flags);
} else {
dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
phys_addr, size,
- PCI32_ATE_BAR);
+ PCI32_ATE_BAR, dma_flags);
}
return dma_handle;
Index: linux-2.6/arch/ia64/sn/pci/tioca_provider.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/pci/tioca_provider.c 2006-03-27 11:10:59.000000000 -0600
+++ linux-2.6/arch/ia64/sn/pci/tioca_provider.c 2006-03-27 14:33:46.983924544 -0600
@@ -515,11 +515,17 @@
* use the GART mapped mode.
*/
static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
{
u64 mapaddr;
/*
+ * Not supported for now ...
+ */
+ if (dma_flags & SN_DMA_MSI)
+ return 0;
+
+ /*
* If card is 64 or 48 bit addresable, use a direct mapping. 32
* bit direct is so restrictive w.r.t. where the memory resides that
* we don't use it even though CA has some support.
Index: linux-2.6/arch/ia64/sn/pci/tioce_provider.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/pci/tioce_provider.c 2006-03-27 11:10:59.000000000 -0600
+++ linux-2.6/arch/ia64/sn/pci/tioce_provider.c 2006-03-27 14:38:54.049198769 -0600
@@ -170,7 +170,8 @@
(ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1)
#define ATE_VALID(ate) ((ate) & (1UL << 63))
-#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63))
+#define ATE_MAKE(addr, ps, msi) \
+ (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0))
/*
* Flavors of ate-based mapping supported by tioce_alloc_map()
@@ -196,15 +197,17 @@
*
* 63 - must be 1 to indicate d64 mode to CE hardware
* 62 - barrier bit ... controlled with tioce_dma_barrier()
- * 61 - 0 since this is not an MSI transaction
+ * 61 - msi bit ... specified through dma_flags
* 60:54 - reserved, MBZ
*/
static u64
-tioce_dma_d64(unsigned long ct_addr)
+tioce_dma_d64(unsigned long ct_addr, int dma_flags)
{
u64 bus_addr;
bus_addr = ct_addr | (1UL << 63);
+ if (dma_flags & SN_DMA_MSI)
+ bus_addr |= (1UL << 61);
return bus_addr;
}
@@ -261,7 +264,7 @@
*/
static u64
tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
- u64 ct_addr, int len)
+ u64 ct_addr, int len, int dma_flags)
{
int i;
int j;
@@ -270,6 +273,7 @@
int entries;
int nates;
u64 pagesize;
+ int msi_capable, msi_wanted;
u64 *ate_shadow;
u64 *ate_reg;
u64 addr;
@@ -291,6 +295,7 @@
ate_reg = ce_mmr->ce_ure_ate3240;
pagesize = ce_kern->ce_ate3240_pagesize;
bus_base = TIOCE_M32_MIN;
+ msi_capable = 1;
break;
case TIOCE_ATE_M40:
first = 0;
@@ -299,6 +304,7 @@
ate_reg = ce_mmr->ce_ure_ate40;
pagesize = MB(64);
bus_base = TIOCE_M40_MIN;
+ msi_capable = 0;
break;
case TIOCE_ATE_M40S:
/*
@@ -311,11 +317,16 @@
ate_reg = ce_mmr->ce_ure_ate3240;
pagesize = GB(16);
bus_base = TIOCE_M40S_MIN;
+ msi_capable = 0;
break;
default:
return 0;
}
+ msi_wanted = dma_flags & SN_DMA_MSI;
+ if (msi_wanted && !msi_capable)
+ return 0;
+
nates = ATE_NPAGES(ct_addr, len, pagesize);
if (nates > entries)
return 0;
@@ -344,7 +355,7 @@
for (j = 0; j < nates; j++) {
u64 ate;
- ate = ATE_MAKE(addr, pagesize);
+ ate = ATE_MAKE(addr, pagesize, msi_wanted);
ate_shadow[i + j] = ate;
tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate);
addr += pagesize;
@@ -371,7 +382,7 @@
* Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
*/
static u64
-tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
+tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags)
{
int dma_ok;
int port;
@@ -381,6 +392,9 @@
u64 ct_lower;
dma_addr_t bus_addr;
+ if (dma_flags & SN_DMA_MSI)
+ return 0;
+
ct_upper = ct_addr & ~0x3fffffffUL;
ct_lower = ct_addr & 0x3fffffffUL;
@@ -507,7 +521,7 @@
*/
static u64
tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
- int barrier)
+ int barrier, int dma_flags)
{
unsigned long flags;
u64 ct_addr;
@@ -523,15 +537,18 @@
if (dma_mask < 0x7fffffffUL)
return 0;
- ct_addr = PHYS_TO_TIODMA(paddr);
+ if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+ ct_addr = PHYS_TO_TIODMA(paddr);
+ else
+ ct_addr = paddr;
/*
* If the device can generate 64 bit addresses, create a D64 map.
- * Since this should never fail, bypass the rest of the checks.
*/
if (dma_mask == ~0UL) {
- mapaddr = tioce_dma_d64(ct_addr);
- goto dma_map_done;
+ mapaddr = tioce_dma_d64(ct_addr, dma_flags);
+ if (mapaddr)
+ goto dma_map_done;
}
pcidev_to_tioce(pdev, NULL, &ce_kern, &port);
@@ -574,18 +591,22 @@
if (byte_count > MB(64)) {
mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
- port, ct_addr, byte_count);
+ port, ct_addr, byte_count,
+ dma_flags);
if (!mapaddr)
mapaddr =
tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
- ct_addr, byte_count);
+ ct_addr, byte_count,
+ dma_flags);
} else {
mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
- ct_addr, byte_count);
+ ct_addr, byte_count,
+ dma_flags);
if (!mapaddr)
mapaddr =
tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
- port, ct_addr, byte_count);
+ port, ct_addr, byte_count,
+ dma_flags);
}
}
@@ -593,7 +614,7 @@
* 32-bit direct is the next mode to try
*/
if (!mapaddr && dma_mask >= 0xffffffffUL)
- mapaddr = tioce_dma_d32(pdev, ct_addr);
+ mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags);
/*
* Last resort, try 32-bit ATE-based map.
@@ -601,7 +622,7 @@
if (!mapaddr)
mapaddr =
tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr,
- byte_count);
+ byte_count, dma_flags);
spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
@@ -622,9 +643,9 @@
* in the address.
*/
static u64
-tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
{
- return tioce_do_dma_map(pdev, paddr, byte_count, 0);
+ return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags);
}
/**
@@ -636,9 +657,9 @@
* Simply call tioce_do_dma_map() to create a map with the barrier bit set
* in the address.
*/ static u64
-tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
{
- return tioce_do_dma_map(pdev, paddr, byte_count, 1);
+ return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
}
/**
@@ -696,7 +717,7 @@
while (ate_index <= last_ate) {
u64 ate;
- ate = ATE_MAKE(0xdeadbeef, ps);
+ ate = ATE_MAKE(0xdeadbeef, ps, 0);
ce_kern->ce_ate3240_shadow[ate_index] = ate;
tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index],
ate);
Index: linux-2.6/include/asm-ia64/sn/intr.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/sn/intr.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/sn/intr.h 2006-03-27 14:33:46.994665669 -0600
@@ -10,6 +10,7 @@
#define _ASM_IA64_SN_INTR_H
#include <linux/rcupdate.h>
+#include <asm/sn/types.h>
#define SGI_UART_VECTOR 0xe9
@@ -40,6 +41,7 @@
int irq_cpuid; /* kernel logical cpuid */
int irq_irq; /* the IRQ number */
int irq_int_bit; /* Bridge interrupt pin */
+ /* <0 means MSI */
u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */
int irq_bridge_type;/* pciio asic type (pciio.h) */
void *irq_bridge; /* bridge generating irq */
@@ -53,6 +55,12 @@
};
extern void sn_send_IPI_phys(int, long, int, int);
+extern u64 sn_intr_alloc(nasid_t, int,
+ struct sn_irq_info *,
+ int, nasid_t, int);
+extern void sn_intr_free(nasid_t, int, struct sn_irq_info *);
+extern struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *, nasid_t, int);
+extern struct list_head **sn_irq_lh;
#define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector)
Index: linux-2.6/include/asm-ia64/sn/pcibr_provider.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/sn/pcibr_provider.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/sn/pcibr_provider.h 2006-03-27 14:33:46.994665669 -0600
@@ -55,6 +55,7 @@
#define PCI32_ATE_V (0x1 << 0)
#define PCI32_ATE_CO (0x1 << 1)
#define PCI32_ATE_PREC (0x1 << 2)
+#define PCI32_ATE_MSI (0x1 << 2)
#define PCI32_ATE_PREF (0x1 << 3)
#define PCI32_ATE_BAR (0x1 << 4)
#define PCI32_ATE_ADDR_SHFT 12
@@ -117,8 +118,8 @@
extern int pcibr_init_provider(void);
extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *);
-extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t);
-extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t);
+extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t, int type);
+extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t, int type);
extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
/*
Index: linux-2.6/include/asm-ia64/sn/pcibus_provider_defs.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/sn/pcibus_provider_defs.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/sn/pcibus_provider_defs.h 2006-03-27 14:33:46.995642134 -0600
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
#define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
@@ -45,13 +45,24 @@
*/
struct sn_pcibus_provider {
- dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t);
- dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t);
+ dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t, int flags);
+ dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t, int flags);
void (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
void (*force_interrupt)(struct sn_irq_info *);
void (*target_interrupt)(struct sn_irq_info *);
};
+/*
+ * Flags used by the map interfaces
+ * bits 3:0 specifies format of passed in address
+ * bit 4 specifies that address is to be used for MSI
+ */
+
+#define SN_DMA_ADDRTYPE(x) ((x) & 0xf)
+#define SN_DMA_ADDR_PHYS 1 /* address is an xio address. */
+#define SN_DMA_ADDR_XIO 2 /* address is phys memory */
+#define SN_DMA_MSI 0x10 /* Bus address is to be used for MSI */
+
extern struct sn_pcibus_provider *sn_pci_provider[];
#endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */
Index: linux-2.6/include/asm-ia64/sn/tiocp.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/sn/tiocp.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/sn/tiocp.h 2006-03-27 14:33:46.995642134 -0600
@@ -3,13 +3,14 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_PCI_TIOCP_H
#define _ASM_IA64_SN_PCI_TIOCP_H
#define TIOCP_HOST_INTR_ADDR 0x003FFFFFFFFFFFFFUL
#define TIOCP_PCI64_CMDTYPE_MEM (0x1ull << 60)
+#define TIOCP_PCI64_CMDTYPE_MSI (0x3ull << 60)
/*****************************************************************************
Index: linux-2.6/drivers/pci/msi-altix.c
===================================================================
--- linux-2.6.orig/drivers/pci/msi-altix.c 2006-03-27 13:22:19.000000000 -0600
+++ linux-2.6/drivers/pci/msi-altix.c 2006-03-27 14:33:47.003453861 -0600
@@ -6,13 +6,205 @@
* Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
*/
-#include <asm/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/cpumask.h>
+
+#include <asm/sn/addrs.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/nodepda.h>
+
+#include "msi.h"
+
+struct sn_msi_info {
+ u64 pci_addr;
+ struct sn_irq_info *sn_irq_info;
+};
+
+static struct sn_msi_info *sn_msi_info;
+
+static void
+sn_msi_teardown(unsigned int vector)
+{
+ nasid_t nasid;
+ int widget;
+ struct pci_dev *pdev;
+ struct pcidev_info *sn_pdev;
+ struct sn_irq_info *sn_irq_info;
+ struct pcibus_bussoft *bussoft;
+ struct sn_pcibus_provider *provider;
+
+ sn_irq_info = sn_msi_info[vector].sn_irq_info;
+ if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+ return;
+
+ sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ pdev = sn_pdev->pdi_linux_pcidev;
+ provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ (*provider->dma_unmap)(pdev,
+ sn_msi_info[vector].pci_addr,
+ PCI_DMA_FROMDEVICE);
+ sn_msi_info[vector].pci_addr = 0;
+
+ bussoft = SN_PCIDEV_BUSSOFT(pdev);
+ nasid = NASID_GET(bussoft->bs_base);
+ widget = (nasid & 1) ?
+ TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+ SWIN_WIDGETNUM(bussoft->bs_base);
+
+ sn_intr_free(nasid, widget, sn_irq_info);
+ sn_msi_info[vector].sn_irq_info = NULL;
+
+ return;
+}
int
-sn_msi_init(void)
+sn_msi_setup(struct pci_dev *pdev, unsigned int vector,
+ u32 *addr_hi, u32 *addr_lo, u32 *data)
{
+ int widget;
+ int status;
+ nasid_t nasid;
+ u64 bus_addr;
+ struct sn_irq_info *sn_irq_info;
+ struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
+ struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ if (bussoft == NULL)
+ return -EINVAL;
+
+ if (provider == NULL || provider->dma_map_consistent == NULL)
+ return -EINVAL;
+
+ /*
+ * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
+ * decide which cpu to direct this msi at by default.
+ */
+
+ nasid = NASID_GET(bussoft->bs_base);
+ widget = (nasid & 1) ?
+ TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+ SWIN_WIDGETNUM(bussoft->bs_base);
+
+ sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+ if (! sn_irq_info)
+ return -ENOMEM;
+
+ status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1);
+ if (status) {
+ kfree(sn_irq_info);
+ return -ENOMEM;
+ }
+
+ sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */
+ sn_irq_fixup(pdev, sn_irq_info);
+
+ /* Prom probably should fill these in, but doesn't ... */
+ sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
+ sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
+
/*
- * return error until MSI is supported on altix platforms
+ * Map the xio address into bus space
*/
- return -EINVAL;
+ bus_addr = (*provider->dma_map_consistent)(pdev,
+ sn_irq_info->irq_xtalkaddr,
+ sizeof(sn_irq_info->irq_xtalkaddr),
+ SN_DMA_MSI|SN_DMA_ADDR_XIO);
+ if (! bus_addr) {
+ sn_intr_free(nasid, widget, sn_irq_info);
+ kfree(sn_irq_info);
+ return -ENOMEM;
+ }
+
+ sn_msi_info[vector].sn_irq_info = sn_irq_info;
+ sn_msi_info[vector].pci_addr = bus_addr;
+
+ *addr_hi = (u32)(bus_addr >> 32);
+ *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+
+ /*
+ * In the SN platform, bit 16 is a "send vector" bit which
+ * must be present in order to move the vector through the system.
+ */
+ *data = 0x100 + (unsigned int)vector;
+
+#ifdef CONFIG_SMP
+ set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0);
+#endif
+
+ return 0;
+}
+
+static void
+sn_msi_target(unsigned int vector, unsigned int cpu,
+ u32 *addr_hi, u32 *addr_lo)
+{
+ int slice;
+ nasid_t nasid;
+ u64 bus_addr;
+ struct pci_dev *pdev;
+ struct pcidev_info *sn_pdev;
+ struct sn_irq_info *sn_irq_info;
+ struct sn_irq_info *new_irq_info;
+ struct sn_pcibus_provider *provider;
+
+ sn_irq_info = sn_msi_info[vector].sn_irq_info;
+ if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+ return;
+
+ /*
+ * Release XIO resources for the old MSI PCI address
+ */
+
+ sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ pdev = sn_pdev->pdi_linux_pcidev;
+ provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo);
+ (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
+ sn_msi_info[vector].pci_addr = 0;
+
+ nasid = cpuid_to_nasid(cpu);
+ slice = cpuid_to_slice(cpu);
+
+ new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
+ sn_msi_info[vector].sn_irq_info = new_irq_info;
+ if (new_irq_info == NULL)
+ return;
+
+ /*
+ * Map the xio address into bus space
+ */
+
+ bus_addr = (*provider->dma_map_consistent)(pdev,
+ new_irq_info->irq_xtalkaddr,
+ sizeof(new_irq_info->irq_xtalkaddr),
+ SN_DMA_MSI|SN_DMA_ADDR_XIO);
+
+ sn_msi_info[vector].pci_addr = bus_addr;
+ *addr_hi = (u32)(bus_addr >> 32);
+ *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+}
+
+struct msi_ops sn_msi_ops = {
+ .setup = sn_msi_setup,
+ .teardown = sn_msi_teardown,
+#ifdef CONFIG_SMP
+ .target = sn_msi_target,
+#endif
+};
+
+int
+sn_msi_init(void)
+{
+ sn_msi_info =
+ kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL);
+ if (! sn_msi_info)
+ return -ENOMEM;
+
+ msi_register(&sn_msi_ops);
+ return 0;
}
^ permalink raw reply
* [PATCH 2/3] per-platform IA64_{FIRST,LAST}_DEVICE_VECTOR definitions
From: Mark Maule @ 2006-03-29 2:31 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
In-Reply-To: <20060329023105.13892.52299.24895@lnx-maule.americas.sgi.com>
Abstract IA64_FIRST_DEVICE_VECTOR/IA64_LAST_DEVICE_VECTOR since SN platforms
use a subset of the IA64 range. Implement this by making the above macros
global variables which the platform can override in it setup code.
Also add a reserve_irq_vector() routine used by SN to mark a vector's as
in-use when that weren't allocated through assign_irq_vector().
Signed-off-by: Mark Maule <maule@sgi.com>
Abstract IA64_FIRST_DEVICE_VECTOR/IA64_LAST_DEVICE_VECTOR since SN platforms
use a subset of the IA64 range. Implement this by making the above macros
global variables which the platform can override in it setup code.
Also add a reserve_irq_vector() routine used by SN to mark a vector's as
in-use when that weren't allocated through assign_irq_vector().
Signed-off-by: Mark Maule <maule@sgi.com>
Index: linux-2.6/arch/ia64/kernel/irq_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/irq_ia64.c 2006-03-27 11:10:59.000000000 -0600
+++ linux-2.6/arch/ia64/kernel/irq_ia64.c 2006-03-27 14:28:49.921546952 -0600
@@ -46,6 +46,10 @@
#define IRQ_DEBUG 0
+/* These can be overridden in platform_irq_init */
+int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
+int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
+
/* default base addr of IPI table */
void __iomem *ipi_base_addr = ((void __iomem *)
(__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
@@ -60,7 +64,7 @@
};
EXPORT_SYMBOL(isa_irq_to_vector_map);
-static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
+static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)];
int
assign_irq_vector (int irq)
@@ -89,6 +93,19 @@
printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
}
+int
+reserve_irq_vector (int vector)
+{
+ int pos;
+
+ if (vector < IA64_FIRST_DEVICE_VECTOR ||
+ vector > IA64_LAST_DEVICE_VECTOR)
+ return -EINVAL;
+
+ pos = vector - IA64_FIRST_DEVICE_VECTOR;
+ return test_and_set_bit(pos, ia64_vector_mask);
+}
+
#ifdef CONFIG_SMP
# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE)
#else
Index: linux-2.6/arch/ia64/sn/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/irq.c 2006-03-27 11:10:59.000000000 -0600
+++ linux-2.6/arch/ia64/sn/kernel/irq.c 2006-03-27 14:28:49.925452815 -0600
@@ -202,6 +202,9 @@
int i;
irq_desc_t *base_desc = irq_desc;
+ ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
+ ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
+
for (i = 0; i < NR_IRQS; i++) {
if (base_desc[i].handler == &no_irq_type) {
base_desc[i].handler = &irq_type_sn;
@@ -285,6 +288,7 @@
/* link it into the sn_irq[irq] list */
spin_lock(&sn_irq_info_lock);
list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
+ reserve_irq_vector(sn_irq_info->irq_irq);
spin_unlock(&sn_irq_info_lock);
register_intr_pda(sn_irq_info);
@@ -310,8 +314,11 @@
spin_lock(&sn_irq_info_lock);
list_del_rcu(&sn_irq_info->list);
spin_unlock(&sn_irq_info_lock);
+ if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
+ free_irq_vector(sn_irq_info->irq_irq);
call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
pci_dev_put(pci_dev);
+
}
static inline void
Index: linux-2.6/include/asm-ia64/hw_irq.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/hw_irq.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/hw_irq.h 2006-03-27 14:28:49.931311610 -0600
@@ -47,9 +47,19 @@
#define IA64_CMC_VECTOR 0x1f /* corrected machine-check interrupt vector */
/*
* Vectors 0x20-0x2f are reserved for legacy ISA IRQs.
+ * Use vectors 0x30-0xe7 as the default device vector range for ia64.
+ * Platforms may choose to reduce this range in platform_irq_setup, but the
+ * platform range must fall within
+ * [IA64_DEF_FIRST_DEVICE_VECTOR..IA64_DEF_LAST_DEVICE_VECTOR]
*/
-#define IA64_FIRST_DEVICE_VECTOR 0x30
-#define IA64_LAST_DEVICE_VECTOR 0xe7
+extern int ia64_first_device_vector;
+extern int ia64_last_device_vector;
+
+#define IA64_DEF_FIRST_DEVICE_VECTOR 0x30
+#define IA64_DEF_LAST_DEVICE_VECTOR 0xe7
+#define IA64_FIRST_DEVICE_VECTOR ia64_first_device_vector
+#define IA64_LAST_DEVICE_VECTOR ia64_last_device_vector
+#define IA64_MAX_DEVICE_VECTORS (IA64_DEF_LAST_DEVICE_VECTOR - IA64_DEF_FIRST_DEVICE_VECTOR + 1)
#define IA64_NUM_DEVICE_VECTORS (IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1)
#define IA64_MCA_RENDEZ_VECTOR 0xe8 /* MCA rendez interrupt */
@@ -83,6 +93,7 @@
extern int assign_irq_vector (int irq); /* allocate a free vector */
extern void free_irq_vector (int vector);
+extern int reserve_irq_vector (int vector);
extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
Index: linux-2.6/drivers/pci/msi.c
===================================================================
--- linux-2.6.orig/drivers/pci/msi.c 2006-03-27 13:44:28.000000000 -0600
+++ linux-2.6/drivers/pci/msi.c 2006-03-27 14:29:51.071737801 -0600
@@ -35,7 +35,7 @@
#ifndef CONFIG_X86_IO_APIC
int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS];
#endif
static struct msi_ops *msi_ops;
@@ -383,6 +383,10 @@
return status;
}
+#ifndef CONFIG_X86_IO_APIC
+ irq_vector[0] = FIRST_DEVICE_VECTOR;
+#endif
+
if (last_alloc_vector < 0) {
pci_msi_enable = 0;
printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n");
^ permalink raw reply
* [PATCH 1/3] msi vector targeting abstractions
From: Mark Maule @ 2006-03-29 2:31 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
In-Reply-To: <20060329023105.13892.52299.24895@lnx-maule.americas.sgi.com>
Abstract portions of the MSI core for platforms that do not use standard
APIC interrupt controllers. This is implemented through a new arch-specific
msi setup routine, and a set of msi ops which can be set on a per platform
basis.
Signed-off-by: Mark Maule <maule@sgi.com>
Index: linux-2.6/drivers/pci/msi.c
===================================================================
--- linux-2.6.orig/drivers/pci/msi.c 2006-03-27 11:11:04.000000000 -0600
+++ linux-2.6/drivers/pci/msi.c 2006-03-27 13:32:56.192398615 -0600
@@ -23,8 +23,6 @@
#include "pci.h"
#include "msi.h"
-#define MSI_TARGET_CPU first_cpu(cpu_online_map)
-
static DEFINE_SPINLOCK(msi_lock);
static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
static kmem_cache_t* msi_cachep;
@@ -40,6 +38,15 @@
u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
#endif
+static struct msi_ops *msi_ops;
+
+int
+msi_register(struct msi_ops *ops)
+{
+ msi_ops = ops;
+ return 0;
+}
+
static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
{
memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
@@ -92,7 +99,7 @@
static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
{
struct msi_desc *entry;
- struct msg_address address;
+ u32 address_hi, address_lo;
unsigned int irq = vector;
unsigned int dest_cpu = first_cpu(cpu_mask);
@@ -108,28 +115,36 @@
if (!pos)
return;
+ pci_read_config_dword(entry->dev, msi_upper_address_reg(pos),
+ &address_hi);
pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
- &address.lo_address.value);
- address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
+ &address_lo);
+
+ msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+ pci_write_config_dword(entry->dev, msi_upper_address_reg(pos),
+ address_hi);
pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
- address.lo_address.value);
+ address_lo);
set_native_irq_info(irq, cpu_mask);
break;
}
case PCI_CAP_ID_MSIX:
{
- int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
- PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
+ int offset_hi =
+ entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET;
+ int offset_lo =
+ entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
- address.lo_address.value = readl(entry->mask_base + offset);
- address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
- writel(address.lo_address.value, entry->mask_base + offset);
+ address_hi = readl(entry->mask_base + offset_hi);
+ address_lo = readl(entry->mask_base + offset_lo);
+
+ msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+ writel(address_hi, entry->mask_base + offset_hi);
+ writel(address_lo, entry->mask_base + offset_lo);
set_native_irq_info(irq, cpu_mask);
break;
}
@@ -251,30 +266,6 @@
.set_affinity = set_msi_affinity
};
-static void msi_data_init(struct msg_data *msi_data,
- unsigned int vector)
-{
- memset(msi_data, 0, sizeof(struct msg_data));
- msi_data->vector = (u8)vector;
- msi_data->delivery_mode = MSI_DELIVERY_MODE;
- msi_data->level = MSI_LEVEL_MODE;
- msi_data->trigger = MSI_TRIGGER_MODE;
-}
-
-static void msi_address_init(struct msg_address *msi_address)
-{
- unsigned int dest_id;
- unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU);
-
- memset(msi_address, 0, sizeof(struct msg_address));
- msi_address->hi_address = (u32)0;
- dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT);
- msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE;
- msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
- msi_address->lo_address.u.dest_id = dest_id;
- msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT);
-}
-
static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
static int assign_msi_vector(void)
{
@@ -369,13 +360,29 @@
return status;
}
+ status = msi_arch_init();
+ if (status < 0) {
+ pci_msi_enable = 0;
+ printk(KERN_WARNING
+ "PCI: MSI arch init failed. MSI disabled.\n");
+ return status;
+ }
+
+ if (! msi_ops) {
+ printk(KERN_WARNING
+ "PCI: MSI ops not registered. MSI disabled.\n");
+ status = -EINVAL;
+ return status;
+ }
+
+ last_alloc_vector = assign_irq_vector(AUTO_ASSIGN);
status = msi_cache_init();
if (status < 0) {
pci_msi_enable = 0;
printk(KERN_WARNING "PCI: MSI cache init failed\n");
return status;
}
- last_alloc_vector = assign_irq_vector(AUTO_ASSIGN);
+
if (last_alloc_vector < 0) {
pci_msi_enable = 0;
printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n");
@@ -515,9 +522,11 @@
**/
static int msi_capability_init(struct pci_dev *dev)
{
+ int status;
struct msi_desc *entry;
- struct msg_address address;
- struct msg_data data;
+ u32 address_lo;
+ u32 address_hi;
+ u32 data;
int pos, vector;
u16 control;
@@ -546,23 +555,27 @@
entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control));
}
+ /* Configure MSI capability structure */
+ status = msi_ops->setup(dev, vector,
+ &address_hi,
+ &address_lo,
+ &data);
+ if (status < 0) {
+ dev->irq = entry->msi_attrib.default_vector;
+ kmem_cache_free(msi_cachep, entry);
+ return status;
+ }
/* Replace with MSI handler */
irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
- /* Configure MSI capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- pci_write_config_dword(dev, msi_lower_address_reg(pos),
- address.lo_address.value);
+
+ pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo);
if (is_64bit_address(control)) {
pci_write_config_dword(dev,
- msi_upper_address_reg(pos), address.hi_address);
- pci_write_config_word(dev,
- msi_data_reg(pos, 1), *((u32*)&data));
+ msi_upper_address_reg(pos), address_hi);
+ pci_write_config_word(dev, msi_data_reg(pos, 1), data);
} else
- pci_write_config_word(dev,
- msi_data_reg(pos, 0), *((u32*)&data));
+ pci_write_config_word(dev, msi_data_reg(pos, 0), data);
+
if (entry->msi_attrib.maskbit) {
unsigned int maskbits, temp;
/* All MSIs are unmasked by default, Mask them all */
@@ -652,18 +665,20 @@
/* Replace with MSI-X handler */
irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
/* Configure MSI-X capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu =
- ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- writel(address.lo_address.value,
+ status = msi_ops->setup(dev, vector,
+ &address_hi,
+ &address_lo,
+ &data);
+ if (status < 0)
+ break;
+
+ writel(address_lo,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
- writel(address.hi_address,
+ writel(address_hi,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
- writel(*(u32*)&data,
+ writel(data,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_DATA_OFFSET);
attach_msi_entry(entry, vector);
@@ -809,6 +824,8 @@
void __iomem *base;
unsigned long flags;
+ msi_ops->teardown(vector);
+
spin_lock_irqsave(&msi_lock, flags);
entry = msi_desc[vector];
if (!entry || entry->dev != dev) {
Index: linux-2.6/include/asm-i386/msi.h
===================================================================
--- linux-2.6.orig/include/asm-i386/msi.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-i386/msi.h 2006-03-27 13:22:19.533603545 -0600
@@ -12,4 +12,12 @@
#define LAST_DEVICE_VECTOR 232
#define MSI_TARGET_CPU_SHIFT 12
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6/include/asm-x86_64/msi.h
===================================================================
--- linux-2.6.orig/include/asm-x86_64/msi.h 2006-03-27 11:11:07.000000000 -0600
+++ linux-2.6/include/asm-x86_64/msi.h 2006-03-27 13:22:19.536532943 -0600
@@ -13,4 +13,12 @@
#define LAST_DEVICE_VECTOR 232
#define MSI_TARGET_CPU_SHIFT 12
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6/include/asm-ia64/machvec.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/machvec.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/machvec.h 2006-03-27 13:27:36.669263094 -0600
@@ -76,6 +76,7 @@
typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
+typedef int ia64_mv_msi_init_t (void);
static inline void
machvec_noop (void)
@@ -154,6 +155,7 @@
# define platform_readl_relaxed ia64_mv.readl_relaxed
# define platform_readq_relaxed ia64_mv.readq_relaxed
# define platform_migrate ia64_mv.migrate
+# define platform_msi_init ia64_mv.msi_init
# endif
/* __attribute__((__aligned__(16))) is required to make size of the
@@ -203,6 +205,7 @@
ia64_mv_readl_relaxed_t *readl_relaxed;
ia64_mv_readq_relaxed_t *readq_relaxed;
ia64_mv_migrate_t *migrate;
+ ia64_mv_msi_init_t *msi_init;
} __attribute__((__aligned__(16))); /* align attrib? see above comment */
#define MACHVEC_INIT(name) \
@@ -248,6 +251,7 @@
platform_readl_relaxed, \
platform_readq_relaxed, \
platform_migrate, \
+ platform_msi_init, \
}
extern struct ia64_machine_vector ia64_mv;
@@ -399,5 +403,8 @@
#ifndef platform_migrate
# define platform_migrate machvec_noop_task
#endif
+#ifndef platform_msi_init
+# define platform_msi_init ((ia64_mv_msi_init_t*)NULL)
+#endif
#endif /* _ASM_IA64_MACHVEC_H */
Index: linux-2.6/include/asm-ia64/machvec_sn2.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/machvec_sn2.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/machvec_sn2.h 2006-03-27 13:29:15.149771095 -0600
@@ -117,6 +117,11 @@
#define platform_dma_mapping_error sn_dma_mapping_error
#define platform_dma_supported sn_dma_supported
#define platform_migrate sn_migrate
+#ifdef CONFIG_PCI_MSI
+#define platform_msi_init sn_msi_init
+#else
+#define platform_msi_init ((ia64_mv_msi_init_t*)NULL)
+#endif
#include <asm/sn/io.h>
Index: linux-2.6/include/asm-ia64/msi.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/msi.h 2006-03-27 11:11:06.000000000 -0600
+++ linux-2.6/include/asm-ia64/msi.h 2006-03-27 13:22:19.540438807 -0600
@@ -14,4 +14,16 @@
#define ack_APIC_irq ia64_eoi
#define MSI_TARGET_CPU_SHIFT 4
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ if (platform_msi_init)
+ return platform_msi_init();
+
+ /* default ops for most ia64 platforms */
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6/drivers/pci/Makefile
===================================================================
--- linux-2.6.orig/drivers/pci/Makefile 2006-03-27 11:11:03.000000000 -0600
+++ linux-2.6/drivers/pci/Makefile 2006-03-27 13:22:19.540438807 -0600
@@ -26,7 +26,11 @@
obj-$(CONFIG_PPC64) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_PCI_MSI) += msi.o
+
+msiobj-y := msi.o msi-apic.o
+msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o
+msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o
+obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
#
# ACPI Related PCI FW Functions
Index: linux-2.6/drivers/pci/msi-apic.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/pci/msi-apic.c 2006-03-27 13:22:19.541415273 -0600
@@ -0,0 +1,100 @@
+/*
+ * MSI hooks for standard x86 apic
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#include "msi.h"
+
+/*
+ * Shifts for APIC-based data
+ */
+
+#define MSI_DATA_VECTOR_SHIFT 0
+#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT)
+
+#define MSI_DATA_DELIVERY_SHIFT 8
+#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT)
+#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT)
+
+#define MSI_DATA_LEVEL_SHIFT 14
+#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
+#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
+
+#define MSI_DATA_TRIGGER_SHIFT 15
+#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
+#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
+
+/*
+ * Shift/mask fields for APIC-based bus address
+ */
+
+#define MSI_ADDR_HEADER 0xfee00000
+
+#define MSI_ADDR_DESTID_MASK 0xfff0000f
+#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT)
+
+#define MSI_ADDR_DESTMODE_SHIFT 2
+#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT)
+#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT)
+
+#define MSI_ADDR_REDIRECTION_SHIFT 3
+#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
+#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
+
+
+static void
+msi_target_apic(unsigned int vector,
+ unsigned int dest_cpu,
+ u32 *address_hi, /* in/out */
+ u32 *address_lo) /* in/out */
+{
+ u32 addr = *address_lo;
+
+ addr &= MSI_ADDR_DESTID_MASK;
+ addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu));
+
+ *address_lo = addr;
+}
+
+static int
+msi_setup_apic(struct pci_dev *pdev, /* unused in generic */
+ unsigned int vector,
+ u32 *address_hi,
+ u32 *address_lo,
+ u32 *data)
+{
+ unsigned long dest_phys_id;
+
+ dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
+
+ *address_hi = 0;
+ *address_lo = MSI_ADDR_HEADER |
+ MSI_ADDR_DESTMODE_PHYS |
+ MSI_ADDR_REDIRECTION_CPU |
+ MSI_ADDR_DESTID_CPU(dest_phys_id);
+
+ *data = MSI_DATA_TRIGGER_EDGE |
+ MSI_DATA_LEVEL_ASSERT |
+ MSI_DATA_DELIVERY_FIXED |
+ MSI_DATA_VECTOR(vector);
+
+ return 0;
+}
+
+static void
+msi_teardown_apic(unsigned int vector)
+{
+ return; /* no-op */
+}
+
+/*
+ * Generic ops used on most IA archs/platforms. Set with msi_register()
+ */
+
+struct msi_ops msi_apic_ops = {
+ .setup = msi_setup_apic,
+ .teardown = msi_teardown_apic,
+ .target = msi_target_apic,
+};
Index: linux-2.6/drivers/pci/msi.h
===================================================================
--- linux-2.6.orig/drivers/pci/msi.h 2006-03-27 11:11:04.000000000 -0600
+++ linux-2.6/drivers/pci/msi.h 2006-03-27 13:22:19.542391739 -0600
@@ -6,6 +6,68 @@
#ifndef MSI_H
#define MSI_H
+/*
+ * MSI operation vector. Used by the msi core code (drivers/pci/msi.c)
+ * to abstract platform-specific tasks relating to MSI address generation
+ * and resource management.
+ */
+struct msi_ops {
+ /**
+ * setup - generate an MSI bus address and data for a given vector
+ * @pdev: PCI device context (in)
+ * @vector: vector allocated by the msi core (in)
+ * @addr_hi: upper 32 bits of PCI bus MSI address (out)
+ * @addr_lo: lower 32 bits of PCI bus MSI address (out)
+ * @data: MSI data payload (out)
+ *
+ * Description: The setup op is used to generate a PCI bus addres and
+ * data which the msi core will program into the card MSI capability
+ * registers. The setup routine is responsible for picking an initial
+ * cpu to target the MSI at. The setup routine is responsible for
+ * examining pdev to determine the MSI capabilities of the card and
+ * generating a suitable address/data. The setup routine is
+ * responsible for allocating and tracking any system resources it
+ * needs to route the MSI to the cpu it picks, and for associating
+ * those resources with the passed in vector.
+ *
+ * Returns 0 if the MSI address/data was successfully setup.
+ **/
+
+ int (*setup) (struct pci_dev *pdev, unsigned int vector,
+ u32 *addr_hi, u32 *addr_lo, u32 *data);
+
+ /**
+ * teardown - release resources allocated by setup
+ * @vector: vector context for resources (in)
+ *
+ * Description: The teardown op is used to release any resources
+ * that were allocated in the setup routine associated with the passed
+ * in vector.
+ **/
+
+ void (*teardown) (unsigned int vector);
+
+ /**
+ * target - retarget an MSI at a different cpu
+ * @vector: vector context for resources (in)
+ * @cpu: new cpu to direct vector at (in)
+ * @addr_hi: new value of PCI bus upper 32 bits (in/out)
+ * @addr_lo: new value of PCI bus lower 32 bits (in/out)
+ *
+ * Description: The target op is used to redirect an MSI vector
+ * at a different cpu. addr_hi/addr_lo coming in are the existing
+ * values that the MSI core has programmed into the card. The
+ * target code is responsible for freeing any resources (if any)
+ * associated with the old address, and generating a new PCI bus
+ * addr_hi/addr_lo that will redirect the vector at the indicated cpu.
+ **/
+
+ void (*target) (unsigned int vector, unsigned int cpu,
+ u32 *addr_hi, u32 *addr_lo);
+};
+
+extern int msi_register(struct msi_ops *ops);
+
#include <asm/msi.h>
/*
@@ -63,67 +125,6 @@
#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK)
#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK)
-/*
- * MSI Defined Data Structures
- */
-#define MSI_ADDRESS_HEADER 0xfee
-#define MSI_ADDRESS_HEADER_SHIFT 12
-#define MSI_ADDRESS_HEADER_MASK 0xfff000
-#define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f
-#define MSI_TARGET_CPU_MASK 0xff
-#define MSI_DELIVERY_MODE 0
-#define MSI_LEVEL_MODE 1 /* Edge always assert */
-#define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */
-#define MSI_PHYSICAL_MODE 0
-#define MSI_LOGICAL_MODE 1
-#define MSI_REDIRECTION_HINT_MODE 0
-
-struct msg_data {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u32 vector : 8;
- __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
- __u32 reserved_1 : 3;
- __u32 level : 1; /* 0: deassert | 1: assert */
- __u32 trigger : 1; /* 0: edge | 1: level */
- __u32 reserved_2 : 16;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u32 reserved_2 : 16;
- __u32 trigger : 1; /* 0: edge | 1: level */
- __u32 level : 1; /* 0: deassert | 1: assert */
- __u32 reserved_1 : 3;
- __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
- __u32 vector : 8;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
-} __attribute__ ((packed));
-
-struct msg_address {
- union {
- struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u32 reserved_1 : 2;
- __u32 dest_mode : 1; /*0:physic | 1:logic */
- __u32 redirection_hint: 1; /*0: dedicated CPU
- 1: lowest priority */
- __u32 reserved_2 : 4;
- __u32 dest_id : 24; /* Destination ID */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u32 dest_id : 24; /* Destination ID */
- __u32 reserved_2 : 4;
- __u32 redirection_hint: 1; /*0: dedicated CPU
- 1: lowest priority */
- __u32 dest_mode : 1; /*0:physic | 1:logic */
- __u32 reserved_1 : 2;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- }u;
- __u32 value;
- }lo_address;
- __u32 hi_address;
-} __attribute__ ((packed));
-
struct msi_desc {
struct {
__u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
@@ -132,7 +133,7 @@
__u8 reserved: 1; /* reserved */
__u8 entry_nr; /* specific enabled entry */
__u8 default_vector; /* default pre-assigned vector */
- __u8 current_cpu; /* current destination cpu */
+ __u8 unused; /* formerly unused destination cpu*/
}msi_attrib;
struct {
Index: linux-2.6/drivers/pci/msi-altix.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/pci/msi-altix.c 2006-03-27 13:22:19.543368205 -0600
@@ -0,0 +1,18 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+#include <asm/errno.h>
+
+int
+sn_msi_init(void)
+{
+ /*
+ * return error until MSI is supported on altix platforms
+ */
+ return -EINVAL;
+}
^ permalink raw reply
* [PATCH 0/3] msi abstractions and support for altix
From: Mark Maule @ 2006-03-29 2:31 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
Resend #7: resubmit against Linus' linux-2.6.git tree
Patch set to abstract portions of the MSI core so that it can be used on
architectures which don't use standard interrupt controllers.
Changes from Resend #6
+ Fix patches so they apply cleanly against
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+ Remove hardcoded setting of pdev->no_msi=1 for altix
Changes from Resend #5
+ Move altix msi ops down into drivers/pci/msi-altix.c
+ Simplify ia64 platform_msi_init machvec
Changes from Resend #4
+ Fix an x86_64 build problem
+ Fix an ia64 CONFIG_IA64_GENERIC build problem
+ Fix a bug in the new ia64 reserve_irq_vector()
+ Restore dev->irq if msi_ops->setup fails
+ Redo msi-altix.patch so it applies on 2.6.16-rc1
Changes from Resend #3
+ Move external declarations of msi_apic_ops out of routines, and up earlier
in the respective .h files.
+ Add comments to the msi_ops structure declaration
Changes from Resend #2
+ Cleanup the ia64 platform_msi_init macro so it works on non-altix ia64
Changes from initial version
+ Change uintXX_t to uXX
+ Change _callouts to _ops
+ Renamed the _generic routines to _apic and moved them to a new file
msi-apic.c
+ Have each msi_arch_init() routine call msi_register() with the desired
msi ops for that platform.
+ Moved msi_address, msi_data, and related defs out of msi.h and into
msi-apic.c, replaced by shifts/masks.
+ Rolled msi-arch-init.patch and msi-callouts.patch into a single msi-ops.patch
Mark
1/3 msi-ops.patch
Add an msi_arch_init() hook which can be used to perform platform
specific setup prior to msi use.
Define a set of msi ops to implement the platform-specific tasks:
setup - set up plumbing to get a vector directed at a default
cpu, and return the corresponding MSI bus address and data.
teardown - inverse of msi_setup
target - retarget a vector to a given cpu
Define the routine msi_register() called from msi_arch_init()
to set the desired ops.
Move a bunch of apic-specific code out of the msi core .h/.c and
into a new msi-apic.c file.
2/3 ia64-per-platform-device-vector.patch
For the ia64 arch, allow per-platform definitions of
IA64_FIRST_DEVICE_VECTOR and IA64_LAST_DEVICE_VECTOR.
3/3 msi-altix.patch
Altix specific callouts to implement MSI.
^ permalink raw reply
* Re: Memory mapping PCI memory region to user space
From: Phil Nitschke @ 2006-03-29 2:26 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-embedded
In-Reply-To: <43A30583-5E99-46A8-B419-1AEAB8440840@kernel.crashing.org>
[-- Attachment #1: Type: text/plain, Size: 1960 bytes --]
On Mon, 2006-03-27 at 10:18 -0600, Kumar Gala wrote:
> On Mar 27, 2006, at 2:02 AM, Phil Nitschke wrote:
>
> > On Thu, 2006-03-23 at 09:44 -0600, Kumar Gala wrote:
> >> On Mar 23, 2006, at 8:21 AM, Wyse, Chris wrote:
> >>
> >>> Hi,
> >>>
> >>> I'm trying to map a PCI memory region 1 into user space from my
> >>> driver (PPC440GX, Linux 2.6.10). Here's the mmap routine of the
> >>> driver that I'm using:
> >>
> >> Why don't use the mmap file exposed by sysfs so you dont have to
> >> write your own code?
> >>
> >> See Documentation/filesystems/sysfs-pci.txt. But effectively down
> >> under /sys/bus/pci/devices/[domain:bus:dev:func]/ you will get
> >> resource[0..N-1] that corresponds to each BAR on the device. This is
> >> a mmap file to access that region.
> >
> > I have some custom hardware that appears on the PCI bus as follows:
> >
> > bash-3.00# lspci -vv
> > 00:01.0 Class 0680: 1172:0004 (rev 01)
> > Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr-
> > Stepping- SERR- FastB2B-
> > Status: Cap- 66Mhz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort+
> > <TAbort- <MAbort- >SERR- <PERR-
> > Latency: 128, Cache Line Size 08
> > Interrupt: pin A routed to IRQ 71
> > Region 0: Memory at 000000009ffff000 (32-bit, non-prefetchable)
> > [size=4K]
> > Region 1: Memory at 000000009fc00000 (32-bit, non-prefetchable)
> > [size=2M]
> >
> > But when I try to access resource0 or resource1, I get a read error.
> > What characteristic of the device or driver determines whether it will
> > allow mmap-ing?
> >
> > (I've written the driver for this device myself.)
>
> Nothing special beyond normal unix perms on the resource[0..n] files
> to my knowledge. When you say you get a read error what exactly does
> that mean?
It means I had a bug in my program which read (mmap()ed) the resouce :-(
It is fixed now (see below). Thanks for the tip.
--
Phil Nitschke <Phil.Nitschke@avalon.com.au>
Avalon Systems Pty Ltd
[-- Attachment #2: mmap.c --]
[-- Type: text/x-csrc, Size: 1009 bytes --]
#include <assert.h>
#include <byteswap.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
int
main (int argc, char **argv)
{
/* Define constants for specific to the Base Address Register(s)
* (defining the PCI I/O Address Region) for our hardware. */
const uint32_t BAR_LENGTH = 0x200000;
const uint32_t CTRL_REGS = 0x80000;
const uint32_t CTRL_LEN = 0x30;
int i, fd;
uint32_t *ptr;
fd = open("/sys/bus/pci/devices/0000:00:01.0/resource1", O_RDWR);
ptr = (uint32_t*) mmap(NULL, BAR_LENGTH, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
// If ptr == -1, then the user was probably not root
assert(ptr != MAP_FAILED);
printf ("Mapped %p bytes beginning at address %p\n", BAR_LENGTH, ptr);
for (i = CTRL_REGS; i < (CTRL_REGS + CTRL_LEN); i += 4)
printf ("mmap[0x%08x] (%p) = 0x%08x [0x%08x]\n",
i, ptr + i/4, *(ptr + i/4), bswap_32(*(ptr + i/4)));
munmap(ptr, BAR_LENGTH);
close(fd);
}
^ permalink raw reply
* Re: [PATCH] DTC - validation by device_type
From: Hollis Blanchard @ 2006-03-29 2:03 UTC (permalink / raw)
To: Paul Nasrat; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <1143586160.2660.19.camel@enki.eridu>
On Mar 28, 2006, at 4:49 PM, Paul Nasrat wrote:
>
> It'd be nice to be able to validate by device_type, to ensure that we
> don't reinvent the wheel (address vs. local-mac-address) and to give
> embedded designers an added level of sanity checking.
>
> Here is a proposed implementation with an implemented check for
> "network".
>
> Signed-off-by: Paul Nasrat <pnasrat@redhat.com>
>
> diff --git a/livetree.c b/livetree.c
> index ef54174..351773b 100644
> --- a/livetree.c
> +++ b/livetree.c
> @@ -441,6 +441,52 @@ static int check_structure(struct node *
> (propname), (node)->fullpath); \
> } while (0)
>
> +static int check_network(struct node *net)
> +{
> +
> + int ok = 1;
> + struct property *prop;
> +
> + CHECK_HAVE_STREQ(net, "device_type", "network");
The only reason you got into this function was that device_type ==
"network"...
> + CHECK_HAVE(net, "reg");
> + CHECK_HAVE(net, "local-mac-address");
> + CHECK_HAVE(net, "mac-address");
> + CHECK_HAVE(net, "address-bits");
> +
> + return ok;
> +}
> +
> +static struct {
> + char *devtype;
> + int (*check_fn)(struct node *node);
> +} devtype_checker_table[] = {
> + {"network", check_network},
> +};
> +
> +static int check_devtypes(struct node *root)
> +{
> +
> + struct node *child;
> + struct property *prop;
> + int ok = 1;
> + int i;
> +
> + for_each_child(root, child) {
> + /* check this node */
> + if ((prop = get_property((child), ("device_type"))))
> + for (i = 0; i < ARRAY_SIZE(devtype_checker_table); i++) {
> + if (streq(prop->val.val, devtype_checker_table[i].devtype))
> + if (! devtype_checker_table[i].check_fn(child)) {
> + ok = 0;
> + break;
> + }
Unless this is some weird style thing, that close brace seems
misindented.
> + }
> + ok = check_devtypes(child);
> + }
> +
> + return ok;
> +}
> +
> static int check_root(struct node *root)
> {
> struct property *prop;
> @@ -716,6 +762,7 @@ int check_device_tree(struct node *dt)
> ok = ok && check_cpus(dt);
> ok = ok && check_memory(dt);
> ok = ok && check_chosen(dt);
> + ok = ok && check_devtypes(dt);
> if (! ok)
> return 0;
>
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* [OT] ppc64 serialization problem
From: Greg Smith @ 2006-03-29 1:58 UTC (permalink / raw)
To: linuxppc-dev
We have a multi-threaded app running on a p520 in 64 bit mode.
Thread A does
pthread_mutex_lock(&lock);
u32 &= ~bitA;
pthread_mutex_unlock(&lock);
and Thread B does
pthread_mutex_lock(&lock);
u32 |= bitB;
A = u32;
B = u32;
pthread_mutex_unlock(&lock);
On rare occasions, values A and B will differ! In the examples that I
have seen, there is contention with `lock'. This phenomenon does not
occur on ppc32 or a number of other architectures that we support.
I confess I do not know the linux version nor the glibc version nor what
pthreads implementation is being used. I'll find that out shortly.
What I am curious about is where the problem might lie
(kernel/lib/pthreads/app) so I can ask the right people.
Thank you for your patience,
Greg Smith
^ permalink raw reply
* Re: snd-aoa: new apple sound driver
From: Benjamin Herrenschmidt @ 2006-03-28 23:40 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev, debian-powerpc, Alastair Poole
In-Reply-To: <1143547826.13615.24.camel@localhost>
> GPIO stuff. Currently, the only GPIO I touch is the amp-mute one to turn
> on the internal speakers. This is done in the onyx codec module which
> obviously isn't the right place for it. This should be moved into the
> layout fabric module which draws on some common gpio code to program the
> GPIOs. Then it creates controls alsa for amp-mute etc. instead of
> unconditionally turning it on, and also registers the interrupts for
> headhpone detection etc.
The GPIO stuff is a bit can-of-worms-ish ... we need at least 2
different implementations for machines using "old style" direct GPIO
access and machines using platform functions. So we may need a gpio
"driver" with 2 instances there.
I think we need to hook that with the input/output net... basically we
just say things like mute/unmute(id) and the gpio "layer" sort of
matches the input/output "id" with whatever gpios it has at hand. That's
also why I think your input/output IDs should have separate entries for
combo connectors vs. analog line out (at least you used not to, I
haven't looked at the latest code).
Then, the core would get events from interrupts (or clock switches from
the codecs) via a yet-to-be-defined call and would react by calling the
various mute/unmutes accordingly for available inputs and outputs on the
bus where the event occured.
For things like headphone/speaker automute, I think we need a kind of
tristate.. either that, or we need a bit mask of mute conditions. When
any of them is set, it's muted. That way, the "user" mute control sticks
regardless of the automute action or temporary mute to analog outputs
because, for example, the digital input lost its clock and we are
switching (we need to mute to avoid "clics").
> Clock setting. I'm clueless as to programming keylargo in linux. Thing
> is, I need to stop the clock to the i2s cell before reprogramming it's
> serial format register, and this requires access to the FCR registers.
> But I don't know how to get at them best. Need help here. Clock setting
> also includes running the i2s cell in slave mode so we can have digital
> input. The infrastructure for slave mode isn't too established yet, but
> it should be easy to fit it over what is currently there in
> soundbus.h/i2sbus.
Hrm... So my feature calls are doing too much at once... (they both do
the clocks and the cell enable). I don't do clock refcounting like Apple
does tho, thus the main clock sources are always enabled. So I think all
you have to do is toggle the I2Sn_CLK_ENABLE bits ...
Can you verify if all machines that have digital inputs (thus all
machines for which you may need to do that kind of clock switching) also
have working platform functions for doing so ? If they do, then it's
really just a matter of calling those. If not, then we can either
ioremap the FCR's in the driver and play with them (evil solution +
possibly locking problems) or add a feature call.
In the later case, you add a feature call in pmac_feature.h and the
appropriate entry in the table in feature.c and then you can toggle bits
as you wish with appropriate locking (look at eixsting code in there). I
can give you more details on irc if you need.
But it would be nice if it could all be done with platform functions
instead.
> Modalias situtation. I played some tricks: i2sbus depends on soundbus
> but announces its willingness to be bound to the i2s OF thing that macio
> exports on its bus, so i2sbus is loaded automatically. i2sbus creates
> some soundbus devices that have a name based on the layout ID if
> possible, which should in turn auto-load snd-aoa-fabric-layout which
> declares its willingness to be bound to such devices. This doesn't
> happen during boot, even though modprobe `cat ...../modalias` works just
> fine. No idea, need help from someone versed with hotplugging.
> But hey, it's already much much closer than snd-powermac ever was ;)
Yeah :) There might be some issue with the macio automatching from
userland, not sure yet, could just be missing bits in hotplug scripts.
> Recording. There's code to record sound, but it doesn't do anything on
> my machine. I have no idea why.
What machine ? The quad ? maybe you need some gpio manipulation or maybe
you just didn't get something right in onyx ... I'll try later.
> Suspend. I have a plan for it, so before thinking about it you may want
> to look at some old revisions of my code where a huge comment about
> suspend is buried in soundbus.h (I removed it again because it wasn't
> quite right any more, but still has the essence of what I intend to do).
No time to look now, but the idea would be that:
- macio_device gets the suspend resume event. That is, the i2s busses
basically. That code should forward to all attaches sub-busses which
then dispatch to codecs.
- ordering of things should be: mute all, stop alsa, stop codecs
(enable whatever internal power management mode they may have), stop
clocks, disable i2s cells.
> Onyx digital output. Currently, onyx always declares that the digital
> output is usable even if it is turned off, leading to a restriction in
> the output formats you can play. Note that due to 'clock switching'
> above, you can only play 44.1KHz currently anyway. But Onyx should make
> that depend on the status of the control, and then lock the control if a
> bitrate was chosen that isn't compatible with the digital output.
Yup.
> Make i2sbus compatible with old machines. I wrote i2sbus for new
> machines only, it relies a lot on stuff that older machines may not have
> in the device tree. So someone who has older machines should look into
> it and give me patches.
I'll play with adapting the whole stuff to older machines, I have plenty
of those :) We also need to implement a davbus module, so make sure you
don't have too much i2s-related assumptions in your core.. No timeframe
for that though, I'm fairly busy with other things at the moment
> Now, that said, it's actually working fine for just playing sound on the
> internal speakers now :)
> The GPIO stuff should be a fairly low-hanging fruit so if someone wants
> to take it...
It's also a complicated thing because of the need to deal with old
machines and the need to coordinate properly & serialize... things like
interrupts or events from the codec should, if possible, use alsa hidden
controls or whatever other ways to properly serialize, if possible, be
run at task level (from a work queue) and things like that (due to the
need for delays etc...
Ben.
^ permalink raw reply
* [PATCH] DTC - validation by device_type
From: Paul Nasrat @ 2006-03-28 22:49 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
Jon,
It'd be nice to be able to validate by device_type, to ensure that we
don't reinvent the wheel (address vs. local-mac-address) and to give
embedded designers an added level of sanity checking.
Here is a proposed implementation with an implemented check for
"network".
Signed-off-by: Paul Nasrat <pnasrat@redhat.com>
diff --git a/livetree.c b/livetree.c
index ef54174..351773b 100644
--- a/livetree.c
+++ b/livetree.c
@@ -441,6 +441,52 @@ static int check_structure(struct node *
(propname), (node)->fullpath); \
} while (0)
+static int check_network(struct node *net)
+{
+
+ int ok = 1;
+ struct property *prop;
+
+ CHECK_HAVE_STREQ(net, "device_type", "network");
+ CHECK_HAVE(net, "reg");
+ CHECK_HAVE(net, "local-mac-address");
+ CHECK_HAVE(net, "mac-address");
+ CHECK_HAVE(net, "address-bits");
+
+ return ok;
+}
+
+static struct {
+ char *devtype;
+ int (*check_fn)(struct node *node);
+} devtype_checker_table[] = {
+ {"network", check_network},
+};
+
+static int check_devtypes(struct node *root)
+{
+
+ struct node *child;
+ struct property *prop;
+ int ok = 1;
+ int i;
+
+ for_each_child(root, child) {
+ /* check this node */
+ if ((prop = get_property((child), ("device_type"))))
+ for (i = 0; i < ARRAY_SIZE(devtype_checker_table); i++) {
+ if (streq(prop->val.val, devtype_checker_table[i].devtype))
+ if (! devtype_checker_table[i].check_fn(child)) {
+ ok = 0;
+ break;
+ }
+ }
+ ok = check_devtypes(child);
+ }
+
+ return ok;
+}
+
static int check_root(struct node *root)
{
struct property *prop;
@@ -716,6 +762,7 @@ int check_device_tree(struct node *dt)
ok = ok && check_cpus(dt);
ok = ok && check_memory(dt);
ok = ok && check_chosen(dt);
+ ok = ok && check_devtypes(dt);
if (! ok)
return 0;
^ permalink raw reply related
* [PATCH] Janitor: drivers/net/pcnet32: fix incorrect comments
From: Linas Vepstas @ 2006-03-28 22:36 UTC (permalink / raw)
To: tsbogend, donf; +Cc: linuxppc-dev, linux-kernel, jklewis, netdev
Please sign-off/ack/apply and/or forward upstream.
[PATCH] Janitor: drivers/net/pcnet32: fix incorrect comments
The comments concerning how the pcnet32 ethernet device driver selects
the MAC addr to use are incorrect. A recent patch (in the last 3 months)
changed how the code worked, but did not change the comments.
Side comment: the new behaviour is good; I've got a pcnet32 card which
powers up with garbage in the CSR's, and a good MAC addr in the PROM.
Signed-off-by: Linas Vepstas <linas@linas.org>
----
drivers/net/pcnet32.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
Index: linux-2.6.16-git6/drivers/net/pcnet32.c
===================================================================
--- linux-2.6.16-git6.orig/drivers/net/pcnet32.c 2006-03-23 12:21:41.000000000 -0600
+++ linux-2.6.16-git6/drivers/net/pcnet32.c 2006-03-28 16:08:23.398158717 -0600
@@ -1167,8 +1167,8 @@ pcnet32_probe1(unsigned long ioaddr, int
* station address PROM at the base address and programmed into the
* "Physical Address Registers" CSR12-14.
* As a precautionary measure, we read the PROM values and complain if
- * they disagree with the CSRs. Either way, we use the CSR values, and
- * double check that they are valid.
+ * they disagree with the CSRs. If they miscompare, and the PROM addr
+ * is valid, then the PROM addr is used.
*/
for (i = 0; i < 3; i++) {
unsigned int val;
^ permalink raw reply
* Re: Kernel for MPC Lite 5200 will not compile
From: Wolfgang Denk @ 2006-03-28 22:33 UTC (permalink / raw)
To: John Rigby; +Cc: linuxppc-embedded
In-Reply-To: <4b73d43f0603280815n3fc7bb5dq38b72f87f18b905f@mail.gmail.com>
In message <4b73d43f0603280815n3fc7bb5dq38b72f87f18b905f@mail.gmail.com> you wrote:
>
> Sorry I'm not sure what the state of 5200 support in the eldk. I know that
> Wolfgang
> has said that 2.6 is not supported though. You may want to try out Sylvains
Well, that's exxactly the state: not supported (i. e. known to be
broken).
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Quotation, n. The act of repeating erroneously the words of another.
The words erroneously repeated.
- Ambrose Bierce _The Devil's Dictionary_
^ permalink raw reply
* Re: Kernel for MPC Lite 5200 will not compile
From: Wolfgang Denk @ 2006-03-28 22:31 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <20060328000703.GA95672@server.idefix.loc>
In message <20060328000703.GA95672@server.idefix.loc> you wrote:
>
> I installed today ELDK 4.0 for the LITE5200 board (icecube).
There is no "ELDK 4.0 for the LITE5200 board".
> ./install -d /usr/local/eldk ppc_6xx
This installas ELDK 4.0 for PPC 6xx processors. Nothing less, but
nothing more either.
> After compiling u-boot and playing a little bit with it, i tried to
> compile the kernel 2.6.
Which kernel tree are you using? There is no support for MPC5200 in
the DENX Linux tree. Well, some code is there, as there is in the
public 2.6 kernel tree, but it's known to be broken and not supported
by us.
> For this I used the git repository.
Which one?
> I copied the file arch/ppc/configs/lite5200_defconfig to .config, and
> tried the following one:
> make ARCH=ppc CROSS_COMPILE=ppc_6xx- uImage
That's not the official way to build images.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
We, the unwilling, led by the unknowing, are doing the impossible for
the ungrateful. We have done so much, for so long, with so little, we
are now qualified to do anything with nothing.
^ permalink raw reply
* Re: 2.6.16 does not boot on powerbook
From: Benjamin Herrenschmidt @ 2006-03-28 22:08 UTC (permalink / raw)
To: Dustin Lang; +Cc: linuxppc-dev, Michal Purzynski
In-Reply-To: <Pine.LNX.4.60.0603280630130.8520@tin.icics.ubc.ca>
> 2.6.16 works fine on my PowerBook 6,2. When I patched up to 2.6.16 I
> found I had to go through the config process - some of the PowerMac
> options seem to have been turned off. Maybe that was just me doing
> something wrong, or maybe some of the Kconfig defaults changed?
Some stuffs changed in Kconfig causing it to stupidly drop most of the
pmac options ...
Ben.
^ permalink raw reply
* Re: 2.6.16 does not boot on powerbook
From: Benjamin Herrenschmidt @ 2006-03-28 22:07 UTC (permalink / raw)
To: wrobell; +Cc: linuxppc-dev
In-Reply-To: <1143556705.3562.104.camel@RECENT-CONVERT>
On Tue, 2006-03-28 at 15:38 +0100, wrobell wrote:
> On Tue, 2006-03-28 at 14:01 +0200, Michal Purzynski wrote:
> > -----BEGIN PGP SIGNED MESSAGE-----
> > Hash: SHA1
> >
> > hey,
> >
> > i've just installed 2.6.16 vanilla kernel on powerbook G4 but it cannot
> > boot.
> [...]
> > my kernel config (the same config works on 2.6.15)
> [...]
> > # CONFIG_PPC_PMAC is not set
>
> you have to go through configuration options carefully.
> some of them are disabled because of ppc32/64 arch merging changes
> (please correct me if i am wrong).
There is a pmac32_defconfig you can use as a basis now.
Ben.
^ permalink raw reply
* Re: snd-aoa & rates
From: Benjamin Herrenschmidt @ 2006-03-28 22:07 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev list
In-Reply-To: <1143548101.13615.30.camel@localhost>
On Tue, 2006-03-28 at 14:15 +0200, Johannes Berg wrote:
> Hi,
>
> > Current snd-aoa blew up on me at module load btw ... anyway, that's not
> > my point here :)
>
> Yeah, keywest programming. Need help, see other mail.
No other mail in the box ...
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox