aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2018-05-30 06:45:12 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-05-30 06:46:21 -0400
commitee7dbd974797e6dcbfd0df6d3c2d95a5a55ac0c8 (patch)
treea153475f8949a8c9d6340b4f52c37b8912d0622d /kernel
parent9ce64f192d161acff17c99ceec7d9ce3db9252fa (diff)
parent6bdd533cee9aadbcd476af30bfff079abe68fcdb (diff)
Merge branch 'bpf-ir-decoder'
Sean Young says: ==================== The kernel IR decoders (drivers/media/rc/ir-*-decoder.c) support the most widely used IR protocols, but there are many protocols which are not supported[1]. For example, the lirc-remotes[2] repo has over 2700 remotes, many of which are not supported by rc-core. There is a "long tail" of unsupported IR protocols, for which lircd is need to decode the IR . IR encoding is done in such a way that some simple circuit can decode it; therefore, bpf is ideal. In order to support all these protocols, here we have bpf based IR decoding. The idea is that user-space can define a decoder in bpf, attach it to the rc device through the lirc chardev. Separate work is underway to extend ir-keytable to have an extensive library of bpf-based decoders, and a much expanded library of rc keymaps. Another future application would be to compile IRP[3] to a IR BPF program, and so support virtually every remote without having to write a decoder for each. It might also be possible to support non-button devices such as analog directional pads or air conditioning remote controls and decode the target temperature in bpf, and pass that to an input device. [1] http://www.hifi-remote.com/wiki/index.php?title=DecodeIR [2] https://sourceforge.net/p/lirc-remotes/code/ci/master/tree/remotes/ [3] http://www.hifi-remote.com/wiki/index.php?title=IRP_Notation Changes since v4: - Renamed rc_dev_bpf_{attach,detach,query} to lirc_bpf_{attach,detach,query} - Fixed error path in lirc_bpf_query - Rebased on bpf-next Changes since v3: - Implemented review comments from Quentin Monnet and Y Song (thanks!) - More helpful and better formatted bpf helper documentation - Changed back to bpf_prog_array rather than open-coded implementation - scancodes can be 64 bit - bpf gets passed values in microseconds, not nanoseconds. microseconds is more than than enough (IR receivers support carriers upto 70kHz, at which point a single period is already 14 microseconds). Also, this makes it much more consistent with lirc mode2. - Since it looks much more like lirc mode2, rename the program type to BPF_PROG_TYPE_LIRC_MODE2. - Rebased on bpf-next Changes since v2: - Fixed locking issues - Improved self-test to cover more cases - Rebased on bpf-next again Changes since v1: - Code review comments from Y Song <ys114321@gmail.com> and Randy Dunlap <rdunlap@infradead.org> - Re-wrote sample bpf to be selftest - Renamed RAWIR_DECODER -> RAWIR_EVENT (Kconfig, context, bpf prog type) - Rebase on bpf-next - Introduced bpf_rawir_event context structure with simpler access checking ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/core.c11
-rw-r--r--kernel/bpf/syscall.c7
-rw-r--r--kernel/trace/bpf_trace.c2
3 files changed, 18 insertions, 2 deletions
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index b574dddc05b8..527587de8a67 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1616,6 +1616,7 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
1616 int new_prog_cnt, carry_prog_cnt = 0; 1616 int new_prog_cnt, carry_prog_cnt = 0;
1617 struct bpf_prog **existing_prog; 1617 struct bpf_prog **existing_prog;
1618 struct bpf_prog_array *array; 1618 struct bpf_prog_array *array;
1619 bool found_exclude = false;
1619 int new_prog_idx = 0; 1620 int new_prog_idx = 0;
1620 1621
1621 /* Figure out how many existing progs we need to carry over to 1622 /* Figure out how many existing progs we need to carry over to
@@ -1624,14 +1625,20 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
1624 if (old_array) { 1625 if (old_array) {
1625 existing_prog = old_array->progs; 1626 existing_prog = old_array->progs;
1626 for (; *existing_prog; existing_prog++) { 1627 for (; *existing_prog; existing_prog++) {
1627 if (*existing_prog != exclude_prog && 1628 if (*existing_prog == exclude_prog) {
1628 *existing_prog != &dummy_bpf_prog.prog) 1629 found_exclude = true;
1630 continue;
1631 }
1632 if (*existing_prog != &dummy_bpf_prog.prog)
1629 carry_prog_cnt++; 1633 carry_prog_cnt++;
1630 if (*existing_prog == include_prog) 1634 if (*existing_prog == include_prog)
1631 return -EEXIST; 1635 return -EEXIST;
1632 } 1636 }
1633 } 1637 }
1634 1638
1639 if (exclude_prog && !found_exclude)
1640 return -ENOENT;
1641
1635 /* How many progs (not NULL) will be in the new array? */ 1642 /* How many progs (not NULL) will be in the new array? */
1636 new_prog_cnt = carry_prog_cnt; 1643 new_prog_cnt = carry_prog_cnt;
1637 if (include_prog) 1644 if (include_prog)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index e254526d6744..7365d79ae00d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -11,6 +11,7 @@
11 */ 11 */
12#include <linux/bpf.h> 12#include <linux/bpf.h>
13#include <linux/bpf_trace.h> 13#include <linux/bpf_trace.h>
14#include <linux/bpf_lirc.h>
14#include <linux/btf.h> 15#include <linux/btf.h>
15#include <linux/syscalls.h> 16#include <linux/syscalls.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
@@ -1582,6 +1583,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1582 case BPF_SK_SKB_STREAM_PARSER: 1583 case BPF_SK_SKB_STREAM_PARSER:
1583 case BPF_SK_SKB_STREAM_VERDICT: 1584 case BPF_SK_SKB_STREAM_VERDICT:
1584 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, true); 1585 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, true);
1586 case BPF_LIRC_MODE2:
1587 return lirc_prog_attach(attr);
1585 default: 1588 default:
1586 return -EINVAL; 1589 return -EINVAL;
1587 } 1590 }
@@ -1654,6 +1657,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
1654 case BPF_SK_SKB_STREAM_PARSER: 1657 case BPF_SK_SKB_STREAM_PARSER:
1655 case BPF_SK_SKB_STREAM_VERDICT: 1658 case BPF_SK_SKB_STREAM_VERDICT:
1656 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, false); 1659 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, false);
1660 case BPF_LIRC_MODE2:
1661 return lirc_prog_detach(attr);
1657 default: 1662 default:
1658 return -EINVAL; 1663 return -EINVAL;
1659 } 1664 }
@@ -1703,6 +1708,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
1703 case BPF_CGROUP_SOCK_OPS: 1708 case BPF_CGROUP_SOCK_OPS:
1704 case BPF_CGROUP_DEVICE: 1709 case BPF_CGROUP_DEVICE:
1705 break; 1710 break;
1711 case BPF_LIRC_MODE2:
1712 return lirc_prog_query(attr, uattr);
1706 default: 1713 default:
1707 return -EINVAL; 1714 return -EINVAL;
1708 } 1715 }
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 81fdf2fc94ac..af1486d9a0ed 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1006,6 +1006,8 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
1006 1006
1007 old_array = event->tp_event->prog_array; 1007 old_array = event->tp_event->prog_array;
1008 ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array); 1008 ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array);
1009 if (ret == -ENOENT)
1010 goto unlock;
1009 if (ret < 0) { 1011 if (ret < 0) {
1010 bpf_prog_array_delete_safe(old_array, event->prog); 1012 bpf_prog_array_delete_safe(old_array, event->prog);
1011 } else { 1013 } else {