Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758252AbZKYCPI (ORCPT ); Tue, 24 Nov 2009 21:15:08 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1758229AbZKYCPH (ORCPT ); Tue, 24 Nov 2009 21:15:07 -0500 Received: from ozlabs.org ([203.10.76.45]:35167 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758228AbZKYCPF (ORCPT ); Tue, 24 Nov 2009 21:15:05 -0500 From: Michael Neuling To: Nathan Fontenot cc: linuxppc-dev@ozlabs.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH 1/3] Kernel DLPAR infrastructure In-reply-to: <4B0C8CE3.4010207@austin.ibm.com> References: <4B0C8B45.6080804@austin.ibm.com> <4B0C8CE3.4010207@austin.ibm.com> Comments: In-reply-to Nathan Fontenot message dated "Tue, 24 Nov 2009 19:48:19 -0600." X-Mailer: MH-E 8.2; nmh 1.3; GNU Emacs 23.1.1 Date: Wed, 25 Nov 2009 13:15:10 +1100 Message-ID: <31581.1259115310@neuling.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 11233 Lines: 413 In message <4B0C8CE3.4010207@austin.ibm.com> you wrote: > This patch provides the kernel DLPAR infrastructure in a new filed named > dlpar.c. The functionality provided is for acquiring and releasing a resourc e > from firmware and the parsing of information returned from the > ibm,configure-connector rtas call. Additionally this exports the pSeries > reconfiguration notifier chain so that it can be invoked when device tree > updates are made. > > Signed-off-by: Nathan Fontenot These look like they got white space munged somewhere... Mikey > --- > > --- > arch/powerpc/include/asm/pSeries_reconfig.h | 1 > arch/powerpc/platforms/pseries/Makefile | 2 > arch/powerpc/platforms/pseries/dlpar.c | 324 +++++++++++++++++++++++++ +++ > arch/powerpc/platforms/pseries/reconfig.c | 2 > 4 files changed, 327 insertions(+), 2 deletions(-) > > Index: powerpc/arch/powerpc/platforms/pseries/dlpar.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ powerpc/arch/powerpc/platforms/pseries/dlpar.c 2009-11-24 23:31:28.000 000000 -0600 > @@ -0,0 +1,324 @@ > +/* > + * Support for dynamic reconfiguration for PCI, Memory, and CPU > + * Hotplug and Dynamic Logical Partitioning on RPA 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. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +struct cc_workarea { > + u32 drc_index; > + u32 zero; > + u32 name_offset; > + u32 prop_length; > + u32 prop_offset; > +}; > + > +static void dlpar_free_cc_property(struct property *prop) > +{ > + kfree(prop->name); > + kfree(prop->value); > + kfree(prop); > +} > + > +static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) > +{ > + struct property *prop; > + char *name; > + char *value; > + > + prop = kzalloc(sizeof(*prop), GFP_KERNEL); > + if (!prop) > + return NULL; > + > + name = (char *)ccwa + ccwa->name_offset; > + prop->name = kstrdup(name, GFP_KERNEL); > + > + prop->length = ccwa->prop_length; > + value = (char *)ccwa + ccwa->prop_offset; > + prop->value = kzalloc(prop->length, GFP_KERNEL); > + if (!prop->value) { > + dlpar_free_cc_property(prop); > + return NULL; > + } > + > + memcpy(prop->value, value, prop->length); > + return prop; > +} > + > +static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa) > +{ > + struct device_node *dn; > + char *name; > + > + dn = kzalloc(sizeof(*dn), GFP_KERNEL); > + if (!dn) > + return NULL; > + > + name = (char *)ccwa + ccwa->name_offset; > + dn->full_name = kstrdup(name, GFP_KERNEL); > + > + return dn; > +} > + > +static void dlpar_free_one_cc_node(struct device_node *dn) > +{ > + struct property *prop; > + > + while (dn->properties) { > + prop = dn->properties; > + dn->properties = prop->next; > + dlpar_free_cc_property(prop); > + } > + > + kfree(dn->full_name); > + kfree(dn); > +} > + > +static void dlpar_free_cc_nodes(struct device_node *dn) > +{ > + if (dn->child) > + dlpar_free_cc_nodes(dn->child); > + > + if (dn->sibling) > + dlpar_free_cc_nodes(dn->sibling); > + > + dlpar_free_one_cc_node(dn); > +} > + > +#define NEXT_SIBLING 1 > +#define NEXT_CHILD 2 > +#define NEXT_PROPERTY 3 > +#define PREV_PARENT 4 > +#define MORE_MEMORY 5 > +#define CALL_AGAIN -2 > +#define ERR_CFG_USE -9003 > + > +struct device_node *dlpar_configure_connector(u32 drc_index) > +{ > + struct device_node *dn; > + struct device_node *first_dn = NULL; > + struct device_node *last_dn = NULL; > + struct property *property; > + struct property *last_property = NULL; > + struct cc_workarea *ccwa; > + int cc_token; > + int rc; > + > + cc_token = rtas_token("ibm,configure-connector"); > + if (cc_token == RTAS_UNKNOWN_SERVICE) > + return NULL; > + > + spin_lock(&rtas_data_buf_lock); > + ccwa = (struct cc_workarea *)&rtas_data_buf[0]; > + ccwa->drc_index = drc_index; > + ccwa->zero = 0; > + > + rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); > + while (rc) { > + switch (rc) { > + case NEXT_SIBLING: > + dn = dlpar_parse_cc_node(ccwa); > + if (!dn) > + goto cc_error; > + > + dn->parent = last_dn->parent; > + last_dn->sibling = dn; > + last_dn = dn; > + break; > + > + case NEXT_CHILD: > + dn = dlpar_parse_cc_node(ccwa); > + if (!dn) > + goto cc_error; > + > + if (!first_dn) > + first_dn = dn; > + else { > + dn->parent = last_dn; > + if (last_dn) > + last_dn->child = dn; > + } > + > + last_dn = dn; > + break; > + > + case NEXT_PROPERTY: > + property = dlpar_parse_cc_property(ccwa); > + if (!property) > + goto cc_error; > + > + if (!last_dn->properties) > + last_dn->properties = property; > + else > + last_property->next = property; > + > + last_property = property; > + break; > + > + case PREV_PARENT: > + last_dn = last_dn->parent; > + break; > + > + case CALL_AGAIN: > + break; > + > + case MORE_MEMORY: > + case ERR_CFG_USE: > + default: > + printk(KERN_ERR "Unexpected Error (%d) " > + "returned from configure-connector\n", rc); > + goto cc_error; > + } > + > + rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); > + } > + > + spin_unlock(&rtas_data_buf_lock); > + return first_dn; > + > +cc_error: > + if (first_dn) > + dlpar_free_cc_nodes(first_dn); > + spin_unlock(&rtas_data_buf_lock); > + return NULL; > +} > + > +static struct device_node *derive_parent(const char *path) > +{ > + struct device_node *parent; > + char parent_path[128]; > + int parent_path_len; > + > + parent_path_len = strrchr(path, '/') - path + 1; > + strlcpy(parent_path, path, parent_path_len); > + > + parent = of_find_node_by_path(parent_path); > + > + return parent; > +} > + > +int dlpar_attach_node(struct device_node *dn) > +{ > + struct proc_dir_entry *ent; > + int rc; > + > + of_node_set_flag(dn, OF_DYNAMIC); > + kref_init(&dn->kref); > + dn->parent = derive_parent(dn->full_name); > + > + rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, > + PSERIES_RECONFIG_ADD, dn); > + if (rc == NOTIFY_BAD) { > + printk(KERN_ERR "Failed to add device node %s\n", > + dn->full_name); > + return -ENOMEM; /* For now, safe to assume kmalloc failure */ > + } > + > + of_attach_node(dn); > + > +#ifdef CONFIG_PROC_DEVICETREE > + ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); > + if (ent) > + proc_device_tree_add_node(dn, ent); > +#endif > + > + of_node_put(dn->parent); > + return 0; > +} > + > +int dlpar_detach_node(struct device_node *dn) > +{ > + struct device_node *parent = dn->parent; > + struct property *prop = dn->properties; > + > +#ifdef CONFIG_PROC_DEVICETREE > + while (prop) { > + remove_proc_entry(prop->name, dn->pde); > + prop = prop->next; > + } > + > + if (dn->pde) > + remove_proc_entry(dn->pde->name, parent->pde); > +#endif > + > + blocking_notifier_call_chain(&pSeries_reconfig_chain, > + PSERIES_RECONFIG_REMOVE, dn); > + of_detach_node(dn); > + of_node_put(dn); /* Must decrement the refcount */ > + > + return 0; > +} > + > +#define DR_ENTITY_SENSE 9003 > +#define DR_ENTITY_PRESENT 1 > +#define DR_ENTITY_UNUSABLE 2 > +#define ALLOCATION_STATE 9003 > +#define ALLOC_UNUSABLE 0 > +#define ALLOC_USABLE 1 > +#define ISOLATION_STATE 9001 > +#define ISOLATE 0 > +#define UNISOLATE 1 > + > +int dlpar_acquire_drc(u32 drc_index) > +{ > + int dr_status, rc; > + > + rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status, > + DR_ENTITY_SENSE, drc_index); > + if (rc || dr_status != DR_ENTITY_UNUSABLE) > + return -1; > + > + rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_USABLE); > + if (rc) > + return rc; > + > + rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); > + if (rc) { > + rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE) ; > + return rc; > + } > + > + return 0; > +} > + > +int dlpar_release_drc(u32 drc_index) > +{ > + int dr_status, rc; > + > + rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status, > + DR_ENTITY_SENSE, drc_index); > + if (rc || dr_status != DR_ENTITY_PRESENT) > + return -1; > + > + rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE); > + if (rc) > + return rc; > + > + rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE); > + if (rc) { > + rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); > + return rc; > + } > + > + return 0; > +} > + > + > Index: powerpc/arch/powerpc/platforms/pseries/Makefile > =================================================================== > --- powerpc.orig/arch/powerpc/platforms/pseries/Makefile 2009-11-20 17:5 3:54.000000000 -0600 > +++ powerpc/arch/powerpc/platforms/pseries/Makefile 2009-11-20 17:55:52.000 000000 -0600 > @@ -8,7 +8,7 @@ > > obj-y := lpar.o hvCall.o nvram.o reconfig.o \ > setup.o iommu.o ras.o rtasd.o \ > - firmware.o power.o > + firmware.o power.o dlpar.o > obj-$(CONFIG_SMP) += smp.o > obj-$(CONFIG_XICS) += xics.o > obj-$(CONFIG_SCANLOG) += scanlog.o > Index: powerpc/arch/powerpc/include/asm/pSeries_reconfig.h > =================================================================== > --- powerpc.orig/arch/powerpc/include/asm/pSeries_reconfig.h 2009-11-20 17:5 3:54.000000000 -0600 > +++ powerpc/arch/powerpc/include/asm/pSeries_reconfig.h 2009-11-20 17:5 5:52.000000000 -0600 > @@ -17,6 +17,7 @@ > #ifdef CONFIG_PPC_PSERIES > extern int pSeries_reconfig_notifier_register(struct notifier_block *); > extern void pSeries_reconfig_notifier_unregister(struct notifier_block *); > +extern struct blocking_notifier_head pSeries_reconfig_chain; > #else /* !CONFIG_PPC_PSERIES */ > static inline int pSeries_reconfig_notifier_register(struct notifier_block * nb) > { > Index: powerpc/arch/powerpc/platforms/pseries/reconfig.c > =================================================================== > --- powerpc.orig/arch/powerpc/platforms/pseries/reconfig.c 2009-11-20 17:5 3:54.000000000 -0600 > +++ powerpc/arch/powerpc/platforms/pseries/reconfig.c 2009-11-20 17:55:52.000 000000 -0600 > @@ -96,7 +96,7 @@ > return parent; > } > > -static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); > +BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); > > int pSeries_reconfig_notifier_register(struct notifier_block *nb) > { > _______________________________________________ > Linuxppc-dev mailing list > Linuxppc-dev@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/linuxppc-dev > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/