diff options
-rw-r--r-- | include/linux/padata.h | 5 | ||||
-rw-r--r-- | kernel/padata.c | 155 |
2 files changed, 150 insertions, 10 deletions
diff --git a/include/linux/padata.h b/include/linux/padata.h index 621e7736690c..293ad46ffced 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/timer.h> | 27 | #include <linux/timer.h> |
28 | #include <linux/notifier.h> | 28 | #include <linux/notifier.h> |
29 | #include <linux/kobject.h> | ||
29 | 30 | ||
30 | #define PADATA_CPU_SERIAL 0x01 | 31 | #define PADATA_CPU_SERIAL 0x01 |
31 | #define PADATA_CPU_PARALLEL 0x02 | 32 | #define PADATA_CPU_PARALLEL 0x02 |
@@ -142,7 +143,8 @@ struct parallel_data { | |||
142 | * cbcpu for parallel and serial works respectivly. | 143 | * cbcpu for parallel and serial works respectivly. |
143 | * @cpumask_change_notifier: Notifiers chain for user-defined notify | 144 | * @cpumask_change_notifier: Notifiers chain for user-defined notify |
144 | * callbacks that will be called when either @pcpu or @cbcpu | 145 | * callbacks that will be called when either @pcpu or @cbcpu |
145 | * or both cpumasks change. | 146 | * or both cpumasks change. |
147 | * @kobj: padata instance kernel object. | ||
146 | * @lock: padata instance lock. | 148 | * @lock: padata instance lock. |
147 | * @flags: padata flags. | 149 | * @flags: padata flags. |
148 | */ | 150 | */ |
@@ -155,6 +157,7 @@ struct padata_instance { | |||
155 | cpumask_var_t cbcpu; | 157 | cpumask_var_t cbcpu; |
156 | } cpumask; | 158 | } cpumask; |
157 | struct blocking_notifier_head cpumask_change_notifier; | 159 | struct blocking_notifier_head cpumask_change_notifier; |
160 | struct kobject kobj; | ||
158 | struct mutex lock; | 161 | struct mutex lock; |
159 | u8 flags; | 162 | u8 flags; |
160 | #define PADATA_INIT 1 | 163 | #define PADATA_INIT 1 |
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 | ||
928 | static 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 | |||
946 | static void padata_sysfs_release(struct kobject *kobj) | ||
947 | { | ||
948 | struct padata_instance *pinst = kobj2pinst(kobj); | ||
949 | __padata_free(pinst); | ||
950 | } | ||
951 | |||
952 | struct 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 | |||
959 | static 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 | |||
982 | static 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 | |||
1004 | out: | ||
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 | |||
1016 | PADATA_ATTR_RW(serial_cpumask, show_cpumask, store_cpumask); | ||
1017 | PADATA_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 | */ | ||
1024 | static struct attribute *padata_default_attrs[] = { | ||
1025 | &serial_cpumask_attr.attr, | ||
1026 | ¶llel_cpumask_attr.attr, | ||
1027 | NULL, | ||
1028 | }; | ||
1029 | |||
1030 | static 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 | |||
1045 | static 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 | |||
1060 | static const struct sysfs_ops padata_sysfs_ops = { | ||
1061 | .show = padata_sysfs_show, | ||
1062 | .store = padata_sysfs_store, | ||
1063 | }; | ||
1064 | |||
1065 | static 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 | */ |
1012 | void padata_free(struct padata_instance *pinst) | 1157 | void 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 | } |
1024 | EXPORT_SYMBOL(padata_free); | 1161 | EXPORT_SYMBOL(padata_free); |