From: Milton Miller <hidden> Date: 2011-05-11 07:42:44
This series represents a somewhat ordered, somewhat meandering series
development series of patches I've been working on for the past few weeks.
It starts with memory corruption fixes that need to go back to stable
relating to slave cpu searches and paca allocation. After refactoring
and taking into consideration of patches merged upstream, I think this
is just the first 4, but the next 3 are related.
powerpc: fix memory corruption from unallocated slaves
powerpc: don't search for paca in freed memory
powerpc/kdump64: Don't reference freed memory as pacas
powerpc/iseries: cleanup and fix secondary startup
powerpc: Respect nr_cpu_ids when calling set_cpu_possible and set_cpu_present
powerpc: use nr_cpu_ids in initial paca allocation
powerpc: call no-longer static setup_nr_cpu_ids instead of replicating it
A search for NR_CPUS found that MSG_ALL_BUT_SELF was only used to enter
the debugger, but caused special code loops in all smp_ops,
so I pulled that code for a bit more path length in the loop to enter
the debugger or kexec. I then simplified the mpic code and factored
out common code in ipi interrupt multiplexing. That allowed an
easy change to remove a set of lwarx/stwcx. in the ipi send path.
powerpc: mpic: limit NR_CPUS loop to 32 bit
powerpc: mpic: break cpumask abstraction earlier
powerpc: remove call sites of MSG_ALL_BUT_SELF
powerpc: remove checks for MSG_ALL and MSG_ALL_BUT_SELF
linux/smp.h: remove unused MSG_ flags
powerpc/mpic: simplify ipi cpu mask handling
powerpc: remove powermac/pic.h
powerpc: remove alloc_maybe_bootmem for zalloc version
powerpc: remove stubbed beat smp support
powerpc cell: use smp_request_message_ipi [ patchwork 3780 ]
powerpc: move smp_ops_t from machdep.h to smp.h
powerpc: consolidate ipi message mux and demux
powerpc: add kconfig for muxed smp ipi support
powerpc: use bytes instead of bitops in smp ipi multiplexing
I then got sidetracked with Grant's quest to create irq_domains from the
irq_host code. I started going through the irq_host implementations in
arch/powerpc, removing some code that was redundant or not called, tring
to simplify the interfaces before we export them. Also standardizing
the use of the per-irq chip data and handler data.
powerpc: xics: cleanup xics_host_map and ipi
powerpc: radix trees are available before init_IRQ
powerpc: return early if irq_host lookup type is wrong
powerpc: remove trival irq_host_ops.unmap
powerpc: remove i8259 irq_host_ops->unmap
powerpc fsl_msi: don't abuse platform_data for driver_data
powerpc: fsl_msi: use chip_data not handler_data
powerpc: mpc5121_ads_cpld: remove use of NO_IRQ_IGNORE
powerpc: mpc62xx_pic: fix get_irq handling of NO_IRQ
powerpc: psurge: create a irq_host for secondary cpus
powerpc: remove irq_host_ops->remap hook
powerpc: spider-pic: get pic from chip_data instead of irq_map
powerpc: axon_msi: validate msi irq via chip_data
powerpc: add virq_is_host to reduce virq_to_host usage
powerpc: remove virq_to_host
powerpc: make IRQ_NOREQUEST last to clear, first to set
My vision is irq_host (or irq_domain) becomes a small wrapper layer
around the irq_desc layer. irq_host details are not needed beyond
that layer; the irq_host is a opaque pointer.
Populating reverse mappings (hwirq to virq) will become part of the
irq_host layer and happen at create_irq or irq_alloc_virt.
The return value of the reverse map functions will be the irqdesc and
ppc_md.get_irq will return the irqdesc. There is no reason to follow
up the radix tree lookup of hwirq to irq only to use that in another
radix-tree lookup to get the irqdesc that we need. (The only remaining
user of NO_IRQ_IGNORE is iSeries, and that special return is the only
holdup.)
I already have patches that replace the irq_map.host pointer with a
per-irq_host NR_IRQ bitmap (but they are entangled with Grant's series
to switch to irq_alloc as the primary allocator). As long as you have
fewer than BITS_PER_LONG irq_hosts that will be a win, and the only
path that might be slower is searching for the irq_host at unmap time.
For small irq count controllers that want to map all interrupts to
linux interrupts (including the legacy irq host), we can replace that
bitmap with an irq range.
The irq_host.hostdata field will become a parameter to alloc_irq_host,
and will be set as the irq's chip_data before calling ->map. The map
routine is free to change this later (ps3 uses per-cpu data, xics now
uses the ics sub-ops as chipdata). This allows a irq_host to have
several irq_chips for different flows but a driver can have multiple
irq_hosts for multiple instances of a given chip, distinguished
by chip_data.
My current thinking is the device node pointer stored in the host will
become generic match data, still used by the of wrapper to irq_domains
as a device node for default matching. Both the match data and the
chip data will be availible to the match routine. (This allows us to
keep the default of device node = match data without standardizing
a match struct inside each irq_hosts chipdata that we have to undo
every irq).
After doing a bunch of grep's on arch/sh, I think the interesting
parts of super8 interrupt handling that Thomas referred to are in
drivers/sh/intc. For some reason they populate the radix tree first
with a descriptor of their common interrupt controler abstraction
then walk the tree, replacing the tagged elements with the pointer
to their equivalent to irq_map. I do not yet understand the purpose
of this two phase allocation.
All patches are being sent to linuxppc-dev, a few have additional
cc's.
All patches were compiled for 3 configs: a smp 32 bit classic, a 32
bit book-e smp, and a 64 bit server, each had most platforms enabled.
I restricted many of my grep searches to arch/powerpc. I boot tested
using bml.
arch/powerpc/include/asm/dbell.h | 3 +-
arch/powerpc/include/asm/irq.h | 5 +-
arch/powerpc/include/asm/machdep.h | 21 ----
arch/powerpc/include/asm/smp.h | 33 +++++-
arch/powerpc/include/asm/system.h | 2 -
arch/powerpc/include/asm/xics.h | 2 +-
arch/powerpc/kernel/crash.c | 2 +-
arch/powerpc/kernel/dbell.c | 65 ++----------
arch/powerpc/kernel/head_64.S | 13 ++-
arch/powerpc/kernel/irq.c | 112 ++++----------------
arch/powerpc/kernel/kgdb.c | 2 +-
arch/powerpc/kernel/misc_64.S | 13 ++-
arch/powerpc/kernel/paca.c | 17 +--
arch/powerpc/kernel/pci_dn.c | 3 +-
arch/powerpc/kernel/setup-common.c | 14 ++--
arch/powerpc/kernel/smp.c | 118 ++++++++++++++-------
arch/powerpc/lib/alloc.c | 8 --
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 6 +-
arch/powerpc/platforms/52xx/mpc52xx_pic.c | 4 +-
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 8 --
arch/powerpc/platforms/85xx/smp.c | 6 +-
arch/powerpc/platforms/Kconfig | 11 ++-
arch/powerpc/platforms/Kconfig.cputype | 2 +
arch/powerpc/platforms/cell/Makefile | 1 -
arch/powerpc/platforms/cell/axon_msi.c | 3 +-
arch/powerpc/platforms/cell/beat_interrupt.c | 27 -----
arch/powerpc/platforms/cell/beat_interrupt.h | 3 -
arch/powerpc/platforms/cell/beat_smp.c | 123 ----------------------
arch/powerpc/platforms/cell/celleb_pci.c | 6 +-
arch/powerpc/platforms/cell/celleb_setup.c | 4 -
arch/powerpc/platforms/cell/interrupt.c | 27 ++----
arch/powerpc/platforms/cell/smp.c | 18 +---
arch/powerpc/platforms/cell/spider-pic.c | 13 ++-
arch/powerpc/platforms/embedded6xx/flipper-pic.c | 7 --
arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 7 --
arch/powerpc/platforms/iseries/Kconfig | 1 +
arch/powerpc/platforms/iseries/exception.S | 59 ++++++----
arch/powerpc/platforms/iseries/irq.c | 3 +-
arch/powerpc/platforms/iseries/setup.c | 5 +
arch/powerpc/platforms/iseries/smp.c | 39 +-------
arch/powerpc/platforms/iseries/smp.h | 6 -
arch/powerpc/platforms/powermac/Kconfig | 11 ++-
arch/powerpc/platforms/powermac/pic.c | 13 +--
arch/powerpc/platforms/powermac/pic.h | 11 --
arch/powerpc/platforms/powermac/pmac.h | 1 +
arch/powerpc/platforms/powermac/smp.c | 87 +++++++++-------
arch/powerpc/platforms/ps3/interrupt.c | 6 -
arch/powerpc/platforms/ps3/smp.c | 22 +----
arch/powerpc/platforms/pseries/smp.c | 3 +-
arch/powerpc/sysdev/fsl_msi.c | 10 +-
arch/powerpc/sysdev/i8259.c | 13 ---
arch/powerpc/sysdev/mpic.c | 52 +++-------
arch/powerpc/sysdev/xics/icp-hv.c | 26 +----
arch/powerpc/sysdev/xics/icp-native.c | 26 +----
arch/powerpc/sysdev/xics/xics-common.c | 42 ++------
arch/powerpc/xmon/xmon.c | 2 +-
include/linux/smp.h | 10 --
57 files changed, 363 insertions(+), 794 deletions(-)
delete mode 100644 arch/powerpc/platforms/cell/beat_smp.c
delete mode 100644 arch/powerpc/platforms/iseries/smp.h
delete mode 100644 arch/powerpc/platforms/powermac/pic.h
From: Milton Miller <hidden> Date: 2011-05-11 07:42:32
Commit 1fc711f7ffb01089efc58042cfdbac8573d1b59a (powerpc/kexec: Fix race
in kexec shutdown) moved the write to signal the cpu had exited the kernel
from before the transition to real mode in kexec_smp_wait to kexec_wait.
Unfornately it missed that kexec_wait is used both by cpus leaving the
kernel and by secondary slave cpus that were not allocated a paca for
what ever reason -- they could be beyond nr_cpus or not described in
the current device tree for whatever reason (for example, kexec-load
was not refreshed after a cpu hotplug operation). Cpus coming through
that path they will write to paca[NR_CPUS] which is beyond the space
allocated for the paca data and overwrite memory not allocated to pacas
but very likely still real mode accessable).
Move the write back to kexec_smp_wait, which is used only by cpus that
found their paca, but after the transition to real mode.
Signed-off-by: Milton Miller <redacted>
Cc: <stable@kernel.org> # (1fc711f was backported to 2.6.32)
---
arch/powerpc/kernel/misc_64.S | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
@@ -471,10 +472,6 @@ _GLOBAL(kexec_wait)1:mflrr5addir5,r5,kexec_flag-1b-lir4,KEXEC_STATE_REAL_MODE-stbr4,PACAKEXECSTATE(r13)-SYNC-99:HMT_LOW#ifdef CONFIG_KEXEC /* use no memory without kexec */lwzr4,0(r5)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:32
Starting with 1426d5a3bd07589534286375998c0c8c6fdc5260 (powerpc:
Dynamically allocate pacas) the space for pacas beyond cpu_possible
is freed, but we failed to update the loop in crash.c.
Since c1854e00727f50f7ac99e98d26ece04c087ef785 (powerpc: Set nr_cpu_ids
early and use it to free PACAs) the number of pacas allocated is
always nr_cpu_ids.
Signed-off-by: Milton Miller <redacted>
Cc: <stable@kernel.org> # .34.x
---
This is the simplest fix, and quite sutiable for stable.
We can merge the crash waits with the normal kexec waits later,
and fix the hole described in the other version.
---
arch/powerpc/kernel/crash.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:34
Building on Grant's efforts to remove the irq_map array, this patch
moves spider-pics use of virq_to_host() to use irq_data_get_chip_data
and sets the irq chip data in the map call, like most other interrupt
controllers in powerpc.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/platforms/cell/spider-pic.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:34
Instead of checking for rogue msi numbers via the irq_map host field
set the chip_data to h.host_data (which is the msic struct pointer)
at map and compare it in get_irq.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/platforms/cell/axon_msi.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:35
When allocating irqs, wait to clear the IRQ_NOREQUEST flag until the
host map hook has been called.
When freeing irqs, set the IRQ_NOREQUEST flag before calling the host
unmap hook.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/kernel/irq.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
@@ -586,14 +586,14 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,irq_map[i].host=host;smp_wmb();-/* Clear norequest flags */-irq_clear_status_flags(i,IRQ_NOREQUEST);-/* Legacy flags are left to default at this point,*onecanthenuseirq_create_mapping()to*explicitlychangethem*/ops->map(host,i,i);++/* Clear norequest flags */+irq_clear_status_flags(i,IRQ_NOREQUEST);}break;caseIRQ_HOST_MAP_LINEAR:
@@ -664,8 +664,6 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,gotoerror;}-irq_clear_status_flags(virq,IRQ_NOREQUEST);-/* map it */smp_wmb();irq_map[virq].hwirq=hwirq;
@@ -676,6 +674,8 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,gotoerrdesc;}+irq_clear_status_flags(virq,IRQ_NOREQUEST);+return0;errdesc:
@@ -819,6 +819,8 @@ void irq_dispose_mapping(unsigned int virq)if(host->revmap_type==IRQ_HOST_MAP_LEGACY)return;+irq_set_status_flags(virq,IRQ_NOREQUEST);+/* remove chip and handler */irq_set_chip_and_handler(virq,NULL,NULL);
@@ -848,8 +850,6 @@ void irq_dispose_mapping(unsigned int virq)smp_mb();irq_map[virq].hwirq=host->inval_irq;-irq_set_status_flags(virq,IRQ_NOREQUEST);-irq_free_descs(virq,1);/* Free it */irq_free_virt(virq,1);
From: Milton Miller <hidden> Date: 2011-05-11 07:42:35
Some irq_host implementations are using virq_to_host to check if
they are the irq_host for a virtual irq. To allow us to make space
versus time tradeoffs, replace this usage with an assertive
virq_is_host that confirms or denies the irq is associated with the
given irq_host.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/include/asm/irq.h | 1 +
arch/powerpc/kernel/irq.c | 6 ++++++
arch/powerpc/sysdev/xics/xics-common.c | 2 +-
3 files changed, 8 insertions(+), 1 deletions(-)
@@ -213,7 +213,7 @@ void xics_migrate_irqs_away(void)/* We can't set affinity on ISA interrupts */if(virq<NUM_ISA_INTERRUPTS)continue;-if(virq_to_host(virq)!=xics_host)+if(!virq_is_host(virq,xics_host))continue;irq=(unsignedint)virq_to_hw(virq);/* We need to get IPIs still. */
From: Milton Miller <hidden> Date: 2011-05-11 07:42:36
Now that we never set a cpu above nr_cpu_ids possible we can
limit our initial paca allocation to nr_cpu_ids. We can then
clamp the number of cpus in platforms/iseries/setup.c.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/kernel/paca.c | 17 ++++++-----------
arch/powerpc/platforms/iseries/setup.c | 5 +++++
2 files changed, 11 insertions(+), 11 deletions(-)
@@ -178,7 +178,7 @@ static int __initdata paca_size;void__initallocate_pacas(void){-intnr_cpus,cpu,limit;+intcpu,limit;/**Wecan'ttakeSLBmissesonthepaca,andwewanttoaccessthem
@@ -190,23 +190,18 @@ void __init allocate_pacas(void)if(firmware_has_feature(FW_FEATURE_ISERIES))limit=min(limit,HvPagesToMap*HVPAGESIZE);-nr_cpus=NR_CPUS;-/* On iSeries we know we can never have more than 64 cpus */-if(firmware_has_feature(FW_FEATURE_ISERIES))-nr_cpus=min(64,nr_cpus);--paca_size=PAGE_ALIGN(sizeof(structpaca_struct)*nr_cpus);+paca_size=PAGE_ALIGN(sizeof(structpaca_struct)*nr_cpu_ids);paca=__va(memblock_alloc_base(paca_size,PAGE_SIZE,limit));memset(paca,0,paca_size);printk(KERN_DEBUG"Allocated %u bytes for %d pacas at %p\n",-paca_size,nr_cpus,paca);+paca_size,nr_cpu_ids,paca);-allocate_lppacas(nr_cpus,limit);+allocate_lppacas(nr_cpu_ids,limit);/* Can't use for_each_*_cpu, as they aren't functional yet */-for(cpu=0;cpu<nr_cpus;cpu++)+for(cpu=0;cpu<nr_cpu_ids;cpu++)initialise_paca(&paca[cpu],cpu);}
@@ -685,6 +685,11 @@ void * __init iSeries_early_setup(void)powerpc_firmware_features|=FW_FEATURE_ISERIES;powerpc_firmware_features|=FW_FEATURE_LPAR;+#ifdef CONFIG_SMP+/* On iSeries we know we can never have more than 64 cpus */+nr_cpu_ids=max(nr_cpu_ids,64);+#endif+iSeries_fixup_klimit();/*
From: Milton Miller <hidden> Date: 2011-05-11 07:42:36
We should not set cpus above nr_cpu_ids to possible. While we
will trigger a warning with CONFIG_CPUMASK_DEBUG, even then the mask
initializers will set the bits beyond what the iterators check and cause
nr_cpu_ids to increase.
Respecting nr_cpu_ids during setup will allow us to use it in our initial
paca allocation. It can be reduced from NR_CPUS by the existing early param
nr_cpus=, which was added in 2b633e3fac5efada088b57d31e65401f22bcc18f (smp:
Use nr_cpus= to set nr_cpu_ids early). We already call parse_early_parms
between finding the command line and allocating the pacas.
Signed-off-by: Milton Miller <redacted>
---
Probably-not-worth-Cc: stable (2.6.34 and up)
---
arch/powerpc/kernel/setup-common.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
@@ -443,7 +443,7 @@ void __init smp_setup_cpu_maps(void)intserv=&cpu;/* assume logical == phys */}-for(j=0;j<nthreads&&cpu<NR_CPUS;j++){+for(j=0;j<nthreads&&cpu<nr_cpu_ids;j++){DBG(" thread %d -> cpu %d (hard id %d)\n",j,cpu,intserv[j]);set_cpu_present(cpu,true);
@@ -483,12 +483,12 @@ void __init smp_setup_cpu_maps(void)if(cpu_has_feature(CPU_FTR_SMT))maxcpus*=nthreads;-if(maxcpus>NR_CPUS){+if(maxcpus>nr_cpu_ids){printk(KERN_WARNING"Partition configured for %d cpus, ""operating system maximum is %d.\n",-maxcpus,NR_CPUS);-maxcpus=NR_CPUS;+maxcpus,nr_cpu_ids);+maxcpus=nr_cpu_ids;}elseprintk(KERN_INFO"Partition configured for %d cpus.\n",maxcpus);
From: Milton Miller <hidden> Date: 2011-05-11 07:42:36
9cb82f2f4692293a27c578c3038518ce4477de72 (Make iSeries spin on
__secondary_hold_spinloop, like pSeries) added a load of current_set
but this load was repeated later and we don't even have the paca yet.
It also checked __secondary_hold_spinloop with a 32 bit compare instead
of a 64 bit compare.
b6f6b98a4e91fcf31db7de54c3aa86252fc6fb5f (Don't spin on sync instruction
at boot time) missed the copy of the startup code in iseries.
1426d5a3bd07589534286375998c0c8c6fdc5260 (Dynamically allocate pacas)
doesn't allow for pacas to be less than lppacas and recalculated the paca
location from the cpu id in r0 every time through the secondary loop.
Various revisions over time made the comments on conditional branches
confusing with respect to being a hold loop or forward progress
Mostly in-order description of the changes:
Replicate the few lines of code saved by the ugly scoped ifdef CONFIG_SMP
in the secondary loop between yielding on UP and marking time with the
hypervisor on SMP. Always compile the iseries_secondary_yield loop and
use it if the cpu id is above nr_cpu_ids. Change all forward progress
paths to be forward branches to the next numerical label. Assign a
label to all loops. Move all sync instructions from the loops to the
forward progress path. Wait to load current_set until paca is set to go.
Move the iseries_secondary_smp_loop label to cover the whole spin loop.
Add HMT_MEDIUM when we make forward progress.
Signed-off-by: Milton Miller <redacted>
---
commpile tested only
---
arch/powerpc/platforms/iseries/exception.S | 59 ++++++++++++++++-----------
1 files changed, 35 insertions(+), 24 deletions(-)
@@ -61,29 +61,31 @@ system_reset_iSeries:/*Spinon__secondary_hold_spinloopuntilitisupdatedbythebootcpu.*//*IntheUPcasewe'll yield() later, and we will not access the paca anyway */#ifdef CONFIG_SMP-1:+iSeries_secondary_wait_paca:HMT_LOWLOAD_REG_ADDR(r23,__secondary_hold_spinloop)ldr23,0(r23)-sync-LOAD_REG_ADDR(r3,current_set)-sldir28,r24,3/*getcurrent_set[cpu#] */-ldxr3,r3,r28-addir1,r3,THREAD_SIZE-subir1,r1,STACK_FRAME_OVERHEAD-cmpwi0,r23,0/*KeeppokingtheHypervisoruntil*/-bne2f/*we're released */-/*LettheHypervisorknowwearealive*/+cmpdi0,r23,0+bne2f/*goonwhenthemasterisready*/++/*KeeppokingtheHypervisoruntilwe're released *//*8002isacalltoHvCallCfg::getLps,aharmlessHypervisorfunction*/lisr3,0x8002rldicrr3,r3,32,15/*r0=(r3<<32)&0xffff000000000000*/lir0,-1/*r0=-1indicatesaHypervisorcall*/sc/*Invokethehypervisorviaasystemcall*/-b1b-#endif+biSeries_secondary_wait_paca2:+HMT_MEDIUM+sync++LOAD_REG_ADDR(r3,nr_cpu_ids)/*getnumberofpacasallocated*/+lwzr3,0(r3)/*nr_cpus=orNR_CPUScanlimit*/+cmpld0,r24,r3/*isourcpunumberallocated?*/+bgeiSeries_secondary_yield/*no,yieldforever*/+/*Loadourpacanowthatit's been allocated */LOAD_REG_ADDR(r13,paca)ldr13,0(r13)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:37
If none of irq category bits were set mpc52xx_get_irq() would pass
NO_IRQ_IGNORE (-1) to irq_linear_revmap, which does an unsigned compare
and declares the interrupt above the linear map range. It then punts
to irq_find_mapping, which performs a linear search of all irqs,
which will likely miss and only then return NO_IRQ.
If no status bit is set, then we should return NO_IRQ directly.
The interrupt should not be suppressed from spurious counting, in fact
that is the definition of supurious.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/platforms/52xx/mpc52xx_pic.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:37
As NO_IRQ_IGNORE is only used between the static function cpld_pic_get_irq
and its caller cpld_pic_cascade, and cpld_pic_cascade only uses it to
suppress calling handle_generic_irq, we can change these uses to NO_IRQ
and remove the extra tests and pathlength in cpld_pic_cascade.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:38
handler_data should be reserved for flow handlers on the dependent
irq, not consumed by the parent irq code that is part of the irq_chip
code. The msi_data pointer was already set in msidesc->irqhost->hostdata
and being copied to irq_data->chipdata in the msidesc->irqhost->map()
method called via create_irq_mapping, so we can obtain the pointer
from there and free the instance it in teardown_msi_irqs.
Also remove the unnecessary cast of irq_get_handler_data in the
cascade handler, which is the demux flow handler of the parent
msi interrupt. (This is the expected usage for handler_data).
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/sysdev/fsl_msi.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
@@ -168,7 +168,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)rc=-ENOSPC;gotoout_free;}-irq_set_handler_data(virq,msi_data);+/* chip_data is msi_data via host->hostdata in host->map() */irq_set_msi_desc(virq,entry);fsl_compose_msi_msg(pdev,hwirq,&msg,msi_data);
From: Milton Miller <hidden> Date: 2011-05-11 07:42:38
The msi platform device driver was abusing dev.platform_data for its
platform_driver_data. Use the correct pointer for storage.
Platform_data is supposed to be for platforms to communicate to drivers
parameters that are not otherwise discoverable. Its lifetime matches
the platform_device not the platform device driver. It is generally
not needed for drivers that only support systems with device trees.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/sysdev/fsl_msi.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:38
Create a dummy irq_host using the generic dummy irq chip for the secondary
cpus to use. Create a direct irq mapping for the ipi and register the
ipi action handler against it. If for some unlikely reason part of this
fails then don't detect the secondary cpus.
This removes another instance of NO_IRQ_IGNORE, records the ipi stats
for the secondary cpus, and runs the ipi on the interrupt stack.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/platforms/powermac/pic.c | 9 ++----
arch/powerpc/platforms/powermac/pmac.h | 1 +
arch/powerpc/platforms/powermac/smp.c | 49 +++++++++++++++++++++++++++----
3 files changed, 46 insertions(+), 13 deletions(-)
@@ -240,12 +240,9 @@ static unsigned int pmac_pic_get_irq(void)unsignedlongflags;#ifdef CONFIG_PPC_PMAC32_PSURGE-voidpsurge_smp_message_recv(void);--/* IPI's are a hack on the powersurge -- Cort */-if(smp_processor_id()!=0){-psurge_smp_message_recv();-returnNO_IRQ_IGNORE;/* ignore, already handled */+/* IPI's are a hack on the powersurge -- Cort */+if(smp_processor_id()!=0){+returnpsurge_secondary_virq;}#endif /* CONFIG_PPC_PMAC32_PSURGE */raw_spin_lock_irqsave(&pmac_pic_lock,flags);
@@ -124,6 +124,10 @@ static volatile u32 __iomem *psurge_start;/* what sort of powersurge board we have */staticintpsurge_type=PSURGE_NONE;+/* irq for secondary cpus to report */+staticstructirq_host*psurge_host;+intpsurge_secondary_virq;+/**SetandclearIPIsforpowersurge.*/
From: Milton Miller <hidden> Date: 2011-05-11 07:42:38
It was called from irq_create_mapping if that was called for a host
and hwirq that was previously mapped, "to update the flags". But the
only implementation was in beat_interrupt and all it did was repeat a
hypervisor call without error checking that was performed with error
checking at the beginning of the map hook. In addition, the comment on
the beat remap hook says it will only called once for a given mapping,
which would apply to map not remap.
All flags should be known by the time the match hook is called, before
we call the map hook. Removing this mostly unused hook will simpify
the requirements of irq_domain concept.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/include/asm/irq.h | 3 ---
arch/powerpc/kernel/irq.c | 2 --
arch/powerpc/platforms/cell/beat_interrupt.c | 11 -----------
3 files changed, 0 insertions(+), 16 deletions(-)
@@ -88,9 +88,6 @@ struct irq_host_ops {/* Dispose of such a mapping */void(*unmap)(structirq_host*h,unsignedintvirq);-/* Update of such a mapping */-void(*remap)(structirq_host*h,unsignedintvirq,irq_hw_number_thw);-/* Translate device-tree interrupt specifier from raw format coming*fromthefirmwaretoairq_hw_number_t(interruptlinenumber)and*type(sense)thatcanbepassedtoset_irq_type().Intheabsence
From: Milton Miller <hidden> Date: 2011-05-11 07:42:38
It was never called because the host is always IRQ_HOST_MAP_LEGACY.
And what it purported to do was mask the interrupt (which will already
have happend if we shutdown the interrupt), then synchronise_irq and
clear the chip pointer, both of which will have been be done by the
caller were we to call unmap on a legacy irq.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/sysdev/i8259.c | 13 -------------
1 files changed, 0 insertions(+), 13 deletions(-)
@@ -185,18 +185,6 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq,return0;}-staticvoidi8259_host_unmap(structirq_host*h,unsignedintvirq)-{-/* Make sure irq is masked in hardware */-i8259_mask_irq(irq_get_irq_data(virq));--/* remove chip and handler */-irq_set_chip_and_handler(virq,NULL,NULL);--/* Make sure it's completed */-synchronize_irq(virq);-}-staticinti8259_host_xlate(structirq_host*h,structdevice_node*ct,constu32*intspec,unsignedintintsize,irq_hw_number_t*out_hwirq,unsignedint*out_flags)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:39
These all just clear chip or chipdata fields, which will be done
by the generic code when we call irq_free_descs.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 8 --------
arch/powerpc/platforms/embedded6xx/flipper-pic.c | 7 -------
arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 7 -------
arch/powerpc/platforms/ps3/interrupt.c | 6 ------
4 files changed, 0 insertions(+), 28 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:39
If for some reason the code incrorectly calls the wrong function to
manage the revmap, not only should we warn, we should take action.
However, in the paths we expect to be taken every delivered interrupt
change to WARN_ON_ONCE. Use the if (WARN_ON(x)) format to get the
unlikely for free.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/kernel/irq.c | 12 +++++++-----
1 files changed, 7 insertions(+), 5 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:40
Since there are only 4 messages, we can replace the atomic bit set
(which uses atomic load reserve and store conditional sequence) with
a byte stores to seperate bytes. We still have to perform a load
reserve and store conditional sequence to avoid loosing messages on
reception but we can do that with a single call to xchg.
The do {} while and __BIG_ENDIAN specific mask testing was chosen by
looking at the generated asm code. On gcc-4.4, the bit masking becomes
a simple bit mask and test of the register returned from xchg without
storing and loading the value to the stack like attempts with a union
of bytes and an int (or worse, loading single bit constants from the
constant pool into non-voliatle registers that had to be preseved on
the stack). The do {} while avoids an unconditional branch to the
end of the loop to test the entry / repeat condition of a while loop
and instead optimises for the expected single iteration of the loop.
We have a full mb() at the beginning to cover ordering between send,
ipi, and receive so we can use xchg_local and forgo the further
acquire and release barriers of xchg.
Signed-off-by: Milton Miller <redacted>
---
v4: cast int to char ptr in msg send instead of char[] to int* for xchg/test
v3a: add resend to replace dorbell_check_self
v3: settle on casting from char message[4] __aligned(4) to int ptr
v2: try initialized messages
(ended up with globals for each check value, increased reg pressure)
v1: initial version, check bytes though pointer to result of xchg
(resulted in store to stack then byte load / compare / branch)
---
arch/powerpc/kernel/smp.c | 31 ++++++++++++++++++-------------
1 files changed, 18 insertions(+), 13 deletions(-)
@@ -180,7 +180,7 @@ int smp_request_message_ipi(int virq, int msg)#ifdef CONFIG_PPC_SMP_MUXED_IPIstructcpu_messages{-unsignedlongmessages;/* current messages bits */+intmessages;/* current messages */unsignedlongdata;/* data for cause ipi */};staticDEFINE_PER_CPU_SHARED_ALIGNED(structcpu_messages,ipi_message);
@@ -195,9 +195,9 @@ void smp_muxed_ipi_set_data(int cpu, unsigned long data)voidsmp_muxed_ipi_message_pass(intcpu,intmsg){structcpu_messages*info=&per_cpu(ipi_message,cpu);-unsignedlong*tgt=&info->messages;+char*message=(char*)&info->messages;-set_bit(msg,tgt);+message[msg]=1;mb();smp_ops->cause_ipi(cpu,info->data);}
@@ -205,30 +205,35 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)voidsmp_muxed_ipi_resend(void){structcpu_messages*info=&__get_cpu_var(ipi_message);-unsignedlong*tgt=&info->messages;-if(*tgt)+if(info->messages)smp_ops->cause_ipi(smp_processor_id(),info->data);}irqreturn_tsmp_ipi_demux(void){structcpu_messages*info=&__get_cpu_var(ipi_message);-unsignedlong*tgt=&info->messages;+unsignedintall;mb();/* order any irq clear */-while(*tgt){-if(test_and_clear_bit(PPC_MSG_CALL_FUNCTION,tgt))++do{+all=xchg_local(&info->messages,0);++#ifdef __BIG_ENDIAN+if(all&(1<<(24-8*PPC_MSG_CALL_FUNCTION)))generic_smp_call_function_interrupt();-if(test_and_clear_bit(PPC_MSG_RESCHEDULE,tgt))+if(all&(1<<(24-8*PPC_MSG_RESCHEDULE)))reschedule_action(0,NULL);/* upcoming sched hook */-if(test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,tgt))+if(all&(1<<(24-8*PPC_MSG_CALL_FUNC_SINGLE)))generic_smp_call_function_single_interrupt();-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)-if(test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,tgt))+if(all&(1<<(24-8*PPC_MSG_DEBUGGER_BREAK)))debug_ipi_action(0,NULL);+#else+#error Unsupported ENDIAN#endif-}+}while(info->messages);+returnIRQ_HANDLED;}#endif /* CONFIG_PPC_SMP_MUXED_IPI */
From: Milton Miller <hidden> Date: 2011-05-11 07:42:40
Since the generic irq code uses a radix tree for sparse interrupts,
the initcall ordering has been changed to initialize radix trees before
irqs. We no longer need to defer creating revmap radix trees to the
arch_initcall irq_late_init.
Also, the kmem caches are allocated so we don't need to use
zalloc_maybe_bootmem.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/kernel/irq.c | 78 ++------------------------------------------
1 files changed, 4 insertions(+), 74 deletions(-)
@@ -537,7 +536,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,/* Allocate structure and revmap table if using linear mapping */if(revmap_type==IRQ_HOST_MAP_LINEAR)size+=revmap_arg*sizeof(unsignedint);-host=zalloc_maybe_bootmem(size,GFP_KERNEL);+host=kzalloc(size,GFP_KERNEL);if(host==NULL)returnNULL;
@@ -839,13 +841,6 @@ void irq_dispose_mapping(unsigned int virq)host->revmap_data.linear.revmap[hwirq]=NO_IRQ;break;caseIRQ_HOST_MAP_TREE:-/*-*Checkifradixtreeallocatedyet,ifnotthennothingto-*remove.-*/-smp_rmb();-if(revmap_trees_allocated<1)-break;mutex_lock(&revmap_trees_mutex);radix_tree_delete(&host->revmap_data.tree,hwirq);mutex_unlock(&revmap_trees_mutex);
@@ -906,14 +901,6 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host,WARN_ON(host->revmap_type!=IRQ_HOST_MAP_TREE);/*-*Checkiftheradixtreeexistsandhasbeeinitialized.-*Ifnot,wefallbacktoslowmode-*/-if(revmap_trees_allocated<2)-returnirq_find_mapping(host,hwirq);--/* Now try to resolve */-/**Norcu_read_lock(ing)needed,theptrreturnedcan'tgounderus*asit'sreferencinganentryinthestaticirq_maptable.*/
@@ -935,18 +922,8 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host,voidirq_radix_revmap_insert(structirq_host*host,unsignedintvirq,irq_hw_number_thwirq){-WARN_ON(host->revmap_type!=IRQ_HOST_MAP_TREE);-/*-*Checkiftheradixtreeexistsyet.-*Ifnot,thentheirqwillbeinsertedintothetreewhenitgets-*initialized.-*/-smp_rmb();-if(revmap_trees_allocated<1)-return;-if(virq!=NO_IRQ){mutex_lock(&revmap_trees_mutex);radix_tree_insert(&host->revmap_data.tree,hwirq,
@@ -1054,53 +1031,6 @@ int arch_early_irq_init(void)return0;}-/* We need to create the radix trees late */-staticintirq_late_init(void)-{-structirq_host*h;-unsignedinti;--/*-*Nomutualexclusionwithrespecttoaccessorsofthetreeisneeded-*hereasthesynchronizationisdoneviathestatevariable-*revmap_trees_allocated.-*/-list_for_each_entry(h,&irq_hosts,link){-if(h->revmap_type==IRQ_HOST_MAP_TREE)-INIT_RADIX_TREE(&h->revmap_data.tree,GFP_KERNEL);-}--/*-*Makesuretheradixtreesinitsarevisiblebeforesetting-*theflag-*/-smp_wmb();-revmap_trees_allocated=1;--/*-*Insertthereversemappingforthoseinterruptsalreadypresent-*inirq_map[].-*/-mutex_lock(&revmap_trees_mutex);-for(i=0;i<irq_virq_count;i++){-if(irq_map[i].host&&-(irq_map[i].host->revmap_type==IRQ_HOST_MAP_TREE))-radix_tree_insert(&irq_map[i].host->revmap_data.tree,-irq_map[i].hwirq,&irq_map[i]);-}-mutex_unlock(&revmap_trees_mutex);--/*-*Makesuretheradixtreesinsertionsarevisiblebeforesetting-*theflag-*/-smp_wmb();-revmap_trees_allocated=2;--return0;-}-arch_initcall(irq_late_init);-#ifdef CONFIG_VIRQ_DEBUGstaticintvirq_debug_show(structseq_file*m,void*private){
From: Milton Miller <hidden> Date: 2011-05-11 07:42:40
Since we already have a special case in map to set the ipi handler, use
the desired flow.
If we don't find an ics to handle the interrupt complain instead of
returning 0 without having set a chip or handler.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/sysdev/xics/xics-common.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
@@ -341,15 +340,16 @@ static int xics_host_map(struct irq_host *h, unsigned int virq,/* Don't call into ICS for IPIs */if(hw==XICS_IPI){irq_set_chip_and_handler(virq,&xics_ipi_chip,-handle_fasteoi_irq);+handle_percpu_irq);return0;}/* Let the ICS setup the chip data */list_for_each_entry(ics,&ics_list,link)if(ics->map(ics,virq)==0)-break;-return0;+return0;++return-EINVAL;}staticintxics_host_xlate(structirq_host*h,structdevice_node*ct,
From: Milton Miller <hidden> Date: 2011-05-11 07:42:40
The only references to the irq_map[].host field are internal to
arch/powerpc/kernel/irq.c
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/include/asm/irq.h | 1 -
arch/powerpc/kernel/irq.c | 6 ------
2 files changed, 0 insertions(+), 7 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:40
Compile the new smp ipi mux and demux code only if a platform
will make use of it. The new config is selected as required.
The new cause_ipi smp op is only available conditionally to point out
configs where the select is required; this makes setting the op an
immediate fail instead of a deferred unresolved symbol at link.
This also creates a new config for power surge powermac upgrade support
that can be disabled in expert mode but is default on.
I also removed the depends / default y on CONFIG_XICS since it is selected
by PSERIES.
Signed-off-by: Milton Miller <redacted>
---
I kept this seperate mostly because of the addition of the PSURGE kconfig
and to focus the discussion on the seperate concepts but it can be merged
into the previous patch if desireed.
---
arch/powerpc/include/asm/smp.h | 2 ++
arch/powerpc/kernel/smp.c | 2 ++
arch/powerpc/platforms/Kconfig | 11 +++++++++--
arch/powerpc/platforms/Kconfig.cputype | 2 ++
arch/powerpc/platforms/iseries/Kconfig | 1 +
arch/powerpc/platforms/powermac/Kconfig | 11 ++++++++++-
arch/powerpc/platforms/powermac/pic.c | 4 ++--
arch/powerpc/platforms/powermac/smp.c | 8 ++++----
8 files changed, 32 insertions(+), 9 deletions(-)
@@ -178,6 +178,7 @@ int smp_request_message_ipi(int virq, int msg)returnerr;}+#ifdef CONFIG_PPC_SMP_MUXED_IPIstructcpu_messages{unsignedlongmessages;/* current messages bits */unsignedlongdata;/* data for cause ipi */
@@ -239,7 +239,7 @@ static unsigned int pmac_pic_get_irq(void)unsignedlongbits=0;unsignedlongflags;-#ifdef CONFIG_SMP+#ifdef CONFIG_PPC_PMAC32_PSURGEvoidpsurge_smp_message_recv(void);/* IPI's are a hack on the powersurge -- Cort */
@@ -980,7 +980,7 @@ void __init pmac_setup_smp(void)of_node_put(np);smp_ops=&core99_smp_ops;}-#ifdef CONFIG_PPC32+#ifdef CONFIG_PPC_PMAC32_PSURGEelse{/* We have to set bits in cpu_possible_mask here since the*secondaryCPU(s)aren'tinthedevicetree.Various
From: Milton Miller <hidden> Date: 2011-05-11 07:42:41
I can't see any reason these functions are needed by machdep.h
and they are all hidden by CONFIG_SMP with no UP alternative.
Also move the declarations for the fallback timebase ops, which
are used to fill in the smp ops.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/include/asm/machdep.h | 21 ---------------------
arch/powerpc/include/asm/smp.h | 15 +++++++++++++++
2 files changed, 15 insertions(+), 21 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:41
Consolidate the mux and demux of ipi messages into smp.c and call
a new smp_ops callback to actually trigger the ipi.
The powerpc architecture code is optimised for having 4 distinct
ipi triggers, which are mapped to 4 distinct messages (ipi many, ipi
single, scheduler ipi, and enter debugger). However, several interrupt
controllers only provide a single software triggered interrupt that
can be delivered to each cpu. To resolve this limitation, each smp_ops
implementation created a per-cpu variable that is manipulated with atomic
bitops. Since these lines will be contended they are optimialy marked as
shared_aligned and take a full cache line for each cpu. Distro kernels
may have 2 or 3 of these in their config, each taking per-cpu space
even though at most one will be in use.
This consolidation removes smp_message_recv and replaces the single call
actions cases with direct calls from the common message recognition loop.
The complicated debugger ipi case with its muxed crash handling code is
moved to debug_ipi_action which is now called from the demux code (instead
of the multi-message action calling smp_message_recv).
I put a call to reschedule_action to increase the likelyhood of correctly
merging the anticipated scheduler_ipi() hook coming from the scheduler
tree; that single required call can be inlined later.
The actual message decode is a copy of the old pseries xics code with its
memory barriers and cache line spacing, augmented with a per-cpu unsigned
long based on the book-e doorbell code. The optional data is set via a
callback from the implementation and is passed to the new cause-ipi hook
along with the logical cpu number. While currently only the doorbell
implemntation uses this data it should be almost zero cost to retrieve and
pass it -- it adds a single register load for the argument from the same
cache line to which we just completed a store and the register is dead
on return from the call. I extended the data element from unsigned int
to unsigned long in case some other code wanted to associate a pointer.
The doorbell check_self is replaced by a call to smp_muxed_ipi_resend,
conditioned on the CPU_DBELL feature. The ifdef guard could be relaxed
to CONFIG_SMP but I left it with BOOKE for now.
Also, the doorbell interrupt vector for book-e was not calling irq_enter
and irq_exit, which throws off cpu accounting and causes code to not
realize it is running in interrupt context. Add the missing calls.
Signed-off-by: Milton Miller <redacted>
---
This requires patch 3780 be applied first for cell to compile.
---
arch/powerpc/include/asm/dbell.h | 3 +-
arch/powerpc/include/asm/smp.h | 14 +++--
arch/powerpc/include/asm/xics.h | 2 +-
arch/powerpc/kernel/dbell.c | 46 +++-------------
arch/powerpc/kernel/irq.c | 4 +-
arch/powerpc/kernel/smp.c | 92 +++++++++++++++++++++----------
arch/powerpc/platforms/85xx/smp.c | 6 ++-
arch/powerpc/platforms/iseries/irq.c | 3 +-
arch/powerpc/platforms/iseries/smp.c | 23 +-------
arch/powerpc/platforms/iseries/smp.h | 6 --
arch/powerpc/platforms/powermac/smp.c | 27 ++-------
arch/powerpc/platforms/pseries/smp.c | 3 +-
arch/powerpc/sysdev/xics/icp-hv.c | 10 +---
arch/powerpc/sysdev/xics/icp-native.c | 10 +---
arch/powerpc/sysdev/xics/xics-common.c | 30 +----------
15 files changed, 107 insertions(+), 172 deletions(-)
delete mode 100644 arch/powerpc/platforms/iseries/smp.h
@@ -109,13 +110,16 @@ extern int cpu_to_core_id(int cpu);#define PPC_MSG_CALL_FUNC_SINGLE 2#define PPC_MSG_DEBUGGER_BREAK 3-/*-*irqcontrollersthathavededicatedipispermessageanddon't-*needadditionalcodeintheactionhandlermayusethis-*/+/* for irq controllers that have dedicated ipis per message (4) */externintsmp_request_message_ipi(intvirq,intmessage);externconstchar*smp_ipi_name[];+/* for irq controllers with only a single ipi */+externvoidsmp_muxed_ipi_set_data(intcpu,unsignedlongdata);+externvoidsmp_muxed_ipi_message_pass(intcpu,intmsg);+externvoidsmp_muxed_ipi_resend(void);+externirqreturn_tsmp_ipi_demux(void);+voidsmp_init_iSeries(void);voidsmp_init_pSeries(void);voidsmp_init_cell(void);
@@ -13,65 +13,35 @@#include<linux/kernel.h>#include<linux/smp.h>#include<linux/threads.h>-#include<linux/percpu.h>+#include<linux/hardirq.h>#include<asm/dbell.h>#include<asm/irq_regs.h>#ifdef CONFIG_SMP-structdoorbell_cpu_info{-unsignedlongmessages;/* current messages bits */-unsignedinttag;/* tag value */-};--staticDEFINE_PER_CPU(structdoorbell_cpu_info,doorbell_cpu_info);-voiddoorbell_setup_this_cpu(void){-structdoorbell_cpu_info*info=&__get_cpu_var(doorbell_cpu_info);+unsignedlongtag=mfspr(SPRN_PIR)&0x3fff;-info->messages=0;-info->tag=mfspr(SPRN_PIR)&0x3fff;+smp_muxed_ipi_set_data(smp_processor_id(),tag);}-voiddoorbell_message_pass(intcpu,intmsg)+voiddoorbell_cause_ipi(intcpu,unsignedlongdata){-structdoorbell_cpu_info*info;--info=&per_cpu(doorbell_cpu_info,cpu);-set_bit(msg,&info->messages);-ppc_msgsnd(PPC_DBELL,0,info->tag);+ppc_msgsnd(PPC_DBELL,0,data);}voiddoorbell_exception(structpt_regs*regs){structpt_regs*old_regs=set_irq_regs(regs);-structdoorbell_cpu_info*info=&__get_cpu_var(doorbell_cpu_info);-intmsg;-/* Warning: regs can be NULL when called from irq enable */+irq_enter();-if(!info->messages||(num_online_cpus()<2))-gotoout;+smp_ipi_demux();-for(msg=0;msg<4;msg++)-if(test_and_clear_bit(msg,&info->messages))-smp_message_recv(msg);--out:+irq_exit();set_irq_regs(old_regs);}--voiddoorbell_check_self(void)-{-structdoorbell_cpu_info*info=&__get_cpu_var(doorbell_cpu_info);--if(!info->messages)-return;--ppc_msgsnd(PPC_DBELL,0,info->tag);-}-#else /* CONFIG_SMP */voiddoorbell_exception(structpt_regs*regs){
@@ -199,6 +178,59 @@ int smp_request_message_ipi(int virq, int msg)returnerr;}+structcpu_messages{+unsignedlongmessages;/* current messages bits */+unsignedlongdata;/* data for cause ipi */+};+staticDEFINE_PER_CPU_SHARED_ALIGNED(structcpu_messages,ipi_message);++voidsmp_muxed_ipi_set_data(intcpu,unsignedlongdata)+{+structcpu_messages*info=&per_cpu(ipi_message,cpu);++info->data=data;+}++voidsmp_muxed_ipi_message_pass(intcpu,intmsg)+{+structcpu_messages*info=&per_cpu(ipi_message,cpu);+unsignedlong*tgt=&info->messages;++set_bit(msg,tgt);+mb();+smp_ops->cause_ipi(cpu,info->data);+}++voidsmp_muxed_ipi_resend(void)+{+structcpu_messages*info=&__get_cpu_var(ipi_message);+unsignedlong*tgt=&info->messages;++if(*tgt)+smp_ops->cause_ipi(smp_processor_id(),info->data);+}++irqreturn_tsmp_ipi_demux(void)+{+structcpu_messages*info=&__get_cpu_var(ipi_message);+unsignedlong*tgt=&info->messages;++mb();/* order any irq clear */+while(*tgt){+if(test_and_clear_bit(PPC_MSG_CALL_FUNCTION,tgt))+generic_smp_call_function_interrupt();+if(test_and_clear_bit(PPC_MSG_RESCHEDULE,tgt))+reschedule_action(0,NULL);/* upcoming sched hook */+if(test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,tgt))+generic_smp_call_function_single_interrupt();+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)+if(test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,tgt))+debug_ipi_action(0,NULL);+#endif+}+returnIRQ_HANDLED;+}+voidsmp_send_reschedule(intcpu){if(likely(smp_ops))
@@ -156,28 +156,13 @@ static inline void psurge_clr_ipi(int cpu)/**Onpowersurge(oldSMPpowermacarchitecture)wedon'thave*separateIPIsforseparatemessageslikeopenpicdoes.Instead-*wehaveabitmapforeachprocessor,wherea1bitmeansthat-*thecorrespondingmessageispendingforthatprocessor.-*Ideallyeachcpu'sentrywouldbeinadifferentcacheline.+*usethegenericdemuxhelpers*--paulus.*/-staticunsignedlongpsurge_smp_message[NR_CPUS];-voidpsurge_smp_message_recv(void){-intcpu=smp_processor_id();-intmsg;--/* clear interrupt */-psurge_clr_ipi(cpu);--if(num_online_cpus()<2)-return;--/* make sure there is a message there */-for(msg=0;msg<4;msg++)-if(test_and_clear_bit(msg,&psurge_smp_message[cpu]))-smp_message_recv(msg);+psurge_clr_ipi(smp_processor_id());+smp_ipi_demux();}irqreturn_tpsurge_primary_intr(intirq,void*d)
@@ -126,32 +126,6 @@ void xics_mask_unknown_vec(unsigned int vec)#ifdef CONFIG_SMP-DEFINE_PER_CPU_SHARED_ALIGNED(unsignedlong,xics_ipi_message);--irqreturn_txics_ipi_dispatch(intcpu)-{-unsignedlong*tgt=&per_cpu(xics_ipi_message,cpu);--mb();/* order mmio clearing qirr */-while(*tgt){-if(test_and_clear_bit(PPC_MSG_CALL_FUNCTION,tgt)){-smp_message_recv(PPC_MSG_CALL_FUNCTION);-}-if(test_and_clear_bit(PPC_MSG_RESCHEDULE,tgt)){-smp_message_recv(PPC_MSG_RESCHEDULE);-}-if(test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,tgt)){-smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);-}-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)-if(test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,tgt)){-smp_message_recv(PPC_MSG_DEBUGGER_BREAK);-}-#endif-}-returnIRQ_HANDLED;-}-staticvoidxics_request_ipi(void){unsignedintipi;
@@ -170,8 +144,8 @@ static void xics_request_ipi(void)int__initxics_smp_probe(void){-/* Setup message_pass callback based on which ICP is used */-smp_ops->message_pass=icp_ops->message_pass;+/* Setup cause_ipi callback based on which ICP is used */+smp_ops->cause_ipi=icp_ops->cause_ipi;/* Register all the IPIs */xics_request_ipi();
From: Milton Miller <hidden> Date: 2011-05-11 07:42:41
I have no idea if the beat hypervisor supports multiple cpus in
a partition, but the code has not been touched since these stubs
were added in February of 2007 except to move them in April of 2008.
These are stubs: start_cpu always returns fail (which is dropped),
the message passing and reciving are empty functions, and the top
of file comment says "Incomplete".
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/platforms/cell/Makefile | 1 -
arch/powerpc/platforms/cell/beat_interrupt.c | 16 ----
arch/powerpc/platforms/cell/beat_interrupt.h | 3 -
arch/powerpc/platforms/cell/beat_smp.c | 107 --------------------------
arch/powerpc/platforms/cell/celleb_setup.c | 4 -
5 files changed, 0 insertions(+), 131 deletions(-)
delete mode 100644 arch/powerpc/platforms/cell/beat_smp.c
@@ -1,107 +0,0 @@-/*- * SMP support for Celleb platform. (Incomplete)- *- * (C) Copyright 2006 TOSHIBA CORPORATION- *- * This code is based on arch/powerpc/platforms/cell/smp.c:- * Dave Engebretsen, Peter Bergner, and- * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com- * Plus various changes from other IBM teams...- *- * 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.,- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.- */--#undef DEBUG--#include <linux/kernel.h>-#include <linux/smp.h>-#include <linux/interrupt.h>-#include <linux/init.h>-#include <linux/threads.h>-#include <linux/cpu.h>--#include <asm/irq.h>-#include <asm/smp.h>-#include <asm/machdep.h>-#include <asm/udbg.h>--#include "beat_interrupt.h"--#ifdef DEBUG-#define DBG(fmt...) udbg_printf(fmt)-#else-#define DBG(fmt...)-#endif--/*- * The primary thread of each non-boot processor is recorded here before- * smp init.- */-/* static cpumask_t of_spin_map; */--/**- * smp_startup_cpu() - start the given cpu- *- * At boot time, there is nothing to do for primary threads which were- * started from Open Firmware. For anything else, call RTAS with the- * appropriate start location.- *- * Returns:- * 0 - failure- * 1 - success- */-static inline int __devinit smp_startup_cpu(unsigned int lcpu)-{- return 0;-}--static int __init smp_beatic_probe(void)-{- return cpumask_weight(cpu_possible_mask);-}--static void __devinit smp_beatic_setup_cpu(int cpu)-{- beatic_setup_cpu(cpu);-}--static int __devinit smp_celleb_kick_cpu(int nr)-{- BUG_ON(nr < 0 || nr >= NR_CPUS);-- return smp_startup_cpu(nr);-}--static int smp_celleb_cpu_bootable(unsigned int nr)-{- return 1;-}-static struct smp_ops_t bpa_beatic_smp_ops = {- .message_pass = beatic_cause_IPI,- .probe = smp_beatic_probe,- .kick_cpu = smp_celleb_kick_cpu,- .setup_cpu = smp_beatic_setup_cpu,- .cpu_bootable = smp_celleb_cpu_bootable,-};--/* This is called very early */-void __init smp_init_celleb(void)-{- DBG(" -> smp_init_celleb()\n");-- smp_ops = &bpa_beatic_smp_ops;-- DBG(" <- smp_init_celleb()\n");-}
From: Milton Miller <hidden> Date: 2011-05-11 07:42:42
Replace all remaining callers of alloc_maybe_bootmem with
zalloc_maybe_bootmem. The callsite in pci_dn is followed with a
memset to clear the memory, and not zeroing at the other callsites
in the celleb fake pci code could lead to following uninitialized
memory as pointers or even freeing said pointers on error paths.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/include/asm/system.h | 2 --
arch/powerpc/kernel/pci_dn.c | 3 +--
arch/powerpc/lib/alloc.c | 8 --------
arch/powerpc/platforms/cell/celleb_pci.c | 6 +++---
4 files changed, 4 insertions(+), 15 deletions(-)
@@ -219,8 +219,6 @@ extern int mem_init_done; /* set on boot once kmalloc can be called */externintinit_bootmem_done;/* set once bootmem is available */externphys_addr_tmemory_limit;externunsignedlongklimit;--externvoid*alloc_maybe_bootmem(size_tsize,gfp_tmask);externvoid*zalloc_maybe_bootmem(size_tsize,gfp_tmask);externintpowersave_nap;/* set if nap mode can be used in idle loop */
@@ -319,7 +319,7 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,size=256;config=&private->fake_config[devno][fn];-*config=alloc_maybe_bootmem(size,GFP_KERNEL);+*config=zalloc_maybe_bootmem(size,GFP_KERNEL);if(*config==NULL){printk(KERN_ERR"PCI: ""not enough memory for fake configuration space\n");
@@ -330,7 +330,7 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,size=sizeof(structcelleb_pci_resource);res=&private->res[devno][fn];-*res=alloc_maybe_bootmem(size,GFP_KERNEL);+*res=zalloc_maybe_bootmem(size,GFP_KERNEL);if(*res==NULL){printk(KERN_ERR"PCI: not enough memory for resource data space\n");
@@ -431,7 +431,7 @@ static int __init phb_set_bus_ranges(struct device_node *dev,staticvoid__initcelleb_alloc_private_mem(structpci_controller*hose){hose->private_data=-alloc_maybe_bootmem(sizeof(structcelleb_pci_private),+zalloc_maybe_bootmem(sizeof(structcelleb_pci_private),GFP_KERNEL);}
From: Milton Miller <hidden> Date: 2011-05-11 07:42:42
Its unused, and of the three declarations, one is duplicated in pmac.h,
the second is static and the third is renamed and static.
Signed-off-by: Milton Miller <redacted>
---
---
arch/powerpc/platforms/powermac/pic.h | 11 -----------
1 files changed, 0 insertions(+), 11 deletions(-)
delete mode 100644 arch/powerpc/platforms/powermac/pic.h
From: Milton Miller <hidden> Date: 2011-05-11 07:42:43
Now that MSG_ALL and MSG_ALL_BUT_SELF have been eliminated,
smp_mpic_mesage_pass no longer needs to lookup the cpumask just to
have mpic_send_ipi extract part of it and recode it in a NR_CPUS loop
by mpic_physmask.
Signed-off-by: Milton Miller <redacted>
---
I chose stepwise refinement but this could be merged into the ALL_BUT_SELF
removal patch.
---
arch/powerpc/sysdev/mpic.c | 24 +++++++++++-------------
1 files changed, 11 insertions(+), 13 deletions(-)
@@ -67,22 +67,6 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)return0;}-staticvoidsmp_beatic_message_pass(inttarget,intmsg)-{-unsignedinti;--if(target<NR_CPUS){-beatic_cause_IPI(target,msg);-}else{-for_each_online_cpu(i){-if(target==MSG_ALL_BUT_SELF-&&i==smp_processor_id())-continue;-beatic_cause_IPI(i,msg);-}-}-}-staticint__initsmp_beatic_probe(void){returncpumask_weight(cpu_possible_mask);
@@ -105,7 +89,7 @@ static int smp_celleb_cpu_bootable(unsigned int nr)return1;}staticstructsmp_ops_tbpa_beatic_smp_ops={-.message_pass=smp_beatic_message_pass,+.message_pass=beatic_cause_IPI,.probe=smp_beatic_probe,.kick_cpu=smp_celleb_kick_cpu,.setup_cpu=smp_beatic_setup_cpu,
@@ -103,22 +103,6 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)return1;}-staticvoidsmp_iic_message_pass(inttarget,intmsg)-{-unsignedinti;--if(target<NR_CPUS){-iic_cause_IPI(target,msg);-}else{-for_each_online_cpu(i){-if(target==MSG_ALL_BUT_SELF-&&i==smp_processor_id())-continue;-iic_cause_IPI(i,msg);-}-}-}-staticint__initsmp_iic_probe(void){iic_request_IPIs();
@@ -168,7 +152,7 @@ static int smp_cell_cpu_bootable(unsigned int nr)return1;}staticstructsmp_ops_tbpa_iic_smp_ops={-.message_pass=smp_iic_message_pass,+.message_pass=iic_cause_IPI,.probe=smp_iic_probe,.kick_cpu=smp_cell_kick_cpu,.setup_cpu=smp_cell_setup_cpu,
From: Milton Miller <hidden> Date: 2011-05-11 07:42:43
The only user of MSG_ALL_BUT_SELF in the whole kernel tree is powerpc,
and it only uses it to start the debugger. Both debuggers always call
smp_send_debugger_break with MSG_ALL_BUT_SELF, and only mpic can do
anything more optimal than a loop over all online cpus, but all message
passing implementations have to code for this special delivery target.
Convert smp_send_debugger_break to take void and loop calling the smp_ops
message_pass function for each of the other cpus in the online cpumask.
Use raw_smp_processor_id() because we are either entering the debugger
or trying to start kdump and the additional warning it not useful were
it to trigger.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/include/asm/smp.h | 2 +-
arch/powerpc/kernel/kgdb.c | 2 +-
arch/powerpc/kernel/smp.c | 19 +++++++++++++------
arch/powerpc/xmon/xmon.c | 2 +-
4 files changed, 16 insertions(+), 9 deletions(-)
@@ -437,7 +437,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)xmon_owner=cpu;mb();if(ncpus>1){-smp_send_debugger_break(MSG_ALL_BUT_SELF);+smp_send_debugger_break();/* wait for other cpus to come in */for(timeout=100000000;timeout!=0;--timeout){if(cpumask_weight(&cpus_in_xmon)>=ncpus)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:44
mpic_set_affinity is allocating and freeing a cpumask var even though
it was breaking the cpumask abstraction when passing the mask to
mpic_physmask. It also didn't have any check for allocatin failure.
Break the cpumask abstraction earlier and use simple bitwise and of the
bits from the mask with the bits of cpu_online_mask.
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/sysdev/mpic.c | 10 +++-------
1 files changed, 3 insertions(+), 7 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:44
mpic_physmask was looping NR_CPUS times over a mask that was passed as
a u32. Since mpic is architecturaly limited to 32 physical cpus, clamp
the logical cpus to 32 when compiling (we could also clamp at runtime
to nr_cpu_ids).
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/sysdev/mpic.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 07:42:44
c1854e00727f50f7ac99e98d26ece04c087ef785 (powerpc: Set nr_cpu_ids early
and use it to free PACAs) copied the formerly static setup_nr_cpu_ids
from init/main.c but 34db18a054c600b6f81787165669dc572fe4de25 (smp:
move smp setup functions to kernel/smp.c) moved it to kernel/smp.c
with a declaration in include/linux/smp.h, so we can call it instead of
replicating it.
Signed-off-by: Milton Miller <redacted>
---
I found this cleanup while c1854e was being merged, but saved it from the
end to ease backporting.
---
arch/powerpc/kernel/setup-common.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
@@ -510,7 +510,7 @@ void __init smp_setup_cpu_maps(void)cpu_init_thread_core_maps(nthreads);/* Now that possible cpus are set, set nr_cpu_ids for later use */-nr_cpu_ids=find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS)+1;+setup_nr_cpu_ids();free_unused_pacas();}
From: Milton Miller <hidden> Date: 2011-05-11 07:47:13
This is a request to merge patchwork id 3780 with the same subject.
I believe it was marked "changes requested" because it depended on a
patch that had requested changes, but those were resolved and this
one got overlooked. The next patch will remove smp_msg_recv.
thanks,
milton
Here is the original change log:
Subject: [PATCH 15/16] powerpc cell: use smp_request_message_ipi
cell native has 4 interrupts for ipis, so use the new smp_request_message_ipi
to save pathlength and the data-dependent branch.
This has the side effects of enabling the debugger ipi for kdump and
setting IRQF_PERCPU for the ipi interrupts. It doesn't undo the virq
mapping if it turns out the ipi is not used.
From: Milton Miller <hidden> Date: 2011-05-11 07:47:13
Starting with 1426d5a3bd07589534286375998c0c8c6fdc5260 (powerpc:
Dynamically allocate pacas) we free the memory for pacas beyond
cpu_possible, but we failed to update the loop the secondary cpus use
to find their paca. If the system has running cpu threads for which
the kernel did not allocate a paca for they will search the memory that
was freed. For instance this could happen when the device tree for
a kdump kernel was not updated after a cpu hotplug, or the kernel is
running with more cpus than the kernel was configured.
Since c1854e00727f50f7ac99e98d26ece04c087ef785 (powerpc: Set nr_cpu_ids
early and use it to free PACAs) we set nr_cpu_ids before telling the
cpus to advance, so use that to limit the search.
We can't reference nr_cpu_ids without CONFIG_SMP because it is defined
as 1 instead of a memory location, but any extra threads should be sent
to kexec_wait in that case anyways, so make that explicit and remove
the search loop for UP.
Note to stable: The fix also requires
c1854e00727f50f7ac99e98d26ece04c087ef785 (powerpc: Set
nr_cpu_ids early and use it to free PACAs) to function. Also
9d07bc841c9779b4d7902e417f4e509996ce805d (Properly handshake CPUs going
out of boot spin loop) affects the second chunk, specifically the branch
target was 3b before and is 4b after that patch, and there was a blank
line before the #ifdef CONFIG_SMP that was removed
Cc: <stable@kernel.org> # .34.x: c1854e0072 powerpc: Set nr_cpu_ids early
Cc: <stable@kernel.org> # .34.x
Signed-off-by: Milton Miller <redacted>
---
arch/powerpc/kernel/head_64.S | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
From: Milton Miller <hidden> Date: 2011-05-11 15:45:52
Now that powerpc has removed its use of MSG_ALL_BUT_SELF and MSG_ALL
all these MSG_ flags are unused.
Signed-off-by: Milton Miller <redacted>
---
To be merged by powerpc with the series posted to linuxppc-dev
After the previous 2 patches, grep shows the following false hits (from
partial symbol matches):
find . -name .git -prune -o -name .pc -prune -o -name patches -prune -o -type f|
xargs grep -E 'MSG_(ALL|RESCHEDULE|CALL_FUNCTION|INVALIDATE_TLB|STOP_CPU)'
XFRM_MSG_ALLOCSPI (include/linux/xfrm.h, net/xfrm/xfrm_user.c)
CHANNELMSG_ALLOFFERS_DELIVERED (drivers/staging/hv/)
PPC_MSG_CALL_FUNCTION, PPC_MSG_RESCHEDULE (arch/powerpc/)
SMP_MSG_RESCHEDULE (arch/sh/)
---
include/linux/smp.h | 10 ----------
1 files changed, 0 insertions(+), 10 deletions(-)
From: Grant Likely <hidden> Date: 2011-05-11 19:00:25
On Wed, May 11, 2011 at 7:29 AM, Milton Miller [off-list ref] wrote:
Since the generic irq code uses a radix tree for sparse interrupts,
the initcall ordering has been changed to initialize radix trees before
irqs. =A0 We no longer need to defer creating revmap radix trees to the
arch_initcall irq_late_init.
Also, the kmem caches are allocated so we don't need to use
zalloc_maybe_bootmem.
Signed-off-by: Milton Miller <redacted>
w00t. Looks right to me.
Reviewed-by: Grant Likely <redacted>
@@ -906,14 +901,6 @@ unsigned int irq_radix_revmap_lookup(struct irq_host=
*host,
=A0 =A0 =A0 =A0WARN_ON(host->revmap_type !=3D IRQ_HOST_MAP_TREE);
=A0 =A0 =A0 =A0/*
- =A0 =A0 =A0 =A0* Check if the radix tree exists and has bee initialized=
.
- =A0 =A0 =A0 =A0* If not, we fallback to slow mode
- =A0 =A0 =A0 =A0*/
- =A0 =A0 =A0 if (revmap_trees_allocated < 2)
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 return irq_find_mapping(host, hwirq);
-
- =A0 =A0 =A0 /* Now try to resolve */
- =A0 =A0 =A0 /*
=A0 =A0 =A0 =A0 * No rcu_read_lock(ing) needed, the ptr returned can't go=
under us
=A0 =A0 =A0 =A0 * as it's referencing an entry in the static irq_map tabl=
e.
quoted hunk
=A0 =A0 =A0 =A0 */
@@ -935,18 +922,8 @@ unsigned int irq_radix_revmap_lookup(struct irq_host=
=A0{
-
=A0 =A0 =A0 =A0WARN_ON(host->revmap_type !=3D IRQ_HOST_MAP_TREE);
- =A0 =A0 =A0 /*
- =A0 =A0 =A0 =A0* Check if the radix tree exists yet.
- =A0 =A0 =A0 =A0* If not, then the irq will be inserted into the tree wh=
@@ -1054,53 +1031,6 @@ int arch_early_irq_init(void)
=A0 =A0 =A0 =A0return 0;
=A0}
-/* We need to create the radix trees late */
-static int irq_late_init(void)
-{
- =A0 =A0 =A0 struct irq_host *h;
- =A0 =A0 =A0 unsigned int i;
-
- =A0 =A0 =A0 /*
- =A0 =A0 =A0 =A0* No mutual exclusion with respect to accessors of the t=
ree is needed
- =A0 =A0 =A0 =A0* here as the synchronization is done via the state vari=
From: Grant Likely <hidden> Date: 2011-05-11 19:04:18
On Wed, May 11, 2011 at 7:29 AM, Milton Miller [off-list ref] wrote:
If for some reason the code incrorectly calls the wrong function to
manage the revmap, not only should we warn, we should take action.
However, in the paths we expect to be taken every delivered interrupt
change to WARN_ON_ONCE. =A0Use the if (WARN_ON(x)) format to get the
unlikely for free.
Signed-off-by: Milton Miller <redacted>
From: Grant Likely <hidden> Date: 2011-05-11 19:06:15
On Wed, May 11, 2011 at 7:30 AM, Milton Miller [off-list ref] wrote:
The msi platform device driver was abusing dev.platform_data for its
platform_driver_data. =A0Use the correct pointer for storage.
Platform_data is supposed to be for platforms to communicate to drivers
parameters that are not otherwise discoverable. =A0Its lifetime matches
the platform_device not the platform device driver. =A0It is generally
not needed for drivers that only support systems with device trees.
Signed-off-by: Milton Miller <redacted>
From: Grant Likely <hidden> Date: 2011-05-11 19:07:54
On Wed, May 11, 2011 at 7:30 AM, Milton Miller [off-list ref] wrote:
As NO_IRQ_IGNORE is only used between the static function cpld_pic_get_ir=
q
and its caller cpld_pic_cascade, and cpld_pic_cascade only uses it to
suppress calling handle_generic_irq, we can change these uses to NO_IRQ
and remove the extra tests and pathlength in cpld_pic_cascade.
Signed-off-by: Milton Miller <redacted>
From: Grant Likely <hidden> Date: 2011-05-11 19:08:40
On Wed, May 11, 2011 at 7:30 AM, Milton Miller [off-list ref] wrote:
If none of irq category bits were set mpc52xx_get_irq() would pass
NO_IRQ_IGNORE (-1) to irq_linear_revmap, which does an unsigned compare
and declares the interrupt above the linear map range. =A0It then punts
to irq_find_mapping, which performs a linear search of all irqs,
which will likely miss and only then return NO_IRQ.
If no status bit is set, then we should return NO_IRQ directly.
The interrupt should not be suppressed from spurious counting, in fact
that is the definition of supurious.
Signed-off-by: Milton Miller <redacted>
From: Grant Likely <hidden> Date: 2011-05-11 19:14:29
On Wed, May 11, 2011 at 7:30 AM, Milton Miller [off-list ref] wrote:
Building on Grant's efforts to remove the irq_map array, this patch
moves spider-pics use of virq_to_host() to use irq_data_get_chip_data
and sets the irq chip data in the map call, like most other interrupt
controllers in powerpc.
From: Grant Likely <hidden> Date: 2011-05-11 19:16:57
On Wed, May 11, 2011 at 7:30 AM, Milton Miller [off-list ref] wrote:
Some irq_host implementations are using virq_to_host to check if
they are the irq_host for a virtual irq. =A0To allow us to make space
versus time tradeoffs, replace this usage with an assertive
virq_is_host that confirms or denies the irq is associated with the
given irq_host.
Signed-off-by: Milton Miller <redacted>
From: Grant Likely <hidden> Date: 2011-05-11 19:18:33
On Wed, May 11, 2011 at 7:30 AM, Milton Miller [off-list ref] wrote:
When allocating irqs, wait to clear the IRQ_NOREQUEST flag until the
host map hook has been called.
When freeing irqs, set the IRQ_NOREQUEST flag before calling the host
unmap hook.
A description describing why this change is being made would be
appreciated here.
g.
From: Grant Likely <hidden> Date: 2011-05-11 19:40:50
On Wed, May 11, 2011 at 7:43 AM, Milton Miller [off-list ref] wrote:
[...]
After doing a bunch of grep's on arch/sh, I think the interesting
parts of super8 interrupt handling that Thomas referred to are in
drivers/sh/intc. =A0For some reason they populate the radix tree first
with a descriptor of their common interrupt controler abstraction
then walk the tree, replacing the tagged elements with the pointer
to their equivalent to irq_map. =A0I do not yet understand the purpose
of this two phase allocation.
BTW, you can also write a patch now that eliminates irq_map entirely.
I just talked to tglx today and we agree in principle to move the
hwirq value and irq_domain pointer directly into irq_data (and hence
directly accessible from the irq_desc). The final form of irq_domain
is still up in the air, but you could do an initial patch that leaves
it as platform defined, and it can be followed up with a patch series
that creates a common irq_domain definition.
g.
From: Milton Miller <hidden> Date: 2011-05-12 08:31:59
On Wed, 11 May 2011 about 21:18:11 +0200, Grant Likely wrote:
On Wed, May 11, 2011 at 7:30 AM, Milton Miller [off-list ref] wrote:
quoted
When allocating irqs, wait to clear the IRQ_NOREQUEST flag until the
host map hook has been called.
When freeing irqs, set the IRQ_NOREQUEST flag before calling the host
unmap hook.
A description describing why this change is being made would be
appreciated here.
g.
You are right. #insert <late addition to series but made cut>
When creating an irq, don't allow a concurent driver request until
we have caled map, which will likley call set_chip_and_handler to
change the irq_chip and its operations.
Similarly, when tearing down an IRQ, make sure no new uses come
along while we change the irq back to the nop chip and then reset
the descriptor to freed status.
If this is acceptable I'll let Ben update the changelog unless
he asks me to resend.
milton
@@ -586,14 +586,14 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,irq_map[i].host=host;smp_wmb();-/* Clear norequest flags */-irq_clear_status_flags(i,IRQ_NOREQUEST);-/* Legacy flags are left to default at this point,*onecanthenuseirq_create_mapping()to*explicitlychangethem*/ops->map(host,i,i);++/* Clear norequest flags */+irq_clear_status_flags(i,IRQ_NOREQUEST);}break;caseIRQ_HOST_MAP_LINEAR:
@@ -664,8 +664,6 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,gotoerror;}-irq_clear_status_flags(virq,IRQ_NOREQUEST);-/* map it */smp_wmb();irq_map[virq].hwirq=hwirq;
@@ -676,6 +674,8 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,gotoerrdesc;}+irq_clear_status_flags(virq,IRQ_NOREQUEST);+return0;
errdesc:
@@ -819,6 +819,8 @@ void irq_dispose_mapping(unsigned int virq) if (host->revmap_type == IRQ_HOST_MAP_LEGACY) return;+ irq_set_status_flags(virq, IRQ_NOREQUEST);+ /* remove chip and handler */ irq_set_chip_and_handler(virq, NULL, NULL);
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-05-19 06:57:09
On Wed, 2011-05-11 at 00:29 -0500, Milton Miller wrote:
Consolidate the mux and demux of ipi messages into smp.c and call
a new smp_ops callback to actually trigger the ipi.
.../...
I'm merging the whole series. I had to do some fixups to this one and
the one adding the CONFIG option, missing cell & wsp bits among others,
but mostly trivial.
Cheers,
Ben.
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2011-05-19 06:58:49
On Thu, 2011-05-19 at 16:57 +1000, Benjamin Herrenschmidt wrote:
On Wed, 2011-05-11 at 00:29 -0500, Milton Miller wrote:
quoted
Consolidate the mux and demux of ipi messages into smp.c and call
a new smp_ops callback to actually trigger the ipi.
.../...
I'm merging the whole series. I had to do some fixups to this one and
the one adding the CONFIG option, missing cell & wsp bits among others,
but mostly trivial.
I forgot to mention... I dropped the change to include/linux/smp.h to
remove the unused MSG_ flags for now. It will not have been in -next
long enough to hit Linus via my tree, just in case somebody started
using the flags while we were not looking :-)
I suggest you send it to Linus directly after he pulls my tree during
the merge window.
Cheers,
Ben.