diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-05-30 06:45:12 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-05-30 06:46:21 -0400 |
commit | ee7dbd974797e6dcbfd0df6d3c2d95a5a55ac0c8 (patch) | |
tree | a153475f8949a8c9d6340b4f52c37b8912d0622d /kernel | |
parent | 9ce64f192d161acff17c99ceec7d9ce3db9252fa (diff) | |
parent | 6bdd533cee9aadbcd476af30bfff079abe68fcdb (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.c | 11 | ||||
-rw-r--r-- | kernel/bpf/syscall.c | 7 | ||||
-rw-r--r-- | kernel/trace/bpf_trace.c | 2 |
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 { |