* Re: [PATCH] Ftrace : fix function_graph tracer OOPS
From: Sachin Sant @ 2009-10-14 6:13 UTC (permalink / raw)
To: rostedt; +Cc: linuxppc-dev
In-Reply-To: <1255489284.7113.3121.camel@gandalf.stny.rr.com>
Steven Rostedt wrote:
> On Thu, 2009-10-08 at 20:21 +0530, Sachin Sant wrote:
>
>> Switch to LOAD_REG_ADDR().
>>
>> Signed-off-by : Sachin Sant <sachinp@in.ibm.com>
>> ---
>> diff -Naurp old/arch/powerpc/kernel/entry_64.S
>> new/arch/powerpc/kernel/entry_64.S
>> --- old/arch/powerpc/kernel/entry_64.S 2009-10-08 18:37:44.000000000
>> +0530
>> +++ new/arch/powerpc/kernel/entry_64.S 2009-10-08 18:34:33.000000000
>> +0530
>> @@ -1038,8 +1038,8 @@ _GLOBAL(mod_return_to_handler)
>> * We are in a module using the module's TOC.
>> * Switch to our TOC to run inside the core kernel.
>> */
>> - LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler)
>> - ld r2, 8(r4)
>> + ld r2, PACATOC(r13)
>> + LOAD_REG_ADDR(r4,ftrace_return_to_handler)
>>
>
> Actually, the loading of this register is not needed. The original used
> the loading to get the r2.
>
> I actually wrote a fix for this a month ago. I never sent it out because
> I was distracted by other issues.
>
> I'll send out the two patches I had now.
>
> Could yo test them?
>
Tested both the patches. Works fine.
Thanks
-Sachin
--
---------------------------------
Sachin Sant
IBM Linux Technology Center
India Systems and Technology Labs
Bangalore, India
---------------------------------
^ permalink raw reply
* [PATCH] Xilinx LL-TEMAC: Add Netpoll controller support
From: santosh shukla @ 2009-10-14 6:12 UTC (permalink / raw)
To: Linuxppc-dev; +Cc: John.Linn
From: Santosh Shukla <sshukla@sh.mvista.com>
Date: Tue, 13 Oct 2009 18:55:57 +0530
Subject: [PATCH] Xilinx LL-TEMAC: Add Netpoll controller support
Adding Netpoll controller support to Xilinx LL-TEMAC ethernet
driver.Repaced Rx, Tx tasklet schedule call with their handlers,
Added correct version of call which can execute interrupt on/off
context i.e. dev_kfree_skb_any().
---
drivers/net/xilinx_lltemac/xlltemac_main.c | 41 +++++++++++++++++++++++++++-
1 files changed, 40 insertions(+), 1 deletions(-)
diff --git a/drivers/net/xilinx_lltemac/xlltemac_main.c b/drivers/net/xilinx_lltemac/xlltemac_main.c
index b245422..697f474 100644
--- a/drivers/net/xilinx_lltemac/xlltemac_main.c
+++ b/drivers/net/xilinx_lltemac/xlltemac_main.c
@@ -87,11 +87,18 @@
#define BUFFER_ALIGNSEND_PERF(adr) ((ALIGNMENT_SEND_PERF - ((u32) adr)) % 32)
#define BUFFER_ALIGNRECV(adr) ((ALIGNMENT_RECV - ((u32) adr)) % 32)
+#ifndef CONFIG_NET_POLL_CONTROLLER
/* Default TX/RX Threshold and waitbound values for SGDMA mode */
#define DFT_TX_THRESHOLD 24
#define DFT_TX_WAITBOUND 254
#define DFT_RX_THRESHOLD 4
#define DFT_RX_WAITBOUND 254
+#else
+#define DFT_TX_THRESHOLD 1
+#define DFT_TX_WAITBOUND 0
+#define DFT_RX_THRESHOLD 1
+#define DFT_RX_WAITBOUND 0
+#endif
#define XTE_AUTOSTRIPPING 1
@@ -1097,7 +1104,11 @@ static irqreturn_t xenet_dma_rx_interrupt(int irq, void *dev_id)
list_add_tail(&lp->rcv, &receivedQueue);
XLlDma_mBdRingIntDisable(&lp->Dma.RxBdRing,
XLLDMA_CR_IRQ_ALL_EN_MASK);
+#ifndef CONFIG_NET_POLL_CONTROLLER
tasklet_schedule(&DmaRecvBH);
+#else
+ DmaRecvHandlerBH(0);
+#endif
}
spin_unlock_irqrestore(&receivedQueueSpin, flags);
}
@@ -1134,7 +1145,11 @@ static irqreturn_t xenet_dma_tx_interrupt(int irq, void *dev_id)
list_add_tail(&lp->xmit, &sentQueue);
XLlDma_mBdRingIntDisable(&lp->Dma.TxBdRing,
XLLDMA_CR_IRQ_ALL_EN_MASK);
+#ifndef CONFIG_NET_POLL_CONTROLLER
tasklet_schedule(&DmaSendBH);
+#else
+ DmaSendHandlerBH(0);
+#endif
}
spin_unlock_irqrestore(&sentQueueSpin, flags);
}
@@ -1711,11 +1726,15 @@ static int xenet_DmaSend(struct sk_buff *skb, struct net_device *dev)
* SgAlloc, SgCommit sequence, which also exists in DmaSendHandlerBH Bottom
* Half, or triggered by other processor in SMP case.
*/
+#ifndef CONFIG_NET_POLL_CONTROLLER
spin_lock_bh(&XTE_tx_spinlock);
+#endif
xenet_DmaSend_internal(skb, dev);
+#ifndef CONFIG_NET_POLL_CONTROLLER
spin_unlock_bh(&XTE_tx_spinlock);
+#endif
return 0;
}
@@ -1764,7 +1783,7 @@ static void DmaSendHandlerBH(unsigned long p)
skb = (struct sk_buff *)
XLlDma_mBdGetId(BdCurPtr);
if (skb)
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
/* reset BD id */
XLlDma_mBdSetId(BdCurPtr, NULL);
@@ -3220,6 +3239,23 @@ static int detect_phy(struct net_local *lp, char *dev_name)
return 0; /* default to zero */
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+lltemac_poll_controller(struct net_device *ndev)
+{
+ struct net_local *lp = netdev_priv(ndev);
+
+ disable_irq(lp->dma_irq_s);
+ disable_irq(lp->dma_irq_r);
+
+ xenet_dma_tx_interrupt(lp->dma_irq_s, ndev);
+ xenet_dma_rx_interrupt(lp->dma_irq_r, ndev);
+
+ enable_irq(lp->dma_irq_s);
+ enable_irq(lp->dma_irq_r);
+}
+#endif
+
static struct net_device_ops xilinx_netdev_ops;
/* From include/linux/ethtool.h */
@@ -3491,6 +3527,9 @@ static struct net_device_ops xilinx_netdev_ops = {
.ndo_change_mtu = xenet_change_mtu,
.ndo_tx_timeout = xenet_tx_timeout,
.ndo_get_stats = xenet_get_stats,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = lltemac_poll_controller,
+#endif
};
static struct of_device_id xtenet_fifo_of_match[] = {
--
1.6.3.3.220.g609a0
^ permalink raw reply related
* [PATCH 10/16] percpu: make percpu symbols in powerpc unique
From: Tejun Heo @ 2009-10-14 6:01 UTC (permalink / raw)
To: linux-kernel, rusty, cl, mingo, tglx, akpm, rostedt, hpa, cebbert
Cc: Tejun Heo, Paul Mackerras, linuxppc-dev
In-Reply-To: <1255500125-3210-1-git-send-email-tj@kernel.org>
This patch updates percpu related symbols in powerpc such that percpu
symbols are unique and don't clash with local symbols. This serves
two purposes of decreasing the possibility of global percpu symbol
collision and allowing dropping per_cpu__ prefix from percpu symbols.
* arch/powerpc/kernel/perf_callchain.c: s/callchain/cpu_perf_callchain/
* arch/powerpc/kernel/setup-common.c: s/pvr/cpu_pvr/
* arch/powerpc/platforms/pseries/dtl.c: s/dtl/cpu_dtl/
* arch/powerpc/platforms/cell/interrupt.c: s/iic/cpu_iic/
Partly based on Rusty Russell's "alloc_percpu: rename percpu vars
which cause name clashes" patch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@ozlabs.org
---
arch/powerpc/include/asm/smp.h | 2 +-
arch/powerpc/kernel/perf_callchain.c | 4 ++--
arch/powerpc/kernel/setup-common.c | 4 ++--
arch/powerpc/kernel/smp.c | 2 +-
arch/powerpc/platforms/cell/interrupt.c | 14 +++++++-------
arch/powerpc/platforms/pseries/dtl.c | 4 ++--
6 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index d9ea8d3..1d3b270 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -37,7 +37,7 @@ extern void cpu_die(void);
extern void smp_send_debugger_break(int cpu);
extern void smp_message_recv(int);
-DECLARE_PER_CPU(unsigned int, pvr);
+DECLARE_PER_CPU(unsigned int, cpu_pvr);
#ifdef CONFIG_HOTPLUG_CPU
extern void fixup_irqs(cpumask_t map);
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c
index 0a03cf7..fe59c44 100644
--- a/arch/powerpc/kernel/perf_callchain.c
+++ b/arch/powerpc/kernel/perf_callchain.c
@@ -497,11 +497,11 @@ static void perf_callchain_user_32(struct pt_regs *regs,
* Since we can't get PMU interrupts inside a PMU interrupt handler,
* we don't need separate irq and nmi entries here.
*/
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
+static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain);
struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
{
- struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
+ struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain);
entry->nr = 0;
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 4271f7a..aa5aeb9 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -157,7 +157,7 @@ extern u32 cpu_temp_both(unsigned long cpu);
#endif /* CONFIG_TAU */
#ifdef CONFIG_SMP
-DEFINE_PER_CPU(unsigned int, pvr);
+DEFINE_PER_CPU(unsigned int, cpu_pvr);
#endif
static int show_cpuinfo(struct seq_file *m, void *v)
@@ -209,7 +209,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
}
#ifdef CONFIG_SMP
- pvr = per_cpu(pvr, cpu_id);
+ pvr = per_cpu(cpu_pvr, cpu_id);
#else
pvr = mfspr(SPRN_PVR);
#endif
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 9b86a74..2ebb484 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -232,7 +232,7 @@ struct thread_info *current_set[NR_CPUS];
static void __devinit smp_store_cpu_info(int id)
{
- per_cpu(pvr, id) = mfspr(SPRN_PVR);
+ per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
}
static void __init smp_create_idle(unsigned int cpu)
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 882e470..54bad90 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -54,7 +54,7 @@ struct iic {
struct device_node *node;
};
-static DEFINE_PER_CPU(struct iic, iic);
+static DEFINE_PER_CPU(struct iic, cpu_iic);
#define IIC_NODE_COUNT 2
static struct irq_host *iic_host;
@@ -82,7 +82,7 @@ static void iic_unmask(unsigned int irq)
static void iic_eoi(unsigned int irq)
{
- struct iic *iic = &__get_cpu_var(iic);
+ struct iic *iic = &__get_cpu_var(cpu_iic);
out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
BUG_ON(iic->eoi_ptr < 0);
}
@@ -146,7 +146,7 @@ static unsigned int iic_get_irq(void)
struct iic *iic;
unsigned int virq;
- iic = &__get_cpu_var(iic);
+ iic = &__get_cpu_var(cpu_iic);
*(unsigned long *) &pending =
in_be64((u64 __iomem *) &iic->regs->pending_destr);
if (!(pending.flags & CBE_IIC_IRQ_VALID))
@@ -161,12 +161,12 @@ static unsigned int iic_get_irq(void)
void iic_setup_cpu(void)
{
- out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+ out_be64(&__get_cpu_var(cpu_iic).regs->prio, 0xff);
}
u8 iic_get_target_id(int cpu)
{
- return per_cpu(iic, cpu).target_id;
+ return per_cpu(cpu_iic, cpu).target_id;
}
EXPORT_SYMBOL_GPL(iic_get_target_id);
@@ -181,7 +181,7 @@ static inline int iic_ipi_to_irq(int ipi)
void iic_cause_IPI(int cpu, int mesg)
{
- out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4);
+ out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - mesg) << 4);
}
struct irq_host *iic_get_irq_host(int node)
@@ -348,7 +348,7 @@ static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
/* XXX FIXME: should locate the linux CPU number from the HW cpu
* number properly. We are lucky for now
*/
- struct iic *iic = &per_cpu(iic, hw_cpu);
+ struct iic *iic = &per_cpu(cpu_iic, hw_cpu);
iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs));
BUG_ON(iic->regs == NULL);
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index 937a544..c5f3116 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -54,7 +54,7 @@ struct dtl {
int buf_entries;
u64 last_idx;
};
-static DEFINE_PER_CPU(struct dtl, dtl);
+static DEFINE_PER_CPU(struct dtl, cpu_dtl);
/*
* Dispatch trace log event mask:
@@ -261,7 +261,7 @@ static int dtl_init(void)
/* set up the per-cpu log structures */
for_each_possible_cpu(i) {
- struct dtl *dtl = &per_cpu(dtl, i);
+ struct dtl *dtl = &per_cpu(cpu_dtl, i);
dtl->cpu = i;
rc = dtl_setup_file(dtl);
--
1.6.4.2
^ permalink raw reply related
* Re: [PATCH, RFC] powerpc, pci: fix MODPOST warning
From: Benjamin Herrenschmidt @ 2009-10-14 5:47 UTC (permalink / raw)
To: hs; +Cc: linuxppc-dev
In-Reply-To: <4AC99B12.8020005@denx.de>
On Mon, 2009-10-05 at 09:06 +0200, Heiko Schocher wrote:
> Hello,
>
> Heiko Schocher wrote:
> > making a powerpc target with PCI support, shows the
> > following warning:
> >
> > MODPOST vmlinux.o
> > WARNING: vmlinux.o(.text+0x10430): Section mismatch in reference from the function pcibios_allocate_bus_resources() to the function .init.text:reparent_resources()
> > The function pcibios_allocate_bus_resources() references
> > the function __init reparent_resources().
> > This is often because pcibios_allocate_bus_resources lacks a __init
> > annotation or the annotation of reparent_resources is wrong.
> >
> > This patch fix this warning by removing the __init
> > annotation before reparent_resources.
>
> No comments? So, is this fix OK, or unusable?
Nah, just me missing it but it's reference on patchwork. I'll pick
the patch up. We can probably make some of that __devinit instead
of __init though but we can look at it later.
Cheers
Ben.
^ permalink raw reply
* [PATCH 6/6] powerpc: Enable sparse irq_descs on powerpc
From: Michael Ellerman @ 2009-10-14 5:45 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <a6fc612b826ff12628e62601203d565df00c6436.1255499081.git.michael@ellerman.id.au>
Defining CONFIG_SPARSE_IRQ enables generic code that gets rid of the
static irq_desc array, and replaces it with an array of pointers to
irq_descs.
It also allows node local allocation of irq_descs, however we
currently don't have the information available to do that, so we just
allocate them on all on node 0.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/Kconfig | 13 ++++++++++++
arch/powerpc/include/asm/irq.h | 3 ++
arch/powerpc/kernel/irq.c | 40 ++++++++++++++++++++++++++++++++------
arch/powerpc/kernel/ppc_ksyms.c | 1 -
arch/powerpc/kernel/setup_64.c | 5 ----
5 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2230e75..825d889 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -388,6 +388,19 @@ config IRQ_ALL_CPUS
CPU. Generally saying Y is safe, although some problems have been
reported with SMP Power Macintoshes with this option enabled.
+config SPARSE_IRQ
+ bool "Support sparse irq numbering"
+ default y
+ help
+ This enables support for sparse irqs. This is useful for distro
+ kernels that want to define a high CONFIG_NR_CPUS value but still
+ want to have low kernel memory footprint on smaller machines.
+
+ ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread
+ out the irq_desc[] array in a more NUMA-friendly way. )
+
+ If you don't know what to do here, say Y.
+
config NUMA
bool "NUMA support"
depends on PPC64
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index 03dc28c..c85a32f 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -38,6 +38,9 @@ extern atomic_t ppc_n_lost_interrupts;
/* Number of irqs reserved for the legacy controller */
#define NUM_ISA_INTERRUPTS 16
+/* Same thing, used by the generic IRQ code */
+#define NR_IRQS_LEGACY NUM_ISA_INTERRUPTS
+
/* This type is the placeholder for a hardware interrupt number. It has to
* be big enough to enclose whatever representation is used by a given
* platform.
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 63e27d5..eba5392 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -85,7 +85,10 @@ extern int tau_interrupts(int);
#endif /* CONFIG_PPC32 */
#ifdef CONFIG_PPC64
+
+#ifndef CONFIG_SPARSE_IRQ
EXPORT_SYMBOL(irq_desc);
+#endif
int distribute_irqs = 1;
@@ -613,8 +616,16 @@ void irq_set_virq_count(unsigned int count)
static int irq_setup_virq(struct irq_host *host, unsigned int virq,
irq_hw_number_t hwirq)
{
+ struct irq_desc *desc;
+
+ desc = irq_to_desc_alloc_node(virq, 0);
+ if (!desc) {
+ pr_debug("irq: -> allocating desc failed\n");
+ goto error;
+ }
+
/* Clear IRQ_NOREQUEST flag */
- irq_to_desc(virq)->status &= ~IRQ_NOREQUEST;
+ desc->status &= ~IRQ_NOREQUEST;
/* map it */
smp_wmb();
@@ -623,11 +634,14 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
if (host->ops->map(host, virq, hwirq)) {
pr_debug("irq: -> mapping failed, freeing\n");
- irq_free_virt(virq, 1);
- return -1;
+ goto error;
}
return 0;
+
+error:
+ irq_free_virt(virq, 1);
+ return -1;
}
unsigned int irq_create_direct_mapping(struct irq_host *host)
@@ -1008,12 +1022,24 @@ void irq_free_virt(unsigned int virq, unsigned int count)
spin_unlock_irqrestore(&irq_big_lock, flags);
}
-void irq_early_init(void)
+int arch_early_irq_init(void)
{
- unsigned int i;
+ struct irq_desc *desc;
+ int i;
- for (i = 0; i < NR_IRQS; i++)
- irq_to_desc(i)->status |= IRQ_NOREQUEST;
+ for (i = 0; i < NR_IRQS; i++) {
+ desc = irq_to_desc(i);
+ if (desc)
+ desc->status |= IRQ_NOREQUEST;
+ }
+
+ return 0;
+}
+
+int arch_init_chip_data(struct irq_desc *desc, int node)
+{
+ desc->status |= IRQ_NOREQUEST;
+ return 0;
}
/* We need to create the radix trees late */
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index c8b27bb..07115d6 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -162,7 +162,6 @@ EXPORT_SYMBOL(screen_info);
#ifdef CONFIG_PPC32
EXPORT_SYMBOL(timer_interrupt);
-EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(tb_ticks_per_jiffy);
EXPORT_SYMBOL(cacheable_memcpy);
EXPORT_SYMBOL(cacheable_memzero);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 797ea95..8e5ec92 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -357,11 +357,6 @@ void __init setup_system(void)
*/
initialize_cache_info();
- /*
- * Initialize irq remapping subsystem
- */
- irq_early_init();
-
#ifdef CONFIG_PPC_RTAS
/*
* Initialize RTAS if available
--
1.6.2.1
^ permalink raw reply related
* [PATCH 5/6] powerpc: Rearrange and fix show_interrupts() for sparse irq_descs
From: Michael Ellerman @ 2009-10-14 5:45 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <a6fc612b826ff12628e62601203d565df00c6436.1255499081.git.michael@ellerman.id.au>
Move the default case out of the if, ie. when we're just displaying
an irq. And consolidate all the odd cases at the top, ie. printing
the header and footer.
And in the process cope with sparse irq_descs.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/irq.c | 64 ++++++++++++++++++++++++++-------------------
1 files changed, 37 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index baa49eb..63e27d5 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -187,33 +187,7 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j)
seq_printf(p, "CPU%d ", j);
seq_putc(p, '\n');
- }
-
- if (i < NR_IRQS) {
- desc = irq_to_desc(i);
- spin_lock_irqsave(&desc->lock, flags);
- action = desc->action;
- if (!action || !action->handler)
- goto skip;
- seq_printf(p, "%3d: ", i);
-#ifdef CONFIG_SMP
- for_each_online_cpu(j)
- seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#else
- seq_printf(p, "%10u ", kstat_irqs(i));
-#endif /* CONFIG_SMP */
- if (desc->chip)
- seq_printf(p, " %s ", desc->chip->typename);
- else
- seq_puts(p, " None ");
- seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
- seq_printf(p, " %s", action->name);
- for (action = action->next; action; action = action->next)
- seq_printf(p, ", %s", action->name);
- seq_putc(p, '\n');
-skip:
- spin_unlock_irqrestore(&desc->lock, flags);
- } else if (i == NR_IRQS) {
+ } else if (i == nr_irqs) {
#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
if (tau_initialized){
seq_puts(p, "TAU: ");
@@ -223,7 +197,43 @@ skip:
}
#endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/
seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
+
+ return 0;
}
+
+ desc = irq_to_desc(i);
+ if (!desc)
+ return 0;
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ action = desc->action;
+ if (!action || !action->handler)
+ goto skip;
+
+ seq_printf(p, "%3d: ", i);
+#ifdef CONFIG_SMP
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+#else
+ seq_printf(p, "%10u ", kstat_irqs(i));
+#endif /* CONFIG_SMP */
+
+ if (desc->chip)
+ seq_printf(p, " %s ", desc->chip->typename);
+ else
+ seq_puts(p, " None ");
+
+ seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
+ seq_printf(p, " %s", action->name);
+
+ for (action = action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+ seq_putc(p, '\n');
+
+skip:
+ spin_unlock_irqrestore(&desc->lock, flags);
+
return 0;
}
--
1.6.2.1
^ permalink raw reply related
* [PATCH 4/6] powerpc: Make virq_debug_show() cope with sparse irq_descs
From: Michael Ellerman @ 2009-10-14 5:44 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <a6fc612b826ff12628e62601203d565df00c6436.1255499081.git.michael@ellerman.id.au>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/irq.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 6563221..baa49eb 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -1065,8 +1065,11 @@ static int virq_debug_show(struct seq_file *m, void *private)
seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq",
"chip name", "host name");
- for (i = 1; i < NR_IRQS; i++) {
+ for (i = 1; i < nr_irqs; i++) {
desc = irq_to_desc(i);
+ if (!desc)
+ continue;
+
spin_lock_irqsave(&desc->lock, flags);
if (desc->action && desc->action->handler) {
--
1.6.2.1
^ permalink raw reply related
* [PATCH 3/6] powerpc: Remove get_irq_desc()
From: Michael Ellerman @ 2009-10-14 5:44 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <a6fc612b826ff12628e62601203d565df00c6436.1255499081.git.michael@ellerman.id.au>
get_irq_desc() is a powerpc-specific version of irq_to_desc(). That
is reason enough to remove it, but it also doesn't know about sparse
irq_desc support which irq_to_desc() does (when we enable it).
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/include/asm/irq.h | 2 -
arch/powerpc/kernel/crash.c | 2 +-
arch/powerpc/kernel/irq.c | 28 ++++++++++++----------
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 2 +-
arch/powerpc/platforms/52xx/media5200.c | 2 +-
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 2 +-
arch/powerpc/platforms/85xx/socrates_fpga_pic.c | 2 +-
arch/powerpc/platforms/86xx/gef_pic.c | 2 +-
arch/powerpc/platforms/cell/beat_interrupt.c | 2 +-
arch/powerpc/platforms/cell/spider-pic.c | 4 +-
arch/powerpc/platforms/iseries/irq.c | 2 +-
arch/powerpc/platforms/powermac/pic.c | 8 +++---
arch/powerpc/platforms/pseries/xics.c | 8 +++---
arch/powerpc/sysdev/cpm1.c | 2 +-
arch/powerpc/sysdev/cpm2_pic.c | 10 +++++---
arch/powerpc/sysdev/fsl_msi.c | 2 +-
arch/powerpc/sysdev/i8259.c | 4 +-
arch/powerpc/sysdev/ipic.c | 2 +-
arch/powerpc/sysdev/mpc8xx_pic.c | 2 +-
arch/powerpc/sysdev/mpic.c | 18 +++++++-------
arch/powerpc/sysdev/mv64x60_pic.c | 2 +-
arch/powerpc/sysdev/qe_lib/qe_ic.c | 4 +-
arch/powerpc/sysdev/tsi108_pci.c | 2 +-
arch/powerpc/sysdev/uic.c | 6 ++--
arch/powerpc/sysdev/xilinx_intc.c | 2 +-
25 files changed, 62 insertions(+), 60 deletions(-)
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index b83fcc8..03dc28c 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -17,8 +17,6 @@
#include <asm/atomic.h>
-#define get_irq_desc(irq) (&irq_desc[(irq)])
-
/* Define a way to iterate across irqs. */
#define for_each_irq(i) \
for ((i) = 0; (i) < NR_IRQS; ++(i))
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 0a8439a..6f4613d 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -373,7 +373,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
hard_irq_disable();
for_each_irq(i) {
- struct irq_desc *desc = irq_desc + i;
+ struct irq_desc *desc = irq_to_desc(i);
if (desc->status & IRQ_INPROGRESS)
desc->chip->eoi(i);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index e5d1211..6563221 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -190,7 +190,7 @@ int show_interrupts(struct seq_file *p, void *v)
}
if (i < NR_IRQS) {
- desc = get_irq_desc(i);
+ desc = irq_to_desc(i);
spin_lock_irqsave(&desc->lock, flags);
action = desc->action;
if (!action || !action->handler)
@@ -230,23 +230,25 @@ skip:
#ifdef CONFIG_HOTPLUG_CPU
void fixup_irqs(cpumask_t map)
{
+ struct irq_desc *desc;
unsigned int irq;
static int warned;
for_each_irq(irq) {
cpumask_t mask;
- if (irq_desc[irq].status & IRQ_PER_CPU)
+ desc = irq_to_desc(irq);
+ if (desc && desc->status & IRQ_PER_CPU)
continue;
- cpumask_and(&mask, irq_desc[irq].affinity, &map);
+ cpumask_and(&mask, desc->affinity, &map);
if (any_online_cpu(mask) == NR_CPUS) {
printk("Breaking affinity for irq %i\n", irq);
mask = map;
}
- if (irq_desc[irq].chip->set_affinity)
- irq_desc[irq].chip->set_affinity(irq, &mask);
- else if (irq_desc[irq].action && !(warned++))
+ if (desc->chip->set_affinity)
+ desc->chip->set_affinity(irq, &mask);
+ else if (desc->action && !(warned++))
printk("Cannot set affinity for irq %i\n", irq);
}
@@ -273,7 +275,7 @@ static inline void handle_one_irq(unsigned int irq)
return;
}
- desc = irq_desc + irq;
+ desc = irq_to_desc(irq);
saved_sp_limit = current->thread.ksp_limit;
irqtp->task = curtp->task;
@@ -535,7 +537,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
smp_wmb();
/* Clear norequest flags */
- get_irq_desc(i)->status &= ~IRQ_NOREQUEST;
+ irq_to_desc(i)->status &= ~IRQ_NOREQUEST;
/* Legacy flags are left to default at this point,
* one can then use irq_create_mapping() to
@@ -602,7 +604,7 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
irq_hw_number_t hwirq)
{
/* Clear IRQ_NOREQUEST flag */
- get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
+ irq_to_desc(virq)->status &= ~IRQ_NOREQUEST;
/* map it */
smp_wmb();
@@ -732,7 +734,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
/* Set type if specified and different than the current one */
if (type != IRQ_TYPE_NONE &&
- type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK))
+ type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
set_irq_type(virq, type);
return virq;
}
@@ -804,7 +806,7 @@ void irq_dispose_mapping(unsigned int virq)
irq_map[virq].hwirq = host->inval_irq;
/* Set some flags */
- get_irq_desc(virq)->status |= IRQ_NOREQUEST;
+ irq_to_desc(virq)->status |= IRQ_NOREQUEST;
/* Free it */
irq_free_virt(virq, 1);
@@ -1001,7 +1003,7 @@ void irq_early_init(void)
unsigned int i;
for (i = 0; i < NR_IRQS; i++)
- get_irq_desc(i)->status |= IRQ_NOREQUEST;
+ irq_to_desc(i)->status |= IRQ_NOREQUEST;
}
/* We need to create the radix trees late */
@@ -1064,7 +1066,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
"chip name", "host name");
for (i = 1; i < NR_IRQS; i++) {
- desc = get_irq_desc(i);
+ desc = irq_to_desc(i);
spin_lock_irqsave(&desc->lock, flags);
if (desc->action && desc->action->handler) {
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
index a6ce805..cd70ee1 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
@@ -132,7 +132,7 @@ static int
cpld_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq);
return 0;
}
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 68e4f16..4780203 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -114,7 +114,7 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
static int media5200_irq_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw);
set_irq_chip_data(virq, &media5200_irq);
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 7ee979f..a682331 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -107,7 +107,7 @@ static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_data(virq, h->host_data);
set_irq_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq);
return 0;
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
index 60edf63..e59920a 100644
--- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -245,7 +245,7 @@ static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hwirq)
{
/* All interrupts are LEVEL sensitive */
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip,
handle_fasteoi_irq);
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c
index 50d0a2b..978d6cb 100644
--- a/arch/powerpc/platforms/86xx/gef_pic.c
+++ b/arch/powerpc/platforms/86xx/gef_pic.c
@@ -163,7 +163,7 @@ static int gef_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hwirq)
{
/* All interrupts are LEVEL sensitive */
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
return 0;
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
index 7225484..4a2bbff 100644
--- a/arch/powerpc/platforms/cell/beat_interrupt.c
+++ b/arch/powerpc/platforms/cell/beat_interrupt.c
@@ -136,7 +136,7 @@ static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq)
static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
int64_t err;
err = beat_construct_and_connect_irq_plug(virq, hw);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 4e56556..9dd63c5 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -102,7 +102,7 @@ static void spider_ack_irq(unsigned int virq)
/* Reset edge detection logic if necessary
*/
- if (get_irq_desc(virq)->status & IRQ_LEVEL)
+ if (irq_to_desc(virq)->status & IRQ_LEVEL)
return;
/* Only interrupts 47 to 50 can be set to edge */
@@ -119,7 +119,7 @@ static int spider_set_irq_type(unsigned int virq, unsigned int type)
struct spider_pic *pic = spider_virq_to_pic(virq);
unsigned int hw = irq_map[virq].hwirq;
void __iomem *cfg = spider_get_irq_config(pic, hw);
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
u32 old_mask;
u32 ic;
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 94f4447..f8446ea 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -214,7 +214,7 @@ void __init iSeries_activate_IRQs()
unsigned long flags;
for_each_irq (irq) {
- struct irq_desc *desc = get_irq_desc(irq);
+ struct irq_desc *desc = irq_to_desc(irq);
if (desc && desc->chip && desc->chip->startup) {
spin_lock_irqsave(&desc->lock, flags);
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index d212006..484d21e 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -152,12 +152,12 @@ static unsigned int pmac_startup_irq(unsigned int virq)
unsigned long bit = 1UL << (src & 0x1f);
int i = src >> 5;
- spin_lock_irqsave(&pmac_pic_lock, flags);
- if ((irq_desc[virq].status & IRQ_LEVEL) == 0)
+ spin_lock_irqsave(&pmac_pic_lock, flags);
+ if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0)
out_le32(&pmac_irq_hw[i]->ack, bit);
__set_bit(src, ppc_cached_irq_mask);
__pmac_set_irq_mask(src, 0);
- spin_unlock_irqrestore(&pmac_pic_lock, flags);
+ spin_unlock_irqrestore(&pmac_pic_lock, flags);
return 0;
}
@@ -285,7 +285,7 @@ static int pmac_pic_host_match(struct irq_host *h, struct device_node *node)
static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
int level;
if (hw >= max_irqs)
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 419f8a6..75935ae 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -156,7 +156,7 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check)
cpumask_t cpumask;
cpumask_t tmp = CPU_MASK_NONE;
- cpumask_copy(&cpumask, irq_desc[virq].affinity);
+ cpumask_copy(&cpumask, irq_to_desc(virq)->affinity);
if (!distribute_irqs)
return default_server;
@@ -419,7 +419,7 @@ static int xics_host_map(struct irq_host *h, unsigned int virq,
/* Insert the interrupt mapping into the radix tree for fast lookup */
irq_radix_revmap_insert(xics_host, virq, hw);
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
return 0;
}
@@ -843,7 +843,7 @@ void xics_migrate_irqs_away(void)
/* We need to get IPIs still. */
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
continue;
- desc = get_irq_desc(virq);
+ desc = irq_to_desc(virq);
/* We only need to migrate enabled IRQS */
if (desc == NULL || desc->chip == NULL
@@ -872,7 +872,7 @@ void xics_migrate_irqs_away(void)
virq, cpu);
/* Reset affinity to all cpus */
- cpumask_setall(irq_desc[virq].affinity);
+ cpumask_setall(irq_to_desc(virq)->affinity);
desc->chip->set_affinity(virq, cpu_all_mask);
unlock:
spin_unlock_irqrestore(&desc->lock, flags);
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index 82424cd..5235373 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -102,7 +102,7 @@ static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
{
pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
return 0;
}
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 78f1f7c..722cf72 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -115,11 +115,13 @@ static void cpm2_ack(unsigned int virq)
static void cpm2_end_irq(unsigned int virq)
{
+ struct irq_desc *desc;
int bit, word;
unsigned int irq_nr = virq_to_hw(virq);
- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
- && irq_desc[irq_nr].action) {
+ desc = irq_to_desc(irq_nr);
+ if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && desc->action) {
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
@@ -138,7 +140,7 @@ static void cpm2_end_irq(unsigned int virq)
static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
{
unsigned int src = virq_to_hw(virq);
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
unsigned int vold, vnew, edibit;
if (flow_type == IRQ_TYPE_NONE)
@@ -210,7 +212,7 @@ static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
{
pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw);
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
return 0;
}
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index da38a1f..7174374 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -55,7 +55,7 @@ static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
{
struct irq_chip *chip = &fsl_msi_chip;
- get_irq_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
+ irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
set_irq_chip_and_handler(virq, chip, handle_edge_irq);
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index a96584a..78ed945 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -175,12 +175,12 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq,
/* We block the internal cascade */
if (hw == 2)
- get_irq_desc(virq)->status |= IRQ_NOREQUEST;
+ irq_to_desc(virq)->status |= IRQ_NOREQUEST;
/* We use the level handler only for now, we might want to
* be more cautious here but that works for now
*/
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq);
return 0;
}
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index cb7689c..f042c1d 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -605,7 +605,7 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
{
struct ipic *ipic = ipic_from_irq(virq);
unsigned int src = ipic_irq_to_hw(virq);
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
unsigned int vold, vnew, edibit;
if (flow_type == IRQ_TYPE_NONE)
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 5d2d552..0117958 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -72,7 +72,7 @@ static void mpc8xx_end_irq(unsigned int virq)
static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
{
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 30c44e6..4fd57ab 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -572,7 +572,7 @@ static int irq_choose_cpu(unsigned int virt_irq)
cpumask_t mask;
int cpuid;
- cpumask_copy(&mask, irq_desc[virt_irq].affinity);
+ cpumask_copy(&mask, irq_to_desc(virt_irq)->affinity);
if (cpus_equal(mask, CPU_MASK_ALL)) {
static int irq_rover;
static DEFINE_SPINLOCK(irq_rover_lock);
@@ -621,7 +621,7 @@ static struct mpic *mpic_find(unsigned int irq)
if (irq < NUM_ISA_INTERRUPTS)
return NULL;
- return irq_desc[irq].chip_data;
+ return irq_to_desc(irq)->chip_data;
}
/* Determine if the linux irq is an IPI */
@@ -648,14 +648,14 @@ static inline u32 mpic_physmask(u32 cpumask)
/* Get the mpic structure from the IPI number */
static inline struct mpic * mpic_from_ipi(unsigned int ipi)
{
- return irq_desc[ipi].chip_data;
+ return irq_to_desc(ipi)->chip_data;
}
#endif
/* Get the mpic structure from the irq number */
static inline struct mpic * mpic_from_irq(unsigned int irq)
{
- return irq_desc[irq].chip_data;
+ return irq_to_desc(irq)->chip_data;
}
/* Send an EOI */
@@ -735,7 +735,7 @@ static void mpic_unmask_ht_irq(unsigned int irq)
mpic_unmask_irq(irq);
- if (irq_desc[irq].status & IRQ_LEVEL)
+ if (irq_to_desc(irq)->status & IRQ_LEVEL)
mpic_ht_end_irq(mpic, src);
}
@@ -745,7 +745,7 @@ static unsigned int mpic_startup_ht_irq(unsigned int irq)
unsigned int src = mpic_irq_to_hw(irq);
mpic_unmask_irq(irq);
- mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
+ mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
return 0;
}
@@ -755,7 +755,7 @@ static void mpic_shutdown_ht_irq(unsigned int irq)
struct mpic *mpic = mpic_from_irq(irq);
unsigned int src = mpic_irq_to_hw(irq);
- mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
+ mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
mpic_mask_irq(irq);
}
@@ -772,7 +772,7 @@ static void mpic_end_ht_irq(unsigned int irq)
* latched another edge interrupt coming in anyway
*/
- if (irq_desc[irq].status & IRQ_LEVEL)
+ if (irq_to_desc(irq)->status & IRQ_LEVEL)
mpic_ht_end_irq(mpic, src);
mpic_eoi(mpic);
}
@@ -856,7 +856,7 @@ int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
{
struct mpic *mpic = mpic_from_irq(virq);
unsigned int src = mpic_irq_to_hw(virq);
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
unsigned int vecpri, vold, vnew;
DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
index 2aa4ed0..485b924 100644
--- a/arch/powerpc/sysdev/mv64x60_pic.c
+++ b/arch/powerpc/sysdev/mv64x60_pic.c
@@ -213,7 +213,7 @@ static int mv64x60_host_map(struct irq_host *h, unsigned int virq,
{
int level1;
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET;
BUG_ON(level1 > MV64x60_LEVEL1_GPP);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 3faa42e..fc09874 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -189,7 +189,7 @@ static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg
static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
{
- return irq_desc[virq].chip_data;
+ return irq_to_desc(virq)->chip_data;
}
#define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
@@ -263,7 +263,7 @@ static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
chip = &qe_ic->hc_irq;
set_irq_chip_data(virq, qe_ic);
- get_irq_desc(virq)->status |= IRQ_LEVEL;
+ irq_to_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, chip, handle_level_irq);
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index cf244a4..02f6009 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -398,7 +398,7 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
DBG("%s(%d, 0x%lx)\n", __func__, virq, hw);
if ((virq >= 1) && (virq <= 4)){
irq = virq + IRQ_PCI_INTAD_BASE - 1;
- get_irq_desc(irq)->status |= IRQ_LEVEL;
+ irq_to_desc(irq)->status |= IRQ_LEVEL;
set_irq_chip(irq, &tsi108_pci_irq);
}
return 0;
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 466ce9a..cf97935 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -57,7 +57,7 @@ struct uic {
static void uic_unmask_irq(unsigned int virq)
{
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
struct uic *uic = get_irq_chip_data(virq);
unsigned int src = uic_irq_to_hw(virq);
unsigned long flags;
@@ -101,7 +101,7 @@ static void uic_ack_irq(unsigned int virq)
static void uic_mask_ack_irq(unsigned int virq)
{
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
struct uic *uic = get_irq_chip_data(virq);
unsigned int src = uic_irq_to_hw(virq);
unsigned long flags;
@@ -129,7 +129,7 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
{
struct uic *uic = get_irq_chip_data(virq);
unsigned int src = uic_irq_to_hw(virq);
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
unsigned long flags;
int trigger, polarity;
u32 tr, pr, mask;
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 40edad5..ab74371 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -79,7 +79,7 @@ static void xilinx_intc_mask(unsigned int virq)
static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type)
{
- struct irq_desc *desc = get_irq_desc(virq);
+ struct irq_desc *desc = irq_to_desc(virq);
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
--
1.6.2.1
^ permalink raw reply related
* [PATCH 2/6] powerpc/pseries: Use irq_has_action() in eeh_disable_irq()
From: Michael Ellerman @ 2009-10-14 5:44 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <a6fc612b826ff12628e62601203d565df00c6436.1255499081.git.michael@ellerman.id.au>
Rather than open-coding our own check, use irq_has_action()
to check if an irq has an action - ie. is "in use".
irq_has_action() doesn't take the descriptor lock, but it
shouldn't matter - we're just using it as an indicator
that the irq is in use. disable_irq_nosync() will take
the descriptor lock before doing anything also.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/pseries/eeh_driver.c | 18 +-----------------
1 files changed, 1 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 0e8db67..ef8e454 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -63,22 +63,6 @@ static void print_device_node_tree(struct pci_dn *pdn, int dent)
}
#endif
-/**
- * irq_in_use - return true if this irq is being used
- */
-static int irq_in_use(unsigned int irq)
-{
- int rc = 0;
- unsigned long flags;
- struct irq_desc *desc = irq_desc + irq;
-
- spin_lock_irqsave(&desc->lock, flags);
- if (desc->action)
- rc = 1;
- spin_unlock_irqrestore(&desc->lock, flags);
- return rc;
-}
-
/**
* eeh_disable_irq - disable interrupt for the recovering device
*/
@@ -93,7 +77,7 @@ static void eeh_disable_irq(struct pci_dev *dev)
if (dev->msi_enabled || dev->msix_enabled)
return;
- if (!irq_in_use(dev->irq))
+ if (!irq_has_action(dev->irq))
return;
PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
--
1.6.2.1
^ permalink raw reply related
* [PATCH 1/6] powerpc: Make NR_IRQS a CONFIG option
From: Michael Ellerman @ 2009-10-14 5:44 UTC (permalink / raw)
To: linuxppc-dev
The irq_desc array consumes quite a lot of space, and for systems
that don't need or can't have 512 irqs it's just wasted space.
The first 16 are reserved for ISA, so the minimum of 32 is really
16 - and no one has asked for more than 512 so leave that as the
maximum.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/Kconfig | 10 ++++++++++
arch/powerpc/include/asm/irq.h | 4 ++--
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 10a0a54..2230e75 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -56,6 +56,16 @@ config IRQ_PER_CPU
bool
default y
+config NR_IRQS
+ int "Number of virtual interrupt numbers"
+ range 32 512
+ default "512"
+ help
+ This defines the number of virtual interrupt numbers the kernel
+ can manage. Virtual interrupt numbers are what you see in
+ /proc/interrupts. If you configure your system to have too few,
+ drivers will fail to load or worse - handle with care.
+
config STACKTRACE_SUPPORT
bool
default y
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index bbcd1aa..b83fcc8 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -34,8 +34,8 @@ extern atomic_t ppc_n_lost_interrupts;
*/
#define NO_IRQ_IGNORE ((unsigned int)-1)
-/* Total number of virq in the platform (make it a CONFIG_* option ? */
-#define NR_IRQS 512
+/* Total number of virq in the platform */
+#define NR_IRQS CONFIG_NR_IRQS
/* Number of irqs reserved for the legacy controller */
#define NUM_ISA_INTERRUPTS 16
--
1.6.2.1
^ permalink raw reply related
* [Fwd: [PATCH 2/2] i2c-powermac: Log errors]
From: Benjamin Herrenschmidt @ 2009-10-14 5:40 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: Forwarded message - [PATCH 2/2] i2c-powermac: Log errors --]
[-- Type: message/rfc822, Size: 3291 bytes --]
From: Jean Delvare <khali@linux-fr.org>
To: Linux I2C <linux-i2c@vger.kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>
Subject: [PATCH 2/2] i2c-powermac: Log errors
Date: Sat, 10 Oct 2009 14:20:28 +0200
Message-ID: <20091010142028.52f19518@hyperion.delvare>
Log errors when they happen, otherwise we have no idea what went
wrong.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
---
drivers/i2c/busses/i2c-powermac.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
--- linux-2.6.32-rc3.orig/drivers/i2c/busses/i2c-powermac.c 2009-10-10 14:13:04.000000000 +0200
+++ linux-2.6.32-rc3/drivers/i2c/busses/i2c-powermac.c 2009-10-10 14:13:12.000000000 +0200
@@ -108,16 +108,25 @@ static s32 i2c_powermac_smbus_xfer( stru
}
rc = pmac_i2c_open(bus, 0);
- if (rc)
+ if (rc) {
+ dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
return rc;
+ }
rc = pmac_i2c_setmode(bus, mode);
- if (rc)
+ if (rc) {
+ dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
+ mode, rc);
goto bail;
+ }
rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
- if (rc)
+ if (rc) {
+ dev_err(&adap->dev,
+ "I2C transfer at 0x%02x failed, size %d, err %d\n",
+ addrdir >> 1, size, rc);
goto bail;
+ }
if (size == I2C_SMBUS_WORD_DATA && read) {
data->word = ((u16)local[1]) << 8;
@@ -157,12 +166,21 @@ static int i2c_powermac_master_xfer( str
addrdir ^= 1;
rc = pmac_i2c_open(bus, 0);
- if (rc)
+ if (rc) {
+ dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
return rc;
+ }
rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
- if (rc)
+ if (rc) {
+ dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
+ pmac_i2c_mode_std, rc);
goto bail;
+ }
rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
+ if (rc < 0)
+ dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
+ addrdir & 1 ? "read from" : "write to", addrdir >> 1,
+ rc);
bail:
pmac_i2c_close(bus);
return rc < 0 ? rc : 1;
--
Jean Delvare
^ permalink raw reply
* [Fwd: [PATCH 1/2] i2c-powermac: Refactor i2c_powermac_smbus_xfer]
From: Benjamin Herrenschmidt @ 2009-10-14 5:40 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: Forwarded message - [PATCH 1/2] i2c-powermac: Refactor i2c_powermac_smbus_xfer --]
[-- Type: message/rfc822, Size: 5169 bytes --]
From: Jean Delvare <khali@linux-fr.org>
To: Linux I2C <linux-i2c@vger.kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>
Subject: [PATCH 1/2] i2c-powermac: Refactor i2c_powermac_smbus_xfer
Date: Sat, 10 Oct 2009 14:19:08 +0200
Message-ID: <20091010141908.0be884a5@hyperion.delvare>
I wanted to add some error logging to the i2c-powermac driver, but
found that it was very difficult due to the way the
i2c_powermac_smbus_xfer function is organized. Refactor the code in
this function so that each low-level function is only called once.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
---
This needs testing! Thanks.
drivers/i2c/busses/i2c-powermac.c | 85 +++++++++++++++++--------------------
1 file changed, 41 insertions(+), 44 deletions(-)
--- linux-2.6.32-rc3.orig/drivers/i2c/busses/i2c-powermac.c 2009-10-10 14:08:39.000000000 +0200
+++ linux-2.6.32-rc3/drivers/i2c/busses/i2c-powermac.c 2009-10-10 14:13:04.000000000 +0200
@@ -49,48 +49,38 @@ static s32 i2c_powermac_smbus_xfer( stru
int rc = 0;
int read = (read_write == I2C_SMBUS_READ);
int addrdir = (addr << 1) | read;
+ int mode, subsize, len;
+ u32 subaddr;
+ u8 *buf;
u8 local[2];
- rc = pmac_i2c_open(bus, 0);
- if (rc)
- return rc;
+ if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) {
+ mode = pmac_i2c_mode_std;
+ subsize = 0;
+ subaddr = 0;
+ } else {
+ mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub;
+ subsize = 1;
+ subaddr = command;
+ }
switch (size) {
case I2C_SMBUS_QUICK:
- rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0);
+ buf = NULL;
+ len = 0;
break;
case I2C_SMBUS_BYTE:
- rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1);
- break;
case I2C_SMBUS_BYTE_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1);
+ buf = &data->byte;
+ len = 1;
break;
case I2C_SMBUS_WORD_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
if (!read) {
local[0] = data->word & 0xff;
local[1] = (data->word >> 8) & 0xff;
}
- rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2);
- if (rc == 0 && read) {
- data->word = ((u16)local[1]) << 8;
- data->word |= local[0];
- }
+ buf = local;
+ len = 2;
break;
/* Note that these are broken vs. the expected smbus API where
@@ -105,28 +95,35 @@ static s32 i2c_powermac_smbus_xfer( stru
* a repeat start/addr phase (but not stop in between)
*/
case I2C_SMBUS_BLOCK_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block,
- data->block[0] + 1);
-
+ buf = data->block;
+ len = data->block[0] + 1;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 1, command,
- &data->block[1], data->block[0]);
+ buf = &data->block[1];
+ len = data->block[0];
break;
default:
- rc = -EINVAL;
+ return -EINVAL;
+ }
+
+ rc = pmac_i2c_open(bus, 0);
+ if (rc)
+ return rc;
+
+ rc = pmac_i2c_setmode(bus, mode);
+ if (rc)
+ goto bail;
+
+ rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
+ if (rc)
+ goto bail;
+
+ if (size == I2C_SMBUS_WORD_DATA && read) {
+ data->word = ((u16)local[1]) << 8;
+ data->word |= local[0];
}
+
bail:
pmac_i2c_close(bus);
return rc;
--
Jean Delvare
^ permalink raw reply
* Re: [PATCH] i2c-powermac: Reject unsupported I2C transactions
From: Benjamin Herrenschmidt @ 2009-10-14 5:39 UTC (permalink / raw)
To: Jean Delvare; +Cc: linuxppc-dev, Paul Mackerras, Linux I2C
In-Reply-To: <20090930221435.58636363@hyperion.delvare>
On Wed, 2009-09-30 at 22:14 +0200, Jean Delvare wrote:
> The i2c-powermac driver doesn't support arbitrary multi-message I2C
> transactions, only SMBus ones. Make it clear by returning an error if
> a multi-message I2C transaction is attempted. This is better than only
> processing the first message, because most callers won't recover from
> the short transaction. Anyone wishing to issue multi-message
> transactions should use the SMBus API instead of the raw I2C API.
>
> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> ---
> drivers/i2c/busses/i2c-powermac.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> --- linux-2.6.32-rc1.orig/drivers/i2c/busses/i2c-powermac.c 2009-06-10 05:05:27.000000000 +0200
> +++ linux-2.6.32-rc1/drivers/i2c/busses/i2c-powermac.c 2009-09-30 20:29:42.000000000 +0200
> @@ -146,6 +146,12 @@ static int i2c_powermac_master_xfer( str
> int read;
> int addrdir;
>
> + if (num != 1) {
> + dev_err(&adap->dev,
> + "Multi-message I2C transactions not supported\n");
> + return -EOPNOTSUPP;
> + }
> +
> if (msgs->flags & I2C_M_TEN)
> return -EINVAL;
> read = (msgs->flags & I2C_M_RD) != 0;
>
>
^ permalink raw reply
* Re: [PATCH] of/platform: Implement support for dev_pm_ops
From: Benjamin Herrenschmidt @ 2009-10-14 4:55 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev, linux-pm, David Miller
In-Reply-To: <20091012224410.GA18923@oksana.dev.rtsoft.ru>
On Tue, 2009-10-13 at 02:44 +0400, Anton Vorontsov wrote:
> I agree that there is some room for improvements in general (e.g.
> merging platform and of_platform devices/drivers), but it's not as
> easy as you would like to think. Let's make it in a separate step
> that don't stop real features from being implemented (e.g.
> hibernate).
>
> For the six functions that we can reuse I can prepare a cleanup
> patch that we can merge via -mm, or it can just sit and collect
> needed acks and can be merged via any tree. But please, no
> cross-tree dependencies for the cruicial features.
I agree. I'll take the patch for now.
In the long run, I'm all for killing of_platform if we can find
a "proper" way to replace it with platform.
IE. With dev_archdata, any device carries the of device node, so
of_platform doesn't really buy us much anymore.
We could even "default" by populating platform device resources
with standard-parsing of "reg" properties etc...
So for devices who don't actually need anything more, we may get
away re-using platform devices as-is, all we would need is some
kind of conversion table or such to map OF match to platform dev names,
or maybe a secondary match table in the drivers themselves.
Anyway, that's an old discussion, something we still need to sort out...
Ben.
^ permalink raw reply
* Re: [RFC PATCH 05/12] of: add common header for flattened device tree representation
From: David Gibson @ 2009-10-14 4:47 UTC (permalink / raw)
To: Grant Likely
Cc: Stephen Rothwell, monstr, microblaze-uclinux, devicetree-discuss,
sparclinux, linuxppc-dev, davem
In-Reply-To: <fa686aa40910090007lef3fddbod0c5843abfe33be5@mail.gmail.com>
On Fri, Oct 09, 2009 at 01:07:57AM -0600, Grant Likely wrote:
> On Fri, Oct 9, 2009 at 12:35 AM, David Gibson
> <david@gibson.dropbear.id.au> wrote:
> > On Tue, Oct 06, 2009 at 10:30:59PM -0600, Grant Likely wrote:
> >> Add a common header file for working with the flattened device tree
> >> data structure and merge the shared data tags used by Microblaze and
> >> PowerPC
> >>
> >> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> >> ---
> >>
> >> arch/microblaze/include/asm/prom.h | 12 +-----------
> >> arch/powerpc/include/asm/prom.h | 12 +-----------
> >> include/linux/of_fdt.h | 30 ++++++++++++++++++++++++++++++
> >> 3 files changed, 32 insertions(+), 22 deletions(-)
> >> create mode 100644 include/linux/of_fdt.h
> >>
> >> diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
> >> index 64e8b3a..5f461f0 100644
> >> --- a/arch/microblaze/include/asm/prom.h
> >> +++ b/arch/microblaze/include/asm/prom.h
> >> @@ -17,20 +17,10 @@
> >> #ifndef _ASM_MICROBLAZE_PROM_H
> >> #define _ASM_MICROBLAZE_PROM_H
> >> #ifdef __KERNEL__
> >> -
> >> -/* Definitions used by the flattened device tree */
> >> -#define OF_DT_HEADER 0xd00dfeed /* marker */
> >> -#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
> >> -#define OF_DT_END_NODE 0x2 /* End node */
> >> -#define OF_DT_PROP 0x3 /* Property: name off, size, content */
> >> -#define OF_DT_NOP 0x4 /* nop */
> >> -#define OF_DT_END 0x9
> >> -
> >> -#define OF_DT_VERSION 0x10
> >
> >
> > So, if you're merging all these, I guess the question is do we also
> > want to merge them with scripts/dtc/libfdt/fdt.h, and by extension
> > with the upstream libfdt header file which defines the same things.
>
> I see your question and raise you another. Where should the merge
> file live for it to be included both by dtc and kernel code? Or should
> it just be cloned in the kernel tree?
Yeah, a good question. As I see it there are two options. Number one
is just make sure everything relevant that the kernel needs is in the
libfdt version, then just have the kernel code reference it from its
location in scripts/dtc. Other option is we clone the file in the
kernel tree. Requires keeping in sync, in theory at least, but since
that file has been pretty static (since it's only supposed to contain
passive structures/constants related to the physical flat tree
structure - no code or prototypes).
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
From: Akinobu Mita @ 2009-10-14 3:39 UTC (permalink / raw)
To: Michael Ellerman
Cc: Fenghua Yu, x86, linux-ia64, Thomas Gleixner, David S. Miller,
netdev, Greg Kroah-Hartman, linux-kernel, linux-altix,
Yevgeny Petrilin, FUJITA Tomonori, linuxppc-dev, Tony Luck,
Paul Mackerras, H. Peter Anvin, sparclinux, Andrew Morton,
linux-usb, Ingo Molnar, Lothar Wassmann
In-Reply-To: <1255470887.21871.2.camel@concordia>
On Wed, Oct 14, 2009 at 08:54:47AM +1100, Michael Ellerman wrote:
> On Tue, 2009-10-13 at 18:10 +0900, Akinobu Mita wrote:
> > My user space testing exposed off-by-one error find_next_zero_area
> > in iommu-helper.
>
> Why not merge those tests into the kernel as a configurable boot-time
> self-test?
I send the test program that I used. Obviously it needs
better diagnostic messages and cleanup to be added into kernel tests.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#if 1 /* Copy and paste from kernel source */
#define BITS_PER_BYTE 8
#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITMAP_LAST_WORD_MASK(nbits) \
( \
((nbits) % BITS_PER_LONG) ? \
(1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \
)
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
void bitmap_set(unsigned long *map, int start, int nr)
{
unsigned long *p = map + BIT_WORD(start);
const int size = start + nr;
int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
while (nr - bits_to_set >= 0) {
*p |= mask_to_set;
nr -= bits_to_set;
bits_to_set = BITS_PER_LONG;
mask_to_set = ~0UL;
p++;
}
if (nr) {
mask_to_set &= BITMAP_LAST_WORD_MASK(size);
*p |= mask_to_set;
}
}
void bitmap_clear(unsigned long *map, int start, int nr)
{
unsigned long *p = map + BIT_WORD(start);
const int size = start + nr;
int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
while (nr - bits_to_clear >= 0) {
*p &= ~mask_to_clear;
nr -= bits_to_clear;
bits_to_clear = BITS_PER_LONG;
mask_to_clear = ~0UL;
p++;
}
if (nr) {
mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
*p &= ~mask_to_clear;
}
}
static unsigned long __ffs(unsigned long word)
{
int num = 0;
if ((word & 0xffff) == 0) {
num += 16;
word >>= 16;
}
if ((word & 0xff) == 0) {
num += 8;
word >>= 8;
}
if ((word & 0xf) == 0) {
num += 4;
word >>= 4;
}
if ((word & 0x3) == 0) {
num += 2;
word >>= 2;
}
if ((word & 0x1) == 0)
num += 1;
return num;
}
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
unsigned long offset)
{
const unsigned long *p = addr + BITOP_WORD(offset);
unsigned long result = offset & ~(BITS_PER_LONG-1);
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset %= BITS_PER_LONG;
if (offset) {
tmp = *(p++);
tmp &= (~0UL << offset);
if (size < BITS_PER_LONG)
goto found_first;
if (tmp)
goto found_middle;
size -= BITS_PER_LONG;
result += BITS_PER_LONG;
}
while (size & ~(BITS_PER_LONG-1)) {
if ((tmp = *(p++)))
goto found_middle;
result += BITS_PER_LONG;
size -= BITS_PER_LONG;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp &= (~0UL >> (BITS_PER_LONG - size));
if (tmp == 0UL) /* Are any bits set? */
return result + size; /* Nope. */
found_middle:
return result + __ffs(tmp);
}
#define ffz(x) __ffs(~(x))
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
unsigned long offset)
{
const unsigned long *p = addr + BITOP_WORD(offset);
unsigned long result = offset & ~(BITS_PER_LONG-1);
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset %= BITS_PER_LONG;
if (offset) {
tmp = *(p++);
tmp |= ~0UL >> (BITS_PER_LONG - offset);
if (size < BITS_PER_LONG)
goto found_first;
if (~tmp)
goto found_middle;
size -= BITS_PER_LONG;
result += BITS_PER_LONG;
}
while (size & ~(BITS_PER_LONG-1)) {
if (~(tmp = *(p++)))
goto found_middle;
result += BITS_PER_LONG;
size -= BITS_PER_LONG;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp |= ~0UL << size;
if (tmp == ~0UL) /* Are any bits zero? */
return result + size; /* Nope. */
found_middle:
return result + ffz(tmp);
}
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
static inline int test_bit(int nr, const volatile unsigned long *addr)
{
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
}
unsigned long bitmap_find_next_zero_area(unsigned long *map,
unsigned long size,
unsigned long start,
unsigned int nr,
unsigned long align_mask)
{
unsigned long index, end, i;
again:
index = find_next_zero_bit(map, size, start);
/* Align allocation */
index = __ALIGN_MASK(index, align_mask);
end = index + nr;
#ifdef ORIGINAL
if (end >= size)
#else
if (end > size)
#endif
return end;
#ifdef ORIGINAL
for (i = index; i < end; i++) {
if (test_bit(i, map)) {
start = i+1;
goto again;
}
}
#else
i = find_next_bit(map, end, index);
if (i < end) {
start = i + 1;
goto again;
}
#endif
return index;
}
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define DECLARE_BITMAP(name,bits) unsigned long name[BITS_TO_LONGS(bits)]
#endif /* Copy and paste from kernel source */
static DECLARE_BITMAP(bitmap, 1000);
static DECLARE_BITMAP(empty, 1000);
static DECLARE_BITMAP(full, 1000);
static void bitmap_dump(unsigned long *bitmap, int size)
{
int i;
for (i = 0; i < size; i++) {
if (test_bit(i, bitmap))
printf("1 ");
else
printf("0 ");
if (i % 10 == 9)
printf("\n");
}
printf("\n");
}
static int test1(int size)
{
int start = random() % size;
int nr = random() % (size - start);
memset(bitmap, 0x00, BITS_TO_LONGS(size) * sizeof(unsigned long));
bitmap_set(bitmap, start, nr);
bitmap_clear(bitmap, start, nr);
if (memcmp(empty, bitmap, BITS_TO_LONGS(size) * sizeof(unsigned long)))
goto error;
return 0;
error:
bitmap_dump(bitmap, size);
return 1;
}
int test2(int size)
{
int start = random() % size;
int nr = random() % (size - start);
memset(bitmap, 0xff, BITS_TO_LONGS(size) * sizeof(unsigned long));
bitmap_clear(bitmap, start, nr);
bitmap_set(bitmap, start, nr);
if (memcmp(full, bitmap, BITS_TO_LONGS(size) * sizeof(unsigned long)))
goto error;
return 0;
error:
bitmap_dump(bitmap, size);
return 1;
}
int test3(int size)
{
int start = random() % size;
int nr = random() % (size - start);
unsigned long offset;
memset(bitmap, 0x00, BITS_TO_LONGS(size) * sizeof(unsigned long));
bitmap_set(bitmap, start, nr);
if (start) {
offset = bitmap_find_next_zero_area(bitmap, size, 0, start, 0);
if (offset != 0) {
printf("start %ld nr %ld\n", start, nr);
printf("offset %ld != 0\n", offset);
goto error;
}
}
offset = bitmap_find_next_zero_area(bitmap, size, start,
size - (start + nr), 0);
if (offset != start + nr) {
printf("start %ld nr %ld\n", start, nr);
printf("offset %ld != size + nr %ld\n", offset, start + nr);
goto error;
}
return 0;
error:
bitmap_dump(bitmap, size);
return 1;
}
int test4(int size)
{
int start = random() % size;
int nr = random() % (size - start);
unsigned long offset;
memset(bitmap, 0xff, BITS_TO_LONGS(size) * sizeof(unsigned long));
bitmap_clear(bitmap, start, nr);
offset = bitmap_find_next_zero_area(bitmap, size, start, nr, 0);
if (nr != 0) {
if (offset != start) {
printf("start %ld nr %ld\n", start, nr);
printf("offset %ld != start %ld\n", offset, start);
goto error;
}
}
return 0;
error:
bitmap_dump(bitmap, size);
return 1;
}
int main(int argc, char *argv[])
{
int err = 0;
srandom(time(NULL));
memset(empty, 0x00, sizeof(empty));
memset(full, 0xff, sizeof(full));
while (!err) {
err |= test1(1000);
err |= test2(1000);
err |= test3(1000);
err |= test4(1000);
}
return 0;
}
^ permalink raw reply
* Re: New percpu & ppc64 perfs
From: Benjamin Herrenschmidt @ 2009-10-14 3:28 UTC (permalink / raw)
To: Tejun Heo; +Cc: linuxppc-dev, linux-kernel@vger.kernel.org
In-Reply-To: <4AD52E37.80209@kernel.org>
On Wed, 2009-10-14 at 10:49 +0900, Tejun Heo wrote:
> For 256M segment, I don't think much can be done but for 1T segment,
> just limiting vmalloc area size to 1T should do the trick, no?
Right. I'll have a look at it.
Cheers,
Ben.
^ permalink raw reply
* [PATCH -mmotm] Fix bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area. patch
From: Akinobu Mita @ 2009-10-14 3:22 UTC (permalink / raw)
To: Andrew Morton
Cc: Fenghua Yu, Greg Kroah-Hartman, linux-ia64, Tony Luck, x86,
netdev, linux-kernel, linux-altix, Yevgeny Petrilin,
FUJITA Tomonori, linuxppc-dev, Ingo Molnar, Paul Mackerras,
H. Peter Anvin, sparclinux, Thomas Gleixner, linux-usb,
David S. Miller, Lothar Wassmann
In-Reply-To: <20091013091017.GA18431@localhost.localdomain>
Update PATCH 2/8 based on review comments by Andrew and bugfix
exposed by user space testing.
I didn't change argument of align_mask at this time because it
turned out that it needs more changes in iommu-helper users.
From: Akinobu Mita <akinobu.mita@gmail.com>
Subject: Fix bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area.patch
- Rewrite bitmap_set and bitmap_clear
Instead of setting or clearing for each bit.
- Fix off-by-one error in bitmap_find_next_zero_area
This bug was derived from find_next_zero_area in iommu-helper.
- Add kerneldoc for bitmap_find_next_zero_area
This patch is supposed to be folded into
bitmap-introduce-bitmap_set-bitmap_clear-bitmap_find_next_zero_area.patch
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
---
lib/bitmap.c | 60 +++++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 47 insertions(+), 13 deletions(-)
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 2415da4..84292c9 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -271,28 +271,62 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
}
EXPORT_SYMBOL(__bitmap_weight);
-void bitmap_set(unsigned long *map, int i, int len)
-{
- int end = i + len;
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
- while (i < end) {
- __set_bit(i, map);
- i++;
+void bitmap_set(unsigned long *map, int start, int nr)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const int size = start + nr;
+ int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+ while (nr - bits_to_set >= 0) {
+ *p |= mask_to_set;
+ nr -= bits_to_set;
+ bits_to_set = BITS_PER_LONG;
+ mask_to_set = ~0UL;
+ p++;
+ }
+ if (nr) {
+ mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+ *p |= mask_to_set;
}
}
EXPORT_SYMBOL(bitmap_set);
void bitmap_clear(unsigned long *map, int start, int nr)
{
- int end = start + nr;
-
- while (start < end) {
- __clear_bit(start, map);
- start++;
+ unsigned long *p = map + BIT_WORD(start);
+ const int size = start + nr;
+ int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+
+ while (nr - bits_to_clear >= 0) {
+ *p &= ~mask_to_clear;
+ nr -= bits_to_clear;
+ bits_to_clear = BITS_PER_LONG;
+ mask_to_clear = ~0UL;
+ p++;
+ }
+ if (nr) {
+ mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+ *p &= ~mask_to_clear;
}
}
EXPORT_SYMBOL(bitmap_clear);
+/*
+ * bitmap_find_next_zero_area - find a contiguous aligned zero area
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @align_mask: Alignment mask for zero area
+ *
+ * The @align_mask should be one less than a power of 2; the effect is that
+ * the bit offset of all zero areas this function finds is multiples of that
+ * power of 2. A @align_mask of 0 means no alignment is required.
+ */
unsigned long bitmap_find_next_zero_area(unsigned long *map,
unsigned long size,
unsigned long start,
@@ -304,10 +338,10 @@ again:
index = find_next_zero_bit(map, size, start);
/* Align allocation */
- index = (index + align_mask) & ~align_mask;
+ index = __ALIGN_MASK(index, align_mask);
end = index + nr;
- if (end >= size)
+ if (end > size)
return end;
i = find_next_bit(map, end, index);
if (i < end) {
--
1.5.4.3
^ permalink raw reply related
* Re: [PATCH] Ftrace : fix function_graph tracer OOPS
From: Steven Rostedt @ 2009-10-14 3:01 UTC (permalink / raw)
To: Sachin Sant; +Cc: linuxppc-dev
In-Reply-To: <4ACDFC83.4080205@in.ibm.com>
On Thu, 2009-10-08 at 20:21 +0530, Sachin Sant wrote:
> Switch to LOAD_REG_ADDR().
>
> Signed-off-by : Sachin Sant <sachinp@in.ibm.com>
> ---
> diff -Naurp old/arch/powerpc/kernel/entry_64.S
> new/arch/powerpc/kernel/entry_64.S
> --- old/arch/powerpc/kernel/entry_64.S 2009-10-08 18:37:44.000000000
> +0530
> +++ new/arch/powerpc/kernel/entry_64.S 2009-10-08 18:34:33.000000000
> +0530
> @@ -1038,8 +1038,8 @@ _GLOBAL(mod_return_to_handler)
> * We are in a module using the module's TOC.
> * Switch to our TOC to run inside the core kernel.
> */
> - LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler)
> - ld r2, 8(r4)
> + ld r2, PACATOC(r13)
> + LOAD_REG_ADDR(r4,ftrace_return_to_handler)
Actually, the loading of this register is not needed. The original used
the loading to get the r2.
I actually wrote a fix for this a month ago. I never sent it out because
I was distracted by other issues.
I'll send out the two patches I had now.
Could yo test them?
Thanks!
-- Steve
>
> bl .ftrace_return_to_handler
> nop
>
^ permalink raw reply
* Re: New percpu & ppc64 perfs
From: Tejun Heo @ 2009-10-14 1:49 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-kernel@vger.kernel.org
In-Reply-To: <1255478358.2347.28.camel@pasglop>
Hello, Benjamin.
Benjamin Herrenschmidt wrote:
> So I found (and fixed, though the patch isn't upstream yet) the problem
> that was causing the new percpu to hang when accessing the top of our
> vmalloc space.
>
> However, I have some concerns about that choice of location for the
> percpu datas.
>
> Basically, our MMU divides the address space into "segments" (of 256M or
> 1T depending on your processor capabilities) and those segments are SW
> loaded into a relatively small (64 entries) SLB buffer.
>
> Thus, by moving the per-cpu to the end of the vmalloc space, you
> essentially make it use a different segment from the rest of the vmalloc
> space, which will overall degrade performances by increasing pressure on
> the SLB.
>
> It would be nicer if we could provide an arch function to provide a
> "preferred" location for the per-cpu data.
>
> I can easily cook up a patch but wanted to discuss that with you first.
> Any reason why we would keep it within vmalloc space for example ? IE. I
> could move VMALLOC_END to below the per-cpu reserved areas, or are they
> subject to expansion past boot time ?
>
> Also, how big can they be ? Ie, will the top of the first 256M segment
> good enough or that will risk blowing out of space ? In general,
> machines with 256M segments won't have more than 64 or maybe 128 CPUs I
> believe. Bigger machines will have CPUs that support 1T segments.
Hmm... I don't think 256M segment will be enough. Percpu area layout
will follow how numa memory is laidd out. For example, if a machine
has 4 nodes (each one with one cpu) and memory for each node is 1G in
size and 1G apart, the first chunk will be embedded in the linear
mapping area (normal kernel addressable area) and each unit in the
chunk will be apart by between 1G and 2G. As the first chunk is
embedded in the linear mapped area, this shouldn't cause any extra
overhead.
The vmalloc area is used when the first chunk is filled and another
chunk need to be allocated. From the second chunk on, vmalloc area is
used to preserve the layout of the first chunk. ie. Each of them will
span across 8G bytes (they will overlap tho, so even with many dynamic
chunks vm usage will only be slightly over 8G).
The reason why vmalloc area from the top is used is that I didn't want
this congruent allocation to compete with normal vmalloc allocations.
Depending on the numa layout, competition between linear allocation
and congruent allocation may create many unnecessary holes.
For 256M segment, I don't think much can be done but for 1T segment,
just limiting vmalloc area size to 1T should do the trick, no?
Thanks.
--
tejun
^ permalink raw reply
* New percpu & ppc64 perfs
From: Benjamin Herrenschmidt @ 2009-10-13 23:59 UTC (permalink / raw)
To: Tejun Heo; +Cc: linuxppc-dev, linux-kernel@vger.kernel.org
Hi Tejun !
So I found (and fixed, though the patch isn't upstream yet) the problem
that was causing the new percpu to hang when accessing the top of our
vmalloc space.
However, I have some concerns about that choice of location for the
percpu datas.
Basically, our MMU divides the address space into "segments" (of 256M or
1T depending on your processor capabilities) and those segments are SW
loaded into a relatively small (64 entries) SLB buffer.
Thus, by moving the per-cpu to the end of the vmalloc space, you
essentially make it use a different segment from the rest of the vmalloc
space, which will overall degrade performances by increasing pressure on
the SLB.
It would be nicer if we could provide an arch function to provide a
"preferred" location for the per-cpu data.
I can easily cook up a patch but wanted to discuss that with you first.
Any reason why we would keep it within vmalloc space for example ? IE. I
could move VMALLOC_END to below the per-cpu reserved areas, or are they
subject to expansion past boot time ?
Also, how big can they be ? Ie, will the top of the first 256M segment
good enough or that will risk blowing out of space ? In general,
machines with 256M segments won't have more than 64 or maybe 128 CPUs I
believe. Bigger machines will have CPUs that support 1T segments.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 4/5 v3] kernel handling of memory DLPAR
From: Michael Ellerman @ 2009-10-13 22:31 UTC (permalink / raw)
To: Nathan Fontenot; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <4AD4C346.20801@austin.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 6749 bytes --]
On Tue, 2009-10-13 at 13:13 -0500, Nathan Fontenot wrote:
> This adds the capability to DLPAR add and remove memory from the kernel. The
Hi Nathan,
Sorry to only get around to reviewing version 3, time is a commodity in
short supply :)
> Index: powerpc/arch/powerpc/platforms/pseries/dlpar.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/platforms/pseries/dlpar.c 2009-10-08 11:08:42.000000000 -0500
> +++ powerpc/arch/powerpc/platforms/pseries/dlpar.c 2009-10-13 13:08:22.000000000 -0500
> @@ -16,6 +16,10 @@
> #include <linux/notifier.h>
> #include <linux/proc_fs.h>
> #include <linux/spinlock.h>
> +#include <linux/memory_hotplug.h>
> +#include <linux/sysdev.h>
> +#include <linux/sysfs.h>
> +
>
> #include <asm/prom.h>
> #include <asm/machdep.h>
> @@ -404,11 +408,165 @@
> return 0;
> }
>
> +#ifdef CONFIG_MEMORY_HOTPLUG
> +
> +static struct property *clone_property(struct property *old_prop)
> +{
> + struct property *new_prop;
> +
> + new_prop = kzalloc((sizeof *new_prop), GFP_KERNEL);
> + if (!new_prop)
> + return NULL;
> +
> + new_prop->name = kzalloc(strlen(old_prop->name) + 1, GFP_KERNEL);
kstrdup()?
> + new_prop->value = kzalloc(old_prop->length + 1, GFP_KERNEL);
> + if (!new_prop->name || !new_prop->value) {
> + free_property(new_prop);
> + return NULL;
> + }
> +
> + strcpy(new_prop->name, old_prop->name);
> + memcpy(new_prop->value, old_prop->value, old_prop->length);
> + new_prop->length = old_prop->length;
> +
> + return new_prop;
> +}
> +
> +int platform_probe_memory(u64 phys_addr)
> +{
> + struct device_node *dn;
> + struct property *new_prop, *old_prop;
> + struct property *lmb_sz_prop;
> + struct of_drconf_cell *drmem;
> + u64 lmb_size;
> + int num_entries, i, rc;
> +
> + if (!phys_addr)
> + return -EINVAL;
> +
> + dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
> + if (!dn)
> + return -EINVAL;
> +
> + lmb_sz_prop = of_find_property(dn, "ibm,lmb-size", NULL);
> + lmb_size = *(u64 *)lmb_sz_prop->value;
of_get_property() ?
> +
> + old_prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
I know we should never fail to find these properties, but it would be
nice to check just in case.
> +
> + num_entries = *(u32 *)old_prop->value;
> + drmem = (struct of_drconf_cell *)
> + ((char *)old_prop->value + sizeof(u32));
You do this dance twice (see below), a struct might make it cleaner.
> + for (i = 0; i < num_entries; i++) {
> + u64 lmb_end_addr = drmem[i].base_addr + lmb_size;
> + if (phys_addr >= drmem[i].base_addr
> + && phys_addr < lmb_end_addr)
> + break;
> + }
> +
> + if (i >= num_entries) {
> + of_node_put(dn);
> + return -EINVAL;
> + }
> +
> + if (drmem[i].flags & DRCONF_MEM_ASSIGNED) {
> + of_node_put(dn);
> + return 0;
This is the already added case?
> + }
> +
> + rc = acquire_drc(drmem[i].drc_index);
> + if (rc) {
> + of_node_put(dn);
> + return -1;
-1 ?
> + }
> +
> + new_prop = clone_property(old_prop);
> + drmem = (struct of_drconf_cell *)
> + ((char *)new_prop->value + sizeof(u32));
> +
> + drmem[i].flags |= DRCONF_MEM_ASSIGNED;
> + prom_update_property(dn, new_prop, old_prop);
> +
> + rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
> + PSERIES_DRCONF_MEM_ADD,
> + &drmem[i].base_addr);
> + if (rc == NOTIFY_BAD) {
> + prom_update_property(dn, old_prop, new_prop);
> + release_drc(drmem[i].drc_index);
> + }
> +
> + of_node_put(dn);
> + return rc == NOTIFY_BAD ? -1 : 0;
-1 ?
> +}
> +
> +static ssize_t memory_release_store(struct class *class, const char *buf,
> + size_t count)
> +{
> + unsigned long drc_index;
> + struct device_node *dn;
> + struct property *new_prop, *old_prop;
> + struct of_drconf_cell *drmem;
> + int num_entries;
> + int i, rc;
> +
> + rc = strict_strtoul(buf, 0, &drc_index);
> + if (rc)
> + return -EINVAL;
> +
> + dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
> + if (!dn)
> + return 0;
0 really?
> +
> + old_prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
> + new_prop = clone_property(old_prop);
> +
> + num_entries = *(u32 *)new_prop->value;
> + drmem = (struct of_drconf_cell *)
> + ((char *)new_prop->value + sizeof(u32));
> +
> + for (i = 0; i < num_entries; i++) {
> + if (drmem[i].drc_index == drc_index)
> + break;
> + }
> +
> + if (i >= num_entries) {
> + free_property(new_prop);
> + of_node_put(dn);
> + return -EINVAL;
> + }
Couldn't use old_prop up until here? They're identical aren't they, so
you can do the clone here and you can avoid the free in the above error
case.
> + drmem[i].flags &= ~DRCONF_MEM_ASSIGNED;
> + prom_update_property(dn, new_prop, old_prop);
> +
> + rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
> + PSERIES_DRCONF_MEM_REMOVE,
> + &drmem[i].base_addr);
> + if (rc != NOTIFY_BAD)
> + rc = release_drc(drc_index);
> +
> + if (rc)
> + prom_update_property(dn, old_prop, new_prop);
> +
> + of_node_put(dn);
> + return rc ? -1 : count;
-1, EPERM?
> +}
> +
> +static struct class_attribute class_attr_mem_release =
> + __ATTR(release, S_IWUSR, NULL, memory_release_store);
> +#endif
> +
> static int pseries_dlpar_init(void)
> {
> if (!machine_is(pseries))
> return 0;
>
> +#ifdef CONFIG_MEMORY_HOTPLUG
> + if (sysfs_create_file(&memory_sysdev_class.kset.kobj,
> + &class_attr_mem_release.attr))
> + printk(KERN_INFO "DLPAR: Could not create sysfs memory "
> + "release file\n");
> +#endif
> +
> return 0;
> }
> device_initcall(pseries_dlpar_init);
> Index: powerpc/arch/powerpc/mm/mem.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/mm/mem.c 2009-10-08 11:07:45.000000000 -0500
> +++ powerpc/arch/powerpc/mm/mem.c 2009-10-08 11:08:54.000000000 -0500
> @@ -111,8 +111,19 @@
> #ifdef CONFIG_MEMORY_HOTPLUG
>
> #ifdef CONFIG_NUMA
> +int __attribute ((weak)) platform_probe_memory(u64 start)
__weak
Though be careful, I think this is vulnerable to a bug in some
toolchains where the compiler will inline this version. See the comment
around early_irq_init() in kernel/softirq.c for example.
This will need to be a ppc_md hook as soon as another platform supports
memory hotplug, though that may be never :)
> +{
> + return 0;
> +}
> +
> int memory_add_physaddr_to_nid(u64 start)
> {
> + int rc;
> +
> + rc = platform_probe_memory(start);
> + if (rc)
> + return rc;
> +
> return hot_add_scn_to_nid(start);
> }
> #endif
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH 5/5 v2] kernel handling of CPU DLPAR
From: Michael Ellerman @ 2009-10-13 22:30 UTC (permalink / raw)
To: Nathan Fontenot; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <4AD4C3A3.5050103@austin.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 3511 bytes --]
On Tue, 2009-10-13 at 13:14 -0500, Nathan Fontenot wrote:
> This adds the capability to DLPAR add and remove CPUs from the kernel. The
> creates two new files /sys/devices/system/cpu/probe and
> /sys/devices/system/cpu/release to handle the DLPAR addition and removal of
> CPUs respectively.
How does this relate to the existing cpu hotplug mechanism? Or is this
making the cpu exist (possible), vs marking it as online?
Is some other platform going to want to do the same? ie. should the
probe/release part be in generic code?
> Index: powerpc/arch/powerpc/platforms/pseries/dlpar.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/platforms/pseries/dlpar.c 2009-10-13 13:08:22.000000000 -0500
> +++ powerpc/arch/powerpc/platforms/pseries/dlpar.c 2009-10-13 13:09:00.000000000 -0500
> @@ -1,11 +1,11 @@
> /*
> - * dlpar.c - support for dynamic reconfiguration (including PCI
> - * Hotplug and Dynamic Logical Partitioning on RPA platforms).
> + * dlpar.c - support for dynamic reconfiguration (including PCI,
We know it's dlpar.c :)
> + * Memory, and CPU Hotplug and Dynamic Logical Partitioning on
> + * PAPR platforms).
> *
> * Copyright (C) 2009 Nathan Fontenot
> * Copyright (C) 2009 IBM Corporation
> *
> - *
> * This program is free software; you can redistribute it and/or
> * modify it under the terms of the GNU General Public License version
> * 2 as published by the Free Software Foundation.
> @@ -19,6 +19,7 @@
> #include <linux/memory_hotplug.h>
> #include <linux/sysdev.h>
> #include <linux/sysfs.h>
> +#include <linux/cpu.h>
>
>
> #include <asm/prom.h>
> @@ -408,6 +409,82 @@
> return 0;
> }
>
> +#ifdef CONFIG_HOTPLUG_CPU
> +static ssize_t cpu_probe_store(struct class *class, const char *buf,
> + size_t count)
> +{
> + struct device_node *dn;
> + unsigned long drc_index;
> + char *cpu_name;
> + int rc;
> +
> + rc = strict_strtoul(buf, 0, &drc_index);
> + if (rc)
> + return -EINVAL;
> +
> + rc = acquire_drc(drc_index);
> + if (rc)
> + return rc;
> +
> + dn = configure_connector(drc_index);
> + if (!dn) {
> + release_drc(drc_index);
> + return rc;
> + }
> +
> + /* fixup dn name */
> + cpu_name = kzalloc(strlen(dn->full_name) + strlen("/cpus/") + 1,
> + GFP_KERNEL);
> + if (!cpu_name) {
> + free_cc_nodes(dn);
> + release_drc(drc_index);
> + return -ENOMEM;
> + }
> +
> + sprintf(cpu_name, "/cpus/%s", dn->full_name);
> + kfree(dn->full_name);
> + dn->full_name = cpu_name;
What was all that? Firmware gives us a bogus full name? But the parent
is right?
> + rc = add_device_tree_nodes(dn);
> + if (rc)
> + release_drc(drc_index);
> +
> + return rc ? rc : count;
You're sure rc is < 0.
> +}
> +
> +static ssize_t cpu_release_store(struct class *class, const char *buf,
> + size_t count)
> +{
> + struct device_node *dn;
> + u32 *drc_index;
> + int rc;
> +
> + dn = of_find_node_by_path(buf);
> + if (!dn)
> + return -EINVAL;
> +
> + drc_index = (u32 *)of_get_property(dn, "ibm,my-drc-index", NULL);
No cast required.
> + if (!drc_index) {
> + of_node_put(dn);
> + return -EINVAL;
> + }
> +
> + rc = release_drc(*drc_index);
> + if (rc) {
> + of_node_put(dn);
> + return rc;
> + }
> +
> + rc = remove_device_tree_nodes(dn);
> + if (rc)
> + acquire_drc(*drc_index);
> +
> + of_node_put(dn);
> + return rc ? rc : count;
> +}
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
From: Michael Ellerman @ 2009-10-13 21:54 UTC (permalink / raw)
To: Akinobu Mita
Cc: Fenghua Yu, x86, linux-ia64, Thomas Gleixner, David S. Miller,
netdev, Greg Kroah-Hartman, linux-kernel, linux-altix,
Yevgeny Petrilin, FUJITA Tomonori, linuxppc-dev, Tony Luck,
Paul Mackerras, H. Peter Anvin, sparclinux, Andrew Morton,
linux-usb, Ingo Molnar, Lothar Wassmann
In-Reply-To: <20091013091017.GA18431@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 241 bytes --]
On Tue, 2009-10-13 at 18:10 +0900, Akinobu Mita wrote:
> My user space testing exposed off-by-one error find_next_zero_area
> in iommu-helper.
Why not merge those tests into the kernel as a configurable boot-time
self-test?
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH 0/8] gianfar: Add support for hibernation
From: David Miller @ 2009-10-13 19:09 UTC (permalink / raw)
To: afleming; +Cc: scottwood, linuxppc-dev, netdev
In-Reply-To: <64B2BB18-32DC-4B98-95D6-F203F74040D5@freescale.com>
From: Andy Fleming <afleming@freescale.com>
Date: Tue, 13 Oct 2009 12:22:38 -0500
> No, it was fine (though made unnecessary by other patches). The BD
> has a union:
>
> struct {
> u16 status; /* Status Fields */
> u16 length; /* Buffer length */
> };
> u32 lstatus;
>
> so when you write "lstatus", you need to use the BD_LFLAG() macro, but
> when you write "status", you are just setting the status bits.
Indeed I missed that, thanks.
^ 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