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); |
