Commit 4af52c23 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ia64 cpu hotplug: /proc rework

From: Ashok Raj <ashok.raj@intel.com>

Changes proc entries for cpu hotplug to be created via the cpu hotplug
notifier callbacks.  Also fixed a bug in the removal code that did not remove
proc entries as expected.
parent f53c027a
......@@ -8,11 +8,14 @@
*
* Copyright (C) 2000-2001, 2003 Hewlett-Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2004 Intel Corporation
* Ashok Raj <ashok.raj@intel.com>
*
* 05/26/2000 S.Eranian initial release
* 08/21/2000 S.Eranian updated to July 2000 PAL specs
* 02/05/2001 S.Eranian fixed module support
* 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes
* 03/24/2004 Ashok Raj updated to work with CPU Hotplug
*/
#include <linux/config.h>
#include <linux/types.h>
......@@ -22,6 +25,9 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/efi.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <asm/pal.h>
#include <asm/sal.h>
......@@ -768,13 +774,12 @@ static palinfo_entry_t palinfo_entries[]={
* does not do recursion of deletion
*
* Notes:
* - first +1 accounts for the cpuN entry
* - second +1 account for toplevel palinfo
*
* - +1 accounts for the cpuN directory entry in /proc/pal
*/
#define NR_PALINFO_PROC_ENTRIES (NR_CPUS*(NR_PALINFO_ENTRIES+1)+1)
#define NR_PALINFO_PROC_ENTRIES (NR_CPUS*(NR_PALINFO_ENTRIES+1))
static struct proc_dir_entry *palinfo_proc_entries[NR_PALINFO_PROC_ENTRIES];
static struct proc_dir_entry *palinfo_dir;
/*
* This data structure is used to pass which cpu,function is being requested
......@@ -888,35 +893,35 @@ palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, voi
return len;
}
static int __init
palinfo_init(void)
static void
create_palinfo_proc_entries(unsigned int cpu)
{
# define CPUSTR "cpu%d"
pal_func_cpu_u_t f;
struct proc_dir_entry **pdir = palinfo_proc_entries;
struct proc_dir_entry *palinfo_dir, *cpu_dir;
int i, j;
struct proc_dir_entry **pdir;
struct proc_dir_entry *cpu_dir;
int j;
char cpustr[sizeof(CPUSTR)];
printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
palinfo_dir = proc_mkdir("pal", NULL);
/*
* we keep track of created entries in a depth-first order for
* cleanup purposes. Each entry is stored into palinfo_proc_entries
*/
for (i=0; i < NR_CPUS; i++) {
if (!cpu_online(i)) continue;
sprintf(cpustr,CPUSTR, i);
sprintf(cpustr,CPUSTR, cpu);
cpu_dir = proc_mkdir(cpustr, palinfo_dir);
f.req_cpu = i;
f.req_cpu = cpu;
/*
* Compute the location to store per cpu entries
* We dont store the top level entry in this list, but
* remove it finally after removing all cpu entries.
*/
pdir = &palinfo_proc_entries[cpu*(NR_PALINFO_ENTRIES+1)];
*pdir++ = cpu_dir;
for (j=0; j < NR_PALINFO_ENTRIES; j++) {
f.func_id = j;
*pdir = create_proc_read_entry(
......@@ -926,9 +931,69 @@ palinfo_init(void)
(*pdir)->owner = THIS_MODULE;
pdir++;
}
*pdir++ = cpu_dir;
}
static void
remove_palinfo_proc_entries(unsigned int hcpu)
{
int j;
struct proc_dir_entry *cpu_dir, **pdir;
pdir = &palinfo_proc_entries[hcpu*(NR_PALINFO_ENTRIES+1)];
cpu_dir = *pdir;
*pdir++=NULL;
for (j=0; j < (NR_PALINFO_ENTRIES); j++) {
if ((*pdir)) {
remove_proc_entry ((*pdir)->name, cpu_dir);
*pdir ++= NULL;
}
}
if (cpu_dir) {
remove_proc_entry(cpu_dir->name, palinfo_dir);
}
}
static int __devinit palinfo_cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
unsigned int hotcpu = (unsigned long)hcpu;
switch (action) {
case CPU_ONLINE:
create_palinfo_proc_entries(hotcpu);
break;
#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
remove_palinfo_proc_entries(hotcpu);
break;
#endif
}
return NOTIFY_OK;
}
static struct notifier_block palinfo_cpu_notifier =
{
.notifier_call = palinfo_cpu_callback,
.priority = 0,
};
static int __init
palinfo_init(void)
{
int i = 0;
printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
palinfo_dir = proc_mkdir("pal", NULL);
/* Create palinfo dirs in /proc for all online cpus */
for_each_online_cpu(i) {
create_palinfo_proc_entries(i);
}
*pdir = palinfo_dir;
/* Register for future delivery via notify registration */
register_cpu_notifier(&palinfo_cpu_notifier);
return 0;
}
......@@ -939,10 +1004,19 @@ palinfo_exit(void)
int i = 0;
/* remove all nodes: depth first pass. Could optimize this */
for (i=0; i< NR_PALINFO_PROC_ENTRIES ; i++) {
if (palinfo_proc_entries[i])
remove_proc_entry (palinfo_proc_entries[i]->name, NULL);
for_each_online_cpu(i) {
remove_palinfo_proc_entries(i);
}
/*
* Remove the top level entry finally
*/
remove_proc_entry(palinfo_dir->name, NULL);
/*
* Unregister from cpu notifier callbacks
*/
unregister_cpu_notifier(&palinfo_cpu_notifier);
}
module_init(palinfo_init);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment