Commit 427714f2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tasklets-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull tasklets API update from Kees Cook:
 "These are the infrastructure updates needed to support converting the
  tasklet API to something more modern (and hopefully for removal
  further down the road).

  There is a 300-patch series waiting in the wings to get set out to
  subsystem maintainers, but these changes need to be present in the
  kernel first. Since this has some treewide changes, I carried this
  series for -next instead of paining Thomas with it in -tip, but it's
  got his Ack.

  This is similar to the timer_struct modernization from a while back,
  but not nearly as messy (I hope). :)

   - Prepare for tasklet API modernization (Romain Perier, Allen Pais,
     Kees Cook)"

* tag 'tasklets-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  tasklet: Introduce new initialization API
  treewide: Replace DECLARE_TASKLET() with DECLARE_TASKLET_OLD()
  usb: gadget: udc: Avoid tasklet passing a global
parents 5b5d3be5 12cc923f
...@@ -46,7 +46,7 @@ struct omap_kp { ...@@ -46,7 +46,7 @@ struct omap_kp {
unsigned short keymap[]; unsigned short keymap[];
}; };
static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); static DECLARE_TASKLET_DISABLED_OLD(kp_tasklet, omap_kp_tasklet);
static unsigned int *row_gpios; static unsigned int *row_gpios;
static unsigned int *col_gpios; static unsigned int *col_gpios;
......
...@@ -77,7 +77,7 @@ static struct timer_list hil_mlcs_kicker; ...@@ -77,7 +77,7 @@ static struct timer_list hil_mlcs_kicker;
static int hil_mlcs_probe; static int hil_mlcs_probe;
static void hil_mlcs_process(unsigned long unused); static void hil_mlcs_process(unsigned long unused);
static DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0); static DECLARE_TASKLET_DISABLED_OLD(hil_mlcs_tasklet, hil_mlcs_process);
/* #define HIL_MLC_DEBUG */ /* #define HIL_MLC_DEBUG */
......
...@@ -569,8 +569,8 @@ static void do_bottom_half_rx(struct fst_card_info *card); ...@@ -569,8 +569,8 @@ static void do_bottom_half_rx(struct fst_card_info *card);
static void fst_process_tx_work_q(unsigned long work_q); static void fst_process_tx_work_q(unsigned long work_q);
static void fst_process_int_work_q(unsigned long work_q); static void fst_process_int_work_q(unsigned long work_q);
static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0); static DECLARE_TASKLET_OLD(fst_tx_task, fst_process_tx_work_q);
static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0); static DECLARE_TASKLET_OLD(fst_int_task, fst_process_int_work_q);
static struct fst_card_info *fst_card_array[FST_MAX_CARDS]; static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
static spinlock_t fst_work_q_lock; static spinlock_t fst_work_q_lock;
......
...@@ -92,7 +92,7 @@ static DECLARE_WORK(ap_scan_work, ap_scan_bus); ...@@ -92,7 +92,7 @@ static DECLARE_WORK(ap_scan_work, ap_scan_bus);
* Tasklet & timer for AP request polling and interrupts * Tasklet & timer for AP request polling and interrupts
*/ */
static void ap_tasklet_fn(unsigned long); static void ap_tasklet_fn(unsigned long);
static DECLARE_TASKLET(ap_tasklet, ap_tasklet_fn, 0); static DECLARE_TASKLET_OLD(ap_tasklet, ap_tasklet_fn);
static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
static struct task_struct *ap_poll_kthread; static struct task_struct *ap_poll_kthread;
static DEFINE_MUTEX(ap_poll_thread_mutex); static DEFINE_MUTEX(ap_poll_thread_mutex);
......
...@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a powe ...@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a powe
static DEFINE_SPINLOCK(dim_lock); static DEFINE_SPINLOCK(dim_lock);
static void dim2_tasklet_fn(unsigned long data); static void dim2_tasklet_fn(unsigned long data);
static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0); static DECLARE_TASKLET_OLD(dim2_tasklet, dim2_tasklet_fn);
/** /**
* struct hdm_channel - private structure to keep channel specific data * struct hdm_channel - private structure to keep channel specific data
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#endif #endif
static void cvm_oct_tx_do_cleanup(unsigned long arg); static void cvm_oct_tx_do_cleanup(unsigned long arg);
static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup, 0); static DECLARE_TASKLET_OLD(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup);
/* Maximum number of SKBs to try to free per xmit packet. */ /* Maximum number of SKBs to try to free per xmit packet. */
#define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2) #define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2)
......
...@@ -1236,7 +1236,7 @@ static void kbd_bh(unsigned long dummy) ...@@ -1236,7 +1236,7 @@ static void kbd_bh(unsigned long dummy)
} }
} }
DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); DECLARE_TASKLET_DISABLED_OLD(keyboard_tasklet, kbd_bh);
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
......
...@@ -96,9 +96,7 @@ static int stop_pollstall_timer; ...@@ -96,9 +96,7 @@ static int stop_pollstall_timer;
static DECLARE_COMPLETION(on_pollstall_exit); static DECLARE_COMPLETION(on_pollstall_exit);
/* tasklet for usb disconnect */ /* tasklet for usb disconnect */
static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, static DECLARE_TASKLET_OLD(disconnect_tasklet, udc_tasklet_disconnect);
(unsigned long) &udc);
/* endpoint names used for print */ /* endpoint names used for print */
static const char ep0_string[] = "ep0in"; static const char ep0_string[] = "ep0in";
...@@ -1661,7 +1659,7 @@ static void usb_disconnect(struct udc *dev) ...@@ -1661,7 +1659,7 @@ static void usb_disconnect(struct udc *dev)
/* Tasklet for disconnect to be outside of interrupt context */ /* Tasklet for disconnect to be outside of interrupt context */
static void udc_tasklet_disconnect(unsigned long par) static void udc_tasklet_disconnect(unsigned long par)
{ {
struct udc *dev = (struct udc *)(*((struct udc **) par)); struct udc *dev = udc;
u32 tmp; u32 tmp;
DBG(dev, "Tasklet disconnect\n"); DBG(dev, "Tasklet disconnect\n");
......
...@@ -677,7 +677,7 @@ static void process_done_list(unsigned long data) ...@@ -677,7 +677,7 @@ static void process_done_list(unsigned long data)
enable_irq(fhci_to_hcd(fhci)->irq); enable_irq(fhci_to_hcd(fhci)->irq);
} }
DECLARE_TASKLET(fhci_tasklet, process_done_list, 0); DECLARE_TASKLET_OLD(fhci_tasklet, process_done_list);
/* transfer complted callback */ /* transfer complted callback */
u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci) u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci)
......
...@@ -585,6 +585,9 @@ static inline struct task_struct *this_cpu_ksoftirqd(void) ...@@ -585,6 +585,9 @@ static inline struct task_struct *this_cpu_ksoftirqd(void)
/* Tasklets --- multithreaded analogue of BHs. /* Tasklets --- multithreaded analogue of BHs.
This API is deprecated. Please consider using threaded IRQs instead:
https://lore.kernel.org/lkml/20200716081538.2sivhkj4hcyrusem@linutronix.de
Main feature differing them of generic softirqs: tasklet Main feature differing them of generic softirqs: tasklet
is running only on one CPU simultaneously. is running only on one CPU simultaneously.
...@@ -608,16 +611,42 @@ struct tasklet_struct ...@@ -608,16 +611,42 @@ struct tasklet_struct
struct tasklet_struct *next; struct tasklet_struct *next;
unsigned long state; unsigned long state;
atomic_t count; atomic_t count;
void (*func)(unsigned long); bool use_callback;
union {
void (*func)(unsigned long data);
void (*callback)(struct tasklet_struct *t);
};
unsigned long data; unsigned long data;
}; };
#define DECLARE_TASKLET(name, func, data) \ #define DECLARE_TASKLET(name, _callback) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data } struct tasklet_struct name = { \
.count = ATOMIC_INIT(0), \
.callback = _callback, \
.use_callback = true, \
}
#define DECLARE_TASKLET_DISABLED(name, _callback) \
struct tasklet_struct name = { \
.count = ATOMIC_INIT(1), \
.callback = _callback, \
.use_callback = true, \
}
#define DECLARE_TASKLET_DISABLED(name, func, data) \ #define from_tasklet(var, callback_tasklet, tasklet_fieldname) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data } container_of(callback_tasklet, typeof(*var), tasklet_fieldname)
#define DECLARE_TASKLET_OLD(name, _func) \
struct tasklet_struct name = { \
.count = ATOMIC_INIT(0), \
.func = _func, \
}
#define DECLARE_TASKLET_DISABLED_OLD(name, _func) \
struct tasklet_struct name = { \
.count = ATOMIC_INIT(1), \
.func = _func, \
}
enum enum
{ {
...@@ -686,6 +715,8 @@ extern void tasklet_kill(struct tasklet_struct *t); ...@@ -686,6 +715,8 @@ extern void tasklet_kill(struct tasklet_struct *t);
extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu); extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
extern void tasklet_init(struct tasklet_struct *t, extern void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data); void (*func)(unsigned long), unsigned long data);
extern void tasklet_setup(struct tasklet_struct *t,
void (*callback)(struct tasklet_struct *));
/* /*
* Autoprobing for irqs: * Autoprobing for irqs:
......
...@@ -29,7 +29,7 @@ static void backtrace_test_irq_callback(unsigned long data) ...@@ -29,7 +29,7 @@ static void backtrace_test_irq_callback(unsigned long data)
complete(&backtrace_work); complete(&backtrace_work);
} }
static DECLARE_TASKLET(backtrace_tasklet, &backtrace_test_irq_callback, 0); static DECLARE_TASKLET_OLD(backtrace_tasklet, &backtrace_test_irq_callback);
static void backtrace_test_irq(void) static void backtrace_test_irq(void)
{ {
......
...@@ -1068,7 +1068,7 @@ static void kgdb_tasklet_bpt(unsigned long ing) ...@@ -1068,7 +1068,7 @@ static void kgdb_tasklet_bpt(unsigned long ing)
atomic_set(&kgdb_break_tasklet_var, 0); atomic_set(&kgdb_break_tasklet_var, 0);
} }
static DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0); static DECLARE_TASKLET_OLD(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt);
void kgdb_schedule_breakpoint(void) void kgdb_schedule_breakpoint(void)
{ {
......
...@@ -45,7 +45,7 @@ static void resend_irqs(unsigned long arg) ...@@ -45,7 +45,7 @@ static void resend_irqs(unsigned long arg)
} }
/* Tasklet to handle resend: */ /* Tasklet to handle resend: */
static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0); static DECLARE_TASKLET_OLD(resend_tasklet, resend_irqs);
static int irq_sw_resend(struct irq_desc *desc) static int irq_sw_resend(struct irq_desc *desc)
{ {
......
...@@ -553,7 +553,10 @@ static void tasklet_action_common(struct softirq_action *a, ...@@ -553,7 +553,10 @@ static void tasklet_action_common(struct softirq_action *a,
if (!test_and_clear_bit(TASKLET_STATE_SCHED, if (!test_and_clear_bit(TASKLET_STATE_SCHED,
&t->state)) &t->state))
BUG(); BUG();
t->func(t->data); if (t->use_callback)
t->callback(t);
else
t->func(t->data);
tasklet_unlock(t); tasklet_unlock(t);
continue; continue;
} }
...@@ -579,6 +582,18 @@ static __latent_entropy void tasklet_hi_action(struct softirq_action *a) ...@@ -579,6 +582,18 @@ static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ); tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
} }
void tasklet_setup(struct tasklet_struct *t,
void (*callback)(struct tasklet_struct *))
{
t->next = NULL;
t->state = 0;
atomic_set(&t->count, 0);
t->callback = callback;
t->use_callback = true;
t->data = 0;
}
EXPORT_SYMBOL(tasklet_setup);
void tasklet_init(struct tasklet_struct *t, void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data) void (*func)(unsigned long), unsigned long data)
{ {
...@@ -586,6 +601,7 @@ void tasklet_init(struct tasklet_struct *t, ...@@ -586,6 +601,7 @@ void tasklet_init(struct tasklet_struct *t,
t->state = 0; t->state = 0;
atomic_set(&t->count, 0); atomic_set(&t->count, 0);
t->func = func; t->func = func;
t->use_callback = false;
t->data = data; t->data = data;
} }
EXPORT_SYMBOL(tasklet_init); EXPORT_SYMBOL(tasklet_init);
......
...@@ -393,7 +393,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg) ...@@ -393,7 +393,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
* Each PPPoATM instance has its own tasklet - this is just a * Each PPPoATM instance has its own tasklet - this is just a
* prototypical one used to initialize them * prototypical one used to initialize them
*/ */
static const DECLARE_TASKLET(tasklet_proto, pppoatm_wakeup_sender, 0); static const DECLARE_TASKLET_OLD(tasklet_proto, pppoatm_wakeup_sender);
if (copy_from_user(&be, arg, sizeof be)) if (copy_from_user(&be, arg, sizeof be))
return -EFAULT; return -EFAULT;
if (be.encaps != PPPOATM_ENCAPS_AUTODETECT && if (be.encaps != PPPOATM_ENCAPS_AUTODETECT &&
......
...@@ -105,7 +105,7 @@ static LIST_HEAD(iucv_task_queue); ...@@ -105,7 +105,7 @@ static LIST_HEAD(iucv_task_queue);
* The tasklet for fast delivery of iucv interrupts. * The tasklet for fast delivery of iucv interrupts.
*/ */
static void iucv_tasklet_fn(unsigned long); static void iucv_tasklet_fn(unsigned long);
static DECLARE_TASKLET(iucv_tasklet, iucv_tasklet_fn,0); static DECLARE_TASKLET_OLD(iucv_tasklet, iucv_tasklet_fn);
/* /*
* Queue of interrupt buffers for delivery via a work queue * Queue of interrupt buffers for delivery via a work queue
......
...@@ -36,7 +36,7 @@ static void pcsp_call_pcm_elapsed(unsigned long priv) ...@@ -36,7 +36,7 @@ static void pcsp_call_pcm_elapsed(unsigned long priv)
} }
} }
static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); static DECLARE_TASKLET_OLD(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed);
/* write the port and returns the next expire time in ns; /* write the port and returns the next expire time in ns;
* called at the trigger-start and in hrtimer callback * called at the trigger-start and in hrtimer callback
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment