* Re: [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function
From: Kumar Gala @ 2006-05-17 13:47 UTC (permalink / raw)
To: Zang Roy-r61911
Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D61D@zch01exm40.ap.freescale.net>
On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:
> Add Tundra Semiconductor tsi108 host bridge common function support.
>
> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
>
> ---
>
> arch/powerpc/sysdev/Makefile | 1
> arch/powerpc/sysdev/tsi108_common.c | 224 ++++++++++++++++++++++++
> +++++++++++
> 2 files changed, 225 insertions(+), 0 deletions(-)
> create mode 100644 arch/powerpc/sysdev/tsi108_common.c
>
> ab3b477b5924d2c9cbf6ba3ae4d95fe333c9bad9
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/
> Makefile
> index 4c2b356..8c0afb7 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
> obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
> obj-$(CONFIG_PPC_83xx) += ipic.o
> obj-$(CONFIG_FSL_SOC) += fsl_soc.o
> +obj-$(CONFIG_TSI108_BRIDGE) += tsi108_common.o tsi108_pic.o
> diff --git a/arch/powerpc/sysdev/tsi108_common.c b/arch/powerpc/
> sysdev/tsi108_common.c
> new file mode 100644
> index 0000000..3c55f99
> --- /dev/null
> +++ b/arch/powerpc/sysdev/tsi108_common.c
> @@ -0,0 +1,224 @@
> +/*
> + * arch/ppc/syslib/tsi108_common.c
> + *
> + * Common routines for Tundra Semiconductor TSI108 host bridge.
> + *
> + * 2004-2005 (c) Tundra Semiconductor Corp.
> + * Author: Alex Bounine (alexandreb@tundra.com)
> + *
> + * This program is free software; you can redistribute it and/or
> modify it
> + * under the terms of the GNU General Public License as published
> by the Free
> + * Software Foundation; either version 2 of the License, or (at
> your option)
> + * any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public
> License along with
> + * this program; if not, write to the Free Software Foundation,
> Inc., 59
> + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/slab.h>
> +
> +#include <asm/byteorder.h>
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/uaccess.h>
> +#include <asm/machdep.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/tsi108.h>
> +#include <asm/prom.h>
> +
> +u32 tsi108_pci_cfg_base;
> +
> +#undef TSI108_PCI_DEBUG
> +
> +#define tsi_mk_config_addr(bus, devfunc, offset) \
> + (((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)|
> tsi108_pci_cfg_base)
> +
> +static phys_addr_t tsi108_csr_base = -1;
> +
> +phys_addr_t get_csrbase(void)
> +{
> + struct device_node *tsi;
> +
> + if (tsi108_csr_base != -1)
> + return tsi108_csr_base;
> +
> + tsi = of_find_node_by_type(NULL, "tsi-bridge");
> + if (tsi) {
> + unsigned int size;
> + void *prop = get_property(tsi, "reg", &size);
> + tsi108_csr_base = of_translate_address(tsi, prop);
> + of_node_put(tsi);
> + };
> + return tsi108_csr_base;
> +}
> +
> +u32 get_vir_csrbase(void)
> +{
> + return (u32) (ioremap(get_csrbase(), 0x10000));
> +}
> +
> +EXPORT_SYMBOL(get_csrbase);
> +EXPORT_SYMBOL(get_vir_csrbase);
> +
> +/*
> + * Prosessor Bus Clock (in MHz) defined by CG_PB_SELECT
> + * (based on recommended Tsi108 reference clock 33MHz)
> + */
> +static int pb_clk_sel[8] = { 0, 0, 183, 100, 133, 167, 200, 233 };
> +
> +/*
> + * SDRAM Clock (in MHz) defined by CG_SD_SELECT
> + * (based on recommended Tsi108 reference clock 33MHz)
> + */
> +static int sd_clk_sel[2][8] = {
> + {0, 0, 183, 100, 133, 167, 200, 233}, /* SYNC */
> + {0, 0, 0, 0, 133, 160, 200, 0} /* ASYNC */
> +};
> +
Can the PCI use indirect like used on most other PPC platforms.
> +int
> +tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc,
> + int offset, int len, u32 val)
> +{
> + volatile unsigned char *cfg_addr;
> +
> + cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
> + devfunc, offset) |
> + (offset & 0x03));
> +
> +#ifdef TSI108_PCI_DEBUG
> + printk("PCI CFG write : ");
> + printk("%d:0x%x:0x%x ", bus->number, devfunc, offset);
> + printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
> + printk("data = 0x%08x\n", val);
> +#endif
> +
> + switch (len) {
> + case 1:
> + out_8((u8 *) cfg_addr, val);
> + break;
> + case 2:
> + out_le16((u16 *) cfg_addr, val);
> + break;
> + default:
> + out_le32((u32 *) cfg_addr, val);
> + break;
> + }
> +
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +void tsi108_clear_pci_error(u32 pci_cfg_base)
> +{
> + u32 err_stat, err_addr, pci_stat;
> +
> + /*
> + * Quietly clear PB and PCI error flags set as result
> + * of PCI/X configuration read requests.
> + */
> +
> + /* Read PB Error Log Registers */
> +
> + err_stat = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS);
> + err_addr = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_AERR);
> +
> + if (err_stat & TSI108_PB_ERRCS_ES) {
> + /* Clear error flag */
> + tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS,
> + TSI108_PB_ERRCS_ES);
> +
> + /* Clear read error reported in PB_ISR */
> + tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ISR,
> + TSI108_PB_ISR_PBS_RD_ERR);
> +
> + /* Clear PCI/X bus cfg errors if applicable */
> + if ((err_addr & 0xFF000000) == pci_cfg_base) {
> + pci_stat =
> + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR);
> + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR,
> + pci_stat);
> + }
> + }
> +
> + return;
> +}
> +
> +#define __tsi108_read_pci_config(x, addr, op) \
> + __asm__ __volatile__( \
> + " "op" %0,0,%1\n" \
> + "1: eieio\n" \
> + "2:\n" \
> + ".section .fixup,\"ax\"\n" \
> + "3: li %0,-1\n" \
> + " b 2b\n" \
> + ".section __ex_table,\"a\"\n" \
> + " .align 2\n" \
> + " .long 1b,3b\n" \
> + ".text" \
> + : "=r"(x) : "r"(addr))
> +
> +int
> +tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn,
> int offset,
> + int len, u32 * val)
> +{
> + volatile unsigned char *cfg_addr;
> + u32 temp;
> +
> + cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
> + devfn,
> + offset) | (offset &
> + 0x03));
> +
> + switch (len) {
> + case 1:
> + __tsi108_read_pci_config(temp, cfg_addr, "lbzx");
> + break;
> + case 2:
> + __tsi108_read_pci_config(temp, cfg_addr, "lhbrx");
> + break;
> + default:
> + __tsi108_read_pci_config(temp, cfg_addr, "lwbrx");
> + break;
> + }
> +
> + *val = temp;
> +
> +#ifdef TSI108_PCI_DEBUG
> + if ((0xFFFFFFFF != temp) && (0xFFFF != temp) && (0xFF != temp)) {
> + printk("PCI CFG read : ");
> + printk("%d:0x%x:0x%x ", bus->number, devfn, offset);
> + printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
> + printk("data = 0x%x\n", *val);
> + }
> +#endif
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +unsigned long tsi108_get_cpu_clk(void)
> +{
> + /* Detect PB clock freq. */
> + u32 i = tsi108_read_reg(TSI108_CLK_OFFSET + TSI108_CG_PWRUP_STATUS);
> +
> + i = (i >> 16) & 0x07; /* Get PB PLL multiplier */
> + return (pb_clk_sel[i] * 1000000);
> +}
> +
> +unsigned long tsi108_get_sdc_clk(void)
> +{
> + u32 i, k;
> +
> + /* Get SDC/PB clock freq. from CG settings */
> + i = tsi108_read_reg(TSI108_CLK_OFFSET + TSI108_CG_PWRUP_STATUS);
> + k = (i >> 16) & 0x07; /* Get PB PLL multiplier */
> + i = (i >> 20) & 0x07; /* Get SDC PLL multiplier */
> + k = (k == i) ? 0 : 1; /* sync/async configuration */
> + return (sd_clk_sel[k][i] * 1000000);
> +}
> --
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Anyone seen this while debugging?
From: Steve Iribarne (GMail) @ 2006-05-17 13:49 UTC (permalink / raw)
To: linuxppc-embedded
I am using linux-2.4.32.
I am using a BDI2000 and I set break to SOFT
I am debugging a module and I use Denx scripts "add-module" so that I
know my module symbols are getting loaded in the right location.
Everytime I set a breakpoint in my module I get....
Program received signal SIGSTOP, Stopped (signal).
0x00000500 in ?? ()
The address moves around a bit but I always get this. If I delete the
breakpoints it works fine.
Thanks in advance.
-stv
^ permalink raw reply
* Re: [RFC PATCH 00/09] robust VM per_cpu variables
From: Christoph Lameter @ 2006-05-17 14:52 UTC (permalink / raw)
To: Steven Rostedt
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, Andi Kleen, linuxppc-dev,
Paul Mackerras, benedict.gaster, sam, bjornw, kenneth.w.chen,
Ingo Molnar, kiran, Nick Piggin, grundler, arnd, Rusty Russell,
starvik, Linus Torvalds, Thomas Gleixner, rth, Chris Zankel,
tony.luck, LKML, ralf, Marc Gauthier, lethal, schwidefsky,
linux390, davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170547490.8408@gandalf.stny.rr.com>
On Wed, 17 May 2006, Steven Rostedt wrote:
> My first attempt to fix this introduced another dereference, to allow
> for modules to allocate their own memory. This was quickly shot down,
> and for good reason, because dereferences kill performance, and don't
> play nice with large SMP systems that depend on per_cpu being fast.
> I now place the per_cpu variables into VM, such that the pages are
> only allocated when needed. All the architecture needs to do is
> supply a VM address range, size for each CPU to use (note this
> implementation expects all the VM CPU areas to be together), and
> three functions to allow for allocating page tables at bootup.
So now instead of an explicit indirection we use an implicit one
through the page tables for this. This happens during early boot which
requires additional page table functions? And it requires the use of an
additional TLB entry? I guess that the additional TLB pressure alone will
result in a performance drop of 3%?
See http://www.gelato.unsw.edu.au/archives/linux-ia64/0602/17311.html
^ permalink raw reply
* [patch] udb_printf() formatting attribute
From: Jimi Xenidis @ 2006-05-17 15:04 UTC (permalink / raw)
To: linuxppc-dev
This patch allows the compiler to catch any printf-like mismatches
for udbg_printf().
After some brute force building I've only found issues with my own
code and lparcfg.c
It could break some developers, but IMHO that would be goodness.
Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
---
diff -r 0163968f7fce arch/powerpc/kernel/lparcfg.c
--- a/arch/powerpc/kernel/lparcfg.c Tue May 16 15:55:19 2006 -0400
+++ b/arch/powerpc/kernel/lparcfg.c Wed May 17 10:43:55 2006 -0400
@@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file
current_weight = (resource >> 5 * 8) & 0xFF;
- pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
+ pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
__FUNCTION__, current_entitled, current_weight);
- pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
+ pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
__FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
diff -r 0163968f7fce include/asm-powerpc/udbg.h
--- a/include/asm-powerpc/udbg.h Tue May 16 15:55:19 2006 -0400
+++ b/include/asm-powerpc/udbg.h Wed May 17 10:43:55 2006 -0400
@@ -23,7 +23,8 @@ extern int udbg_read(char *buf, int bufl
extern int udbg_read(char *buf, int buflen);
extern void register_early_udbg_console(void);
-extern void udbg_printf(const char *fmt, ...);
+extern void udbg_printf(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern void udbg_progress(char *s, unsigned short hex);
extern void udbg_init_uart(void __iomem *comport, unsigned int speed,
^ permalink raw reply
* Re: [RFC PATCH 00/09] robust VM per_cpu variables
From: Steven Rostedt @ 2006-05-17 15:18 UTC (permalink / raw)
To: Christoph Lameter
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, Andi Kleen, linuxppc-dev,
Paul Mackerras, benedict.gaster, sam, bjornw, kenneth.w.chen,
Ingo Molnar, kiran, Nick Piggin, grundler, arnd, Rusty Russell,
starvik, Linus Torvalds, Thomas Gleixner, rth, Chris Zankel,
tony.luck, LKML, ralf, Marc Gauthier, lethal, schwidefsky,
linux390, davem, parisc-linux
In-Reply-To: <Pine.LNX.4.64.0605170744360.13021@schroedinger.engr.sgi.com>
Hi Christoph,
Thanks for replying!
On Wed, 17 May 2006, Christoph Lameter wrote:
> On Wed, 17 May 2006, Steven Rostedt wrote:
>
> > My first attempt to fix this introduced another dereference, to allow
> > for modules to allocate their own memory. This was quickly shot down,
> > and for good reason, because dereferences kill performance, and don't
> > play nice with large SMP systems that depend on per_cpu being fast.
>
> > I now place the per_cpu variables into VM, such that the pages are
> > only allocated when needed. All the architecture needs to do is
> > supply a VM address range, size for each CPU to use (note this
> > implementation expects all the VM CPU areas to be together), and
> > three functions to allow for allocating page tables at bootup.
>
> So now instead of an explicit indirection we use an implicit one
> through the page tables for this. This happens during early boot which
> requires additional page table functions? And it requires the use of an
> additional TLB entry? I guess that the additional TLB pressure alone will
> result in a performance drop of 3%?
Ouch!
>
> See http://www.gelato.unsw.edu.au/archives/linux-ia64/0602/17311.html
Thanks for the link.
Hmm, my main goal is still to make the per_cpu more robust, so that the
generic code is truely that, and the hacks are better managed. Would the
TLB pressure on a normal desktop also cause the drop in performance? I
haven't tried any benchmarks. Have any tests I can run on two kernels?
I'm currently running my machine with the patches and I haven't noticed
a difference. Although I'm not doing database work, I'm still compiling
kernels.
Reason I'm asking, is that I wonder if the whole VM idea is a waste, or is
it only a problem on certain archs?
Perhaps move the whole of percpu_boot_alloc into the arch, and let it do
the allocation as is. Could perhaps use some arch specific register to
calculate the entries.
OK, now I'm just rambling. I don't know, have any other ideas on making
this more robust? Or is this all in vain, and I should spend my evenings
walking around this beautiful town of Karlsruhe ;)
-- Steve
^ permalink raw reply
* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Wolfgang Pfeiffer @ 2006-05-17 15:38 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev list, ALSA development, Lee Revell
In-Reply-To: <1147791315.983.21.camel@johannes>
On Tue, May 16, 2006 at 04:55:15PM +0200, Johannes Berg wrote:
> On Tue, 2006-05-16 at 10:53 -0400, Lee Revell wrote:
>
> > Ummm... what problem is this patch fixing?
>
> The problems that
> (a) kmix, gnome-alsamixer, gnome-volume-control and others can't
> properly use the playback volume control because it has a range
> that doesn't start at 0
True if you only use kmix, that via 'ps ax' shows up as something like this:
[ ... ] kmix [kdeinit] -caption KMix -icon kmix -miniicon kmix
But if you - separately and additionally - add the "Sound Mixer"
applet to the KDE kicker (the panel) *plus* make sure you split the
volume control slider for the "Sound Mixer" channel you have a working
volume control .. :)
At least this is how it works here, with
"Kmix Panel Applet 2.6 (Using KDE 3.5.2)", and on Debian unstable ..
If I play with these apps there seem to be glitches, so they do not
seem to work "properly". But with a bit of fiddling between what KDE
calls "Sound Mixer" and "Kmix" (both actually seem to be part of the
same application, i.e. kmix) you should have a working volume slider
...
HTH
Best Regards
Wolfgang
--
Wolfgang Pfeiffer: /ICQ: 286585973/ + + + /AIM: crashinglinux/
http://profiles.yahoo.com/wolfgangpfeiffer
Key ID: E3037113
http://keyserver.mine.nu/pks/lookup?search=0xE3037113&fingerprint=on
^ permalink raw reply
* Re: [RFC PATCH 00/09] robust VM per_cpu variables
From: Christoph Lameter @ 2006-05-17 15:49 UTC (permalink / raw)
To: Steven Rostedt
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, Andi Kleen, linuxppc-dev,
Paul Mackerras, benedict.gaster, sam, bjornw, kenneth.w.chen,
Ingo Molnar, kiran, Nick Piggin, grundler, arnd, Rusty Russell,
starvik, Linus Torvalds, Thomas Gleixner, rth, Chris Zankel,
tony.luck, LKML, ralf, Marc Gauthier, lethal, schwidefsky,
linux390, davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605171104100.13160@gandalf.stny.rr.com>
On Wed, 17 May 2006, Steven Rostedt wrote:
> OK, now I'm just rambling. I don't know, have any other ideas on making
> this more robust? Or is this all in vain, and I should spend my evenings
> walking around this beautiful town of Karlsruhe ;)
Well I'd like to see a comprehensive solution including a fix for the
problems with allocper_cpu() allocations (allocper_cpu has to allocate
memory for potential processors... which could be a lot on
some types of systems and its allocated somewhere not on the nodes of the
processor since they may not yet be online).
Wish I could be back home in Germany to talk a walk with you. Are you
coming to the OLS?
^ permalink raw reply
* Re: [RFC PATCH 00/09] robust VM per_cpu variables
From: Steven Rostedt @ 2006-05-17 15:56 UTC (permalink / raw)
To: Christoph Lameter
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, Andi Kleen, linuxppc-dev,
Paul Mackerras, benedict.gaster, sam, bjornw, kenneth.w.chen,
Ingo Molnar, kiran, Nick Piggin, grundler, arnd, Rusty Russell,
starvik, Linus Torvalds, Thomas Gleixner, rth, Chris Zankel,
tony.luck, LKML, ralf, Marc Gauthier, lethal, schwidefsky,
linux390, davem, parisc-linux
In-Reply-To: <Pine.LNX.4.64.0605170846190.13337@schroedinger.engr.sgi.com>
On Wed, 17 May 2006, Christoph Lameter wrote:
> On Wed, 17 May 2006, Steven Rostedt wrote:
>
> > OK, now I'm just rambling. I don't know, have any other ideas on making
> > this more robust? Or is this all in vain, and I should spend my evenings
> > walking around this beautiful town of Karlsruhe ;)
>
> Well I'd like to see a comprehensive solution including a fix for the
> problems with allocper_cpu() allocations (allocper_cpu has to allocate
> memory for potential processors... which could be a lot on
> some types of systems and its allocated somewhere not on the nodes of the
> processor since they may not yet be online).
OK, now you're beyond what I'm working with ;) No hot plug CPUs for me.
Well, at least not yet!
>
> Wish I could be back home in Germany to talk a walk with you. Are you
> coming to the OLS?
I'm just here on business. Will be back home in the States on Saturday.
Yep, I'll be at OLS. Hopefully we can get a group together to do some
brainstorming.
Thanks,
-- Steve
^ permalink raw reply
* Re: [PATCH/2.6.17-rc4 6/10] Add Tundra pci vendor and device ID
From: Kumar Gala @ 2006-05-17 16:04 UTC (permalink / raw)
To: Zang Roy-r61911
Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D623@zch01exm40.ap.freescale.net>
On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:
> Add Tundra Semiconductor pci host bridge vendor ID and device ID
>
> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Did you guys submit http://pciids.sourceforge.net/ ?
- k
> ---
>
> include/linux/pci_ids.h | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> 14bddf6670ca982d5cee57afa472d2199e2170fc
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index d6fe048..c39fcfc 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2276,3 +2276,7 @@ #define PCI_DEVICE_ID_RME_DIGI32 0x9896
> #define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897
> #define PCI_DEVICE_ID_RME_DIGI32_8 0x9898
>
> +#define PCI_VENDOR_ID_TUNDRA 0x10e3
> +#define PCI_DEVICE_ID_TUNDRA_CA91C042 0x0000
> +#define PCI_DEVICE_ID_TUNDRA_TSI108 0x0108
> +#define PCI_DEVICE_ID_TUNDRA_TSI109 0xA108
> --
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH/2.6.17-rc4 4/10]Powerpc: Add tsi108 pic support
From: Kumar Gala @ 2006-05-17 16:05 UTC (permalink / raw)
To: Zang Roy-r61911
Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D61F@zch01exm40.ap.freescale.net>
On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:
> Add Tundra Semiconductor tsi108 host bridge interrupt controller
> support.
>
> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
>
> ---
The TSI 108 looks like an OpenPIC derivative you should look at using
mpic for this instead of introducing new pic code.
- k
>
> arch/powerpc/sysdev/tsi108_pic.c | 813 +++++++++++++++++++++++++++
> +++++++++++
> include/asm-powerpc/tsi108_pic.h | 232 +++++++++++
> 2 files changed, 1045 insertions(+), 0 deletions(-)
> create mode 100644 arch/powerpc/sysdev/tsi108_pic.c
> create mode 100644 include/asm-powerpc/tsi108_pic.h
>
> 7d23f6a0984cd54ca787f880a57067330900abe8
> diff --git a/arch/powerpc/sysdev/tsi108_pic.c b/arch/powerpc/sysdev/
> tsi108_pic.c
> new file mode 100644
> index 0000000..bbca587
> --- /dev/null
> +++ b/arch/powerpc/sysdev/tsi108_pic.c
> @@ -0,0 +1,813 @@
> +/*
> + * (C) Copyright 2005 Tundra Semiconductor Corp.
> + * Alex Bounine, <alexandreb@tundra.com).
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/*
> + * Tsi108 Interrupt Controller Handling
> + */
> +
> +#include <linux/config.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/sysdev.h>
> +#include <asm/ptrace.h>
> +#include <asm/signal.h>
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/prom.h>
> +#include <asm/sections.h>
> +#include <asm/hardirq.h>
> +#include <asm/machdep.h>
> +
> +#include <asm/tsi108.h>
> +#include <asm/tsi108_irq.h>
> +#include <asm/tsi108_pic.h>
> +#undef DEBUG
> +
> +#ifdef DEBUG
> +#define DBG(fmt...) do { printk(fmt); } while(0)
> +#else
> +#define DBG(fmt...) do { } while(0)
> +#endif
> +
> +extern u32 get_vir_csrbase(void);
> +extern u32 tsi108_read_reg(u32 reg_offset);
> +extern void tsi108_write_reg(u32 reg_offset, u32 val);
> +
> +static phys_addr_t tsi108_pic_phy_addr;
> +static u32 tsi108_pic_vir_addr;
> +
> +static int tsi108_pic_cascade_irq = -1;
> +static int (*tsi108_pic_cascade_fn) (struct pt_regs *);
> +
> +/* Global Operations */
> +static void tsi108_pic_set_task_priority(u_int pri);
> +static void tsi108_pic_set_spurious(u_int vector);
> +void tsi108_pic_mask_all(void);
> +
> +/* Timer Interrupts */
> +static void tsi108_pic_inittimer(u_int timer, u_int pri, u_int
> vector);
> +static void tsi108_pic_maptimer(u_int timer, u_int cpumask);
> +
> +/* Interrupt Sources */
> +static void tsi108_pic_enable_irq(u_int irq);
> +static void tsi108_pic_disable_irq(u_int irq);
> +static void tsi108_pic_initirq(u_int irq, u_int pri, u_int vector,
> int polarity,
> + int is_level);
> +static void tsi108_pic_mapirq(u_int irq, u_int cpumask, u_int
> keepmask);
> +static void init_pci_source(void);
> +static inline int get_pci_source(int vector);
> +int tsi108_pic_set_irq_sense(int irq, int pol, int sense);
> +
> +/*
> + * tsi108_pic interface routines
> + */
> +static void tsi108_pic_end_irq(unsigned int irq_nr);
> +static void tsi108_pic_ack_irq(unsigned int irq_nr);
> +void tsi108_pic_set_affinity(unsigned int irq_nr, unsigned long
> cpumask);
> +
> +static struct hw_interrupt_type tsi108_pic_irq = {
> + "tsi108_pic",
> + NULL,
> + NULL,
> + tsi108_pic_enable_irq,
> + tsi108_pic_disable_irq,
> + tsi108_pic_ack_irq,
> + tsi108_pic_end_irq,
> + NULL
> +};
> +
> +static void tsi108_pci_irq_enable(u_int irq);
> +static void tsi108_pci_irq_disable(u_int irq);
> +static void tsi108_pci_irq_ack(u_int irq);
> +static void tsi108_pci_irq_end(u_int irq);
> +
> +static struct hw_interrupt_type tsi108_pci_irq = {
> + "tsi108_PCI_int",
> + NULL,
> + NULL,
> + tsi108_pci_irq_enable,
> + tsi108_pci_irq_disable,
> + tsi108_pci_irq_ack,
> + tsi108_pci_irq_end,
> + NULL
> +};
> +
> +#ifdef DBG_TSI108_INTERRUPT
> +#define ASSERT(expr) if (!(expr)) { \
> + printk("tsi108pic :" \
> + "assertion failed! %s[%d]: %s\n", \
> + __FUNCTION__, __LINE__, #expr); \
> + dump_stack(); \
> + }
> +#else
> +#define ASSERT(expr) do {} while (0)
> +#endif
> +
> +static inline u_int get_vector_offset(u_int irq)
> +{
> + u_int offset;
> +
> + if (irq < TSI108_IRQ_BASE || irq >= IRQ_PCI_INTAD_BASE)
> + return 0;
> +
> + if (irq < IRQ_TSI108_MBOX0)
> + offset = TSI108_INT_IVPR(irq - TSI108_IRQ_BASE);
> + else if (irq < IRQ_TSI108_DBELL0)
> + offset = TSI108_INT_MBVPR(irq - IRQ_TSI108_MBOX0);
> + else if (irq < IRQ_TSI108_TIMER0)
> + offset = TSI108_INT_DVPR(irq - IRQ_TSI108_DBELL0);
> + else
> + offset = TSI108_INT_GTVPR(irq - IRQ_TSI108_TIMER0);
> +
> + return offset;
> +}
> +
> +static inline u_int tsi108_pic_read_reg(u_int reg_offset)
> +{
> + return in_be32((volatile u32 *)(tsi108_pic_vir_addr + reg_offset));
> +}
> +
> +static inline void tsi108_pic_write_reg(u_int reg_offset, u_int val)
> +{
> + out_be32((volatile u32 *)(tsi108_pic_vir_addr + reg_offset), val);
> +}
> +
> +void tsi108_pic_reset(void)
> +{
> + tsi108_pic_write_reg(TSI108_INT_GCR, TSI108PIC_INT_GCR_R);
> + while (tsi108_pic_read_reg(TSI108_INT_GCR) & TSI108PIC_INT_GCR_R)
> + mb();
> +}
> +
> +void tsi108_pic_set_output(int dest_num, u32 sense, u32 polarity)
> +{
> + u32 temp = 0;
> + temp |= (IRQ_SENSE_LEVEL == sense) ?
> + (TSI108PIC_INT_CSR_S_LEVEL) : (TSI108PIC_INT_CSR_S_EDGE);
> + temp |= (IRQ_POLARITY_POSITIVE == polarity) ?
> + (TSI108PIC_INT_CSR_P_HIGH) : (TSI108PIC_INT_CSR_P_LOW);
> + tsi108_pic_write_reg(TSI108_INT_CSR(dest_num), temp);
> + mb();
> +}
> +
> +int tsi108_pic_source_cfg(int src_num, /* interrupt source number */
> + u32 sense, /* interrupt source Sense */
> + u32 polarity, /* interrupt source Polarity */
> + TSI108_IRQ_MODE mode /* interrupt delivery Mode */
> + )
> +{
> + unsigned temp;
> +
> + temp = tsi108_pic_read_reg(TSI108_INT_IVPR(src_num));
> +
> + if (temp & TSI108PIC_ACTIVITY) /* error if source is active */
> + return -1;
> +
> + if (0 == (temp & TSI108PIC_MASK)) {
> + temp |= TSI108PIC_MASK; /* mask IRQ prior making changes */
> + tsi108_pic_write_reg(TSI108_INT_IVPR(src_num), temp);
> + }
> +
> + temp &= ~(TSI108PIC_INT_IVPR_MODE |
> + TSI108PIC_INT_IVPR_S | TSI108PIC_INT_IVPR_P);
> +
> + temp |= (IRQ_SENSE_LEVEL == sense) ?
> + (TSI108PIC_INT_CSR_S_LEVEL) : (TSI108PIC_INT_CSR_S_EDGE);
> + temp |= (IRQ_POLARITY_POSITIVE == polarity) ?
> + (TSI108PIC_INT_CSR_P_HIGH) : (TSI108PIC_INT_CSR_P_LOW);
> +
> + tsi108_pic_write_reg(TSI108_INT_IVPR(src_num),
> + TSI108PIC_MASK | (mode << 29) | temp);
> + return (0);
> +}
> +
> +int tsi108_pic_set_vector(int src_num, /* source number */
> + int vect, /* vector number */
> + int prio /* interrupt source priority */
> + )
> +{
> + unsigned tmp;
> +
> + tmp = tsi108_pic_read_reg(TSI108_INT_IVPR(src_num));
> +
> + if (tmp & TSI108PIC_ACTIVITY) /* error if source is active */
> + return -1;
> +
> + if (0 == (tmp & TSI108PIC_MASK)) {
> + tmp |= TSI108PIC_MASK; /* mask IRQ prior making changes */
> + tsi108_pic_write_reg(TSI108_INT_IVPR(src_num), tmp);
> + }
> +
> + /* clear bits to be changed */
> + tmp &= ~(TSI108PIC_VECTOR_MASK | TSI108PIC_PRIORITY_MASK);
> +
> + tmp |= (prio << 16) | vect;
> + tsi108_pic_write_reg(TSI108_INT_IVPR(src_num), tmp);
> + return 0;
> +}
> +
> +void tsi108_pic_mask_all()
> +{
> + int i;
> + unsigned int vp;
> +
> + /* Mask all external and internal interrupt sources */
> + for (i = 0; i < TSI108PIC_MAX_SOURCES; i++) {
> + vp = tsi108_pic_read_reg(TSI108_INT_IVPR(i));
> + tsi108_pic_write_reg(TSI108_INT_IVPR(i), vp | TSI108PIC_MASK);
> + mb();
> +
> + /* Make sure that irq is masked */
> + do {
> + vp = tsi108_pic_read_reg(TSI108_INT_IVPR(i));
> + } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
> + }
> +
> + /* Mask all timer interrupts */
> + for (i = 0; i < TSI108PIC_NUM_TIMERS; i++) {
> + vp = tsi108_pic_read_reg(TSI108_INT_GTVPR(i));
> + tsi108_pic_write_reg(TSI108_INT_GTVPR(i), vp | TSI108PIC_MASK);
> + mb();
> +
> + do {
> + vp = tsi108_pic_read_reg(TSI108_INT_GTVPR(i));
> + } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
> + }
> +
> + /* Mask all doorbell interrupts */
> + for (i = 0; i < TSI108PIC_NUM_DBELLS; i++) {
> + vp = tsi108_pic_read_reg(TSI108_INT_DVPR(i));
> + tsi108_pic_write_reg(TSI108_INT_IVPR(i), vp | TSI108PIC_MASK);
> + mb();
> +
> + do {
> + vp = tsi108_pic_read_reg(TSI108_INT_DVPR(i));
> + } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
> + }
> +
> + /* Mask all mailbox interrupts */
> + for (i = 0; i < 4; i++) {
> + vp = tsi108_pic_read_reg(TSI108_INT_MBVPR(i));
> + tsi108_pic_write_reg(TSI108_INT_MBVPR(i), vp | TSI108PIC_MASK);
> + mb();
> +
> + do {
> + vp = tsi108_pic_read_reg(TSI108_INT_MBVPR(i));
> + } while ((vp & TSI108PIC_ACTIVITY) && !(vp & TSI108PIC_MASK));
> + }
> +}
> +
> +/*
> + * The Tsi108 PC initialization routine.
> + * A caller routine (usually from platform-specific code has to
> provide
> + * sense/polarity configuration information for four external
> interrupt
> + * sources INT0 - INT3. This should be done in form of four-byte
> array
> + * (one byte per source ) that contains combination of sensitivity/
> polarity
> + * flags defined in asm-ppc/irq.h.
> + *
> + * Example of PIC initialization call is shown below:
> + *
> + * u_char your_board_pic_initsenses[] __initdata = {
> + * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), // INT[0]
> + * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), // INT[1]
> + * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), // INT[2]
> + * (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE) // INT[3]
> + * };
> + *
> + * tsi108_pic_init(your_board_pic_initsenses);
> + */
> +
> +void __init tsi108_pic_init(u_char * board_init_senses)
> +{
> + u_int i;
> + u32 sense;
> +
> + struct device_node *tsi_pic;
> + tsi_pic = of_find_node_by_type(NULL, "open-pic");
> + if (tsi_pic) {
> + unsigned int size;
> + void *prop = get_property(tsi_pic, "reg", &size);
> + tsi108_pic_phy_addr = of_translate_address(tsi_pic, prop);
> + }
> +
> + DBG("%s: Tsi108 pic phy addr = 0x%x\n", __FUNCTION__,
> + (u32) tsi108_pic_phy_addr);
> + if (tsi108_pic_phy_addr == 0) {
> + printk("No tsi108 PIC found !\n");
> + return;
> + }
> +
> + tsi108_pic_vir_addr = (u32) ioremap(tsi108_pic_phy_addr, 0x400);
> +
> + tsi108_pic_reset();
> +
> + if (ppc_md.progress)
> + ppc_md.progress("tsi108_pic_init: enter", 0x122);
> +
> + /* Initialize timer interrupts */
> + for (i = 0; i < TSI108PIC_NUM_TIMERS; i++) {
> + /* Disabled, Priority 0 */
> + tsi108_pic_inittimer(i, 0, IRQ_TSI108_TIMER0 + i);
> + /* No processor */
> + tsi108_pic_maptimer(i, 0);
> + }
> +
> + /* Init board-specific external sources */
> + for (i = 0; i < 4; i++) {
> + sense = board_init_senses[i];
> +
> + if (sense & IRQ_SENSE_MASK)
> + irq_desc[TSI108_IRQ(i)].status |= IRQ_LEVEL;
> +
> + /* Enabled, Priority 8 */
> + tsi108_pic_initirq(i, 8, TSI108_IRQ(i),
> + (sense & IRQ_POLARITY_MASK),
> + (sense & IRQ_SENSE_MASK));
> + /* Map to CPU #0 */
> + tsi108_pic_mapirq(TSI108_IRQ(i), 1 << 0, 0);
> + }
> +
> + /* Init remaining internal sources. */
> + for (; i < TSI108PIC_MAX_SOURCES; i++) {
> + /* Disabled, Priority 8, by default - Positive Edge */
> + tsi108_pic_initirq(i, 8, TSI108_IRQ(i),
> + IRQ_POLARITY_POSITIVE, IRQ_SENSE_EDGE);
> + /* Map to CPU #0 */
> + tsi108_pic_mapirq(TSI108_IRQ(i), (1 << 0), 0);
> + }
> +
> + /*
> + * Change sensitivity to level for sources that require it.
> + */
> +
> + irq_desc[IRQ_TSI108_GIGE0].status |= IRQ_LEVEL;
> + irq_desc[IRQ_TSI108_GIGE1].status |= IRQ_LEVEL;
> + irq_desc[IRQ_TSI108_PCI].status |= IRQ_LEVEL;
> +
> + /* Init descriptors */
> + for (i = 0; i < TSI108PIC_MAX_SOURCES; i++)
> + irq_desc[i + TSI108_IRQ_BASE].handler = &tsi108_pic_irq;
> +
> + for (i = 0; i < NUM_PCI_IRQS; i++) {
> + irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq;
> + irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
> + }
> +
> + /* Initialize the spurious interrupt */
> + tsi108_pic_set_spurious(TSI108_IRQ_SPURIOUS);
> + tsi108_pic_set_task_priority(0);
> +
> + init_pci_source();
> + tsi108_pic_enable_irq(IRQ_TSI108_PCI);
> +
> + i = tsi108_pic_read_reg(TSI108_INT_VECTOR(0));
> + tsi108_pic_write_reg(TSI108_INT_EOI(0), 0);
> +
> + if (ppc_md.progress)
> + ppc_md.progress("tsi108_pic_init: exit", 0x222);
> +}
> +
> +/*
> + * Find out the current interrupt
> + */
> +static u_int tsi108_pic_get_vect(void)
> +{
> + u_int vec;
> +
> + vec = tsi108_pic_read_reg(TSI108_INT_VECTOR(0)) &
> TSI108PIC_VECTOR_MASK;
> +
> +#ifdef DBG_TSI108_INTERRUPT
> + if (vec == TSI108_IRQ_SPURIOUS)
> + printk("TSI108: SPURIOUS vec=0x%08x\n", vec);
> + else
> + printk("TSI108: read vec=0x%08x\n", vec);
> +#endif
> + return (vec);
> +}
> +
> +static inline void tsi108_pic_eoi(void)
> +{
> + tsi108_pic_write_reg(TSI108_INT_EOI(0), 0);
> + mb();
> +}
> +
> +static void __init tsi108_pic_set_task_priority(u_int pri)
> +{
> + ASSERT(pri >= 0 && pri < TSI108PIC_NUM_PRI);
> +
> + tsi108_pic_write_reg(TSI108_INT_TASKP(0),
> + pri & TSI108PIC_INT_TASKP_TASKP);
> + mb();
> +}
> +
> +static void tsi108_pic_set_spurious(u_int vec)
> +{
> + ASSERT(vec == TSI108_IRQ_SPURIOUS);
> + tsi108_pic_write_reg(TSI108_INT_SVR, vec);
> + mb();
> +}
> +
> +#ifdef CONFIG_SMP
> +/*
> + * Convert a cpu mask from logical to physical cpu numbers.
> + */
> +static inline u32 physmask(u32 cpumask)
> +{
> + int i;
> + u32 mask = 0;
> +
> + for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
> + if (cpu_online(i))
> + mask |= (cpumask & 1) << smp_hw_index[i];
> + return mask;
> +}
> +#else
> +#define physmask(cpumask) (cpumask)
> +#endif
> +
> +/*
> + * Initialize a timer interrupt (and disable it)
> + *
> + * timer: timer number
> + * pri: interrupt source priority
> + * vec: the vector it will produce
> + */
> +static void __init tsi108_pic_inittimer(u_int timer, u_int pri,
> u_int vec)
> +{
> + unsigned int gtvpr;
> +
> + ASSERT(timer >= 0 && timer < TSI108PIC_NUM_TIMERS);
> + ASSERT(pri >= 0 && pri < TSI108PIC_NUM_PRI);
> + ASSERT(vec >= 0 && vec < TSI108PIC_NUM_VECTORS);
> +
> + gtvpr = tsi108_pic_read_reg(TSI108_INT_GTVPR(timer));
> + gtvpr &= ~(TSI108PIC_PRIORITY_MASK | TSI108PIC_VECTOR_MASK);
> + gtvpr |= (pri << 16) | vec;
> + tsi108_pic_write_reg(TSI108_INT_GTVPR(timer), gtvpr |
> TSI108PIC_MASK);
> + mb();
> +}
> +
> +/*
> + * Map a timer interrupt to one or more CPUs
> + */
> +static void __init tsi108_pic_maptimer(u_int timer, u_int cpumask)
> +{
> + ASSERT(timer >= 0 && timer < TSI108PIC_NUM_TIMERS);
> +
> + tsi108_pic_write_reg(TSI108_INT_GTDR(timer), physmask(cpumask));
> + mb();
> +}
> +
> +/*
> + * Initalize the interrupt source which will generate an NMI.
> + * This raises the interrupt's priority from 8 to 9.
> + *
> + * irq: The logical IRQ which generates an NMI.
> + */
> +void __init tsi108_pic_init_nmi_irq(u_int irq)
> +{
> + u_int offset = get_vector_offset(irq);
> + u_int vpr = tsi108_pic_read_reg(offset);
> + vpr &= ~TSI108PIC_PRIORITY_MASK;
> + tsi108_pic_write_reg(offset, vpr | (9 << 16));
> + mb();
> +}
> +
> +/*
> + *
> + * All functions below take an offset'ed irq argument
> + *
> + */
> +
> +/*
> + * Hookup a cascade to the tsi108 PIC.
> + */
> +void __init
> +tsi108_pic_hookup_cascade(u_int irq, char *name,
> + int (*cascade_fn) (struct pt_regs *))
> +{
> + tsi108_pic_cascade_irq = irq;
> + tsi108_pic_cascade_fn = cascade_fn;
> + if (request_irq(irq, no_action, SA_INTERRUPT, name, NULL))
> + printk("Unable to get Tsi108 PIC IRQ %d for cascade\n",
> + irq - TSI108_IRQ_BASE);
> +}
> +
> +/*
> + * Enable/disable an external interrupt source
> + *
> + * Externally called, irq is an offseted system-wide interrupt
> number
> + */
> +static void tsi108_pic_enable_irq(u_int irq)
> +{
> + u32 offset = get_vector_offset(irq);
> + u32 vpr = tsi108_pic_read_reg(offset);
> +
> + /*
> + * Undo sensitivity change (see tsi108_pic_disable_irq())
> + */
> + if (irq_desc[irq].status & IRQ_LEVEL)
> + vpr |= TSI108PIC_INT_IVPR_S;
> +
> + tsi108_pic_write_reg(offset, vpr & ~TSI108PIC_MASK);
> + mb();
> +}
> +
> +static void tsi108_pic_disable_irq(u_int irq)
> +{
> + u32 offset = get_vector_offset(irq);
> + u32 vpr = tsi108_pic_read_reg(offset);
> +
> + /*
> + * Switch level interrupt to edge sensitivity to avoid generation
> + * of spurious interrupt request. See design note in Tsi108 PIC
> + * section of Tsi108 manual.
> + */
> + if (irq_desc[irq].status & IRQ_LEVEL)
> + vpr &= ~TSI108PIC_INT_IVPR_S;
> +
> + tsi108_pic_write_reg(offset, vpr | TSI108PIC_MASK);
> + mb();
> + vpr = tsi108_pic_read_reg(offset);
> + if (!(vpr & TSI108PIC_MASK))
> + printk("TSI108_PIC: Error - Unable disable IRQ %d\n", irq);
> +}
> +
> +/*
> + * Initialize an interrupt source (and disable it!)
> + *
> + * irq: Tsi108 PIC interrupt source number
> + * pri: interrupt source priority
> + * vec: the vector it will produce
> + * pol: polarity (1 for positive, 0 for negative)
> + * sense: 1 for level, 0 for edge
> + */
> +static void __init
> +tsi108_pic_initirq(u_int irq, u_int pri, u_int vec, int pol, int
> sense)
> +{
> + unsigned int ivpr;
> +
> + ivpr = TSI108PIC_MASK | (pri << 16) | vec;
> + ivpr |= (IRQ_SENSE_LEVEL == sense) ?
> + TSI108PIC_INT_IVPR_S_LEVEL : TSI108PIC_INT_IVPR_S_EDGE;
> + ivpr |= (IRQ_POLARITY_POSITIVE == pol) ?
> + TSI108PIC_INT_IVPR_P_HIGH : TSI108PIC_INT_IVPR_P_LOW;
> + tsi108_pic_write_reg(TSI108_INT_IVPR(irq), ivpr);
> + mb();
> +}
> +
> +int tsi108_pic_set_irq_sense(int irq, /* PIC source number */
> + int pol, /* interrupt source polarity */
> + int sense /* interrupt source sense */
> + )
> +{
> + unsigned int ivpr;
> +
> + ivpr = tsi108_pic_read_reg(TSI108_INT_IVPR(irq));
> +
> + if (ivpr & TSI108PIC_ACTIVITY) /* error if source is active */
> + return -1;
> +
> + if (0 == (ivpr & TSI108PIC_MASK)) {
> + ivpr |= TSI108PIC_MASK; /* mask IRQ prior making changes */
> + tsi108_pic_write_reg(TSI108_INT_IVPR(irq), ivpr);
> + }
> +
> + /* clear bits to be changed */
> + ivpr &= ~(TSI108PIC_INT_IVPR_P | TSI108PIC_INT_IVPR_S);
> +
> + ivpr |= (IRQ_SENSE_LEVEL == sense) ?
> + TSI108PIC_INT_IVPR_S_LEVEL : TSI108PIC_INT_IVPR_S_EDGE;
> + ivpr |= (IRQ_POLARITY_POSITIVE == pol) ?
> + TSI108PIC_INT_IVPR_P_HIGH : TSI108PIC_INT_IVPR_P_LOW;
> +
> + tsi108_pic_write_reg(TSI108_INT_IVPR(irq), ivpr);
> + return 0;
> +}
> +
> +/*
> + * Map an interrupt source to one or more CPUs
> + */
> +static void tsi108_pic_mapirq(u_int irq, u_int physmask, u_int
> keepmask)
> +{
> + u_int offset = get_vector_offset(irq);
> +
> + if (0 == offset)
> + return;
> + if (keepmask != 0)
> + physmask |= tsi108_pic_read_reg(offset + 4);
> + tsi108_pic_write_reg(offset + 4, physmask);
> + mb();
> +}
> +
> +/* No spinlocks, should not be necessary with the Tsi108 PIC
> + * (1 register = 1 interrupt and we have the desc lock).
> + */
> +static void tsi108_pic_ack_irq(unsigned int irq_nr)
> +{
> + if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
> + tsi108_pic_eoi();
> +}
> +
> +static void tsi108_pic_end_irq(unsigned int irq_nr)
> +{
> + if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
> + tsi108_pic_eoi();
> +}
> +
> +void tsi108_pic_set_affinity(unsigned int irq_nr, unsigned long
> cpumask)
> +{
> + tsi108_pic_mapirq(irq_nr, physmask(cpumask), 0);
> +}
> +
> +int tsi108_pic_get_irq(struct pt_regs *regs)
> +{
> + int vector = tsi108_pic_get_vect();
> +
> + if (vector == TSI108_IRQ_SPURIOUS) {
> + vector = -1;
> + }
> +
> + if (vector == IRQ_TSI108_PCI) {
> + vector = get_pci_source(vector);
> + }
> +
> + if (vector == -1) {
> + tsi108_pic_write_reg(TSI108_INT_EOI(0), 0);
> + }
> +
> + return vector;
> +}
> +
> +static void tsi108_pci_int_mask(u_int irq)
> +{
> + u_int irp_cfg;
> + int int_line = (irq - IRQ_PCI_INTAD_BASE);
> +
> + irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET +
> TSI108_PCI_IRP_CFG_CTL);
> + mb();
> + irp_cfg |= (1 << int_line); /* INTx_DIR = output */
> + irp_cfg &= ~(3 << (8 + (int_line * 2))); /* INTx_TYPE = unused */
> + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
> irp_cfg);
> + mb();
> + irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET +
> TSI108_PCI_IRP_CFG_CTL);
> +}
> +
> +static void tsi108_pci_int_unmask(u_int irq)
> +{
> + u_int irp_cfg;
> + int int_line = (irq - IRQ_PCI_INTAD_BASE);
> +
> + irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET +
> TSI108_PCI_IRP_CFG_CTL);
> + mb();
> + irp_cfg &= ~(1 << int_line);
> + irp_cfg |= (3 << (8 + (int_line * 2)));
> + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
> irp_cfg);
> + mb();
> +}
> +
> +static void tsi108_pci_irq_enable(u_int irq)
> +{
> + tsi108_pci_int_unmask(irq);
> +}
> +
> +static void tsi108_pci_irq_disable(u_int irq)
> +{
> + tsi108_pci_int_mask(irq);
> +}
> +
> +static void tsi108_pci_irq_ack(u_int irq)
> +{
> + tsi108_pci_int_mask(irq);
> +}
> +
> +static void tsi108_pci_irq_end(u_int irq)
> +{
> + tsi108_pic_eoi(); /* eoi IRQ_TSI108_PCI */
> + tsi108_pci_int_unmask(irq);
> +}
> +
> +static inline int get_pci_source(int vector)
> +{
> + u_int temp = 0;
> + int irq = -1;
> + int i;
> + u_int pci_irp_stat;
> + static int mask = 0;
> +
> + /* Read PCI/X block interrupt status register */
> + pci_irp_stat = tsi108_read_reg(TSI108_PCI_OFFSET +
> TSI108_PCI_IRP_STAT);
> + mb();
> +
> + if (pci_irp_stat & TSI108_PCI_IRP_STAT_P_INT) {
> + /* Process Interrupt from PCI bus INTA# - INTD# lines */
> + temp =
> + tsi108_read_reg(TSI108_PCI_OFFSET +
> + TSI108_PCI_IRP_INTAD) & 0xf;
> + mb();
> + for (i = 0; i < 4; i++, mask++) {
> + if (temp & (1 << mask % 4)) {
> + irq = IRQ_PCI_INTA + mask % 4;
> + mask++;
> + break;
> + }
> + }
> + }
> +#ifdef DBG_TSI108_INTERRUPT
> + else {
> + printk("TSI108_PIC: error in TSI108_PCI_IRP_STAT\n");
> + pci_irp_stat =
> + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
> + temp =
> + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_INTAD);
> + mb();
> + printk(">> stat=0x%08x intad=0x%08x ", pci_irp_stat, temp);
> + temp =
> + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
> + mb();
> + printk("cfg_ctl=0x%08x ", temp);
> + temp =
> + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
> + mb();
> + printk("irp_enable=0x%08x\n", temp);
> + }
> +#endif /* DBG_TSI108_INTERRUPT */
> +
> + return irq;
> +}
> +
> +static void init_pci_source(void)
> +{
> + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
> + 0x0000ff00);
> + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
> + 0x00400000);
> + mb();
> +}
> +
> +static struct sysdev_class tsi108_pic_sysclass = {
> + set_kset_name("tsi108_pic"),
> +};
> +
> +static struct sys_device device_tsi108_pic = {
> + .id = 0,
> + .cls = &tsi108_pic_sysclass,
> +};
> +
> +static struct sysdev_driver driver_tsi108_pic = {
> +#ifdef CONFIG_PM /* FIXME: placeholder for future development */
> + .suspend = &tsi108_pic_suspend,
> + .resume = &tsi108_pic_resume,
> +#endif /* CONFIG_PM */
> +};
> +
> +static int __init init_tsi108_pic_sysfs(void)
> +{
> + int rc;
> +
> + if (!get_csrbase())
> + return -ENODEV;
> + printk(KERN_DEBUG "Registering tsi108_pic with sysfs...\n");
> + rc = sysdev_class_register(&tsi108_pic_sysclass);
> + if (rc) {
> + printk(KERN_ERR "Failed registering tsi108_pic sys class\n");
> + return -ENODEV;
> + }
> + rc = sysdev_register(&device_tsi108_pic);
> + if (rc) {
> + printk(KERN_ERR "Failed registering tsi108_pic sys device\n");
> + return -ENODEV;
> + }
> + rc = sysdev_driver_register(&tsi108_pic_sysclass,
> &driver_tsi108_pic);
> + if (rc) {
> + printk(KERN_ERR "Failed registering tsi108_pic sys driver\n");
> + return -ENODEV;
> + }
> + return 0;
> +}
> +
> +subsys_initcall(init_tsi108_pic_sysfs);
> diff --git a/include/asm-powerpc/tsi108_pic.h b/include/asm-powerpc/
> tsi108_pic.h
> new file mode 100644
> index 0000000..7b23352
> --- /dev/null
> +++ b/include/asm-powerpc/tsi108_pic.h
> @@ -0,0 +1,232 @@
> +/*
> + * (C) Copyright 2005 Tundra Semiconductor Corp.
> + * Alex Bounine, <alexandreb@tundra.com).
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/*
> + * arch/ppc/syslib/tsi108_pic.h - Tsi108 Interrupt Controller
> definitions
> + */
> +
> +#ifndef _LINUX_TSI108_PIC_H
> +#define _LINUX_TSI108_PIC_H
> +
> +#include <asm/tsi108_irq.h>
> +
> +#ifdef __KERNEL__
> +
> +/*
> + * Tsi108 PIC supports up to 24 interrupt sources and up to 4
> processors
> + */
> +
> +#define TSI108PIC_MAX_SOURCES 24
> +#define TSI108PIC_MAX_PROCESSORS 4
> +
> +#define TSI108PIC_NUM_TIMERS 4
> +#define TSI108PIC_NUM_DBELLS 4
> +#define TSI108PIC_NUM_PROC 4
> +#define TSI108PIC_NUM_PRI 16
> +#define TSI108PIC_NUM_VECTORS 256
> +
> +/*
> + * Tsi108 PIC Register offsets within block.
> + */
> +
> +/* Registers controlling sources */
> +#define TSI108_INT_FRR (0x000)
> +#define TSI108_INT_GCR (0x004)
> +#define TSI108_INT_SVR (0x010)
> +#define TSI108_INT_GTVPR(n) (0x38 + 0x10*(n))
> +#define TSI108_INT_GTDR(n) (0x3C + 0x10*(n))
> +#define TSI108_INT_IVPR(n) (0x100 + 0x8*(n))
> +#define TSI108_INT_IDR(n) (0x104 + 0x8*(n))
> +#define TSI108_INT_DVPR(n) (0x204 + 0xC*(n))
> +#define TSI108_INT_DDR(n) (0x208 + 0xC*(n))
> +#define TSI108_INT_MBVPR(n) (0x284 + 0x10*(n))
> +#define TSI108_INT_MBDR(n) (0x288 + 0x10*(n))
> +
> +/* Registers controlling destinations */
> +#define TSI108_INT_TASKP(n) (0x300 + 0x40*(n))
> +#define TSI108_INT_VECTOR(n) (0x304 + 0x40*(n))
> +#define TSI108_INT_EOI(n) (0x308 + 0x40*(n))
> +#define TSI108_INT_CSR(n) (0x30C + 0x40*(n))
> +
> +/*
> + * Generic definitions common for different types of interrupt
> + * sources.
> + */
> +
> +#define TSI108PIC_MASK (0x80000000)
> +#define TSI108PIC_ACTIVITY (0x40000000)
> +#define TSI108PIC_PRIORITY_MASK (0x000f0000)
> +#define TSI108PIC_VECTOR_MASK (0x000000ff)
> +
> +/**********************************************************
> + * Register Bit Masks definitions for every register
> + */
> +
> +/* TSI108PIC_INT_FRR : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_FRR_VID (0x000000ff)
> +#define TSI108PIC_INT_FRR_NCPU (0x00001f00)
> +#define TSI108PIC_INT_FRR_NITM (0x0000e000)
> +#define TSI108PIC_INT_FRR_NIRQ (0x07ff0000)
> +#define TSI108PIC_INT_FRR_NIDOOR (0xe0000000)
> +#define TSI108PIC_INT_FRR_RESERVED (0x18000000)
> +
> +/* TSI108PIC_INT_GCR : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_GCR_R (0x80000000)
> +#define TSI108PIC_INT_GCR_RESERVED (0x7fffffff)
> +
> +/* TSI108PIC_INT_ICR : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_ICR_R (0x0000000f)
> +#define TSI108PIC_INT_ICR_RESERVED (0xfffffff0)
> +
> +/* TSI108PIC_INT_MVI : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_MVI_VID (0x000000ff)
> +#define TSI108PIC_INT_MVI_DID (0x0000ff00)
> +#define TSI108PIC_INT_MVI_STEP (0x00ff0000)
> +#define TSI108PIC_INT_MVI_RESERVED (0xff000000)
> +
> +/* TSI108PIC_INT_SVR : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_SVR_VECTOR (0x000000ff)
> +#define TSI108PIC_INT_SVR_RESERVED (0xffffff00)
> +
> +/* TSI108PIC_INT_TFRR : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_TFRR_TIME_FREQ (0xffffffff)
> +
> +/* TSI108PIC_INT_SOFT_SET : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_SOFT_SET_S (0x00ffffff)
> +#define TSI108PIC_INT_SOFT_SET_RESERVED (0xff000000)
> +
> +/* TSI108PIC_INT_SOFT_ENABLE : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_SOFT_ENABLE_EN (0x00ffffff)
> +#define TSI108PIC_INT_SOFT_ENABLE_RESERVED (0xff000000)
> +
> +/* TSI108PIC_INT_GTCCR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_GTCCR_COUNT (0x7fffffff)
> +#define TSI108PIC_INT_GTCCR_T (0x80000000)
> +
> +/* TSI108PIC_INT_GTBCR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_GTBCR_B_COUNT (0x7fffffff)
> +#define TSI108PIC_INT_GTBCR_CI (0x80000000)
> +
> +/* TSI108PIC_INT_GTVPR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_GTVPR_VECTOR (0x000000ff)
> +#define TSI108PIC_INT_GTVPR_PRIORITY (0x000f0000)
> +#define TSI108PIC_INT_GTVPR_PRESCALE (0x00f00000)
> +#define TSI108PIC_INT_GTVPR_A (0x40000000)
> +#define TSI108PIC_INT_GTVPR_M (0x80000000)
> +#define TSI108PIC_INT_GTVPR_RESERVED (0x3f00ff00)
> +
> +/* TSI108PIC_INT_GTDR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_GTDR_SEL_OUT (0x0000000f)
> +#define TSI108PIC_INT_GTDR_RESERVED (0xfffffff0)
> +
> +/* TSI108PIC_INT_IVPR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_IVPR_VECTOR (0x000000ff)
> +#define TSI108PIC_INT_IVPR_PRIORITY (0x000f0000)
> +
> +#define TSI108PIC_INT_IVPR_P (0x01000000)
> +#define TSI108PIC_INT_IVPR_P_LOW (0 << 24)
> +#define TSI108PIC_INT_IVPR_P_HIGH (1 << 24)
> +
> +#define TSI108PIC_INT_IVPR_S (0x02000000)
> +#define TSI108PIC_INT_IVPR_S_EDGE (0 << 25)
> +#define TSI108PIC_INT_IVPR_S_LEVEL (1 << 25)
> +
> +#define TSI108PIC_INT_IVPR_MODE (0x20000000)
> +#define TSI108PIC_INT_IVPR_A (0x40000000)
> +#define TSI108PIC_INT_IVPR_M (0x80000000)
> +#define TSI108PIC_INT_IVPR_RESERVED (0x1cf0ff00)
> +
> +/* TSI108PIC_INT_IDR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_IDR_SEL_OUT (0x0000000f)
> +#define TSI108PIC_INT_IDR_RESERVED (0xfffffff0)
> +
> +/* TSI108PIC_INT_DAR : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_DAR_A (0x0000000f)
> +#define TSI108PIC_INT_DAR_RESERVED (0xfffffff0)
> +
> +/* TSI108PIC_INT_DVPR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_DVPR_VECTOR (0x000000ff)
> +#define TSI108PIC_INT_DVPR_PRIORITY (0x000f0000)
> +#define TSI108PIC_INT_DVPR_A (0x40000000)
> +#define TSI108PIC_INT_DVPR_M (0x80000000)
> +#define TSI108PIC_INT_DVPR_RESERVED (0x3ff0ff00)
> +
> +/* TSI108PIC_INT_DDR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_DDR_SEL_OUT (0x0000000f)
> +#define TSI108PIC_INT_DDR_RESERVED (0xfffffff0)
> +
> +/* TSI108PIC_INT_DMR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_DMR_M (0xffffffff)
> +
> +/* TSI108PIC_INT_MBR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_MBR_M (0xffffffff)
> +
> +/* TSI108PIC_INT_MBVPR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_MBVPR_VECTOR (0x000000ff)
> +#define TSI108PIC_INT_MBVPR_PRIORITY (0x000f0000)
> +#define TSI108PIC_INT_MBVPR_A (0x40000000)
> +#define TSI108PIC_INT_MBVPR_M (0x80000000)
> +#define TSI108PIC_INT_MBVPR_RESERVED (0x3ff0ff00)
> +
> +/* TSI108PIC_INT_MBDR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_MBDR_SEL_OUT (0x0000000f)
> +#define TSI108PIC_INT_MBDR_RESERVED (0xfffffff0)
> +
> +/* TSI108PIC_INT_TASKP(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_TASKP_TASKP (0x0000000f)
> +#define TSI108PIC_INT_TASKP_RESERVED (0xfffffff0)
> +
> +/* TSI108PIC_INT_VECTOR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_VECTOR_VECTOR (0x000000ff)
> +#define TSI108PIC_INT_VECTOR_LS_VECTOR (0xff000000)
> +#define TSI108PIC_INT_VECTOR_RESERVED (0x00ffff00)
> +
> +/* TSI108PIC_INT_EOI(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_EOI_EOI (0x000000ff)
> +#define TSI108PIC_INT_EOI_RESERVED (0xffffff00)
> +
> +/* TSI108PIC_INT_CSR(X) : Register Bits Masks Definitions */
> +#define TSI108PIC_INT_CSR_RESERVED (0xfffffffc)
> +
> +#define TSI108PIC_INT_CSR_P (1 << 0)
> +#define TSI108PIC_INT_CSR_P_LOW (0 << 0)
> +#define TSI108PIC_INT_CSR_P_HIGH (1 << 0)
> +
> +#define TSI108PIC_INT_CSR_S (1 << 1)
> +#define TSI108PIC_INT_CSR_S_EDGE (0 << 1)
> +#define TSI108PIC_INT_CSR_S_LEVEL (1 << 1)
> +
> +extern void tsi108_pic_init(u_char * board_init_senses);
> +extern void tsi108_pic_reset(void);
> +extern void tsi108_pic_set_output(int dest_num, u32 sense, u32
> polarity);
> +extern int tsi108_pic_source_cfg(int src_num, u32 sense,
> + u32 polarity, TSI108_IRQ_MODE mode);
> +extern int tsi108_pic_set_vector(int src_num, int vect, int prio);
> +extern void tsi108_pic_init_nmi_irq(u_int irq);
> +extern void tsi108_pic_hookup_cascade(u_int irq, char *name,
> + int (*cascade_fn) (struct pt_regs *));
> +extern int tsi108_pic_get_irq(struct pt_regs *regs);
> +
> +#endif /* __KERNEL__ */
> +
> +#endif /* _LINUX_TSI108_PIC_H */
> --
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH/2.6.17-rc4 7/10] Powerpc: workaround for tsi108 pci confi g read exception
From: Kumar Gala @ 2006-05-17 16:07 UTC (permalink / raw)
To: Zang Roy-r61911
Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D624@zch01exm40.ap.freescale.net>
On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:
> Workaround for Tundra Semiconductor tsi108 host bridge pci config read
> exception
Can you explain further why this is needed?
>
> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
>
> ---
>
> arch/powerpc/kernel/traps.c | 13 +++++++++++++
> 1 files changed, 13 insertions(+), 0 deletions(-)
>
> 0575fbe21e4f1045528bb91ec4b34bb7955c4a92
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index 064a525..7468d76 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -262,6 +262,19 @@ #if defined(CONFIG_PPC_PMAC) && defined(
> }
> }
> #endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */
> +
> +#ifdef CONFIG_TSI108_BRIDGE
> + extern void tsi108_clear_pci_cfg_error(void);
> + const struct exception_table_entry *entry;
> +
> + /* Are we prepared to handle this fault? */
> + if ((entry = search_exception_tables(regs->nip)) != NULL) {
> + tsi108_clear_pci_cfg_error();
> + regs->msr |= MSR_RI;
> + regs->nip = entry->fixup;
> + return 1;
> + }
> +#endif /* CONFIG_TSI108_BRIDGE */
> return 0;
> }
>
> --
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [patch] udb_printf() formatting attribute
From: Nathan Lynch @ 2006-05-17 16:00 UTC (permalink / raw)
To: Jimi Xenidis; +Cc: linuxppc-dev
In-Reply-To: <4025245D-6BAB-41D3-ADB6-2748741F223E@watson.ibm.com>
Jimi Xenidis wrote:
> This patch allows the compiler to catch any printf-like mismatches
> for udbg_printf().
> After some brute force building I've only found issues with my own
> code and lparcfg.c
> It could break some developers, but IMHO that would be goodness.
>
> Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
> ---
> diff -r 0163968f7fce arch/powerpc/kernel/lparcfg.c
> --- a/arch/powerpc/kernel/lparcfg.c Tue May 16 15:55:19 2006 -0400
> +++ b/arch/powerpc/kernel/lparcfg.c Wed May 17 10:43:55 2006 -0400
> @@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file
> current_weight = (resource >> 5 * 8) & 0xFF;
> - pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
> + pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
> __FUNCTION__, current_entitled, current_weight);
> - pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
> + pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
> __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
> retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
Does this really fix a bug? What warnings are you able to get gcc to
emit?
^ permalink raw reply
* [PATCH] Fix do_mlock so page alignment is to hugepage boundries when needed
From: Eric Paris @ 2006-05-17 17:01 UTC (permalink / raw)
To: linux-kernel; +Cc: discuss, wli, linuxppc-dev
sys_m{,un}lock and do_mlock all align memory references and the length
of the mlock given by userspace to page boundaries. If the page being
mlocked is a hugepage instead of a normal page the start and finish of
the mlock will still only be aligned to normal page boundaries.
Ultimately upon the process exiting we will eventually call unmap_vmas
which will call unmap_hugepage_range for all of the ranges.
unmap_hugepage_range checks to make sure the beginning and the end of
the range are actually hugepage aligned and if not will BUG(). Since we
only aligned to a normal page boundary the end of the first range and
the beginning of the second will likely (unless userspace passed of
values already hugepage aligned) not be hugepage aligned and thus we
bomb.
To recreate (on any arch with hugepages) just create a hugepage and
allow shared memory segments to be at least as large as a hugepage.
Attach to that hugepage and then mlock on a non hugepage aligned
boundary when you call exit() the kernel will panic with a BUG() in
unmap_hugepage_range because the end of the range being unmapped is not
aligned properly. Part of a quick reproducer program for i686 where
PAGE_SIZE=1024*4 and HPAGE_SIZE=4*1024*1024 is below.
shmflg = SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W;
shmid = shmget (IPC_PRIVATE, 4*1024*1024, shmflg);
a = shmat(shmid, NULL, shmflg);
ret = mlock(a, 1024*4); // 1024*4 is PAGE_ALIGN'ed but this is a hugepage
exit(0)
This will panic because the end of the area to be unmapped will be 4k
(the regular pace boundary) not 4M (the hugepage page boundary on this
arch)
To fix this I created 2 new macros in mlock.c and a new macro in all of
the page.h files that defined HPAGE_SIZE. I also had to move the
resource limit checks from sys_mlock to do_mlock. The reason for this
is that we can't tell if it is a hugepage unless we have the vma. And
so we don't know how long the mlock length will be unless we know how to
round the length to the correct page length. Thus resource checking
can't be done until after we have the vma in question.
The two macros in mlock.c will, only on systems compiled with
CONFIG_HUGETLB_PAGE, check if the page being locked or unlocked is a
hugepage and if so ALIGN it to hugepage boundaries rather than normal
page boundaries. If the vma is not for a hugepage it will use the same
methods as before for alignment. The macro addition to page.h copies
the PAGE_ALIGN macro but uses HPAGE_SIZE and HPAGE_MASK. I created this
HPAGE_ALIGN macro on the i386, x86_64, ia64, sh, sh64, sparc64, parisc
and powerpc archs. Since they appear to be the all arches that
implement HPAGE_SIZE. Two points of oddity, x86_64 seems to have
HPAGE_SIZE defined irrespective of CONFIG_HUGETLB_PAGE so my new
HPAGE_ALIGN macro is always defined as well. It will still only get
used if CONFIG_HUGETLB_PAGE is set.
The other point of oddity that I don't know if it is right is the
definition on powerpc. include/asm-powerpc/page_64.h does not quite
follow the same layout as the other arches so I think it's in the right
place but don't have a good place to test. So if a person with power pc
is willing to test for me please just let me know if it is either fixed
or if it doesn't compile correctly. I think it's right, but I'm not
100%.
Signed-off-by: Eric Paris <eparis@redhat.com>
include/asm-i386/page.h | 2 +
include/asm-ia64/page.h | 2 +
include/asm-parisc/page.h | 2 +
include/asm-powerpc/page_64.h | 2 +
include/asm-sh/page.h | 2 +
include/asm-sh64/page.h | 2 +
include/asm-sparc64/page.h | 2 +
include/asm-x86_64/page.h | 2 +
mm/mlock.c | 54 ++++++++++++++++++++++++------------------
9 files changed, 48 insertions(+), 22 deletions(-)
--- linux-2.6.16.14/include/asm-sparc64/page.h.paris
+++ linux-2.6.16.14/include/asm-sparc64/page.h
@@ -104,6 +104,8 @@ typedef unsigned long pgprot_t;
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
#define ARCH_HAS_SETCLEAR_HUGE_PTE
#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#endif
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
--- linux-2.6.16.14/include/asm-i386/page.h.paris
+++ linux-2.6.16.14/include/asm-i386/page.h
@@ -68,6 +68,8 @@ typedef struct { unsigned long pgprot; }
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#endif
#define pgd_val(x) ((x).pgd)
--- linux-2.6.16.14/include/asm-sh64/page.h.paris
+++ linux-2.6.16.14/include/asm-sh64/page.h
@@ -42,6 +42,8 @@
#define HPAGE_MASK (~(HPAGE_SIZE-1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
#define ARCH_HAS_SETCLEAR_HUGE_PTE
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#endif
#ifdef __KERNEL__
--- linux-2.6.16.14/include/asm-sh/page.h.paris
+++ linux-2.6.16.14/include/asm-sh/page.h
@@ -32,6 +32,8 @@
#define HPAGE_MASK (~(HPAGE_SIZE-1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
#define ARCH_HAS_SETCLEAR_HUGE_PTE
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#endif
#ifdef __KERNEL__
--- linux-2.6.16.14/include/asm-x86_64/page.h.paris
+++ linux-2.6.16.14/include/asm-x86_64/page.h
@@ -40,6 +40,8 @@
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
--- linux-2.6.16.14/include/asm-parisc/page.h.paris
+++ linux-2.6.16.14/include/asm-parisc/page.h
@@ -140,6 +140,8 @@ extern int npmem_ranges;
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#endif
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
--- linux-2.6.16.14/include/asm-ia64/page.h.paris
+++ linux-2.6.16.14/include/asm-ia64/page.h
@@ -57,6 +57,8 @@
# define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
# define ARCH_HAS_HUGEPAGE_ONLY_RANGE
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#endif /* CONFIG_HUGETLB_PAGE */
#ifdef __ASSEMBLY__
--- linux-2.6.16.14/include/asm-powerpc/page_64.h.paris
+++ linux-2.6.16.14/include/asm-powerpc/page_64.h
@@ -85,6 +85,8 @@ extern unsigned int HPAGE_SHIFT;
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+/* to align the pointer to the (next) page boundary when dealing with hugepages*/
+#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
#endif /* __ASSEMBLY__ */
--- linux-2.6.16.14/mm/mlock.c.paris
+++ linux-2.6.16.14/mm/mlock.c
@@ -11,6 +11,13 @@
#include <linux/mempolicy.h>
#include <linux/syscalls.h>
+#ifdef CONFIG_HUGETLB_PAGE
+#define MLOCK_PAGE_ALIGN(len,vma) (((vma)->vm_flags & VM_HUGETLB) ? HPAGE_ALIGN(len) : PAGE_ALIGN(len))
+#define MLOCK_PAGE_MASK(vma) (((vma)->vm_flags & VM_HUGETLB) ? HPAGE_MASK : PAGE_MASK)
+#else
+#define MLOCK_PAGE_ALIGN(len,vma) PAGE_ALIGN(len)
+#define MLOCK_PAGE_MASK(vma) PAGE_MASK
+#endif
static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
unsigned long start, unsigned long end, unsigned int newflags)
@@ -78,19 +85,37 @@ static int do_mlock(unsigned long start,
struct vm_area_struct * vma, * prev;
int error;
- len = PAGE_ALIGN(len);
- end = start + len;
- if (end < start)
- return -EINVAL;
- if (end == start)
- return 0;
vma = find_vma_prev(current->mm, start, &prev);
if (!vma || vma->vm_start > start)
return -ENOMEM;
+ len = MLOCK_PAGE_ALIGN((len + (start & ~MLOCK_PAGE_MASK(vma))), vma);
+ start = start & MLOCK_PAGE_MASK(vma);
+
if (start > vma->vm_start)
prev = vma;
+ end = start + len;
+ if (end < start)
+ return -EINVAL;
+ if (end == start)
+ return 0;
+
+ if (on) {
+ unsigned long locked;
+ unsigned long lock_limit;
+
+ locked = len >> PAGE_SHIFT;
+ locked += current->mm->locked_vm;
+
+ lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit >>= PAGE_SHIFT;
+
+ /* check against resource limits */
+ if ((locked > lock_limit) && !capable(CAP_IPC_LOCK))
+ return -ENOMEM;
+ }
+
for (nstart = start ; ; ) {
unsigned int newflags;
@@ -123,26 +148,13 @@ static int do_mlock(unsigned long start,
asmlinkage long sys_mlock(unsigned long start, size_t len)
{
- unsigned long locked;
- unsigned long lock_limit;
int error = -ENOMEM;
if (!can_do_mlock())
return -EPERM;
down_write(¤t->mm->mmap_sem);
- len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
- start &= PAGE_MASK;
-
- locked = len >> PAGE_SHIFT;
- locked += current->mm->locked_vm;
-
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
- lock_limit >>= PAGE_SHIFT;
-
- /* check against resource limits */
- if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
- error = do_mlock(start, len, 1);
+ error = do_mlock(start, len, 1);
up_write(¤t->mm->mmap_sem);
return error;
}
@@ -152,8 +164,6 @@ asmlinkage long sys_munlock(unsigned lon
int ret;
down_write(¤t->mm->mmap_sem);
- len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
- start &= PAGE_MASK;
ret = do_mlock(start, len, 0);
up_write(¤t->mm->mmap_sem);
return ret;
^ permalink raw reply
* Re: Bigphysarea vs. kernel 2.4.32 and PPC405GPr
From: Stephen Williams @ 2006-05-17 17:07 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <200605150835.48745.jgeissel@gmx.net>
That works nicely, thanks. I was under the mistaken impression that
the bigphysarea routines returned a physical address.
So now I can report that the bigphysarea patch works great on PPC
kernels 2.4.32+
Arno Geissel wrote:
> Try
>
> rc = remap_page_range(vma->vm_start,
> virt_to_phys(heap_map_base),
> npages*PAGE_SIZE,
> vma->vm_page_prot);
>
> Arno
>
>> I'm trying to use the bigphysarea patch to help me allocate big
>> physical chunks of memory for use by some custom embedded devices.
>> I've applied the bigphysarea-2.4.20 patch and built, no trouble,
>> and I've got it to config for my PPC. I can see at boot time that
>> the bigphysarea is getting its pages.
>>
>> I'm trying to use a mmap call to the driver to map a chunk of this
>> memory into the process. The mmap for the driver has this:
>>
>> pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
>> vma->vm_flags |= VM_RESERVED;
>>
>> npages = (vma->vm_end - vma->vm_start) / PAGE_SIZE;
>> heap_map_base = bigphysarea_alloc_pages(npages, 1, GFP_KERNEL);
>>
>> printk("XXXX Map base=%p, %ld pages\n", heap_map_base, npages);
>>
>> rc = remap_page_range(vma->vm_start,
>> (unsigned long)heap_map_base,
>> npages*PAGE_SIZE,
>> vma->vm_page_prot);
>>
>> The mmap returns without an error, but any access to the mapped
>> region gets me an immediate "Oops: machine check, sig: 7". I don't
>> see it. Where is the stupid mistake that I'm invariably making?
--
Steve Williams "The woods are lovely, dark and deep.
steve at icarus.com But I have promises to keep,
http://www.icarus.com and lines to code before I sleep,
http://www.picturel.com And lines to code before I sleep."
^ permalink raw reply
* Re: [PATCH] Fix do_mlock so page alignment is to hugepage boundries when needed
From: Christoph Lameter @ 2006-05-17 17:24 UTC (permalink / raw)
To: Eric Paris; +Cc: discuss, linux-kernel, wli, linuxppc-dev
In-Reply-To: <1147885316.26468.15.camel@localhost.localdomain>
On Wed, 17 May 2006, Eric Paris wrote:
> --- linux-2.6.16.14/include/asm-sparc64/page.h.paris
> +++ linux-2.6.16.14/include/asm-sparc64/page.h
> @@ -104,6 +104,8 @@ typedef unsigned long pgprot_t;
> #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
> #define ARCH_HAS_SETCLEAR_HUGE_PTE
> #define ARCH_HAS_HUGETLB_PREFAULT_HOOK
> +/* to align the pointer to the (next) page boundary when dealing with hugepages*/
> +#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
> #endif
Could you put the definition of HPAGE_ALIGN into include/linux/hugetlb.h
to avoid modifying all the page.h files?
^ permalink raw reply
* Re: [RFC PATCH 00/09] robust VM per_cpu variables
From: Christoph Lameter @ 2006-05-17 17:40 UTC (permalink / raw)
To: Steven Rostedt
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, Andi Kleen, linuxppc-dev,
Paul Mackerras, benedict.gaster, sam, bjornw, kenneth.w.chen,
Ingo Molnar, kiran, Nick Piggin, grundler, arnd, Rusty Russell,
starvik, Linus Torvalds, Thomas Gleixner, rth, Chris Zankel,
tony.luck, LKML, ralf, Marc Gauthier, lethal, schwidefsky,
linux390, davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605171152190.15798@gandalf.stny.rr.com>
On Wed, 17 May 2006, Steven Rostedt wrote:
> > Well I'd like to see a comprehensive solution including a fix for the
> > problems with allocper_cpu() allocations (allocper_cpu has to allocate
> > memory for potential processors... which could be a lot on
> > some types of systems and its allocated somewhere not on the nodes of the
> > processor since they may not yet be online).
>
> OK, now you're beyond what I'm working with ;) No hot plug CPUs for me.
> Well, at least not yet!
You need to at least consider how this could be handled by the per_cpu
memory manangement. The VM thingie with dynamic per cpu memory would allow
a fixup of allocpercpu.
^ permalink raw reply
* Re: [PATCH] Fix do_mlock so page alignment is to hugepage boundries when needed
From: Hugh Dickins @ 2006-05-17 17:42 UTC (permalink / raw)
To: Eric Paris; +Cc: discuss, linux-kernel, wli, linuxppc-dev
In-Reply-To: <1147885316.26468.15.camel@localhost.localdomain>
On Wed, 17 May 2006, Eric Paris wrote:
> sys_m{,un}lock and do_mlock all align memory references and the length
> of the mlock given by userspace to page boundaries. If the page being
> mlocked is a hugepage instead of a normal page the start and finish of
> the mlock will still only be aligned to normal page boundaries.
> Ultimately upon the process exiting we will eventually call unmap_vmas
> which will call unmap_hugepage_range for all of the ranges.
> unmap_hugepage_range checks to make sure the beginning and the end of
> the range are actually hugepage aligned and if not will BUG(). Since we
> only aligned to a normal page boundary the end of the first range and
> the beginning of the second will likely (unless userspace passed of
> values already hugepage aligned) not be hugepage aligned and thus we
> bomb.
When did you test this? It should have been fixed in 2.6.11 onwards
by split_vma()'s simple:
if (is_vm_hugetlb_page(vma) && (addr & ~HPAGE_MASK))
return -EINVAL;
Hugh
^ permalink raw reply
* Re: [PATCH] Fix do_mlock so page alignment is to hugepage boundries when needed
From: Eric Paris @ 2006-05-17 18:20 UTC (permalink / raw)
To: Christoph Lameter; +Cc: discuss, linux-kernel, wli, linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0605171020390.13767@schroedinger.engr.sgi.com>
On Wed, 2006-05-17 at 10:24 -0700, Christoph Lameter wrote:
> On Wed, 17 May 2006, Eric Paris wrote:
>
> > --- linux-2.6.16.14/include/asm-sparc64/page.h.paris
> > +++ linux-2.6.16.14/include/asm-sparc64/page.h
> > @@ -104,6 +104,8 @@ typedef unsigned long pgprot_t;
> > #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
> > #define ARCH_HAS_SETCLEAR_HUGE_PTE
> > #define ARCH_HAS_HUGETLB_PREFAULT_HOOK
> > +/* to align the pointer to the (next) page boundary when dealing with hugepages*/
> > +#define HPAGE_ALIGN(addr) (((addr)+HPAGE_SIZE-1)&HPAGE_MASK)
> > #endif
>
> Could you put the definition of HPAGE_ALIGN into include/linux/hugetlb.h
> to avoid modifying all the page.h files?
I could, I was just following the example of PAGE_ALIGN which was in all
the page.h files. But since it really is a nonarch specific hugepage
only macro maybe that is a better place for it.
If other results come back positive I'll repost with that change if
others think it best.
-Eric
^ permalink raw reply
* Re: [patch] udb_printf() formatting attribute
From: Jimi Xenidis @ 2006-05-17 18:31 UTC (permalink / raw)
To: Nathan Lynch; +Cc: linuxppc-dev
In-Reply-To: <20060517160053.GE10310@localdomain>
On May 17, 2006, at 12:00 PM, Nathan Lynch wrote:
> Jimi Xenidis wrote:
>> This patch allows the compiler to catch any printf-like mismatches
>> for udbg_printf().
>> After some brute force building I've only found issues with my own
>> code and lparcfg.c
>> It could break some developers, but IMHO that would be goodness.
>>
>> Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
>> ---
>> diff -r 0163968f7fce arch/powerpc/kernel/lparcfg.c
>> --- a/arch/powerpc/kernel/lparcfg.c Tue May 16 15:55:19 2006 -0400
>> +++ b/arch/powerpc/kernel/lparcfg.c Wed May 17 10:43:55 2006 -0400
>> @@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file
>> current_weight = (resource >> 5 * 8) & 0xFF;
>> - pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
>> + pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
>> __FUNCTION__, current_entitled, current_weight);
>> - pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
>> + pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
>> __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
>> retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
>
> Does this really fix a bug? What warnings are you able to get gcc to
> emit?
>
My sniff test that resulted in this patch was a manual build of all
arch/powerpc dirs with -DDEBUG added to CFLAGS.
To see these particular warnings simply add a #define DEBUG before
the includes of this file you will get:
.../linux-2.6/arch/powerpc/kernel/lparcfg.c: In function
`lparcfg_write':
.../linux-2.6/arch/powerpc/kernel/lparcfg.c:524: warning: long
unsigned int format, different type arg (arg 4)
.../linux-2.6/arch/powerpc/kernel/lparcfg.c:527: warning: long
unsigned int format, different type arg (arg 4)
^ permalink raw reply
* Re: [patch] udb_printf() formatting attribute
From: Jimi Xenidis @ 2006-05-17 18:30 UTC (permalink / raw)
To: Nathan Lynch; +Cc: linuxppc-dev
In-Reply-To: <20060517160053.GE10310@localdomain>
On May 17, 2006, at 12:00 PM, Nathan Lynch wrote:
> Jimi Xenidis wrote:
>> This patch allows the compiler to catch any printf-like mismatches
>> for udbg_printf().
>> After some brute force building I've only found issues with my own
>> code and lparcfg.c
>> It could break some developers, but IMHO that would be goodness.
>>
>> Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
>> ---
>> diff -r 0163968f7fce arch/powerpc/kernel/lparcfg.c
>> --- a/arch/powerpc/kernel/lparcfg.c Tue May 16 15:55:19 2006 -0400
>> +++ b/arch/powerpc/kernel/lparcfg.c Wed May 17 10:43:55 2006 -0400
>> @@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file
>> current_weight = (resource >> 5 * 8) & 0xFF;
>> - pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
>> + pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
>> __FUNCTION__, current_entitled, current_weight);
>> - pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
>> + pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
>> __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
>> retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
>
> Does this really fix a bug? What warnings are you able to get gcc to
> emit?
>
My sniff test that resulted in this patch was a manual build of all
arch/powerpc dirs with -DDEBUG added to CFLAGS.
To see these particular warnings simply add a #define DEBUG before
the includes of this file you will get:
.../linux-2.6/arch/powerpc/kernel/lparcfg.c: In function
`lparcfg_write':
.../linux-2.6/arch/powerpc/kernel/lparcfg.c:524: warning: long
unsigned int format, different type arg (arg 4)
.../linux-2.6/arch/powerpc/kernel/lparcfg.c:527: warning: long
unsigned int format, different type arg (arg 4)
^ permalink raw reply
* [PATCH][resend] udbg_printf() formatting attribute
From: jimix @ 2006-05-17 16:00 UTC (permalink / raw)
To: linuxppc-dev
Sorry, Previous patch was munged by MTA.
This patch allows the compiler to catch any printf-like mismatches for
udbg_printf(). After some brute force building I've only found issues
with my own code and lparcfg.c It could break some developers, but
IMHO that would be goodness.
Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
---
diff -r 0163968f7fce arch/powerpc/kernel/lparcfg.c
--- a/arch/powerpc/kernel/lparcfg.c Tue May 16 15:55:19 2006 -0400
+++ b/arch/powerpc/kernel/lparcfg.c Wed May 17 11:55:21 2006 -0400
@@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file
current_weight = (resource >> 5 * 8) & 0xFF;
- pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
+ pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
__FUNCTION__, current_entitled, current_weight);
- pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
+ pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
__FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
diff -r 0163968f7fce include/asm-powerpc/udbg.h
--- a/include/asm-powerpc/udbg.h Tue May 16 15:55:19 2006 -0400
+++ b/include/asm-powerpc/udbg.h Wed May 17 11:55:21 2006 -0400
@@ -23,7 +23,8 @@ extern int udbg_read(char *buf, int bufl
extern int udbg_read(char *buf, int buflen);
extern void register_early_udbg_console(void);
-extern void udbg_printf(const char *fmt, ...);
+extern void udbg_printf(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern void udbg_progress(char *s, unsigned short hex);
extern void udbg_init_uart(void __iomem *comport, unsigned int speed,
^ permalink raw reply
* Re: PowerMac7,3 sound (was: PowerBook5,4 -- no sound?)
From: Andreas Schwab @ 2006-05-17 19:32 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev
In-Reply-To: <1147862072.14395.25.camel@johannes>
Johannes Berg <johannes@sipsolutions.net> writes:
> Andreas, you'll probably be able to get a bit further by inserting the
> following code in front of the loop in i2sbus-core.c line 162, and
> removing the of_address_to_resource call inside the loop.
>
> dev->resources[0].start = 0x80010000;
> dev->resources[0].end = 0x80010fff;
> dev->resources[1].start = 0x80008000;
> dev->resources[1].end = 0x800080ff;
> dev->resources[2].start = 0x80008100;
> dev->resources[2].end = 0x800081ff;
>
> But I'm not sure that is correct on all machines (in fact, I'm not
> perfectly sure it is correct on your machine).
I have the following sound resources in /proc/iomem:
80008000-800083ff : 0.00010000:i2s
80008000-800083ff : Sound DMA
80010000-80010fff : 0.00010000:i2s
80010000-80010fff : Sound Control
I'm not sure whether the first mapping should be split, but I don't know
much about how resource mappings work.
> After that, you'll probably still not have usable sound though because I
> know nothing about the layout-id of your machine. If I have support for
> your codec already, that should be easy though.
The layout id is 36, and it has both line out and headphone, detected as a
Snapper.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply
* Re: snd-aoa status update / automatic driver loading
From: Andreas Schwab @ 2006-05-17 19:53 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev list, debian-powerpc
In-Reply-To: <1147860564.14395.6.camel@johannes>
Johannes Berg <johannes@sipsolutions.net> writes:
> Hey,
>
> Currently snd-aoa is known to work on the following machines:
> * PowerBook5,8
> * PowerBook5,7
> * PowerMac8,1
> * PowerMac8,2
> * 17" October 2005 PowerBook (don't know the number)
> * PowerMac11,2
> * PowerBook6,8
> and my
> * PowerBook5,6
For PowerBook6,7:
/* PowerBook6,7 */
{ .layout_id = 92,
.codecs[0] = {
.name = "tas",
.connections = tas_connections_nolineout,
},
},
Appears to work fine, apart from the missing features.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply
* Re: snd-aoa status update / automatic driver loading
From: Tony Vroon @ 2006-05-17 18:57 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev list, debian-powerpc
In-Reply-To: <1147860564.14395.6.camel@johannes>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Johannes Berg wrote:
> Hey,
>
> Currently snd-aoa is known to work on the following machines:
> * PowerBook5,8
> * PowerBook5,7
> * PowerMac8,1
> * PowerMac8,2
> * 17" October 2005 PowerBook (don't know the number)
That would be the PowerBook 5,9 (confirmed working, that's what I have).
> * PowerMac11,2
> * PowerBook6,8
> and my
> * PowerBook5,6
> People with those machines are encouraged to use and stress-test it, it
> also provides much better hardware support than snd-powermac, for
> example it can actually reprogram the hardware if you have a 48KHz file
> instead of having to digitally downsample it to 44.1KHz like required
> with snd-powermac in most cases.
When writing documentation, you might want to add that the ALSA-plugin
in XMMS & Audacious requires a period time of 100ms instead of the
default of 50ms, as otherwise the sou*click*nd is n*click*ot ver*click*y
good.
(A look at the current code of that plugin, to see how the volume
control code can be fixed would be highly appreciated)
> There are apparently some cases where it loses interrupts and then the
> sound is garbled, my brother's investigating that at the moment, it
> doesn't happen with my powerbook nor with my powermac.
Not seen this, although I must say it does not resume from sleep as
gracefully as I have seen you describe it.
> But the other reason for writing this mail is that I finally found the
> last remaining bug that prevented sound module autoloading! :)
Much appreciated, thank you :)
> Now, when you boot, mac-io is already built-in so provides the i2s
> device, which my i2sbus module binds to. Since udev synthesizes events,
> i2sbus gets loaded automatically. Now, i2sbus creates uevents on its
> own, with the layout number given as the MODALIAS. Hence, the layout
> fabric module is loaded because it has an alias for all the layouts it
> handles, and it in turn requests all the codec modules that it requires.
> Also, this means that 'modprobe i2sbus' will suffice to get the driver
> up and running without a reboot, provided that all modules are
> installed.
>
> Have fun,
> johannes
Regards,
Tony V.
(Chainsaw)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3-ecc0.1.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFEa3Icp5vW4rUFj5oRAuFXAJwMgzHiZLal33irvZt6qtDbo1L+rQCbBb4d
KF5TAISi/CUHYj+ZqJjPpFE=
=ptuO
-----END PGP SIGNATURE-----
^ permalink raw reply
* Re: [PATCH] Fix do_mlock so page alignment is to hugepage boundries when needed
From: Eric Paris @ 2006-05-17 19:59 UTC (permalink / raw)
To: Hugh Dickins; +Cc: discuss, linux-kernel, wli, linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0605171840310.14529@blonde.wat.veritas.com>
On Wed, 2006-05-17 at 18:42 +0100, Hugh Dickins wrote:
> On Wed, 17 May 2006, Eric Paris wrote:
> > sys_m{,un}lock and do_mlock all align memory references and the length
> > of the mlock given by userspace to page boundaries. If the page being
> > mlocked is a hugepage instead of a normal page the start and finish of
> > the mlock will still only be aligned to normal page boundaries.
> > Ultimately upon the process exiting we will eventually call unmap_vmas
> > which will call unmap_hugepage_range for all of the ranges.
> > unmap_hugepage_range checks to make sure the beginning and the end of
> > the range are actually hugepage aligned and if not will BUG(). Since we
> > only aligned to a normal page boundary the end of the first range and
> > the beginning of the second will likely (unless userspace passed of
> > values already hugepage aligned) not be hugepage aligned and thus we
> > bomb.
>
> When did you test this? It should have been fixed in 2.6.11 onwards
> by split_vma()'s simple:
>
> if (is_vm_hugetlb_page(vma) && (addr & ~HPAGE_MASK))
> return -EINVAL;
>
> Hugh
You're right. My initial BUG() problem was on pre 2.6.11. I wrote this
patch and tested that it worked on 2.6.16 to allow the test program I
described to run successfully. Admittedly this is the first time I
tested on unpatched 2.6.16 and as you said the mlock will fail with
"Invalid Argument" instead of BUG(). So the panic is gone post 2.6.11,
but the problem remains. We still are rounding incorrectly for
hugepages in the sys_mlock and do_mlock functions.
This patch still solves the problem of the kernel currently being more
restrictive on what we accept from userspace for the length of the mlock
if it is a hugepage rather than a regular page. With a regular page we
will round the value from userspace and happily go about our business of
mlocking. For a hugepage it just rejects it if userspace doesn't align
it themselves. This allows the kernel to do the same work for hugepages
that it does for normal pages.
-Eric
^ 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