From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from e28smtp01.in.ibm.com (e28smtp01.in.ibm.com [122.248.162.1]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "e28smtp01.in.ibm.com", Issuer "GeoTrust SSL CA" (not verified)) by ozlabs.org (Postfix) with ESMTPS id B98962C00AF for ; Thu, 25 Jul 2013 04:46:01 +1000 (EST) Received: from /spool/local by e28smtp01.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 25 Jul 2013 00:07:57 +0530 Received: from d28relay05.in.ibm.com (d28relay05.in.ibm.com [9.184.220.62]) by d28dlp02.in.ibm.com (Postfix) with ESMTP id C81C83940058 for ; Thu, 25 Jul 2013 00:15:46 +0530 (IST) Received: from d28av04.in.ibm.com (d28av04.in.ibm.com [9.184.220.66]) by d28relay05.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r6OIjm8725165948 for ; Thu, 25 Jul 2013 00:15:48 +0530 Received: from d28av04.in.ibm.com (loopback [127.0.0.1]) by d28av04.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r6OIjpXb007492 for ; Thu, 25 Jul 2013 04:45:51 +1000 Message-ID: <51F020DB.3090909@linux.vnet.ibm.com> Date: Wed, 24 Jul 2013 13:45:47 -0500 From: Nathan Fontenot MIME-Version: 1.0 To: LKML , linux-mm , linuxppc-dev@lists.ozlabs.org Subject: [PATCH 7/8] Add memory hot add/remove notifier handlers for pwoerpc References: <51F01E06.6090800@linux.vnet.ibm.com> In-Reply-To: <51F01E06.6090800@linux.vnet.ibm.com> Content-Type: text/plain; charset=ISO-8859-1 Cc: Greg Kroah-Hartman List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Add memory hot add/remove notifier handlers for powerpc/pseries. This patch allows the powerpc/pseries platforms to perform memory DLPAR int the kernel. The handlers for add and remove do the work of acquiring/releasing the memory to firmware and updating the device tree. This is only used when memory is specified in the ibm,dynamic-reconfiguration-memory device tree node so the memory notifiers are registered contingent on its existence. Signed-off-by: Nathan Fontenot --- arch/powerpc/platforms/pseries/dlpar.c | 103 +++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) Index: linux/arch/powerpc/platforms/pseries/dlpar.c =================================================================== --- linux.orig/arch/powerpc/platforms/pseries/dlpar.c +++ linux/arch/powerpc/platforms/pseries/dlpar.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include "offline_states.h" @@ -531,11 +532,113 @@ out: return rc ? rc : count; } +static struct of_drconf_cell *dlpar_get_drconf_cell(struct device_node *dn, + unsigned long phys_addr) +{ + struct of_drconf_cell *drmem; + u32 entries; + u32 *prop; + int i; + + prop = (u32 *)of_get_property(dn, "ibm,dynamic-memory", NULL); + of_node_put(dn); + if (!prop) + return NULL; + + entries = *prop++; + drmem = (struct of_drconf_cell *)prop; + + for (i = 0; i < entries; i++) { + if (drmem[i].base_addr == phys_addr) + return &drmem[i]; + } + + return NULL; +} + +static int dlpar_mem_probe(unsigned long phys_addr) +{ + struct device_node *dn; + struct of_drconf_cell *drmem; + int rc; + + dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); + if (!dn) + return -EINVAL; + + drmem = dlpar_get_drconf_cell(dn, phys_addr); + of_node_put(dn); + + if (!drmem) + return -EINVAL; + + if (drmem->flags & DRCONF_MEM_ASSIGNED) + return 0; + + drmem->flags |= DRCONF_MEM_ASSIGNED; + + rc = dlpar_acquire_drc(drmem->drc_index); + return rc; +} + +static int dlpar_mem_release(unsigned long phys_addr) +{ + struct device_node *dn; + struct of_drconf_cell *drmem; + int rc; + + dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); + if (!dn) + return -EINVAL; + + drmem = dlpar_get_drconf_cell(dn, phys_addr); + of_node_put(dn); + + if (!drmem) + return -EINVAL; + + if (!drmem->flags & DRCONF_MEM_ASSIGNED) + return 0; + + drmem->flags &= ~DRCONF_MEM_ASSIGNED; + + rc = dlpar_release_drc(drmem->drc_index); + return rc; +} + +static int pseries_dlpar_mem_callback(struct notifier_block *nb, + unsigned long action, void *hp_arg) +{ + struct memory_notify *arg = hp_arg; + unsigned long phys_addr = arg->start_pfn << PAGE_SHIFT; + int rc = 0; + + + switch (action) { + case MEM_BEING_HOT_ADDED: + rc = dlpar_mem_probe(phys_addr); + break; + case MEM_HOT_REMOVED: + rc = dlpar_mem_release(phys_addr); + break; + } + + return notifier_from_errno(rc); +} + static int __init pseries_dlpar_init(void) { + struct device_node *dn; + ppc_md.cpu_probe = dlpar_cpu_probe; ppc_md.cpu_release = dlpar_cpu_release; + dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); + if (dn) { + hotplug_memory_notifier(pseries_dlpar_mem_callback, 0); + of_node_put(dn); + } + return 0; } machine_device_initcall(pseries, pseries_dlpar_init);