| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * padata.h - header for the padata parallelization interface |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2008, 2009 secunet Security Networks AG |
|---|
| 5 | 6 | * Copyright (C) 2008, 2009 Steffen Klassert <steffen.klassert@secunet.com> |
|---|
| 6 | 7 | * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 8 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 9 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 12 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 13 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 14 | | - * more details. |
|---|
| 15 | | - * |
|---|
| 16 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 17 | | - * this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 18 | | - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
|---|
| 8 | + * Copyright (c) 2020 Oracle and/or its affiliates. |
|---|
| 9 | + * Author: Daniel Jordan <daniel.m.jordan@oracle.com> |
|---|
| 19 | 10 | */ |
|---|
| 20 | 11 | |
|---|
| 21 | 12 | #ifndef PADATA_H |
|---|
| 22 | 13 | #define PADATA_H |
|---|
| 23 | 14 | |
|---|
| 15 | +#include <linux/compiler_types.h> |
|---|
| 24 | 16 | #include <linux/workqueue.h> |
|---|
| 25 | 17 | #include <linux/spinlock.h> |
|---|
| 26 | 18 | #include <linux/list.h> |
|---|
| 27 | | -#include <linux/notifier.h> |
|---|
| 28 | 19 | #include <linux/kobject.h> |
|---|
| 29 | 20 | |
|---|
| 30 | 21 | #define PADATA_CPU_SERIAL 0x01 |
|---|
| 31 | 22 | #define PADATA_CPU_PARALLEL 0x02 |
|---|
| 32 | 23 | |
|---|
| 33 | 24 | /** |
|---|
| 34 | | - * struct padata_priv - Embedded to the users data structure. |
|---|
| 25 | + * struct padata_priv - Represents one job |
|---|
| 35 | 26 | * |
|---|
| 36 | 27 | * @list: List entry, to attach to the padata lists. |
|---|
| 37 | 28 | * @pd: Pointer to the internal control structure. |
|---|
| 38 | 29 | * @cb_cpu: Callback cpu for serializatioon. |
|---|
| 39 | | - * @cpu: Cpu for parallelization. |
|---|
| 40 | 30 | * @seq_nr: Sequence number of the parallelized data object. |
|---|
| 41 | 31 | * @info: Used to pass information from the parallel to the serial function. |
|---|
| 42 | 32 | * @parallel: Parallel execution function. |
|---|
| .. | .. |
|---|
| 46 | 36 | struct list_head list; |
|---|
| 47 | 37 | struct parallel_data *pd; |
|---|
| 48 | 38 | int cb_cpu; |
|---|
| 49 | | - int cpu; |
|---|
| 39 | + unsigned int seq_nr; |
|---|
| 50 | 40 | int info; |
|---|
| 51 | 41 | void (*parallel)(struct padata_priv *padata); |
|---|
| 52 | 42 | void (*serial)(struct padata_priv *padata); |
|---|
| 53 | 43 | }; |
|---|
| 54 | 44 | |
|---|
| 55 | 45 | /** |
|---|
| 56 | | - * struct padata_list |
|---|
| 46 | + * struct padata_list - one per work type per CPU |
|---|
| 57 | 47 | * |
|---|
| 58 | 48 | * @list: List head. |
|---|
| 59 | 49 | * @lock: List lock. |
|---|
| .. | .. |
|---|
| 77 | 67 | }; |
|---|
| 78 | 68 | |
|---|
| 79 | 69 | /** |
|---|
| 80 | | - * struct padata_parallel_queue - The percpu padata parallel queue |
|---|
| 81 | | - * |
|---|
| 82 | | - * @parallel: List to wait for parallelization. |
|---|
| 83 | | - * @reorder: List to wait for reordering after parallel processing. |
|---|
| 84 | | - * @serial: List to wait for serialization after reordering. |
|---|
| 85 | | - * @pwork: work struct for parallelization. |
|---|
| 86 | | - * @swork: work struct for serialization. |
|---|
| 87 | | - * @work: work struct for parallelization. |
|---|
| 88 | | - * @num_obj: Number of objects that are processed by this cpu. |
|---|
| 89 | | - * @cpu_index: Index of the cpu. |
|---|
| 90 | | - */ |
|---|
| 91 | | -struct padata_parallel_queue { |
|---|
| 92 | | - struct padata_list parallel; |
|---|
| 93 | | - struct padata_list reorder; |
|---|
| 94 | | - struct work_struct work; |
|---|
| 95 | | - atomic_t num_obj; |
|---|
| 96 | | - int cpu_index; |
|---|
| 97 | | -}; |
|---|
| 98 | | - |
|---|
| 99 | | -/** |
|---|
| 100 | 70 | * struct padata_cpumask - The cpumasks for the parallel/serial workers |
|---|
| 101 | 71 | * |
|---|
| 102 | 72 | * @pcpu: cpumask for the parallel workers. |
|---|
| .. | .. |
|---|
| 111 | 81 | * struct parallel_data - Internal control structure, covers everything |
|---|
| 112 | 82 | * that depends on the cpumask in use. |
|---|
| 113 | 83 | * |
|---|
| 114 | | - * @pinst: padata instance. |
|---|
| 115 | | - * @pqueue: percpu padata queues used for parallelization. |
|---|
| 84 | + * @ps: padata_shell object. |
|---|
| 85 | + * @reorder_list: percpu reorder lists |
|---|
| 116 | 86 | * @squeue: percpu padata queues used for serialuzation. |
|---|
| 117 | | - * @reorder_objects: Number of objects waiting in the reorder queues. |
|---|
| 118 | 87 | * @refcnt: Number of objects holding a reference on this parallel_data. |
|---|
| 119 | | - * @max_seq_nr: Maximal used sequence number. |
|---|
| 88 | + * @seq_nr: Sequence number of the parallelized data object. |
|---|
| 89 | + * @processed: Number of already processed objects. |
|---|
| 120 | 90 | * @cpu: Next CPU to be processed. |
|---|
| 121 | 91 | * @cpumask: The cpumasks in use for parallel and serial workers. |
|---|
| 122 | 92 | * @reorder_work: work struct for reordering. |
|---|
| 123 | 93 | * @lock: Reorder lock. |
|---|
| 124 | 94 | */ |
|---|
| 125 | 95 | struct parallel_data { |
|---|
| 126 | | - struct padata_instance *pinst; |
|---|
| 127 | | - struct padata_parallel_queue __percpu *pqueue; |
|---|
| 96 | + struct padata_shell *ps; |
|---|
| 97 | + struct padata_list __percpu *reorder_list; |
|---|
| 128 | 98 | struct padata_serial_queue __percpu *squeue; |
|---|
| 129 | | - atomic_t reorder_objects; |
|---|
| 130 | 99 | atomic_t refcnt; |
|---|
| 131 | | - atomic_t seq_nr; |
|---|
| 100 | + unsigned int seq_nr; |
|---|
| 101 | + unsigned int processed; |
|---|
| 132 | 102 | int cpu; |
|---|
| 133 | 103 | struct padata_cpumask cpumask; |
|---|
| 134 | 104 | struct work_struct reorder_work; |
|---|
| 135 | | - spinlock_t lock ____cacheline_aligned; |
|---|
| 105 | + spinlock_t ____cacheline_aligned lock; |
|---|
| 106 | +}; |
|---|
| 107 | + |
|---|
| 108 | +/** |
|---|
| 109 | + * struct padata_shell - Wrapper around struct parallel_data, its |
|---|
| 110 | + * purpose is to allow the underlying control structure to be replaced |
|---|
| 111 | + * on the fly using RCU. |
|---|
| 112 | + * |
|---|
| 113 | + * @pinst: padat instance. |
|---|
| 114 | + * @pd: Actual parallel_data structure which may be substituted on the fly. |
|---|
| 115 | + * @opd: Pointer to old pd to be freed by padata_replace. |
|---|
| 116 | + * @list: List entry in padata_instance list. |
|---|
| 117 | + */ |
|---|
| 118 | +struct padata_shell { |
|---|
| 119 | + struct padata_instance *pinst; |
|---|
| 120 | + struct parallel_data __rcu *pd; |
|---|
| 121 | + struct parallel_data *opd; |
|---|
| 122 | + struct list_head list; |
|---|
| 123 | +}; |
|---|
| 124 | + |
|---|
| 125 | +/** |
|---|
| 126 | + * struct padata_mt_job - represents one multithreaded job |
|---|
| 127 | + * |
|---|
| 128 | + * @thread_fn: Called for each chunk of work that a padata thread does. |
|---|
| 129 | + * @fn_arg: The thread function argument. |
|---|
| 130 | + * @start: The start of the job (units are job-specific). |
|---|
| 131 | + * @size: size of this node's work (units are job-specific). |
|---|
| 132 | + * @align: Ranges passed to the thread function fall on this boundary, with the |
|---|
| 133 | + * possible exceptions of the beginning and end of the job. |
|---|
| 134 | + * @min_chunk: The minimum chunk size in job-specific units. This allows |
|---|
| 135 | + * the client to communicate the minimum amount of work that's |
|---|
| 136 | + * appropriate for one worker thread to do at once. |
|---|
| 137 | + * @max_threads: Max threads to use for the job, actual number may be less |
|---|
| 138 | + * depending on task size and minimum chunk size. |
|---|
| 139 | + */ |
|---|
| 140 | +struct padata_mt_job { |
|---|
| 141 | + void (*thread_fn)(unsigned long start, unsigned long end, void *arg); |
|---|
| 142 | + void *fn_arg; |
|---|
| 143 | + unsigned long start; |
|---|
| 144 | + unsigned long size; |
|---|
| 145 | + unsigned long align; |
|---|
| 146 | + unsigned long min_chunk; |
|---|
| 147 | + int max_threads; |
|---|
| 136 | 148 | }; |
|---|
| 137 | 149 | |
|---|
| 138 | 150 | /** |
|---|
| 139 | 151 | * struct padata_instance - The overall control structure. |
|---|
| 140 | 152 | * |
|---|
| 141 | | - * @cpu_notifier: cpu hotplug notifier. |
|---|
| 142 | | - * @wq: The workqueue in use. |
|---|
| 143 | | - * @pd: The internal control structure. |
|---|
| 153 | + * @cpu_online_node: Linkage for CPU online callback. |
|---|
| 154 | + * @cpu_dead_node: Linkage for CPU offline callback. |
|---|
| 155 | + * @parallel_wq: The workqueue used for parallel work. |
|---|
| 156 | + * @serial_wq: The workqueue used for serial work. |
|---|
| 157 | + * @pslist: List of padata_shell objects attached to this instance. |
|---|
| 144 | 158 | * @cpumask: User supplied cpumasks for parallel and serial works. |
|---|
| 145 | | - * @cpumask_change_notifier: Notifiers chain for user-defined notify |
|---|
| 146 | | - * callbacks that will be called when either @pcpu or @cbcpu |
|---|
| 147 | | - * or both cpumasks change. |
|---|
| 148 | 159 | * @kobj: padata instance kernel object. |
|---|
| 149 | 160 | * @lock: padata instance lock. |
|---|
| 150 | 161 | * @flags: padata flags. |
|---|
| 151 | 162 | */ |
|---|
| 152 | 163 | struct padata_instance { |
|---|
| 153 | | - struct hlist_node node; |
|---|
| 154 | | - struct workqueue_struct *wq; |
|---|
| 155 | | - struct parallel_data *pd; |
|---|
| 164 | + struct hlist_node cpu_online_node; |
|---|
| 165 | + struct hlist_node cpu_dead_node; |
|---|
| 166 | + struct workqueue_struct *parallel_wq; |
|---|
| 167 | + struct workqueue_struct *serial_wq; |
|---|
| 168 | + struct list_head pslist; |
|---|
| 156 | 169 | struct padata_cpumask cpumask; |
|---|
| 157 | | - struct blocking_notifier_head cpumask_change_notifier; |
|---|
| 158 | 170 | struct kobject kobj; |
|---|
| 159 | 171 | struct mutex lock; |
|---|
| 160 | 172 | u8 flags; |
|---|
| .. | .. |
|---|
| 163 | 175 | #define PADATA_INVALID 4 |
|---|
| 164 | 176 | }; |
|---|
| 165 | 177 | |
|---|
| 166 | | -extern struct padata_instance *padata_alloc_possible( |
|---|
| 167 | | - struct workqueue_struct *wq); |
|---|
| 178 | +#ifdef CONFIG_PADATA |
|---|
| 179 | +extern void __init padata_init(void); |
|---|
| 180 | +#else |
|---|
| 181 | +static inline void __init padata_init(void) {} |
|---|
| 182 | +#endif |
|---|
| 183 | + |
|---|
| 184 | +extern struct padata_instance *padata_alloc(const char *name); |
|---|
| 168 | 185 | extern void padata_free(struct padata_instance *pinst); |
|---|
| 169 | | -extern int padata_do_parallel(struct padata_instance *pinst, |
|---|
| 170 | | - struct padata_priv *padata, int cb_cpu); |
|---|
| 186 | +extern struct padata_shell *padata_alloc_shell(struct padata_instance *pinst); |
|---|
| 187 | +extern void padata_free_shell(struct padata_shell *ps); |
|---|
| 188 | +extern int padata_do_parallel(struct padata_shell *ps, |
|---|
| 189 | + struct padata_priv *padata, int *cb_cpu); |
|---|
| 171 | 190 | extern void padata_do_serial(struct padata_priv *padata); |
|---|
| 191 | +extern void __init padata_do_multithreaded(struct padata_mt_job *job); |
|---|
| 172 | 192 | extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, |
|---|
| 173 | 193 | cpumask_var_t cpumask); |
|---|
| 174 | | -extern int padata_start(struct padata_instance *pinst); |
|---|
| 175 | | -extern void padata_stop(struct padata_instance *pinst); |
|---|
| 176 | | -extern int padata_register_cpumask_notifier(struct padata_instance *pinst, |
|---|
| 177 | | - struct notifier_block *nblock); |
|---|
| 178 | | -extern int padata_unregister_cpumask_notifier(struct padata_instance *pinst, |
|---|
| 179 | | - struct notifier_block *nblock); |
|---|
| 180 | 194 | #endif |
|---|