Skip to content

Commit

Permalink
powerpc+of: Add of node/property notification chain for adds and removes
Browse files Browse the repository at this point in the history
This patch moves the notification chain for updates to the device tree
from the powerpc/pseries code to the base OF code. This makes this
functionality available to all architectures.

Additionally the notification chain is updated to allow notifications
for property add/remove/update. To make this work a pointer to a new
struct (of_prop_reconfig) is passed to the routines in the notification chain.
The of_prop_reconfig property contains a pointer to the node containing the
property and a pointer to the property itself. In the case of property
updates, the property pointer refers to the new property.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Acked-by: Rob Herring <rob.herring@calxeda.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Nathan Fontenot authored and Benjamin Herrenschmidt committed Nov 15, 2012
1 parent f594972 commit 1cf3d8b
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 154 deletions.
32 changes: 0 additions & 32 deletions arch/powerpc/include/asm/pSeries_reconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,11 @@
#define _PPC64_PSERIES_RECONFIG_H
#ifdef __KERNEL__

#include <linux/notifier.h>

/*
* Use this API if your code needs to know about OF device nodes being
* added or removed on pSeries systems.
*/

#define PSERIES_RECONFIG_ADD 0x0001
#define PSERIES_RECONFIG_REMOVE 0x0002
#define PSERIES_DRCONF_MEM_ADD 0x0003
#define PSERIES_DRCONF_MEM_REMOVE 0x0004
#define PSERIES_UPDATE_PROPERTY 0x0005

/**
* pSeries_reconfig_notify - Notifier value structure for OFDT property updates
*
* @node: Device tree node which owns the property being updated
* @property: Updated property
*/
struct pSeries_reconfig_prop_update {
struct device_node *node;
struct property *property;
};

#ifdef CONFIG_PPC_PSERIES
extern int pSeries_reconfig_notifier_register(struct notifier_block *);
extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
extern int pSeries_reconfig_notify(unsigned long action, void *p);
/* Not the best place to put this, will be fixed when we move some
* of the rtas suspend-me stuff to pseries */
extern void pSeries_coalesce_init(void);
#else /* !CONFIG_PPC_PSERIES */
static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
return 0;
}
static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
static inline void pSeries_coalesce_init(void) { }
#endif /* CONFIG_PPC_PSERIES */

Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <linux/debugfs.h>
#include <linux/irq.h>
#include <linux/memblock.h>
#include <linux/of.h>

#include <asm/prom.h>
#include <asm/rtas.h>
Expand All @@ -49,7 +50,6 @@
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h>
#include <asm/kexec.h>
#include <asm/opal.h>
Expand Down Expand Up @@ -802,7 +802,7 @@ static int prom_reconfig_notifier(struct notifier_block *nb,
int err;

switch (action) {
case PSERIES_RECONFIG_ADD:
case OF_RECONFIG_ATTACH_NODE:
err = of_finish_dynamic_node(node);
if (err < 0)
printk(KERN_ERR "finish_node returned %d\n", err);
Expand All @@ -821,7 +821,7 @@ static struct notifier_block prom_reconfig_nb = {

static int __init prom_reconfig_setup(void)
{
return pSeries_reconfig_notifier_register(&prom_reconfig_nb);
return of_reconfig_notifier_register(&prom_reconfig_nb);
}
__initcall(prom_reconfig_setup);
#endif
Expand Down
14 changes: 8 additions & 6 deletions arch/powerpc/platforms/pseries/dlpar.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
#include <linux/spinlock.h>
#include <linux/cpu.h>
#include <linux/slab.h>
#include <linux/of.h>
#include "offline_states.h"

#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
#include <asm/pSeries_reconfig.h>

struct cc_workarea {
u32 drc_index;
Expand Down Expand Up @@ -262,24 +262,26 @@ int dlpar_attach_node(struct device_node *dn)
if (!dn->parent)
return -ENOMEM;

rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn);
rc = of_attach_node(dn);
if (rc) {
printk(KERN_ERR "Failed to add device node %s\n",
dn->full_name);
return rc;
}

of_attach_node(dn);
of_node_put(dn->parent);
return 0;
}

int dlpar_detach_node(struct device_node *dn)
{
pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
of_detach_node(dn);
of_node_put(dn); /* Must decrement the refcount */
int rc;

rc = of_detach_node(dn);
if (rc)
return rc;

of_node_put(dn); /* Must decrement the refcount */
return 0;
}

Expand Down
8 changes: 4 additions & 4 deletions arch/powerpc/platforms/pseries/hotplug-cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
#include <linux/delay.h>
#include <linux/sched.h> /* for idle_task_exit */
#include <linux/cpu.h>
#include <linux/of.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/firmware.h>
#include <asm/machdep.h>
#include <asm/vdso_datapage.h>
#include <asm/pSeries_reconfig.h>
#include <asm/xics.h>
#include "plpar_wrappers.h"
#include "offline_states.h"
Expand Down Expand Up @@ -333,10 +333,10 @@ static int pseries_smp_notifier(struct notifier_block *nb,
int err = 0;

switch (action) {
case PSERIES_RECONFIG_ADD:
case OF_RECONFIG_ATTACH_NODE:
err = pseries_add_processor(node);
break;
case PSERIES_RECONFIG_REMOVE:
case OF_RECONFIG_DETACH_NODE:
pseries_remove_processor(node);
break;
}
Expand Down Expand Up @@ -399,7 +399,7 @@ static int __init pseries_cpu_hotplug_init(void)

/* Processors can be added/removed only on LPAR */
if (firmware_has_feature(FW_FEATURE_LPAR)) {
pSeries_reconfig_notifier_register(&pseries_smp_nb);
of_reconfig_notifier_register(&pseries_smp_nb);
cpu_maps_update_begin();
if (cede_offline_enabled && parse_cede_parameters() == 0) {
default_offline_state = CPU_STATE_INACTIVE;
Expand Down
60 changes: 43 additions & 17 deletions arch/powerpc/platforms/pseries/hotplug-memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#include <asm/firmware.h>
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/sparsemem.h>

static unsigned long get_memblock_size(void)
Expand Down Expand Up @@ -187,42 +186,69 @@ static int pseries_add_memory(struct device_node *np)
return (ret < 0) ? -EINVAL : 0;
}

static int pseries_drconf_memory(unsigned long *base, unsigned int action)
static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
{
struct of_drconf_cell *new_drmem, *old_drmem;
unsigned long memblock_size;
int rc;
u32 entries;
u32 *p;
int i, rc = -EINVAL;

memblock_size = get_memblock_size();
if (!memblock_size)
return -EINVAL;

if (action == PSERIES_DRCONF_MEM_ADD) {
rc = memblock_add(*base, memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
} else if (action == PSERIES_DRCONF_MEM_REMOVE) {
rc = pseries_remove_memblock(*base, memblock_size);
} else {
rc = -EINVAL;
p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL);
if (!p)
return -EINVAL;

/* The first int of the property is the number of lmb's described
* by the property. This is followed by an array of of_drconf_cell
* entries. Get the niumber of entries and skip to the array of
* of_drconf_cell's.
*/
entries = *p++;
old_drmem = (struct of_drconf_cell *)p;

p = (u32 *)pr->prop->value;
p++;
new_drmem = (struct of_drconf_cell *)p;

for (i = 0; i < entries; i++) {
if ((old_drmem[i].flags & DRCONF_MEM_ASSIGNED) &&
(!(new_drmem[i].flags & DRCONF_MEM_ASSIGNED))) {
rc = pseries_remove_memblock(old_drmem[i].base_addr,
memblock_size);
break;
} else if ((!(old_drmem[i].flags & DRCONF_MEM_ASSIGNED)) &&
(new_drmem[i].flags & DRCONF_MEM_ASSIGNED)) {
rc = memblock_add(old_drmem[i].base_addr,
memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
break;
}
}

return rc;
}

static int pseries_memory_notifier(struct notifier_block *nb,
unsigned long action, void *node)
unsigned long action, void *node)
{
struct of_prop_reconfig *pr;
int err = 0;

switch (action) {
case PSERIES_RECONFIG_ADD:
case OF_RECONFIG_ATTACH_NODE:
err = pseries_add_memory(node);
break;
case PSERIES_RECONFIG_REMOVE:
case OF_RECONFIG_DETACH_NODE:
err = pseries_remove_memory(node);
break;
case PSERIES_DRCONF_MEM_ADD:
case PSERIES_DRCONF_MEM_REMOVE:
err = pseries_drconf_memory(node, action);
case OF_RECONFIG_UPDATE_PROPERTY:
pr = (struct of_prop_reconfig *)node;
if (!strcmp(pr->prop->name, "ibm,dynamic-memory"))
err = pseries_update_drconf_memory(pr);
break;
}
return notifier_from_errno(err);
Expand All @@ -235,7 +261,7 @@ static struct notifier_block pseries_mem_nb = {
static int __init pseries_memory_hotplug_init(void)
{
if (firmware_has_feature(FW_FEATURE_LPAR))
pSeries_reconfig_notifier_register(&pseries_mem_nb);
of_reconfig_notifier_register(&pseries_mem_nb);

return 0;
}
Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/platforms/pseries/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@
#include <linux/dma-mapping.h>
#include <linux/crash_dump.h>
#include <linux/memory.h>
#include <linux/of.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/iommu.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/firmware.h>
#include <asm/tce.h>
#include <asm/ppc-pci.h>
Expand Down Expand Up @@ -1294,7 +1294,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
struct direct_window *window;

switch (action) {
case PSERIES_RECONFIG_REMOVE:
case OF_RECONFIG_DETACH_NODE:
if (pci && pci->iommu_table)
iommu_free_table(pci->iommu_table, np->full_name);

Expand Down Expand Up @@ -1357,7 +1357,7 @@ void iommu_init_early_pSeries(void)
}


pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
of_reconfig_notifier_register(&iommu_reconfig_nb);
register_memory_notifier(&iommu_mem_nb);

set_pci_dma_ops(&dma_iommu_ops);
Expand Down
Loading

0 comments on commit 1cf3d8b

Please sign in to comment.