From: Nathan F. <nf...@au...> - 2009-09-15 19:06:49
|
This patch enables drmgr to do DLPAR operations for memory on systems that can do the acquisition via rtas and device tree updating in the kernel. NOTE: This patch depends on the DLPAR infrastructure patch set posted to linuxppc-dev. Signed-off-by: Nathan Fontenot <nf...@au...> --- Index: powerpc-utils/src/drmgr/drmem.h =================================================================== --- powerpc-utils.orig/src/drmgr/drmem.h 2009-09-15 13:30:26.000000000 -0500 +++ powerpc-utils/src/drmgr/drmem.h 2009-09-15 13:37:40.000000000 -0500 @@ -19,6 +19,7 @@ #define DRMEM_DRC_INVALID 0x00000020 #define MEM_PROBE_FILE "/sys/devices/system/memory/probe" +#define MEM_RELEASE_FILE "/sys/devices/system/memory/release" #define MEM_BLOCK_SIZE_BYTES "/sys/devices/system/memory/block_size_bytes" #define DYNAMIC_RECONFIG_MEM "/proc/device-tree/ibm,dynamic-reconfiguration-memory" Index: powerpc-utils/src/drmgr/drslot_chrp_mem.c =================================================================== --- powerpc-utils.orig/src/drmgr/drslot_chrp_mem.c 2009-09-15 13:30:26.000000000 -0500 +++ powerpc-utils/src/drmgr/drslot_chrp_mem.c 2009-09-15 13:39:32.000000000 -0500 @@ -35,6 +35,16 @@ *pusage = usagestr; } +static int +is_kernel_dlpar_capable(void) +{ + struct stat sbuf; + int rc; + + rc = stat(MEM_RELEASE_FILE, &sbuf); + return !rc; +} + /** * get_phandle * @@ -302,13 +312,13 @@ if (drmem->flags & DRMEM_ASSIGNED) { found++; lmb->is_owned = 1; - - /* find the associated sysfs memory blocks */ - rc = get_mem_scns(lmb); - if (rc) - break; } + /* find the associated sysfs memory blocks */ + rc = get_mem_scns(lmb); + if (rc) + break; + drmem++; /* trust your compiler */ } @@ -756,6 +766,34 @@ return 0; } +static int +release_lmb(struct dr_node *lmb) +{ + char buf[DR_STR_MAX]; + int release_file; + int write_len; + int rc; + + release_file = open(MEM_RELEASE_FILE, O_WRONLY); + if (release_file <= 0) { + dbg("Could not open %s to release lmb\n", MEM_RELEASE_FILE); + return errno; + } + + memset(buf, 0, DR_STR_MAX); + write_len = sprintf(buf, "0x%x", lmb->drc_index); + rc = write(release_file, buf, write_len); + if (rc != write_len) + dbg("Write to %s failed!\n%s\n", MEM_RELEASE_FILE, + strerror(errno)); + else + /* reset rc to success */ + rc = 0; + + close(release_file); + return rc; +} + /** * set_lmb_state * @@ -818,6 +856,7 @@ { int rc = 0; struct dr_node *lmb; + int kernel_dlpar_capable = is_kernel_dlpar_capable(); lmb_list->lmbs_modified = 0; while (lmb_list->lmbs_modified < (int)opts->quantity) { @@ -825,23 +864,28 @@ if (lmb == NULL) return -1; - rc = acquire_drc(lmb->drc_index); - if (rc) { - lmb->unusable = 1; - continue; - } + if (!kernel_dlpar_capable) { + rc = acquire_drc(lmb->drc_index); + if (rc) { + lmb->unusable = 1; + continue; + } - rc = add_device_tree_lmb(lmb, lmb_list); - if (rc) { - release_drc(lmb->drc_index, MEM_DEV); - lmb->unusable = 1; - continue; + rc = add_device_tree_lmb(lmb, lmb_list); + if (rc) { + release_drc(lmb->drc_index, MEM_DEV); + lmb->unusable = 1; + continue; + } } rc = set_lmb_state(lmb, ONLINE); if (rc) { - remove_device_tree_lmb(lmb, lmb_list); - release_drc(lmb->drc_index, MEM_DEV); + if (!kernel_dlpar_capable) { + remove_device_tree_lmb(lmb, lmb_list); + release_drc(lmb->drc_index, MEM_DEV); + } + lmb->unusable = 1; continue; } @@ -893,6 +937,7 @@ { struct dr_node *lmb; int rc; + int kernel_dlpar_capable = is_kernel_dlpar_capable(); while (lmb_list->lmbs_modified < (int)opts->quantity) { lmb = get_available_lmb(opts, lmb_list); @@ -905,25 +950,33 @@ continue; } - rc = remove_device_tree_lmb(lmb, lmb_list); - if (rc) { - set_lmb_state(lmb, ONLINE); - lmb->unusable = 1; - continue; - } + if (kernel_dlpar_capable) { + rc = release_lmb(lmb); + if (rc) { + lmb->unusable = 1; + continue; + } + } else { + rc = remove_device_tree_lmb(lmb, lmb_list); + if (rc) { + set_lmb_state(lmb, ONLINE); + lmb->unusable = 1; + continue; + } - while (lmb->lmb_mem_scns) { - struct mem_scn *scn = lmb->lmb_mem_scns; - lmb->lmb_mem_scns = scn->next; - free(scn); - } + while (lmb->lmb_mem_scns) { + struct mem_scn *scn = lmb->lmb_mem_scns; + lmb->lmb_mem_scns = scn->next; + free(scn); + } - rc = release_drc(lmb->drc_index, 0); - if (rc) { - add_device_tree_lmb(lmb, lmb_list); - set_lmb_state(lmb, ONLINE); - lmb->unusable = 1; - continue; + rc = release_drc(lmb->drc_index, 0); + if (rc) { + add_device_tree_lmb(lmb, lmb_list); + set_lmb_state(lmb, ONLINE); + lmb->unusable = 1; + continue; + } } lmb->is_removable = 0; |