aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-23 21:45:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-23 21:45:06 -0500
commit048ccca8c1c8f583deec3367d7df521bb1f542ae (patch)
treeefa882c88f658f711d63581a3063203c63682338 /lib
parentb3e27d5d4a29bcc8e057b496d5ef5194addaaac0 (diff)
parent34356f64ac0df2326fa50e2d4bca6f7c03ed16c1 (diff)
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
Pull rdma updates from Doug Ledford: "Initial roundup of 4.5 merge window patches - Remove usage of ib_query_device and instead store attributes in ib_device struct - Move iopoll out of block and into lib, rename to irqpoll, and use in several places in the rdma stack as our new completion queue polling library mechanism. Update the other block drivers that already used iopoll to use the new mechanism too. - Replace the per-entry GID table locks with a single GID table lock - IPoIB multicast cleanup - Cleanups to the IB MR facility - Add support for 64bit extended IB counters - Fix for netlink oops while parsing RDMA nl messages - RoCEv2 support for the core IB code - mlx4 RoCEv2 support - mlx5 RoCEv2 support - Cross Channel support for mlx5 - Timestamp support for mlx5 - Atomic support for mlx5 - Raw QP support for mlx5 - MAINTAINERS update for mlx4/mlx5 - Misc ocrdma, qib, nes, usNIC, cxgb3, cxgb4, mlx4, mlx5 updates - Add support for remote invalidate to the iSER driver (pushed through the RDMA tree due to dependencies, acknowledged by nab) - Update to NFSoRDMA (pushed through the RDMA tree due to dependencies, acknowledged by Bruce)" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma: (169 commits) IB/mlx5: Unify CQ create flags check IB/mlx5: Expose Raw Packet QP to user space consumers {IB, net}/mlx5: Move the modify QP operation table to mlx5_ib IB/mlx5: Support setting Ethernet priority for Raw Packet QPs IB/mlx5: Add Raw Packet QP query functionality IB/mlx5: Add create and destroy functionality for Raw Packet QP IB/mlx5: Refactor mlx5_ib_qp to accommodate other QP types IB/mlx5: Allocate a Transport Domain for each ucontext net/mlx5_core: Warn on unsupported events of QP/RQ/SQ net/mlx5_core: Add RQ and SQ event handling net/mlx5_core: Export transport objects IB/mlx5: Expose CQE version to user-space IB/mlx5: Add CQE version 1 support to user QPs and SRQs IB/mlx5: Fix data validation in mlx5_ib_alloc_ucontext IB/sa: Fix netlink local service GFP crash IB/srpt: Remove redundant wc array IB/qib: Improve ipoib UD performance IB/mlx4: Advertise RoCE v2 support IB/mlx4: Create and use another QP1 for RoCEv2 IB/mlx4: Enable send of RoCE QP1 packets with IP/UDP headers ...
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig5
-rw-r--r--lib/Makefile1
-rw-r--r--lib/irq_poll.c222
3 files changed, 228 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 435f7315bc89..133ebc0c1773 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -477,6 +477,11 @@ config DDR
477 information. This data is useful for drivers handling 477 information. This data is useful for drivers handling
478 DDR SDRAM controllers. 478 DDR SDRAM controllers.
479 479
480config IRQ_POLL
481 bool "IRQ polling library"
482 help
483 Helper library to poll interrupt mitigation using polling.
484
480config MPILIB 485config MPILIB
481 tristate 486 tristate
482 select CLZ_TAB 487 select CLZ_TAB
diff --git a/lib/Makefile b/lib/Makefile
index 2d4bc33d09b4..a7c26a41a738 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -165,6 +165,7 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o
165 165
166obj-$(CONFIG_SG_SPLIT) += sg_split.o 166obj-$(CONFIG_SG_SPLIT) += sg_split.o
167obj-$(CONFIG_STMP_DEVICE) += stmp_device.o 167obj-$(CONFIG_STMP_DEVICE) += stmp_device.o
168obj-$(CONFIG_IRQ_POLL) += irq_poll.o
168 169
169libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ 170libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \
170 fdt_empty_tree.o 171 fdt_empty_tree.o
diff --git a/lib/irq_poll.c b/lib/irq_poll.c
new file mode 100644
index 000000000000..836f7db4e548
--- /dev/null
+++ b/lib/irq_poll.c
@@ -0,0 +1,222 @@
1/*
2 * Functions related to interrupt-poll handling in the block layer. This
3 * is similar to NAPI for network devices.
4 */
5#include <linux/kernel.h>
6#include <linux/module.h>
7#include <linux/init.h>
8#include <linux/bio.h>
9#include <linux/interrupt.h>
10#include <linux/cpu.h>
11#include <linux/irq_poll.h>
12#include <linux/delay.h>
13
14static unsigned int irq_poll_budget __read_mostly = 256;
15
16static DEFINE_PER_CPU(struct list_head, blk_cpu_iopoll);
17
18/**
19 * irq_poll_sched - Schedule a run of the iopoll handler
20 * @iop: The parent iopoll structure
21 *
22 * Description:
23 * Add this irq_poll structure to the pending poll list and trigger the
24 * raise of the blk iopoll softirq.
25 **/
26void irq_poll_sched(struct irq_poll *iop)
27{
28 unsigned long flags;
29
30 if (test_bit(IRQ_POLL_F_DISABLE, &iop->state))
31 return;
32 if (test_and_set_bit(IRQ_POLL_F_SCHED, &iop->state))
33 return;
34
35 local_irq_save(flags);
36 list_add_tail(&iop->list, this_cpu_ptr(&blk_cpu_iopoll));
37 __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
38 local_irq_restore(flags);
39}
40EXPORT_SYMBOL(irq_poll_sched);
41
42/**
43 * __irq_poll_complete - Mark this @iop as un-polled again
44 * @iop: The parent iopoll structure
45 *
46 * Description:
47 * See irq_poll_complete(). This function must be called with interrupts
48 * disabled.
49 **/
50static void __irq_poll_complete(struct irq_poll *iop)
51{
52 list_del(&iop->list);
53 smp_mb__before_atomic();
54 clear_bit_unlock(IRQ_POLL_F_SCHED, &iop->state);
55}
56
57/**
58 * irq_poll_complete - Mark this @iop as un-polled again
59 * @iop: The parent iopoll structure
60 *
61 * Description:
62 * If a driver consumes less than the assigned budget in its run of the
63 * iopoll handler, it'll end the polled mode by calling this function. The
64 * iopoll handler will not be invoked again before irq_poll_sched()
65 * is called.
66 **/
67void irq_poll_complete(struct irq_poll *iop)
68{
69 unsigned long flags;
70
71 local_irq_save(flags);
72 __irq_poll_complete(iop);
73 local_irq_restore(flags);
74}
75EXPORT_SYMBOL(irq_poll_complete);
76
77static void irq_poll_softirq(struct softirq_action *h)
78{
79 struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll);
80 int rearm = 0, budget = irq_poll_budget;
81 unsigned long start_time = jiffies;
82
83 local_irq_disable();
84
85 while (!list_empty(list)) {
86 struct irq_poll *iop;
87 int work, weight;
88
89 /*
90 * If softirq window is exhausted then punt.
91 */
92 if (budget <= 0 || time_after(jiffies, start_time)) {
93 rearm = 1;
94 break;
95 }
96
97 local_irq_enable();
98
99 /* Even though interrupts have been re-enabled, this
100 * access is safe because interrupts can only add new
101 * entries to the tail of this list, and only ->poll()
102 * calls can remove this head entry from the list.
103 */
104 iop = list_entry(list->next, struct irq_poll, list);
105
106 weight = iop->weight;
107 work = 0;
108 if (test_bit(IRQ_POLL_F_SCHED, &iop->state))
109 work = iop->poll(iop, weight);
110
111 budget -= work;
112
113 local_irq_disable();
114
115 /*
116 * Drivers must not modify the iopoll state, if they
117 * consume their assigned weight (or more, some drivers can't
118 * easily just stop processing, they have to complete an
119 * entire mask of commands).In such cases this code
120 * still "owns" the iopoll instance and therefore can
121 * move the instance around on the list at-will.
122 */
123 if (work >= weight) {
124 if (test_bit(IRQ_POLL_F_DISABLE, &iop->state))
125 __irq_poll_complete(iop);
126 else
127 list_move_tail(&iop->list, list);
128 }
129 }
130
131 if (rearm)
132 __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
133
134 local_irq_enable();
135}
136
137/**
138 * irq_poll_disable - Disable iopoll on this @iop
139 * @iop: The parent iopoll structure
140 *
141 * Description:
142 * Disable io polling and wait for any pending callbacks to have completed.
143 **/
144void irq_poll_disable(struct irq_poll *iop)
145{
146 set_bit(IRQ_POLL_F_DISABLE, &iop->state);
147 while (test_and_set_bit(IRQ_POLL_F_SCHED, &iop->state))
148 msleep(1);
149 clear_bit(IRQ_POLL_F_DISABLE, &iop->state);
150}
151EXPORT_SYMBOL(irq_poll_disable);
152
153/**
154 * irq_poll_enable - Enable iopoll on this @iop
155 * @iop: The parent iopoll structure
156 *
157 * Description:
158 * Enable iopoll on this @iop. Note that the handler run will not be
159 * scheduled, it will only mark it as active.
160 **/
161void irq_poll_enable(struct irq_poll *iop)
162{
163 BUG_ON(!test_bit(IRQ_POLL_F_SCHED, &iop->state));
164 smp_mb__before_atomic();
165 clear_bit_unlock(IRQ_POLL_F_SCHED, &iop->state);
166}
167EXPORT_SYMBOL(irq_poll_enable);
168
169/**
170 * irq_poll_init - Initialize this @iop
171 * @iop: The parent iopoll structure
172 * @weight: The default weight (or command completion budget)
173 * @poll_fn: The handler to invoke
174 *
175 * Description:
176 * Initialize and enable this irq_poll structure.
177 **/
178void irq_poll_init(struct irq_poll *iop, int weight, irq_poll_fn *poll_fn)
179{
180 memset(iop, 0, sizeof(*iop));
181 INIT_LIST_HEAD(&iop->list);
182 iop->weight = weight;
183 iop->poll = poll_fn;
184}
185EXPORT_SYMBOL(irq_poll_init);
186
187static int irq_poll_cpu_notify(struct notifier_block *self,
188 unsigned long action, void *hcpu)
189{
190 /*
191 * If a CPU goes away, splice its entries to the current CPU
192 * and trigger a run of the softirq
193 */
194 if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
195 int cpu = (unsigned long) hcpu;
196
197 local_irq_disable();
198 list_splice_init(&per_cpu(blk_cpu_iopoll, cpu),
199 this_cpu_ptr(&blk_cpu_iopoll));
200 __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
201 local_irq_enable();
202 }
203
204 return NOTIFY_OK;
205}
206
207static struct notifier_block irq_poll_cpu_notifier = {
208 .notifier_call = irq_poll_cpu_notify,
209};
210
211static __init int irq_poll_setup(void)
212{
213 int i;
214
215 for_each_possible_cpu(i)
216 INIT_LIST_HEAD(&per_cpu(blk_cpu_iopoll, i));
217
218 open_softirq(IRQ_POLL_SOFTIRQ, irq_poll_softirq);
219 register_hotcpu_notifier(&irq_poll_cpu_notifier);
220 return 0;
221}
222subsys_initcall(irq_poll_setup);