1a61127c2SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 216295becSSteffen Klassert /* 316295becSSteffen Klassert * padata.h - header for the padata parallelization interface 416295becSSteffen Klassert * 516295becSSteffen Klassert * Copyright (C) 2008, 2009 secunet Security Networks AG 616295becSSteffen Klassert * Copyright (C) 2008, 2009 Steffen Klassert <steffen.klassert@secunet.com> 7004ed426SDaniel Jordan * 8004ed426SDaniel Jordan * Copyright (c) 2020 Oracle and/or its affiliates. 9004ed426SDaniel Jordan * Author: Daniel Jordan <daniel.m.jordan@oracle.com> 1016295becSSteffen Klassert */ 1116295becSSteffen Klassert 1216295becSSteffen Klassert #ifndef PADATA_H 1316295becSSteffen Klassert #define PADATA_H 1416295becSSteffen Klassert 15bbefa1ddSHerbert Xu #include <linux/compiler_types.h> 1616295becSSteffen Klassert #include <linux/workqueue.h> 1716295becSSteffen Klassert #include <linux/spinlock.h> 1816295becSSteffen Klassert #include <linux/list.h> 195e017dc3SDan Kruchinin #include <linux/kobject.h> 20e15bacbeSDan Kruchinin 21e15bacbeSDan Kruchinin #define PADATA_CPU_SERIAL 0x01 22e15bacbeSDan Kruchinin #define PADATA_CPU_PARALLEL 0x02 2316295becSSteffen Klassert 240198ffd1SSteffen Klassert /** 25bfcdcef8SDaniel Jordan * struct padata_priv - Represents one job 260198ffd1SSteffen Klassert * 270198ffd1SSteffen Klassert * @list: List entry, to attach to the padata lists. 280198ffd1SSteffen Klassert * @pd: Pointer to the internal control structure. 290198ffd1SSteffen Klassert * @cb_cpu: Callback cpu for serializatioon. 300198ffd1SSteffen Klassert * @seq_nr: Sequence number of the parallelized data object. 310198ffd1SSteffen Klassert * @info: Used to pass information from the parallel to the serial function. 320198ffd1SSteffen Klassert * @parallel: Parallel execution function. 330198ffd1SSteffen Klassert * @serial: Serial complete function. 340198ffd1SSteffen Klassert */ 3516295becSSteffen Klassert struct padata_priv { 3616295becSSteffen Klassert struct list_head list; 3716295becSSteffen Klassert struct parallel_data *pd; 3816295becSSteffen Klassert int cb_cpu; 39bfde23ceSDaniel Jordan unsigned int seq_nr; 4016295becSSteffen Klassert int info; 4116295becSSteffen Klassert void (*parallel)(struct padata_priv *padata); 4216295becSSteffen Klassert void (*serial)(struct padata_priv *padata); 4316295becSSteffen Klassert }; 4416295becSSteffen Klassert 450198ffd1SSteffen Klassert /** 46bfcdcef8SDaniel Jordan * struct padata_list - one per work type per CPU 470198ffd1SSteffen Klassert * 480198ffd1SSteffen Klassert * @list: List head. 490198ffd1SSteffen Klassert * @lock: List lock. 500198ffd1SSteffen Klassert */ 5116295becSSteffen Klassert struct padata_list { 5216295becSSteffen Klassert struct list_head list; 5316295becSSteffen Klassert spinlock_t lock; 5416295becSSteffen Klassert }; 5516295becSSteffen Klassert 560198ffd1SSteffen Klassert /** 57e15bacbeSDan Kruchinin * struct padata_serial_queue - The percpu padata serial queue 58e15bacbeSDan Kruchinin * 59e15bacbeSDan Kruchinin * @serial: List to wait for serialization after reordering. 60e15bacbeSDan Kruchinin * @work: work struct for serialization. 61e15bacbeSDan Kruchinin * @pd: Backpointer to the internal control structure. 62e15bacbeSDan Kruchinin */ 63e15bacbeSDan Kruchinin struct padata_serial_queue { 64e15bacbeSDan Kruchinin struct padata_list serial; 65e15bacbeSDan Kruchinin struct work_struct work; 66e15bacbeSDan Kruchinin struct parallel_data *pd; 67e15bacbeSDan Kruchinin }; 68e15bacbeSDan Kruchinin 69e15bacbeSDan Kruchinin /** 70e15bacbeSDan Kruchinin * struct padata_parallel_queue - The percpu padata parallel queue 710198ffd1SSteffen Klassert * 720198ffd1SSteffen Klassert * @reorder: List to wait for reordering after parallel processing. 73e15bacbeSDan Kruchinin * @num_obj: Number of objects that are processed by this cpu. 740198ffd1SSteffen Klassert */ 75e15bacbeSDan Kruchinin struct padata_parallel_queue { 7616295becSSteffen Klassert struct padata_list reorder; 77e15bacbeSDan Kruchinin atomic_t num_obj; 7816295becSSteffen Klassert }; 7916295becSSteffen Klassert 80c635696cSSteffen Klassert /** 81c635696cSSteffen Klassert * struct padata_cpumask - The cpumasks for the parallel/serial workers 82c635696cSSteffen Klassert * 83c635696cSSteffen Klassert * @pcpu: cpumask for the parallel workers. 84c635696cSSteffen Klassert * @cbcpu: cpumask for the serial (callback) workers. 85c635696cSSteffen Klassert */ 86c635696cSSteffen Klassert struct padata_cpumask { 87c635696cSSteffen Klassert cpumask_var_t pcpu; 88c635696cSSteffen Klassert cpumask_var_t cbcpu; 89c635696cSSteffen Klassert }; 90e15bacbeSDan Kruchinin 910198ffd1SSteffen Klassert /** 920198ffd1SSteffen Klassert * struct parallel_data - Internal control structure, covers everything 930198ffd1SSteffen Klassert * that depends on the cpumask in use. 940198ffd1SSteffen Klassert * 95bfcdcef8SDaniel Jordan * @ps: padata_shell object. 96e15bacbeSDan Kruchinin * @pqueue: percpu padata queues used for parallelization. 97e15bacbeSDan Kruchinin * @squeue: percpu padata queues used for serialuzation. 980198ffd1SSteffen Klassert * @refcnt: Number of objects holding a reference on this parallel_data. 99bfcdcef8SDaniel Jordan * @seq_nr: Sequence number of the parallelized data object. 100bfde23ceSDaniel Jordan * @processed: Number of already processed objects. 1016fc4dbcfSHerbert Xu * @cpu: Next CPU to be processed. 102c635696cSSteffen Klassert * @cpumask: The cpumasks in use for parallel and serial workers. 1036fc4dbcfSHerbert Xu * @reorder_work: work struct for reordering. 1040198ffd1SSteffen Klassert * @lock: Reorder lock. 1050198ffd1SSteffen Klassert */ 10616295becSSteffen Klassert struct parallel_data { 107bbefa1ddSHerbert Xu struct padata_shell *ps; 10857a2ce5fSNamhyung Kim struct padata_parallel_queue __percpu *pqueue; 10957a2ce5fSNamhyung Kim struct padata_serial_queue __percpu *squeue; 11016295becSSteffen Klassert atomic_t refcnt; 1114611ce22SDaniel Jordan unsigned int seq_nr; 112bfde23ceSDaniel Jordan unsigned int processed; 1136fc4dbcfSHerbert Xu int cpu; 114c635696cSSteffen Klassert struct padata_cpumask cpumask; 1156fc4dbcfSHerbert Xu struct work_struct reorder_work; 116bfcdcef8SDaniel Jordan spinlock_t ____cacheline_aligned lock; 11716295becSSteffen Klassert }; 11816295becSSteffen Klassert 1190198ffd1SSteffen Klassert /** 120bbefa1ddSHerbert Xu * struct padata_shell - Wrapper around struct parallel_data, its 121bbefa1ddSHerbert Xu * purpose is to allow the underlying control structure to be replaced 122bbefa1ddSHerbert Xu * on the fly using RCU. 123bbefa1ddSHerbert Xu * 124bbefa1ddSHerbert Xu * @pinst: padat instance. 125bbefa1ddSHerbert Xu * @pd: Actual parallel_data structure which may be substituted on the fly. 126bbefa1ddSHerbert Xu * @opd: Pointer to old pd to be freed by padata_replace. 127bbefa1ddSHerbert Xu * @list: List entry in padata_instance list. 128bbefa1ddSHerbert Xu */ 129bbefa1ddSHerbert Xu struct padata_shell { 130bbefa1ddSHerbert Xu struct padata_instance *pinst; 131bbefa1ddSHerbert Xu struct parallel_data __rcu *pd; 132bbefa1ddSHerbert Xu struct parallel_data *opd; 133bbefa1ddSHerbert Xu struct list_head list; 134bbefa1ddSHerbert Xu }; 135bbefa1ddSHerbert Xu 136bbefa1ddSHerbert Xu /** 137004ed426SDaniel Jordan * struct padata_mt_job - represents one multithreaded job 138004ed426SDaniel Jordan * 139004ed426SDaniel Jordan * @thread_fn: Called for each chunk of work that a padata thread does. 140004ed426SDaniel Jordan * @fn_arg: The thread function argument. 141004ed426SDaniel Jordan * @start: The start of the job (units are job-specific). 142004ed426SDaniel Jordan * @size: size of this node's work (units are job-specific). 143004ed426SDaniel Jordan * @align: Ranges passed to the thread function fall on this boundary, with the 144004ed426SDaniel Jordan * possible exceptions of the beginning and end of the job. 145004ed426SDaniel Jordan * @min_chunk: The minimum chunk size in job-specific units. This allows 146004ed426SDaniel Jordan * the client to communicate the minimum amount of work that's 147004ed426SDaniel Jordan * appropriate for one worker thread to do at once. 148004ed426SDaniel Jordan * @max_threads: Max threads to use for the job, actual number may be less 149004ed426SDaniel Jordan * depending on task size and minimum chunk size. 150004ed426SDaniel Jordan */ 151004ed426SDaniel Jordan struct padata_mt_job { 152004ed426SDaniel Jordan void (*thread_fn)(unsigned long start, unsigned long end, void *arg); 153004ed426SDaniel Jordan void *fn_arg; 154004ed426SDaniel Jordan unsigned long start; 155004ed426SDaniel Jordan unsigned long size; 156004ed426SDaniel Jordan unsigned long align; 157004ed426SDaniel Jordan unsigned long min_chunk; 158004ed426SDaniel Jordan int max_threads; 159004ed426SDaniel Jordan }; 160004ed426SDaniel Jordan 161004ed426SDaniel Jordan /** 1620198ffd1SSteffen Klassert * struct padata_instance - The overall control structure. 1630198ffd1SSteffen Klassert * 1643c2214b6SDaniel Jordan * @cpu_online_node: Linkage for CPU online callback. 1653c2214b6SDaniel Jordan * @cpu_dead_node: Linkage for CPU offline callback. 16645d153c0SDaniel Jordan * @parallel_wq: The workqueue used for parallel work. 16745d153c0SDaniel Jordan * @serial_wq: The workqueue used for serial work. 168bbefa1ddSHerbert Xu * @pslist: List of padata_shell objects attached to this instance. 169c635696cSSteffen Klassert * @cpumask: User supplied cpumasks for parallel and serial works. 170bbefa1ddSHerbert Xu * @rcpumask: Actual cpumasks based on user cpumask and cpu_online_mask. 1715e017dc3SDan Kruchinin * @kobj: padata instance kernel object. 1720198ffd1SSteffen Klassert * @lock: padata instance lock. 1730198ffd1SSteffen Klassert * @flags: padata flags. 1740198ffd1SSteffen Klassert */ 17516295becSSteffen Klassert struct padata_instance { 1763c2214b6SDaniel Jordan struct hlist_node cpu_online_node; 1773c2214b6SDaniel Jordan struct hlist_node cpu_dead_node; 17845d153c0SDaniel Jordan struct workqueue_struct *parallel_wq; 17945d153c0SDaniel Jordan struct workqueue_struct *serial_wq; 180bbefa1ddSHerbert Xu struct list_head pslist; 181c635696cSSteffen Klassert struct padata_cpumask cpumask; 182bbefa1ddSHerbert Xu struct padata_cpumask rcpumask; 1835e017dc3SDan Kruchinin struct kobject kobj; 18416295becSSteffen Klassert struct mutex lock; 18516295becSSteffen Klassert u8 flags; 18616295becSSteffen Klassert #define PADATA_INIT 1 18716295becSSteffen Klassert #define PADATA_RESET 2 1884c879170SSteffen Klassert #define PADATA_INVALID 4 18916295becSSteffen Klassert }; 19016295becSSteffen Klassert 191f1b192b1SDaniel Jordan #ifdef CONFIG_PADATA 192f1b192b1SDaniel Jordan extern void __init padata_init(void); 193f1b192b1SDaniel Jordan #else 194f1b192b1SDaniel Jordan static inline void __init padata_init(void) {} 195f1b192b1SDaniel Jordan #endif 196f1b192b1SDaniel Jordan 197b128a304SDaniel Jordan extern struct padata_instance *padata_alloc_possible(const char *name); 19816295becSSteffen Klassert extern void padata_free(struct padata_instance *pinst); 199bbefa1ddSHerbert Xu extern struct padata_shell *padata_alloc_shell(struct padata_instance *pinst); 200bbefa1ddSHerbert Xu extern void padata_free_shell(struct padata_shell *ps); 201bbefa1ddSHerbert Xu extern int padata_do_parallel(struct padata_shell *ps, 202e6ce0e08SDaniel Jordan struct padata_priv *padata, int *cb_cpu); 20316295becSSteffen Klassert extern void padata_do_serial(struct padata_priv *padata); 204004ed426SDaniel Jordan extern void __init padata_do_multithreaded(struct padata_mt_job *job); 205e15bacbeSDan Kruchinin extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, 20616295becSSteffen Klassert cpumask_var_t cpumask); 2074c879170SSteffen Klassert extern int padata_start(struct padata_instance *pinst); 20816295becSSteffen Klassert extern void padata_stop(struct padata_instance *pinst); 20916295becSSteffen Klassert #endif 210