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 /** 70c635696cSSteffen Klassert * struct padata_cpumask - The cpumasks for the parallel/serial workers 71c635696cSSteffen Klassert * 72c635696cSSteffen Klassert * @pcpu: cpumask for the parallel workers. 73c635696cSSteffen Klassert * @cbcpu: cpumask for the serial (callback) workers. 74c635696cSSteffen Klassert */ 75c635696cSSteffen Klassert struct padata_cpumask { 76c635696cSSteffen Klassert cpumask_var_t pcpu; 77c635696cSSteffen Klassert cpumask_var_t cbcpu; 78c635696cSSteffen Klassert }; 79e15bacbeSDan Kruchinin 800198ffd1SSteffen Klassert /** 810198ffd1SSteffen Klassert * struct parallel_data - Internal control structure, covers everything 820198ffd1SSteffen Klassert * that depends on the cpumask in use. 830198ffd1SSteffen Klassert * 84bfcdcef8SDaniel Jordan * @ps: padata_shell object. 85f601c725SDaniel Jordan * @reorder_list: percpu reorder lists 86e15bacbeSDan Kruchinin * @squeue: percpu padata queues used for serialuzation. 870198ffd1SSteffen Klassert * @refcnt: Number of objects holding a reference on this parallel_data. 88bfcdcef8SDaniel Jordan * @seq_nr: Sequence number of the parallelized data object. 89bfde23ceSDaniel Jordan * @processed: Number of already processed objects. 906fc4dbcfSHerbert Xu * @cpu: Next CPU to be processed. 91c635696cSSteffen Klassert * @cpumask: The cpumasks in use for parallel and serial workers. 926fc4dbcfSHerbert Xu * @reorder_work: work struct for reordering. 930198ffd1SSteffen Klassert * @lock: Reorder lock. 940198ffd1SSteffen Klassert */ 9516295becSSteffen Klassert struct parallel_data { 96bbefa1ddSHerbert Xu struct padata_shell *ps; 97f601c725SDaniel Jordan struct padata_list __percpu *reorder_list; 9857a2ce5fSNamhyung Kim struct padata_serial_queue __percpu *squeue; 9916295becSSteffen Klassert atomic_t refcnt; 1004611ce22SDaniel Jordan unsigned int seq_nr; 101bfde23ceSDaniel Jordan unsigned int processed; 1026fc4dbcfSHerbert Xu int cpu; 103c635696cSSteffen Klassert struct padata_cpumask cpumask; 1046fc4dbcfSHerbert Xu struct work_struct reorder_work; 105bfcdcef8SDaniel Jordan spinlock_t ____cacheline_aligned lock; 10616295becSSteffen Klassert }; 10716295becSSteffen Klassert 1080198ffd1SSteffen Klassert /** 109bbefa1ddSHerbert Xu * struct padata_shell - Wrapper around struct parallel_data, its 110bbefa1ddSHerbert Xu * purpose is to allow the underlying control structure to be replaced 111bbefa1ddSHerbert Xu * on the fly using RCU. 112bbefa1ddSHerbert Xu * 113bbefa1ddSHerbert Xu * @pinst: padat instance. 114bbefa1ddSHerbert Xu * @pd: Actual parallel_data structure which may be substituted on the fly. 115bbefa1ddSHerbert Xu * @opd: Pointer to old pd to be freed by padata_replace. 116bbefa1ddSHerbert Xu * @list: List entry in padata_instance list. 117bbefa1ddSHerbert Xu */ 118bbefa1ddSHerbert Xu struct padata_shell { 119bbefa1ddSHerbert Xu struct padata_instance *pinst; 120bbefa1ddSHerbert Xu struct parallel_data __rcu *pd; 121bbefa1ddSHerbert Xu struct parallel_data *opd; 122bbefa1ddSHerbert Xu struct list_head list; 123bbefa1ddSHerbert Xu }; 124bbefa1ddSHerbert Xu 125bbefa1ddSHerbert Xu /** 126004ed426SDaniel Jordan * struct padata_mt_job - represents one multithreaded job 127004ed426SDaniel Jordan * 128004ed426SDaniel Jordan * @thread_fn: Called for each chunk of work that a padata thread does. 129004ed426SDaniel Jordan * @fn_arg: The thread function argument. 130004ed426SDaniel Jordan * @start: The start of the job (units are job-specific). 131004ed426SDaniel Jordan * @size: size of this node's work (units are job-specific). 132004ed426SDaniel Jordan * @align: Ranges passed to the thread function fall on this boundary, with the 133004ed426SDaniel Jordan * possible exceptions of the beginning and end of the job. 134004ed426SDaniel Jordan * @min_chunk: The minimum chunk size in job-specific units. This allows 135004ed426SDaniel Jordan * the client to communicate the minimum amount of work that's 136004ed426SDaniel Jordan * appropriate for one worker thread to do at once. 137004ed426SDaniel Jordan * @max_threads: Max threads to use for the job, actual number may be less 138004ed426SDaniel Jordan * depending on task size and minimum chunk size. 139004ed426SDaniel Jordan */ 140004ed426SDaniel Jordan struct padata_mt_job { 141004ed426SDaniel Jordan void (*thread_fn)(unsigned long start, unsigned long end, void *arg); 142004ed426SDaniel Jordan void *fn_arg; 143004ed426SDaniel Jordan unsigned long start; 144004ed426SDaniel Jordan unsigned long size; 145004ed426SDaniel Jordan unsigned long align; 146004ed426SDaniel Jordan unsigned long min_chunk; 147004ed426SDaniel Jordan int max_threads; 148004ed426SDaniel Jordan }; 149004ed426SDaniel Jordan 150004ed426SDaniel Jordan /** 1510198ffd1SSteffen Klassert * struct padata_instance - The overall control structure. 1520198ffd1SSteffen Klassert * 1533c2214b6SDaniel Jordan * @cpu_online_node: Linkage for CPU online callback. 1543c2214b6SDaniel Jordan * @cpu_dead_node: Linkage for CPU offline callback. 15545d153c0SDaniel Jordan * @parallel_wq: The workqueue used for parallel work. 15645d153c0SDaniel Jordan * @serial_wq: The workqueue used for serial work. 157bbefa1ddSHerbert Xu * @pslist: List of padata_shell objects attached to this instance. 158c635696cSSteffen Klassert * @cpumask: User supplied cpumasks for parallel and serial works. 1595e017dc3SDan Kruchinin * @kobj: padata instance kernel object. 1600198ffd1SSteffen Klassert * @lock: padata instance lock. 1610198ffd1SSteffen Klassert * @flags: padata flags. 1620198ffd1SSteffen Klassert */ 16316295becSSteffen Klassert struct padata_instance { 1643c2214b6SDaniel Jordan struct hlist_node cpu_online_node; 1653c2214b6SDaniel Jordan struct hlist_node cpu_dead_node; 16645d153c0SDaniel Jordan struct workqueue_struct *parallel_wq; 16745d153c0SDaniel Jordan struct workqueue_struct *serial_wq; 168bbefa1ddSHerbert Xu struct list_head pslist; 169c635696cSSteffen Klassert struct padata_cpumask cpumask; 1705e017dc3SDan Kruchinin struct kobject kobj; 17116295becSSteffen Klassert struct mutex lock; 17216295becSSteffen Klassert u8 flags; 17316295becSSteffen Klassert #define PADATA_INIT 1 17416295becSSteffen Klassert #define PADATA_RESET 2 1754c879170SSteffen Klassert #define PADATA_INVALID 4 17616295becSSteffen Klassert }; 17716295becSSteffen Klassert 178f1b192b1SDaniel Jordan #ifdef CONFIG_PADATA 179f1b192b1SDaniel Jordan extern void __init padata_init(void); 180f1b192b1SDaniel Jordan #else 181f1b192b1SDaniel Jordan static inline void __init padata_init(void) {} 182f1b192b1SDaniel Jordan #endif 183f1b192b1SDaniel Jordan 1843f257191SDaniel Jordan extern struct padata_instance *padata_alloc(const char *name); 18516295becSSteffen Klassert extern void padata_free(struct padata_instance *pinst); 186bbefa1ddSHerbert Xu extern struct padata_shell *padata_alloc_shell(struct padata_instance *pinst); 187bbefa1ddSHerbert Xu extern void padata_free_shell(struct padata_shell *ps); 188bbefa1ddSHerbert Xu extern int padata_do_parallel(struct padata_shell *ps, 189e6ce0e08SDaniel Jordan struct padata_priv *padata, int *cb_cpu); 19016295becSSteffen Klassert extern void padata_do_serial(struct padata_priv *padata); 191004ed426SDaniel Jordan extern void __init padata_do_multithreaded(struct padata_mt_job *job); 192e15bacbeSDan Kruchinin extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, 19316295becSSteffen Klassert cpumask_var_t cpumask); 19416295becSSteffen Klassert #endif 195