aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/padata.c
diff options
context:
space:
mode:
authorDan Kruchinin <dkruchinin@acm.org>2010-07-14 06:33:08 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2010-07-19 01:50:19 -0400
commit5e017dc3f8bc9e4a28983666e6bc00114a2018bb (patch)
tree4057e6322bc43d5b833b65b5f7372ae57a709fb3 /kernel/padata.c
parente15bacbebb9dcc95f148f28dfc83a6d5e48b60b8 (diff)
padata: Added sysfs primitives to padata subsystem
Added sysfs primitives to padata subsystem. Now API user may embedded kobject each padata instance contains into any sysfs hierarchy. For now padata sysfs interface provides only two objects: serial_cpumask [RW] - cpumask for serial workers parallel_cpumask [RW] - cpumask for parallel workers Signed-off-by: Dan Kruchinin <dkruchinin@acm.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'kernel/padata.c')
-rw-r--r--kernel/padata.c155
1 files changed, 146 insertions, 9 deletions
diff --git a/kernel/padata.c b/kernel/padata.c
index 84d0ca9dac9c..526f9ea2fcc8 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -26,6 +26,7 @@
26#include <linux/mutex.h> 26#include <linux/mutex.h>
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/sysfs.h>
29#include <linux/rcupdate.h> 30#include <linux/rcupdate.h>
30 31
31#define MAX_SEQ_NR (INT_MAX - NR_CPUS) 32#define MAX_SEQ_NR (INT_MAX - NR_CPUS)
@@ -924,6 +925,149 @@ static int padata_cpu_callback(struct notifier_block *nfb,
924} 925}
925#endif 926#endif
926 927
928static void __padata_free(struct padata_instance *pinst)
929{
930#ifdef CONFIG_HOTPLUG_CPU
931 unregister_hotcpu_notifier(&pinst->cpu_notifier);
932#endif
933
934 padata_stop(pinst);
935 padata_free_pd(pinst->pd);
936 free_cpumask_var(pinst->cpumask.pcpu);
937 free_cpumask_var(pinst->cpumask.cbcpu);
938 kfree(pinst);
939}
940
941#define kobj2pinst(_kobj) \
942 container_of(_kobj, struct padata_instance, kobj)
943#define attr2pentry(_attr) \
944 container_of(_attr, struct padata_sysfs_entry, attr)
945
946static void padata_sysfs_release(struct kobject *kobj)
947{
948 struct padata_instance *pinst = kobj2pinst(kobj);
949 __padata_free(pinst);
950}
951
952struct padata_sysfs_entry {
953 struct attribute attr;
954 ssize_t (*show)(struct padata_instance *, struct attribute *, char *);
955 ssize_t (*store)(struct padata_instance *, struct attribute *,
956 const char *, size_t);
957};
958
959static ssize_t show_cpumask(struct padata_instance *pinst,
960 struct attribute *attr, char *buf)
961{
962 struct cpumask *cpumask;
963 ssize_t len;
964
965 mutex_lock(&pinst->lock);
966 if (!strcmp(attr->name, "serial_cpumask"))
967 cpumask = pinst->cpumask.cbcpu;
968 else
969 cpumask = pinst->cpumask.pcpu;
970
971 len = bitmap_scnprintf(buf, PAGE_SIZE, cpumask_bits(cpumask),
972 nr_cpu_ids);
973 if (PAGE_SIZE - len < 2)
974 len = -EINVAL;
975 else
976 len += sprintf(buf + len, "\n");
977
978 mutex_unlock(&pinst->lock);
979 return len;
980}
981
982static ssize_t store_cpumask(struct padata_instance *pinst,
983 struct attribute *attr,
984 const char *buf, size_t count)
985{
986 cpumask_var_t new_cpumask;
987 ssize_t ret;
988 int mask_type;
989
990 if (!alloc_cpumask_var(&new_cpumask, GFP_KERNEL))
991 return -ENOMEM;
992
993 ret = bitmap_parse(buf, count, cpumask_bits(new_cpumask),
994 nr_cpumask_bits);
995 if (ret < 0)
996 goto out;
997
998 mask_type = !strcmp(attr->name, "serial_cpumask") ?
999 PADATA_CPU_SERIAL : PADATA_CPU_PARALLEL;
1000 ret = padata_set_cpumask(pinst, mask_type, new_cpumask);
1001 if (!ret)
1002 ret = count;
1003
1004out:
1005 free_cpumask_var(new_cpumask);
1006 return ret;
1007}
1008
1009#define PADATA_ATTR_RW(_name, _show_name, _store_name) \
1010 static struct padata_sysfs_entry _name##_attr = \
1011 __ATTR(_name, 0644, _show_name, _store_name)
1012#define PADATA_ATTR_RO(_name, _show_name) \
1013 static struct padata_sysfs_entry _name##_attr = \
1014 __ATTR(_name, 0400, _show_name, NULL)
1015
1016PADATA_ATTR_RW(serial_cpumask, show_cpumask, store_cpumask);
1017PADATA_ATTR_RW(parallel_cpumask, show_cpumask, store_cpumask);
1018
1019/*
1020 * Padata sysfs provides the following objects:
1021 * serial_cpumask [RW] - cpumask for serial workers
1022 * parallel_cpumask [RW] - cpumask for parallel workers
1023 */
1024static struct attribute *padata_default_attrs[] = {
1025 &serial_cpumask_attr.attr,
1026 &parallel_cpumask_attr.attr,
1027 NULL,
1028};
1029
1030static ssize_t padata_sysfs_show(struct kobject *kobj,
1031 struct attribute *attr, char *buf)
1032{
1033 struct padata_instance *pinst;
1034 struct padata_sysfs_entry *pentry;
1035 ssize_t ret = -EIO;
1036
1037 pinst = kobj2pinst(kobj);
1038 pentry = attr2pentry(attr);
1039 if (pentry->show)
1040 ret = pentry->show(pinst, attr, buf);
1041
1042 return ret;
1043}
1044
1045static ssize_t padata_sysfs_store(struct kobject *kobj, struct attribute *attr,
1046 const char *buf, size_t count)
1047{
1048 struct padata_instance *pinst;
1049 struct padata_sysfs_entry *pentry;
1050 ssize_t ret = -EIO;
1051
1052 pinst = kobj2pinst(kobj);
1053 pentry = attr2pentry(attr);
1054 if (pentry->show)
1055 ret = pentry->store(pinst, attr, buf, count);
1056
1057 return ret;
1058}
1059
1060static const struct sysfs_ops padata_sysfs_ops = {
1061 .show = padata_sysfs_show,
1062 .store = padata_sysfs_store,
1063};
1064
1065static struct kobj_type padata_attr_type = {
1066 .sysfs_ops = &padata_sysfs_ops,
1067 .default_attrs = padata_default_attrs,
1068 .release = padata_sysfs_release,
1069};
1070
927/** 1071/**
928 * padata_alloc - Allocate and initialize padata instance. 1072 * padata_alloc - Allocate and initialize padata instance.
929 * Use default cpumask(cpu_possible_mask) 1073 * Use default cpumask(cpu_possible_mask)
@@ -989,6 +1133,7 @@ struct padata_instance *__padata_alloc(struct workqueue_struct *wq,
989 put_online_cpus(); 1133 put_online_cpus();
990 1134
991 BLOCKING_INIT_NOTIFIER_HEAD(&pinst->cpumask_change_notifier); 1135 BLOCKING_INIT_NOTIFIER_HEAD(&pinst->cpumask_change_notifier);
1136 kobject_init(&pinst->kobj, &padata_attr_type);
992 mutex_init(&pinst->lock); 1137 mutex_init(&pinst->lock);
993 1138
994 return pinst; 1139 return pinst;
@@ -1011,14 +1156,6 @@ EXPORT_SYMBOL(__padata_alloc);
1011 */ 1156 */
1012void padata_free(struct padata_instance *pinst) 1157void padata_free(struct padata_instance *pinst)
1013{ 1158{
1014#ifdef CONFIG_HOTPLUG_CPU 1159 kobject_put(&pinst->kobj);
1015 unregister_hotcpu_notifier(&pinst->cpu_notifier);
1016#endif
1017
1018 padata_stop(pinst);
1019 padata_free_pd(pinst->pd);
1020 free_cpumask_var(pinst->cpumask.pcpu);
1021 free_cpumask_var(pinst->cpumask.cbcpu);
1022 kfree(pinst);
1023} 1160}
1024EXPORT_SYMBOL(padata_free); 1161EXPORT_SYMBOL(padata_free);