Branch data Line data Source code
1 : : #include <linux/kernel.h>
2 : : #include <linux/module.h>
3 : : #include <linux/init.h>
4 : : #include <linux/blkdev.h>
5 : : #include <linux/list.h>
6 : : #include <linux/llist.h>
7 : : #include <linux/smp.h>
8 : : #include <linux/cpu.h>
9 : :
10 : : #include <linux/blk-mq.h>
11 : : #include "blk-mq.h"
12 : :
13 : : static LIST_HEAD(blk_mq_cpu_notify_list);
14 : : static DEFINE_SPINLOCK(blk_mq_cpu_notify_lock);
15 : :
16 : 0 : static int blk_mq_main_cpu_notify(struct notifier_block *self,
17 : : unsigned long action, void *hcpu)
18 : : {
19 : 0 : unsigned int cpu = (unsigned long) hcpu;
20 : : struct blk_mq_cpu_notifier *notify;
21 : :
22 : : spin_lock(&blk_mq_cpu_notify_lock);
23 : :
24 [ # # ]: 0 : list_for_each_entry(notify, &blk_mq_cpu_notify_list, list)
25 : 0 : notify->notify(notify->data, action, cpu);
26 : :
27 : : spin_unlock(&blk_mq_cpu_notify_lock);
28 : 0 : return NOTIFY_OK;
29 : : }
30 : :
31 : 0 : static void blk_mq_cpu_notify(void *data, unsigned long action,
32 : : unsigned int cpu)
33 : : {
34 [ # # ]: 0 : if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
35 : : /*
36 : : * If the CPU goes away, ensure that we run any pending
37 : : * completions.
38 : : */
39 : : struct llist_node *node;
40 : : struct request *rq;
41 : :
42 : : local_irq_disable();
43 : :
44 : 0 : node = llist_del_all(&per_cpu(ipi_lists, cpu));
45 [ # # ]: 0 : while (node) {
46 : 0 : struct llist_node *next = node->next;
47 : :
48 : : rq = llist_entry(node, struct request, ll_list);
49 : 0 : __blk_mq_end_io(rq, rq->errors);
50 : : node = next;
51 : : }
52 : :
53 : : local_irq_enable();
54 : : }
55 : 0 : }
56 : :
57 : : static struct notifier_block __cpuinitdata blk_mq_main_cpu_notifier = {
58 : : .notifier_call = blk_mq_main_cpu_notify,
59 : : };
60 : :
61 : 0 : void blk_mq_register_cpu_notifier(struct blk_mq_cpu_notifier *notifier)
62 : : {
63 [ # # ]: 0 : BUG_ON(!notifier->notify);
64 : :
65 : : spin_lock(&blk_mq_cpu_notify_lock);
66 : 0 : list_add_tail(¬ifier->list, &blk_mq_cpu_notify_list);
67 : : spin_unlock(&blk_mq_cpu_notify_lock);
68 : 0 : }
69 : :
70 : 0 : void blk_mq_unregister_cpu_notifier(struct blk_mq_cpu_notifier *notifier)
71 : : {
72 : : spin_lock(&blk_mq_cpu_notify_lock);
73 : : list_del(¬ifier->list);
74 : : spin_unlock(&blk_mq_cpu_notify_lock);
75 : 0 : }
76 : :
77 : 0 : void blk_mq_init_cpu_notifier(struct blk_mq_cpu_notifier *notifier,
78 : : void (*fn)(void *, unsigned long, unsigned int),
79 : : void *data)
80 : : {
81 : 0 : notifier->notify = fn;
82 : 0 : notifier->data = data;
83 : 0 : }
84 : :
85 : : static struct blk_mq_cpu_notifier __cpuinitdata cpu_notifier = {
86 : : .notify = blk_mq_cpu_notify,
87 : : };
88 : :
89 : 0 : void __init blk_mq_cpu_init(void)
90 : : {
91 : 0 : register_hotcpu_notifier(&blk_mq_main_cpu_notifier);
92 : 0 : blk_mq_register_cpu_notifier(&cpu_notifier);
93 : 0 : }
|