mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) Significantly shrink the core networking routing structures. Result of http://vger.kernel.org/~davem/seoul2017_netdev_keynote.pdf 2) Add netdevsim driver for testing various offloads, from Jakub Kicinski. 3) Support cross-chip FDB operations in DSA, from Vivien Didelot. 4) Add a 2nd listener hash table for TCP, similar to what was done for UDP. From Martin KaFai Lau. 5) Add eBPF based queue selection to tun, from Jason Wang. 6) Lockless qdisc support, from John Fastabend. 7) SCTP stream interleave support, from Xin Long. 8) Smoother TCP receive autotuning, from Eric Dumazet. 9) Lots of erspan tunneling enhancements, from William Tu. 10) Add true function call support to BPF, from Alexei Starovoitov. 11) Add explicit support for GRO HW offloading, from Michael Chan. 12) Support extack generation in more netlink subsystems. From Alexander Aring, Quentin Monnet, and Jakub Kicinski. 13) Add 1000BaseX, flow control, and EEE support to mvneta driver. From Russell King. 14) Add flow table abstraction to netfilter, from Pablo Neira Ayuso. 15) Many improvements and simplifications to the NFP driver bpf JIT, from Jakub Kicinski. 16) Support for ipv6 non-equal cost multipath routing, from Ido Schimmel. 17) Add resource abstration to devlink, from Arkadi Sharshevsky. 18) Packet scheduler classifier shared filter block support, from Jiri Pirko. 19) Avoid locking in act_csum, from Davide Caratti. 20) devinet_ioctl() simplifications from Al viro. 21) More TCP bpf improvements from Lawrence Brakmo. 22) Add support for onlink ipv6 route flag, similar to ipv4, from David Ahern. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1925 commits) tls: Add support for encryption using async offload accelerator ip6mr: fix stale iterator net/sched: kconfig: Remove blank help texts openvswitch: meter: Use 64-bit arithmetic instead of 32-bit tcp_nv: fix potential integer overflow in tcpnv_acked r8169: fix RTL8168EP take too long to complete driver initialization. qmi_wwan: Add support for Quectel EP06 rtnetlink: enable IFLA_IF_NETNSID for RTM_NEWLINK ipmr: Fix ptrdiff_t print formatting ibmvnic: Wait for device response when changing MAC qlcnic: fix deadlock bug tcp: release sk_frag.page in tcp_disconnect ipv4: Get the address of interface correctly. net_sched: gen_estimator: fix lockdep splat net: macb: Handle HRESP error net/mlx5e: IPoIB, Fix copy-paste bug in flow steering refactoring ipv6: addrconf: break critical section in addrconf_verify_rtnl() ipv6: change route cache aging logic i40e/i40evf: Update DESC_NEEDED value to reflect larger value bnxt_en: cleanup DIM work on device shutdown ...
This commit is contained in:
commit
b2fe5fa686
33
Documentation/ABI/testing/devlink-resource-mlxsw
Normal file
33
Documentation/ABI/testing/devlink-resource-mlxsw
Normal file
@ -0,0 +1,33 @@
|
||||
What: /kvd/
|
||||
Date: 08-Jan-2018
|
||||
KernelVersion: v4.16
|
||||
Contact: mlxsw@mellanox.com
|
||||
Description: The main database in the Spectrum device is a centralized
|
||||
KVD database used for many of the tables used to configure
|
||||
the chip including L2 FDB, L3 LPM, ECMP and more. The KVD
|
||||
is divided into two sections, the first is hash-based table
|
||||
and the second is a linear access table. The division
|
||||
between the linear and hash-based sections is static and
|
||||
require reload before the changes take effect.
|
||||
|
||||
What: /kvd/linear
|
||||
Date: 08-Jan-2018
|
||||
KernelVersion: v4.16
|
||||
Contact: mlxsw@mellanox.com
|
||||
Description: The linear section of the KVD is managed by software as a
|
||||
flat memory accessed using an index.
|
||||
|
||||
What: /kvd/hash_single
|
||||
Date: 08-Jan-2018
|
||||
KernelVersion: v4.16
|
||||
Contact: mlxsw@mellanox.com
|
||||
Description: The hash based section of the KVD is managed by the switch
|
||||
device. Used in case the key size is smaller or equal to
|
||||
64bit.
|
||||
|
||||
What: /kvd/hash_double
|
||||
Date: 08-Jan-2018
|
||||
KernelVersion: v4.16
|
||||
Contact: mlxsw@mellanox.com
|
||||
Description: The hash based section of the KVD is managed by the switch
|
||||
device. Used in case the key is larger than 64 bit.
|
@ -259,3 +259,27 @@ Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Symbolic link to the PHY device this network device is attached
|
||||
to.
|
||||
|
||||
What: /sys/class/net/<iface>/carrier_changes
|
||||
Date: Mar 2014
|
||||
KernelVersion: 3.15
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
32-bit unsigned integer counting the number of times the link has
|
||||
seen a change from UP to DOWN and vice versa
|
||||
|
||||
What: /sys/class/net/<iface>/carrier_up_count
|
||||
Date: Jan 2018
|
||||
KernelVersion: 4.16
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
32-bit unsigned integer counting the number of times the link has
|
||||
been up
|
||||
|
||||
What: /sys/class/net/<iface>/carrier_down_count
|
||||
Date: Jan 2018
|
||||
KernelVersion: 4.16
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
32-bit unsigned integer counting the number of times the link has
|
||||
been down
|
||||
|
519
Documentation/bpf/bpf_devel_QA.txt
Normal file
519
Documentation/bpf/bpf_devel_QA.txt
Normal file
@ -0,0 +1,519 @@
|
||||
This document provides information for the BPF subsystem about various
|
||||
workflows related to reporting bugs, submitting patches, and queueing
|
||||
patches for stable kernels.
|
||||
|
||||
For general information about submitting patches, please refer to
|
||||
Documentation/process/. This document only describes additional specifics
|
||||
related to BPF.
|
||||
|
||||
Reporting bugs:
|
||||
---------------
|
||||
|
||||
Q: How do I report bugs for BPF kernel code?
|
||||
|
||||
A: Since all BPF kernel development as well as bpftool and iproute2 BPF
|
||||
loader development happens through the netdev kernel mailing list,
|
||||
please report any found issues around BPF to the following mailing
|
||||
list:
|
||||
|
||||
netdev@vger.kernel.org
|
||||
|
||||
This may also include issues related to XDP, BPF tracing, etc.
|
||||
|
||||
Given netdev has a high volume of traffic, please also add the BPF
|
||||
maintainers to Cc (from kernel MAINTAINERS file):
|
||||
|
||||
Alexei Starovoitov <ast@kernel.org>
|
||||
Daniel Borkmann <daniel@iogearbox.net>
|
||||
|
||||
In case a buggy commit has already been identified, make sure to keep
|
||||
the actual commit authors in Cc as well for the report. They can
|
||||
typically be identified through the kernel's git tree.
|
||||
|
||||
Please do *not* report BPF issues to bugzilla.kernel.org since it
|
||||
is a guarantee that the reported issue will be overlooked.
|
||||
|
||||
Submitting patches:
|
||||
-------------------
|
||||
|
||||
Q: To which mailing list do I need to submit my BPF patches?
|
||||
|
||||
A: Please submit your BPF patches to the netdev kernel mailing list:
|
||||
|
||||
netdev@vger.kernel.org
|
||||
|
||||
Historically, BPF came out of networking and has always been maintained
|
||||
by the kernel networking community. Although these days BPF touches
|
||||
many other subsystems as well, the patches are still routed mainly
|
||||
through the networking community.
|
||||
|
||||
In case your patch has changes in various different subsystems (e.g.
|
||||
tracing, security, etc), make sure to Cc the related kernel mailing
|
||||
lists and maintainers from there as well, so they are able to review
|
||||
the changes and provide their Acked-by's to the patches.
|
||||
|
||||
Q: Where can I find patches currently under discussion for BPF subsystem?
|
||||
|
||||
A: All patches that are Cc'ed to netdev are queued for review under netdev
|
||||
patchwork project:
|
||||
|
||||
http://patchwork.ozlabs.org/project/netdev/list/
|
||||
|
||||
Those patches which target BPF, are assigned to a 'bpf' delegate for
|
||||
further processing from BPF maintainers. The current queue with
|
||||
patches under review can be found at:
|
||||
|
||||
https://patchwork.ozlabs.org/project/netdev/list/?delegate=77147
|
||||
|
||||
Once the patches have been reviewed by the BPF community as a whole
|
||||
and approved by the BPF maintainers, their status in patchwork will be
|
||||
changed to 'Accepted' and the submitter will be notified by mail. This
|
||||
means that the patches look good from a BPF perspective and have been
|
||||
applied to one of the two BPF kernel trees.
|
||||
|
||||
In case feedback from the community requires a respin of the patches,
|
||||
their status in patchwork will be set to 'Changes Requested', and purged
|
||||
from the current review queue. Likewise for cases where patches would
|
||||
get rejected or are not applicable to the BPF trees (but assigned to
|
||||
the 'bpf' delegate).
|
||||
|
||||
Q: How do the changes make their way into Linux?
|
||||
|
||||
A: There are two BPF kernel trees (git repositories). Once patches have
|
||||
been accepted by the BPF maintainers, they will be applied to one
|
||||
of the two BPF trees:
|
||||
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git/
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/
|
||||
|
||||
The bpf tree itself is for fixes only, whereas bpf-next for features,
|
||||
cleanups or other kind of improvements ("next-like" content). This is
|
||||
analogous to net and net-next trees for networking. Both bpf and
|
||||
bpf-next will only have a master branch in order to simplify against
|
||||
which branch patches should get rebased to.
|
||||
|
||||
Accumulated BPF patches in the bpf tree will regularly get pulled
|
||||
into the net kernel tree. Likewise, accumulated BPF patches accepted
|
||||
into the bpf-next tree will make their way into net-next tree. net and
|
||||
net-next are both run by David S. Miller. From there, they will go
|
||||
into the kernel mainline tree run by Linus Torvalds. To read up on the
|
||||
process of net and net-next being merged into the mainline tree, see
|
||||
the netdev FAQ under:
|
||||
|
||||
Documentation/networking/netdev-FAQ.txt
|
||||
|
||||
Occasionally, to prevent merge conflicts, we might send pull requests
|
||||
to other trees (e.g. tracing) with a small subset of the patches, but
|
||||
net and net-next are always the main trees targeted for integration.
|
||||
|
||||
The pull requests will contain a high-level summary of the accumulated
|
||||
patches and can be searched on netdev kernel mailing list through the
|
||||
following subject lines (yyyy-mm-dd is the date of the pull request):
|
||||
|
||||
pull-request: bpf yyyy-mm-dd
|
||||
pull-request: bpf-next yyyy-mm-dd
|
||||
|
||||
Q: How do I indicate which tree (bpf vs. bpf-next) my patch should be
|
||||
applied to?
|
||||
|
||||
A: The process is the very same as described in the netdev FAQ, so
|
||||
please read up on it. The subject line must indicate whether the
|
||||
patch is a fix or rather "next-like" content in order to let the
|
||||
maintainers know whether it is targeted at bpf or bpf-next.
|
||||
|
||||
For fixes eventually landing in bpf -> net tree, the subject must
|
||||
look like:
|
||||
|
||||
git format-patch --subject-prefix='PATCH bpf' start..finish
|
||||
|
||||
For features/improvements/etc that should eventually land in
|
||||
bpf-next -> net-next, the subject must look like:
|
||||
|
||||
git format-patch --subject-prefix='PATCH bpf-next' start..finish
|
||||
|
||||
If unsure whether the patch or patch series should go into bpf
|
||||
or net directly, or bpf-next or net-next directly, it is not a
|
||||
problem either if the subject line says net or net-next as target.
|
||||
It is eventually up to the maintainers to do the delegation of
|
||||
the patches.
|
||||
|
||||
If it is clear that patches should go into bpf or bpf-next tree,
|
||||
please make sure to rebase the patches against those trees in
|
||||
order to reduce potential conflicts.
|
||||
|
||||
In case the patch or patch series has to be reworked and sent out
|
||||
again in a second or later revision, it is also required to add a
|
||||
version number (v2, v3, ...) into the subject prefix:
|
||||
|
||||
git format-patch --subject-prefix='PATCH net-next v2' start..finish
|
||||
|
||||
When changes have been requested to the patch series, always send the
|
||||
whole patch series again with the feedback incorporated (never send
|
||||
individual diffs on top of the old series).
|
||||
|
||||
Q: What does it mean when a patch gets applied to bpf or bpf-next tree?
|
||||
|
||||
A: It means that the patch looks good for mainline inclusion from
|
||||
a BPF point of view.
|
||||
|
||||
Be aware that this is not a final verdict that the patch will
|
||||
automatically get accepted into net or net-next trees eventually:
|
||||
|
||||
On the netdev kernel mailing list reviews can come in at any point
|
||||
in time. If discussions around a patch conclude that they cannot
|
||||
get included as-is, we will either apply a follow-up fix or drop
|
||||
them from the trees entirely. Therefore, we also reserve to rebase
|
||||
the trees when deemed necessary. After all, the purpose of the tree
|
||||
is to i) accumulate and stage BPF patches for integration into trees
|
||||
like net and net-next, and ii) run extensive BPF test suite and
|
||||
workloads on the patches before they make their way any further.
|
||||
|
||||
Once the BPF pull request was accepted by David S. Miller, then
|
||||
the patches end up in net or net-next tree, respectively, and
|
||||
make their way from there further into mainline. Again, see the
|
||||
netdev FAQ for additional information e.g. on how often they are
|
||||
merged to mainline.
|
||||
|
||||
Q: How long do I need to wait for feedback on my BPF patches?
|
||||
|
||||
A: We try to keep the latency low. The usual time to feedback will
|
||||
be around 2 or 3 business days. It may vary depending on the
|
||||
complexity of changes and current patch load.
|
||||
|
||||
Q: How often do you send pull requests to major kernel trees like
|
||||
net or net-next?
|
||||
|
||||
A: Pull requests will be sent out rather often in order to not
|
||||
accumulate too many patches in bpf or bpf-next.
|
||||
|
||||
As a rule of thumb, expect pull requests for each tree regularly
|
||||
at the end of the week. In some cases pull requests could additionally
|
||||
come also in the middle of the week depending on the current patch
|
||||
load or urgency.
|
||||
|
||||
Q: Are patches applied to bpf-next when the merge window is open?
|
||||
|
||||
A: For the time when the merge window is open, bpf-next will not be
|
||||
processed. This is roughly analogous to net-next patch processing,
|
||||
so feel free to read up on the netdev FAQ about further details.
|
||||
|
||||
During those two weeks of merge window, we might ask you to resend
|
||||
your patch series once bpf-next is open again. Once Linus released
|
||||
a v*-rc1 after the merge window, we continue processing of bpf-next.
|
||||
|
||||
For non-subscribers to kernel mailing lists, there is also a status
|
||||
page run by David S. Miller on net-next that provides guidance:
|
||||
|
||||
http://vger.kernel.org/~davem/net-next.html
|
||||
|
||||
Q: I made a BPF verifier change, do I need to add test cases for
|
||||
BPF kernel selftests?
|
||||
|
||||
A: If the patch has changes to the behavior of the verifier, then yes,
|
||||
it is absolutely necessary to add test cases to the BPF kernel
|
||||
selftests suite. If they are not present and we think they are
|
||||
needed, then we might ask for them before accepting any changes.
|
||||
|
||||
In particular, test_verifier.c is tracking a high number of BPF test
|
||||
cases, including a lot of corner cases that LLVM BPF back end may
|
||||
generate out of the restricted C code. Thus, adding test cases is
|
||||
absolutely crucial to make sure future changes do not accidentally
|
||||
affect prior use-cases. Thus, treat those test cases as: verifier
|
||||
behavior that is not tracked in test_verifier.c could potentially
|
||||
be subject to change.
|
||||
|
||||
Q: When should I add code to samples/bpf/ and when to BPF kernel
|
||||
selftests?
|
||||
|
||||
A: In general, we prefer additions to BPF kernel selftests rather than
|
||||
samples/bpf/. The rationale is very simple: kernel selftests are
|
||||
regularly run by various bots to test for kernel regressions.
|
||||
|
||||
The more test cases we add to BPF selftests, the better the coverage
|
||||
and the less likely it is that those could accidentally break. It is
|
||||
not that BPF kernel selftests cannot demo how a specific feature can
|
||||
be used.
|
||||
|
||||
That said, samples/bpf/ may be a good place for people to get started,
|
||||
so it might be advisable that simple demos of features could go into
|
||||
samples/bpf/, but advanced functional and corner-case testing rather
|
||||
into kernel selftests.
|
||||
|
||||
If your sample looks like a test case, then go for BPF kernel selftests
|
||||
instead!
|
||||
|
||||
Q: When should I add code to the bpftool?
|
||||
|
||||
A: The main purpose of bpftool (under tools/bpf/bpftool/) is to provide
|
||||
a central user space tool for debugging and introspection of BPF programs
|
||||
and maps that are active in the kernel. If UAPI changes related to BPF
|
||||
enable for dumping additional information of programs or maps, then
|
||||
bpftool should be extended as well to support dumping them.
|
||||
|
||||
Q: When should I add code to iproute2's BPF loader?
|
||||
|
||||
A: For UAPI changes related to the XDP or tc layer (e.g. cls_bpf), the
|
||||
convention is that those control-path related changes are added to
|
||||
iproute2's BPF loader as well from user space side. This is not only
|
||||
useful to have UAPI changes properly designed to be usable, but also
|
||||
to make those changes available to a wider user base of major
|
||||
downstream distributions.
|
||||
|
||||
Q: Do you accept patches as well for iproute2's BPF loader?
|
||||
|
||||
A: Patches for the iproute2's BPF loader have to be sent to:
|
||||
|
||||
netdev@vger.kernel.org
|
||||
|
||||
While those patches are not processed by the BPF kernel maintainers,
|
||||
please keep them in Cc as well, so they can be reviewed.
|
||||
|
||||
The official git repository for iproute2 is run by Stephen Hemminger
|
||||
and can be found at:
|
||||
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git/
|
||||
|
||||
The patches need to have a subject prefix of '[PATCH iproute2 master]'
|
||||
or '[PATCH iproute2 net-next]'. 'master' or 'net-next' describes the
|
||||
target branch where the patch should be applied to. Meaning, if kernel
|
||||
changes went into the net-next kernel tree, then the related iproute2
|
||||
changes need to go into the iproute2 net-next branch, otherwise they
|
||||
can be targeted at master branch. The iproute2 net-next branch will get
|
||||
merged into the master branch after the current iproute2 version from
|
||||
master has been released.
|
||||
|
||||
Like BPF, the patches end up in patchwork under the netdev project and
|
||||
are delegated to 'shemminger' for further processing:
|
||||
|
||||
http://patchwork.ozlabs.org/project/netdev/list/?delegate=389
|
||||
|
||||
Q: What is the minimum requirement before I submit my BPF patches?
|
||||
|
||||
A: When submitting patches, always take the time and properly test your
|
||||
patches *prior* to submission. Never rush them! If maintainers find
|
||||
that your patches have not been properly tested, it is a good way to
|
||||
get them grumpy. Testing patch submissions is a hard requirement!
|
||||
|
||||
Note, fixes that go to bpf tree *must* have a Fixes: tag included. The
|
||||
same applies to fixes that target bpf-next, where the affected commit
|
||||
is in net-next (or in some cases bpf-next). The Fixes: tag is crucial
|
||||
in order to identify follow-up commits and tremendously helps for people
|
||||
having to do backporting, so it is a must have!
|
||||
|
||||
We also don't accept patches with an empty commit message. Take your
|
||||
time and properly write up a high quality commit message, it is
|
||||
essential!
|
||||
|
||||
Think about it this way: other developers looking at your code a month
|
||||
from now need to understand *why* a certain change has been done that
|
||||
way, and whether there have been flaws in the analysis or assumptions
|
||||
that the original author did. Thus providing a proper rationale and
|
||||
describing the use-case for the changes is a must.
|
||||
|
||||
Patch submissions with >1 patch must have a cover letter which includes
|
||||
a high level description of the series. This high level summary will
|
||||
then be placed into the merge commit by the BPF maintainers such that
|
||||
it is also accessible from the git log for future reference.
|
||||
|
||||
Q: What do I need to consider when adding a new instruction or feature
|
||||
that would require BPF JIT and/or LLVM integration as well?
|
||||
|
||||
A: We try hard to keep all BPF JITs up to date such that the same user
|
||||
experience can be guaranteed when running BPF programs on different
|
||||
architectures without having the program punt to the less efficient
|
||||
interpreter in case the in-kernel BPF JIT is enabled.
|
||||
|
||||
If you are unable to implement or test the required JIT changes for
|
||||
certain architectures, please work together with the related BPF JIT
|
||||
developers in order to get the feature implemented in a timely manner.
|
||||
Please refer to the git log (arch/*/net/) to locate the necessary
|
||||
people for helping out.
|
||||
|
||||
Also always make sure to add BPF test cases (e.g. test_bpf.c and
|
||||
test_verifier.c) for new instructions, so that they can receive
|
||||
broad test coverage and help run-time testing the various BPF JITs.
|
||||
|
||||
In case of new BPF instructions, once the changes have been accepted
|
||||
into the Linux kernel, please implement support into LLVM's BPF back
|
||||
end. See LLVM section below for further information.
|
||||
|
||||
Stable submission:
|
||||
------------------
|
||||
|
||||
Q: I need a specific BPF commit in stable kernels. What should I do?
|
||||
|
||||
A: In case you need a specific fix in stable kernels, first check whether
|
||||
the commit has already been applied in the related linux-*.y branches:
|
||||
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/
|
||||
|
||||
If not the case, then drop an email to the BPF maintainers with the
|
||||
netdev kernel mailing list in Cc and ask for the fix to be queued up:
|
||||
|
||||
netdev@vger.kernel.org
|
||||
|
||||
The process in general is the same as on netdev itself, see also the
|
||||
netdev FAQ document.
|
||||
|
||||
Q: Do you also backport to kernels not currently maintained as stable?
|
||||
|
||||
A: No. If you need a specific BPF commit in kernels that are currently not
|
||||
maintained by the stable maintainers, then you are on your own.
|
||||
|
||||
The current stable and longterm stable kernels are all listed here:
|
||||
|
||||
https://www.kernel.org/
|
||||
|
||||
Q: The BPF patch I am about to submit needs to go to stable as well. What
|
||||
should I do?
|
||||
|
||||
A: The same rules apply as with netdev patch submissions in general, see
|
||||
netdev FAQ under:
|
||||
|
||||
Documentation/networking/netdev-FAQ.txt
|
||||
|
||||
Never add "Cc: stable@vger.kernel.org" to the patch description, but
|
||||
ask the BPF maintainers to queue the patches instead. This can be done
|
||||
with a note, for example, under the "---" part of the patch which does
|
||||
not go into the git log. Alternatively, this can be done as a simple
|
||||
request by mail instead.
|
||||
|
||||
Q: Where do I find currently queued BPF patches that will be submitted
|
||||
to stable?
|
||||
|
||||
A: Once patches that fix critical bugs got applied into the bpf tree, they
|
||||
are queued up for stable submission under:
|
||||
|
||||
http://patchwork.ozlabs.org/bundle/bpf/stable/?state=*
|
||||
|
||||
They will be on hold there at minimum until the related commit made its
|
||||
way into the mainline kernel tree.
|
||||
|
||||
After having been under broader exposure, the queued patches will be
|
||||
submitted by the BPF maintainers to the stable maintainers.
|
||||
|
||||
Testing patches:
|
||||
----------------
|
||||
|
||||
Q: Which BPF kernel selftests version should I run my kernel against?
|
||||
|
||||
A: If you run a kernel xyz, then always run the BPF kernel selftests from
|
||||
that kernel xyz as well. Do not expect that the BPF selftest from the
|
||||
latest mainline tree will pass all the time.
|
||||
|
||||
In particular, test_bpf.c and test_verifier.c have a large number of
|
||||
test cases and are constantly updated with new BPF test sequences, or
|
||||
existing ones are adapted to verifier changes e.g. due to verifier
|
||||
becoming smarter and being able to better track certain things.
|
||||
|
||||
LLVM:
|
||||
-----
|
||||
|
||||
Q: Where do I find LLVM with BPF support?
|
||||
|
||||
A: The BPF back end for LLVM is upstream in LLVM since version 3.7.1.
|
||||
|
||||
All major distributions these days ship LLVM with BPF back end enabled,
|
||||
so for the majority of use-cases it is not required to compile LLVM by
|
||||
hand anymore, just install the distribution provided package.
|
||||
|
||||
LLVM's static compiler lists the supported targets through 'llc --version',
|
||||
make sure BPF targets are listed. Example:
|
||||
|
||||
$ llc --version
|
||||
LLVM (http://llvm.org/):
|
||||
LLVM version 6.0.0svn
|
||||
Optimized build.
|
||||
Default target: x86_64-unknown-linux-gnu
|
||||
Host CPU: skylake
|
||||
|
||||
Registered Targets:
|
||||
bpf - BPF (host endian)
|
||||
bpfeb - BPF (big endian)
|
||||
bpfel - BPF (little endian)
|
||||
x86 - 32-bit X86: Pentium-Pro and above
|
||||
x86-64 - 64-bit X86: EM64T and AMD64
|
||||
|
||||
For developers in order to utilize the latest features added to LLVM's
|
||||
BPF back end, it is advisable to run the latest LLVM releases. Support
|
||||
for new BPF kernel features such as additions to the BPF instruction
|
||||
set are often developed together.
|
||||
|
||||
All LLVM releases can be found at: http://releases.llvm.org/
|
||||
|
||||
Q: Got it, so how do I build LLVM manually anyway?
|
||||
|
||||
A: You need cmake and gcc-c++ as build requisites for LLVM. Once you have
|
||||
that set up, proceed with building the latest LLVM and clang version
|
||||
from the git repositories:
|
||||
|
||||
$ git clone http://llvm.org/git/llvm.git
|
||||
$ cd llvm/tools
|
||||
$ git clone --depth 1 http://llvm.org/git/clang.git
|
||||
$ cd ..; mkdir build; cd build
|
||||
$ cmake .. -DLLVM_TARGETS_TO_BUILD="BPF;X86" \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DLLVM_BUILD_RUNTIME=OFF
|
||||
$ make -j $(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
The built binaries can then be found in the build/bin/ directory, where
|
||||
you can point the PATH variable to.
|
||||
|
||||
Q: Should I notify BPF kernel maintainers about issues in LLVM's BPF code
|
||||
generation back end or about LLVM generated code that the verifier
|
||||
refuses to accept?
|
||||
|
||||
A: Yes, please do! LLVM's BPF back end is a key piece of the whole BPF
|
||||
infrastructure and it ties deeply into verification of programs from the
|
||||
kernel side. Therefore, any issues on either side need to be investigated
|
||||
and fixed whenever necessary.
|
||||
|
||||
Therefore, please make sure to bring them up at netdev kernel mailing
|
||||
list and Cc BPF maintainers for LLVM and kernel bits:
|
||||
|
||||
Yonghong Song <yhs@fb.com>
|
||||
Alexei Starovoitov <ast@kernel.org>
|
||||
Daniel Borkmann <daniel@iogearbox.net>
|
||||
|
||||
LLVM also has an issue tracker where BPF related bugs can be found:
|
||||
|
||||
https://bugs.llvm.org/buglist.cgi?quicksearch=bpf
|
||||
|
||||
However, it is better to reach out through mailing lists with having
|
||||
maintainers in Cc.
|
||||
|
||||
Q: I have added a new BPF instruction to the kernel, how can I integrate
|
||||
it into LLVM?
|
||||
|
||||
A: LLVM has a -mcpu selector for the BPF back end in order to allow the
|
||||
selection of BPF instruction set extensions. By default the 'generic'
|
||||
processor target is used, which is the base instruction set (v1) of BPF.
|
||||
|
||||
LLVM has an option to select -mcpu=probe where it will probe the host
|
||||
kernel for supported BPF instruction set extensions and selects the
|
||||
optimal set automatically.
|
||||
|
||||
For cross-compilation, a specific version can be select manually as well.
|
||||
|
||||
$ llc -march bpf -mcpu=help
|
||||
Available CPUs for this target:
|
||||
|
||||
generic - Select the generic processor.
|
||||
probe - Select the probe processor.
|
||||
v1 - Select the v1 processor.
|
||||
v2 - Select the v2 processor.
|
||||
[...]
|
||||
|
||||
Newly added BPF instructions to the Linux kernel need to follow the same
|
||||
scheme, bump the instruction set version and implement probing for the
|
||||
extensions such that -mcpu=probe users can benefit from the optimization
|
||||
transparently when upgrading their kernels.
|
||||
|
||||
If you are unable to implement support for the newly added BPF instruction
|
||||
please reach out to BPF developers for help.
|
||||
|
||||
By the way, the BPF kernel selftests run with -mcpu=probe for better
|
||||
test coverage.
|
||||
|
||||
Happy BPF hacking!
|
@ -2,7 +2,10 @@
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be "brcm,bcm7445-switch-v4.0" or "brcm,bcm7278-switch-v4.0"
|
||||
- compatible: should be one of
|
||||
"brcm,bcm7445-switch-v4.0"
|
||||
"brcm,bcm7278-switch-v4.0"
|
||||
"brcm,bcm7278-switch-v4.8"
|
||||
- reg: addresses and length of the register sets for the device, must be 6
|
||||
pairs of register addresses and lengths
|
||||
- interrupts: interrupts for the devices, must be two interrupts
|
||||
|
@ -0,0 +1,24 @@
|
||||
Generic CAN transceiver Device Tree binding
|
||||
------------------------------
|
||||
|
||||
CAN transceiver typically limits the max speed in standard CAN and CAN FD
|
||||
modes. Typically these limitations are static and the transceivers themselves
|
||||
provide no way to detect this limitation at runtime. For this situation,
|
||||
the "can-transceiver" node can be used.
|
||||
|
||||
Required Properties:
|
||||
max-bitrate: a positive non 0 value that determines the max
|
||||
speed that CAN/CAN-FD can run. Any other value
|
||||
will be ignored.
|
||||
|
||||
Examples:
|
||||
|
||||
Based on Texas Instrument's TCAN1042HGV CAN Transceiver
|
||||
|
||||
m_can0 {
|
||||
....
|
||||
can-transceiver {
|
||||
max-bitrate = <5000000>;
|
||||
};
|
||||
...
|
||||
};
|
@ -18,6 +18,12 @@ Optional properties:
|
||||
|
||||
- xceiver-supply: Regulator that powers the CAN transceiver
|
||||
|
||||
- big-endian: This means the registers of FlexCAN controller are big endian.
|
||||
This is optional property.i.e. if this property is not present in
|
||||
device tree node then controller is assumed to be little endian.
|
||||
if this property is present then controller is assumed to be big
|
||||
endian.
|
||||
|
||||
Example:
|
||||
|
||||
can@1c000 {
|
||||
|
@ -43,6 +43,11 @@ Required properties:
|
||||
Please refer to 2.4.1 Message RAM Configuration in
|
||||
Bosch M_CAN user manual for details.
|
||||
|
||||
Optional Subnode:
|
||||
- can-transceiver : Can-transceiver subnode describing maximum speed
|
||||
that can be used for CAN/CAN-FD modes. See
|
||||
Documentation/devicetree/bindings/net/can/can-transceiver.txt
|
||||
for details.
|
||||
Example:
|
||||
SoC dtsi:
|
||||
m_can1: can@20e8000 {
|
||||
@ -63,4 +68,8 @@ Board dts:
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_m_can1>;
|
||||
status = "enabled";
|
||||
|
||||
can-transceiver {
|
||||
max-bitrate = <5000000>;
|
||||
};
|
||||
};
|
||||
|
@ -2,7 +2,9 @@ Renesas R-Car CAN controller Device Tree Bindings
|
||||
-------------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
|
||||
- compatible: "renesas,can-r8a7743" if CAN controller is a part of R8A7743 SoC.
|
||||
"renesas,can-r8a7745" if CAN controller is a part of R8A7745 SoC.
|
||||
"renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
|
||||
"renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC.
|
||||
"renesas,can-r8a7790" if CAN controller is a part of R8A7790 SoC.
|
||||
"renesas,can-r8a7791" if CAN controller is a part of R8A7791 SoC.
|
||||
@ -12,7 +14,8 @@ Required properties:
|
||||
"renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC.
|
||||
"renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC.
|
||||
"renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device.
|
||||
"renesas,rcar-gen2-can" for a generic R-Car Gen2 compatible device.
|
||||
"renesas,rcar-gen2-can" for a generic R-Car Gen2 or RZ/G1
|
||||
compatible device.
|
||||
"renesas,rcar-gen3-can" for a generic R-Car Gen3 compatible device.
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first
|
||||
|
@ -0,0 +1,92 @@
|
||||
Cortina Systems Gemini Ethernet Controller
|
||||
==========================================
|
||||
|
||||
This ethernet controller is found in the Gemini SoC family:
|
||||
StorLink SL3512 and SL3516, also known as Cortina Systems
|
||||
CS3512 and CS3516.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "cortina,gemini-ethernet"
|
||||
- reg: must contain the global registers and the V-bit and A-bit
|
||||
memory areas, in total three register sets.
|
||||
- syscon: a phandle to the system controller
|
||||
- #address-cells: must be specified, must be <1>
|
||||
- #size-cells: must be specified, must be <1>
|
||||
- ranges: should be state like this giving a 1:1 address translation
|
||||
for the subnodes
|
||||
|
||||
The subnodes represents the two ethernet ports in this device.
|
||||
They are not independent of each other since they share resources
|
||||
in the parent node, and are thus children.
|
||||
|
||||
Required subnodes:
|
||||
- port0: contains the resources for ethernet port 0
|
||||
- port1: contains the resources for ethernet port 1
|
||||
|
||||
Required subnode properties:
|
||||
- compatible: must be "cortina,gemini-ethernet-port"
|
||||
- reg: must contain two register areas: the DMA/TOE memory and
|
||||
the GMAC memory area of the port
|
||||
- interrupts: should contain the interrupt line of the port.
|
||||
this is nominally a level interrupt active high.
|
||||
- resets: this must provide an SoC-integrated reset line for
|
||||
the port.
|
||||
- clocks: this should contain a handle to the PCLK clock for
|
||||
clocking the silicon in this port
|
||||
- clock-names: must be "PCLK"
|
||||
|
||||
Optional subnode properties:
|
||||
- phy-mode: see ethernet.txt
|
||||
- phy-handle: see ethernet.txt
|
||||
|
||||
Example:
|
||||
|
||||
mdio-bus {
|
||||
(...)
|
||||
phy0: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
phy1: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
ethernet@60000000 {
|
||||
compatible = "cortina,gemini-ethernet";
|
||||
reg = <0x60000000 0x4000>, /* Global registers, queue */
|
||||
<0x60004000 0x2000>, /* V-bit */
|
||||
<0x60006000 0x2000>; /* A-bit */
|
||||
syscon = <&syscon>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
gmac0: ethernet-port@0 {
|
||||
compatible = "cortina,gemini-ethernet-port";
|
||||
reg = <0x60008000 0x2000>, /* Port 0 DMA/TOE */
|
||||
<0x6000a000 0x2000>; /* Port 0 GMAC */
|
||||
interrupt-parent = <&intcon>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
|
||||
resets = <&syscon GEMINI_RESET_GMAC0>;
|
||||
clocks = <&syscon GEMINI_CLK_GATE_GMAC0>;
|
||||
clock-names = "PCLK";
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
gmac1: ethernet-port@1 {
|
||||
compatible = "cortina,gemini-ethernet-port";
|
||||
reg = <0x6000c000 0x2000>, /* Port 1 DMA/TOE */
|
||||
<0x6000e000 0x2000>; /* Port 1 GMAC */
|
||||
interrupt-parent = <&intcon>;
|
||||
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
|
||||
resets = <&syscon GEMINI_RESET_GMAC1>;
|
||||
clocks = <&syscon GEMINI_CLK_GATE_GMAC1>;
|
||||
clock-names = "PCLK";
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <&phy1>;
|
||||
};
|
||||
};
|
@ -59,7 +59,7 @@ ethernet@83fec000 {
|
||||
reg = <0x83fec000 0x4000>;
|
||||
interrupts = <87>;
|
||||
phy-mode = "mii";
|
||||
phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
|
||||
phy-reset-gpios = <&gpio2 14 GPIO_ACTIVE_LOW>; /* GPIO2_14 */
|
||||
local-mac-address = [00 04 9F 01 1B B9];
|
||||
phy-supply = <®_fec_supply>;
|
||||
};
|
||||
@ -71,7 +71,7 @@ ethernet@83fec000 {
|
||||
reg = <0x83fec000 0x4000>;
|
||||
interrupts = <87>;
|
||||
phy-mode = "mii";
|
||||
phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
|
||||
phy-reset-gpios = <&gpio2 14 GPIO_ACTIVE_LOW>; /* GPIO2_14 */
|
||||
local-mac-address = [00 04 9F 01 1B B9];
|
||||
phy-supply = <®_fec_supply>;
|
||||
phy-handle = <ðphy>;
|
||||
|
@ -1,7 +1,7 @@
|
||||
* ADF7242 IEEE 802.15.4 *
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "adi,adf7242"
|
||||
- compatible: should be "adi,adf7242", "adi,adf7241"
|
||||
- spi-max-frequency: maximal bus speed (12.5 MHz)
|
||||
- reg: the chipselect index
|
||||
- interrupts: the interrupt generated by the device via pin IRQ1.
|
||||
|
@ -28,7 +28,7 @@ Required properties:
|
||||
- mediatek,sgmiisys: phandle to the syscon node that handles the SGMII setup
|
||||
which is required for those SoCs equipped with SGMII such as MT7622 SoC.
|
||||
- mediatek,pctl: phandle to the syscon node that handles the ports slew rate
|
||||
and driver current
|
||||
and driver current: only for MT2701 and MT7623 SoC
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
|
@ -53,6 +53,14 @@ Optional Properties:
|
||||
to ensure the integrated PHY is used. The absence of this property indicates
|
||||
the muxers should be configured so that the external PHY is used.
|
||||
|
||||
- reset-gpios: The GPIO phandle and specifier for the PHY reset signal.
|
||||
|
||||
- reset-assert-us: Delay after the reset was asserted in microseconds.
|
||||
If this property is missing the delay will be skipped.
|
||||
|
||||
- reset-deassert-us: Delay after the reset was deasserted in microseconds.
|
||||
If this property is missing the delay will be skipped.
|
||||
|
||||
Example:
|
||||
|
||||
ethernet-phy@0 {
|
||||
@ -60,4 +68,8 @@ ethernet-phy@0 {
|
||||
interrupt-parent = <&PIC>;
|
||||
interrupts = <35 IRQ_TYPE_EDGE_RISING>;
|
||||
reg = <0>;
|
||||
|
||||
reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
|
||||
reset-assert-us = <1000>;
|
||||
reset-deassert-us = <2000>;
|
||||
};
|
||||
|
@ -3,7 +3,9 @@ Transceiver
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : must be "sff,sfp"
|
||||
- compatible : must be one of
|
||||
"sff,sfp" for SFP modules
|
||||
"sff,sff" for soldered down SFF modules
|
||||
|
||||
Optional Properties:
|
||||
|
||||
@ -11,7 +13,8 @@ Optional Properties:
|
||||
interface
|
||||
|
||||
- mod-def0-gpios : GPIO phandle and a specifier of the MOD-DEF0 (AKA Mod_ABS)
|
||||
module presence input gpio signal, active (module absent) high
|
||||
module presence input gpio signal, active (module absent) high. Must
|
||||
not be present for SFF modules
|
||||
|
||||
- los-gpios : GPIO phandle and a specifier of the Receiver Loss of Signal
|
||||
Indication input gpio signal, active (signal lost) high
|
||||
@ -24,10 +27,11 @@ Optional Properties:
|
||||
|
||||
- rate-select0-gpios : GPIO phandle and a specifier of the Rx Signaling Rate
|
||||
Select (AKA RS0) output gpio signal, low: low Rx rate, high: high Rx rate
|
||||
Must not be present for SFF modules
|
||||
|
||||
- rate-select1-gpios : GPIO phandle and a specifier of the Tx Signaling Rate
|
||||
Select (AKA RS1) output gpio signal (SFP+ only), low: low Tx rate, high:
|
||||
high Tx rate
|
||||
high Tx rate. Must not be present for SFF modules
|
||||
|
||||
Example #1: Direct serdes to SFP connection
|
||||
|
||||
|
@ -0,0 +1,48 @@
|
||||
* Socionext AVE ethernet controller
|
||||
|
||||
This describes the devicetree bindings for AVE ethernet controller
|
||||
implemented on Socionext UniPhier SoCs.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be
|
||||
- "socionext,uniphier-pro4-ave4" : for Pro4 SoC
|
||||
- "socionext,uniphier-pxs2-ave4" : for PXs2 SoC
|
||||
- "socionext,uniphier-ld11-ave4" : for LD11 SoC
|
||||
- "socionext,uniphier-ld20-ave4" : for LD20 SoC
|
||||
- reg: Address where registers are mapped and size of region.
|
||||
- interrupts: Should contain the MAC interrupt.
|
||||
- phy-mode: See ethernet.txt in the same directory. Allow to choose
|
||||
"rgmii", "rmii", or "mii" according to the PHY.
|
||||
- phy-handle: Should point to the external phy device.
|
||||
See ethernet.txt file in the same directory.
|
||||
- clocks: A phandle to the clock for the MAC.
|
||||
|
||||
Optional properties:
|
||||
- resets: A phandle to the reset control for the MAC.
|
||||
- local-mac-address: See ethernet.txt in the same directory.
|
||||
|
||||
Required subnode:
|
||||
- mdio: A container for child nodes representing phy nodes.
|
||||
See phy.txt in the same directory.
|
||||
|
||||
Example:
|
||||
|
||||
ether: ethernet@65000000 {
|
||||
compatible = "socionext,uniphier-ld20-ave4";
|
||||
reg = <0x65000000 0x8500>;
|
||||
interrupts = <0 66 4>;
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <ðphy>;
|
||||
clocks = <&sys_clk 6>;
|
||||
resets = <&sys_rst 6>;
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethphy: ethphy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
};
|
53
Documentation/devicetree/bindings/net/socionext-netsec.txt
Normal file
53
Documentation/devicetree/bindings/net/socionext-netsec.txt
Normal file
@ -0,0 +1,53 @@
|
||||
* Socionext NetSec Ethernet Controller IP
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "socionext,synquacer-netsec"
|
||||
- reg: Address and length of the control register area, followed by the
|
||||
address and length of the EEPROM holding the MAC address and
|
||||
microengine firmware
|
||||
- interrupts: Should contain ethernet controller interrupt
|
||||
- clocks: phandle to the PHY reference clock
|
||||
- clock-names: Should be "phy_ref_clk"
|
||||
- phy-mode: See ethernet.txt file in the same directory
|
||||
- phy-handle: See ethernet.txt in the same directory.
|
||||
|
||||
- mdio device tree subnode: When the Netsec has a phy connected to its local
|
||||
mdio, there must be device tree subnode with the following
|
||||
required properties:
|
||||
|
||||
- #address-cells: Must be <1>.
|
||||
- #size-cells: Must be <0>.
|
||||
|
||||
For each phy on the mdio bus, there must be a node with the following
|
||||
fields:
|
||||
- compatible: Refer to phy.txt
|
||||
- reg: phy id used to communicate to phy.
|
||||
|
||||
Optional properties: (See ethernet.txt file in the same directory)
|
||||
- dma-coherent: Boolean property, must only be present if memory
|
||||
accesses performed by the device are cache coherent.
|
||||
- local-mac-address: See ethernet.txt in the same directory.
|
||||
- mac-address: See ethernet.txt in the same directory.
|
||||
- max-speed: See ethernet.txt in the same directory.
|
||||
- max-frame-size: See ethernet.txt in the same directory.
|
||||
|
||||
Example:
|
||||
eth0: ethernet@522d0000 {
|
||||
compatible = "socionext,synquacer-netsec";
|
||||
reg = <0 0x522d0000 0x0 0x10000>, <0 0x10000000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk_netsec>;
|
||||
clock-names = "phy_ref_clk";
|
||||
phy-mode = "rgmii";
|
||||
max-speed = <1000>;
|
||||
max-frame-size = <9000>;
|
||||
phy-handle = <&phy1>;
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy1: ethernet-phy@1 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
@ -1,10 +1,18 @@
|
||||
TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
|
||||
Texas Instruments Bluetooth Chips
|
||||
---------------------------------
|
||||
|
||||
This documents the binding structure and common properties for serial
|
||||
attached TI Bluetooth devices. The following chips are included in this
|
||||
binding:
|
||||
|
||||
* TI CC256x Bluetooth devices
|
||||
* TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
|
||||
|
||||
TI WiLink devices have a UART interface for providing Bluetooth, FM radio,
|
||||
and GPS over what's called "shared transport". The shared transport is
|
||||
standard BT HCI protocol with additional channels for the other functions.
|
||||
|
||||
These devices also have a separate WiFi interface as described in
|
||||
TI WiLink devices also have a separate WiFi interface as described in
|
||||
wireless/ti,wlcore.txt.
|
||||
|
||||
This bindings follows the UART slave device binding in
|
||||
@ -12,6 +20,7 @@ This bindings follows the UART slave device binding in
|
||||
|
||||
Required properties:
|
||||
- compatible: should be one of the following:
|
||||
"ti,cc2560"
|
||||
"ti,wl1271-st"
|
||||
"ti,wl1273-st"
|
||||
"ti,wl1281-st"
|
||||
@ -32,6 +41,9 @@ Optional properties:
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
- clock-names : Must include the following entry:
|
||||
"ext_clock" (External clock provided to the TI combo chip).
|
||||
- nvmem-cells: phandle to nvmem data cell that contains a 6 byte BD address
|
||||
with the most significant byte first (big-endian).
|
||||
- nvmem-cell-names: "bd-address" (required when nvmem-cells is specified)
|
||||
|
||||
Example:
|
||||
|
||||
@ -43,5 +55,7 @@ Example:
|
||||
enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&clk32k_wl18xx>;
|
||||
clock-names = "ext_clock";
|
||||
nvmem-cells = <&bd_address>;
|
||||
nvmem-cell-names = "bd-address";
|
||||
};
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
* MediaTek mt76xx devices
|
||||
|
||||
This node provides properties for configuring the MediaTek mt76xx wireless
|
||||
device. The node is expected to be specified as a child node of the PCI
|
||||
controller to which the wireless chip is connected.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- mac-address: See ethernet.txt in the parent directory
|
||||
- local-mac-address: See ethernet.txt in the parent directory
|
||||
- ieee80211-freq-limit: See ieee80211.txt
|
||||
- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
|
||||
|
||||
Optional nodes:
|
||||
- led: Properties for a connected LED
|
||||
Optional properties:
|
||||
- led-sources: See Documentation/devicetree/bindings/leds/common.txt
|
||||
|
||||
&pcie {
|
||||
pcie0 {
|
||||
wifi@0,0 {
|
||||
compatible = "mediatek,mt76";
|
||||
reg = <0x0000 0 0 0 0>;
|
||||
ieee80211-freq-limit = <5000000 6000000>;
|
||||
mediatek,mtd-eeprom = <&factory 0x8000>;
|
||||
|
||||
led {
|
||||
led-sources = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -41,6 +41,9 @@ Optional properties:
|
||||
- qcom,msi_addr: MSI interrupt address.
|
||||
- qcom,msi_base: Base value to add before writing MSI data into
|
||||
MSI address register.
|
||||
- qcom,ath10k-calibration-variant: string to search for in the board-2.bin
|
||||
variant list with the same bus and device
|
||||
specific ids
|
||||
- qcom,ath10k-calibration-data : calibration data + board specific data
|
||||
as an array, the length can vary between
|
||||
hw versions.
|
||||
|
@ -195,4 +195,4 @@ External interrupts:
|
||||
|
||||
fsl,mpc5200-mscan nodes
|
||||
-----------------------
|
||||
See file can.txt in this directory.
|
||||
See file Documentation/devicetree/bindings/powerpc/fsl/mpc5200.txt
|
||||
|
@ -30,6 +30,12 @@ o fail_mmc_request
|
||||
injects MMC data errors on devices permitted by setting
|
||||
debugfs entries under /sys/kernel/debug/mmc0/fail_mmc_request
|
||||
|
||||
o fail_function
|
||||
|
||||
injects error return on specific functions, which are marked by
|
||||
ALLOW_ERROR_INJECTION() macro, by setting debugfs entries
|
||||
under /sys/kernel/debug/fail_function. No boot option supported.
|
||||
|
||||
Configure fault-injection capabilities behavior
|
||||
-----------------------------------------------
|
||||
|
||||
@ -123,6 +129,29 @@ configuration of fault-injection capabilities.
|
||||
default is 'N', setting it to 'Y' will disable failure injections
|
||||
when dealing with private (address space) futexes.
|
||||
|
||||
- /sys/kernel/debug/fail_function/inject:
|
||||
|
||||
Format: { 'function-name' | '!function-name' | '' }
|
||||
specifies the target function of error injection by name.
|
||||
If the function name leads '!' prefix, given function is
|
||||
removed from injection list. If nothing specified ('')
|
||||
injection list is cleared.
|
||||
|
||||
- /sys/kernel/debug/fail_function/injectable:
|
||||
|
||||
(read only) shows error injectable functions and what type of
|
||||
error values can be specified. The error type will be one of
|
||||
below;
|
||||
- NULL: retval must be 0.
|
||||
- ERRNO: retval must be -1 to -MAX_ERRNO (-4096).
|
||||
- ERR_NULL: retval must be 0 or -1 to -MAX_ERRNO (-4096).
|
||||
|
||||
- /sys/kernel/debug/fail_function/<functiuon-name>/retval:
|
||||
|
||||
specifies the "error" return value to inject to the given
|
||||
function for given function. This will be created when
|
||||
user specifies new injection entry.
|
||||
|
||||
o Boot option
|
||||
|
||||
In order to inject faults while debugfs is not available (early boot time),
|
||||
@ -268,6 +297,45 @@ trap "echo 0 > /sys/kernel/debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
|
||||
echo "Injecting errors into the module $module... (interrupt to stop)"
|
||||
sleep 1000000
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
o Inject open_ctree error while btrfs mount
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
rm -f testfile.img
|
||||
dd if=/dev/zero of=testfile.img bs=1M seek=1000 count=1
|
||||
DEVICE=$(losetup --show -f testfile.img)
|
||||
mkfs.btrfs -f $DEVICE
|
||||
mkdir -p tmpmnt
|
||||
|
||||
FAILTYPE=fail_function
|
||||
FAILFUNC=open_ctree
|
||||
echo $FAILFUNC > /sys/kernel/debug/$FAILTYPE/inject
|
||||
echo -12 > /sys/kernel/debug/$FAILTYPE/$FAILFUNC/retval
|
||||
echo N > /sys/kernel/debug/$FAILTYPE/task-filter
|
||||
echo 100 > /sys/kernel/debug/$FAILTYPE/probability
|
||||
echo 0 > /sys/kernel/debug/$FAILTYPE/interval
|
||||
echo -1 > /sys/kernel/debug/$FAILTYPE/times
|
||||
echo 0 > /sys/kernel/debug/$FAILTYPE/space
|
||||
echo 1 > /sys/kernel/debug/$FAILTYPE/verbose
|
||||
|
||||
mount -t btrfs $DEVICE tmpmnt
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "SUCCESS!"
|
||||
else
|
||||
echo "FAILED!"
|
||||
umount tmpmnt
|
||||
fi
|
||||
|
||||
echo > /sys/kernel/debug/$FAILTYPE/inject
|
||||
|
||||
rmdir tmpmnt
|
||||
losetup -d $DEVICE
|
||||
rm testfile.img
|
||||
|
||||
|
||||
Tool to run command with failslab or fail_page_alloc
|
||||
----------------------------------------------------
|
||||
In order to make it easier to accomplish the tasks mentioned above, we can use
|
||||
|
@ -36,8 +36,6 @@ bonding.txt
|
||||
- Linux Ethernet Bonding Driver HOWTO: link aggregation in Linux.
|
||||
bridge.txt
|
||||
- where to get user space programs for ethernet bridging with Linux.
|
||||
can.txt
|
||||
- documentation on CAN protocol family.
|
||||
cdc_mbim.txt
|
||||
- 3G/LTE USB modem (Mobile Broadband Interface Model)
|
||||
checksum-offloads.txt
|
||||
@ -228,6 +226,8 @@ x25.txt
|
||||
- general info on X.25 development.
|
||||
x25-iface.txt
|
||||
- description of the X.25 Packet Layer to LAPB device interface.
|
||||
xfrm_device.txt
|
||||
- description of XFRM offload API
|
||||
xfrm_proc.txt
|
||||
- description of the statistics package for XFRM.
|
||||
xfrm_sync.txt
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========
|
||||
batman-adv
|
||||
==========
|
||||
|
1437
Documentation/networking/can.rst
Normal file
1437
Documentation/networking/can.rst
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -385,11 +385,6 @@ Switch configuration
|
||||
avoid relying on what a previous software agent such as a bootloader/firmware
|
||||
may have previously configured.
|
||||
|
||||
- set_addr: Some switches require the programming of the management interface's
|
||||
Ethernet MAC address, switch drivers can also disable ageing of MAC addresses
|
||||
on the management interface and "hardcode"/"force" this MAC address for the
|
||||
CPU/management interface as an optimization
|
||||
|
||||
PHY devices and link management
|
||||
-------------------------------
|
||||
|
||||
|
@ -1134,7 +1134,7 @@ The verifier's knowledge about the variable offset consists of:
|
||||
mask and value; no bit should ever be 1 in both. For example, if a byte is read
|
||||
into a register from memory, the register's top 56 bits are known zero, while
|
||||
the low 8 are unknown - which is represented as the tnum (0x0; 0xff). If we
|
||||
then OR this with 0x40, we get (0x40; 0xcf), then if we add 1 we get (0x0;
|
||||
then OR this with 0x40, we get (0x40; 0xbf), then if we add 1 we get (0x0;
|
||||
0x1ff), because of potential carries.
|
||||
Besides arithmetic, the register state can also be updated by conditional
|
||||
branches. For instance, if a SCALAR_VALUE is compared > 8, in the 'true' branch
|
||||
|
@ -97,6 +97,46 @@ The include/net/mac802154.h defines following functions:
|
||||
- void ieee802154_unregister_hw(struct ieee802154_hw *hw):
|
||||
freeing registered PHY
|
||||
|
||||
- void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
|
||||
u8 lqi):
|
||||
telling 802.15.4 module there is a new received frame in the skb with
|
||||
the RF Link Quality Indicator (LQI) from the hardware device
|
||||
|
||||
- void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
|
||||
bool ifs_handling):
|
||||
telling 802.15.4 module the frame in the skb is or going to be
|
||||
transmitted through the hardware device
|
||||
|
||||
The device driver must implement the following callbacks in the IEEE 802.15.4
|
||||
operations structure at least:
|
||||
struct ieee802154_ops {
|
||||
...
|
||||
int (*start)(struct ieee802154_hw *hw);
|
||||
void (*stop)(struct ieee802154_hw *hw);
|
||||
...
|
||||
int (*xmit_async)(struct ieee802154_hw *hw, struct sk_buff *skb);
|
||||
int (*ed)(struct ieee802154_hw *hw, u8 *level);
|
||||
int (*set_channel)(struct ieee802154_hw *hw, u8 page, u8 channel);
|
||||
...
|
||||
};
|
||||
|
||||
- int start(struct ieee802154_hw *hw):
|
||||
handler that 802.15.4 module calls for the hardware device initialization.
|
||||
|
||||
- void stop(struct ieee802154_hw *hw):
|
||||
handler that 802.15.4 module calls for the hardware device cleanup.
|
||||
|
||||
- int xmit_async(struct ieee802154_hw *hw, struct sk_buff *skb):
|
||||
handler that 802.15.4 module calls for each frame in the skb going to be
|
||||
transmitted through the hardware device.
|
||||
|
||||
- int ed(struct ieee802154_hw *hw, u8 *level):
|
||||
handler that 802.15.4 module calls for Energy Detection from the hardware
|
||||
device.
|
||||
|
||||
- int set_channel(struct ieee802154_hw *hw, u8 page, u8 channel):
|
||||
set radio for listening on specific channel of the hardware device.
|
||||
|
||||
Moreover IEEE 802.15.4 device operations structure should be filled.
|
||||
|
||||
Fake drivers
|
||||
|
@ -7,6 +7,7 @@ Contents:
|
||||
:maxdepth: 2
|
||||
|
||||
batman-adv
|
||||
can
|
||||
kapi
|
||||
z8530book
|
||||
msg_zerocopy
|
||||
|
@ -606,6 +606,7 @@ tcp_fastopen_blackhole_timeout_sec - INTEGER
|
||||
This time period will grow exponentially when more blackhole issues
|
||||
get detected right after Fastopen is re-enabled and will reset to
|
||||
initial value when the blackhole issue goes away.
|
||||
0 to disable the blackhole detection.
|
||||
By default, it is set to 1hr.
|
||||
|
||||
tcp_syn_retries - INTEGER
|
||||
|
@ -145,3 +145,27 @@ PHY Support
|
||||
|
||||
.. kernel-doc:: drivers/net/phy/mdio_bus.c
|
||||
:internal:
|
||||
|
||||
PHYLINK
|
||||
-------
|
||||
|
||||
PHYLINK interfaces traditional network drivers with PHYLIB, fixed-links,
|
||||
and SFF modules (eg, hot-pluggable SFP) that may contain PHYs. PHYLINK
|
||||
provides management of the link state and link modes.
|
||||
|
||||
.. kernel-doc:: include/linux/phylink.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/net/phy/phylink.c
|
||||
|
||||
SFP support
|
||||
-----------
|
||||
|
||||
.. kernel-doc:: drivers/net/phy/sfp-bus.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: include/linux/sfp.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/net/phy/sfp-bus.c
|
||||
:export:
|
||||
|
@ -163,3 +163,12 @@ This requests that the NIC receive all possible frames, including errored
|
||||
frames (such as bad FCS, etc). This can be helpful when sniffing a link with
|
||||
bad packets on it. Some NICs may receive more packets if also put into normal
|
||||
PROMISC mode.
|
||||
|
||||
* rx-gro-hw
|
||||
|
||||
This requests that the NIC enables Hardware GRO (generic receive offload).
|
||||
Hardware GRO is basically the exact reverse of TSO, and is generally
|
||||
stricter than Hardware LRO. A packet stream merged by Hardware GRO must
|
||||
be re-segmentable by GSO or TSO back to the exact original packet stream.
|
||||
Hardware GRO is dependent on RXCSUM since every packet successfully merged
|
||||
by hardware must also have the checksum verified by hardware.
|
||||
|
@ -12,8 +12,8 @@ suitable sample script and configure that.
|
||||
On a dual CPU:
|
||||
|
||||
ps aux | grep pkt
|
||||
root 129 0.3 0.0 0 0 ? SW 2003 523:20 [pktgen/0]
|
||||
root 130 0.3 0.0 0 0 ? SW 2003 509:50 [pktgen/1]
|
||||
root 129 0.3 0.0 0 0 ? SW 2003 523:20 [kpktgend_0]
|
||||
root 130 0.3 0.0 0 0 ? SW 2003 509:50 [kpktgend_1]
|
||||
|
||||
|
||||
For monitoring and control pktgen creates:
|
||||
@ -113,9 +113,16 @@ Configuring devices
|
||||
===================
|
||||
This is done via the /proc interface, and most easily done via pgset
|
||||
as defined in the sample scripts.
|
||||
You need to specify PGDEV environment variable to use functions from sample
|
||||
scripts, i.e.:
|
||||
export PGDEV=/proc/net/pktgen/eth4@0
|
||||
source samples/pktgen/functions.sh
|
||||
|
||||
Examples:
|
||||
|
||||
pg_ctrl start starts injection.
|
||||
pg_ctrl stop aborts injection. Also, ^C aborts generator.
|
||||
|
||||
pgset "clone_skb 1" sets the number of copies of the same packet
|
||||
pgset "clone_skb 0" use single SKB for all transmits
|
||||
pgset "burst 8" uses xmit_more API to queue 8 copies of the same
|
||||
@ -165,8 +172,12 @@ Examples:
|
||||
IPSEC # IPsec encapsulation (needs CONFIG_XFRM)
|
||||
NODE_ALLOC # node specific memory allocation
|
||||
NO_TIMESTAMP # disable timestamping
|
||||
pgset 'flag ![name]' Clear a flag to determine behaviour.
|
||||
Note that you might need to use single quote in
|
||||
interactive mode, so that your shell wouldn't expand
|
||||
the specified flag as a history command.
|
||||
|
||||
pgset spi SPI_VALUE Set specific SA used to transform packet.
|
||||
pgset "spi [SPI_VALUE]" Set specific SA used to transform packet.
|
||||
|
||||
pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
|
||||
cycle through the port range.
|
||||
@ -207,8 +218,6 @@ Examples:
|
||||
pgset "tos XX" set former IPv4 TOS field (e.g. "tos 28" for AF11 no ECN, default 00)
|
||||
pgset "traffic_class XX" set former IPv6 TRAFFIC CLASS (e.g. "traffic_class B8" for EF no ECN, default 00)
|
||||
|
||||
pgset stop aborts injection. Also, ^C aborts generator.
|
||||
|
||||
pgset "rate 300M" set rate to 300 Mb/s
|
||||
pgset "ratep 1000000" set rate to 1Mpps
|
||||
|
||||
|
135
Documentation/networking/xfrm_device.txt
Normal file
135
Documentation/networking/xfrm_device.txt
Normal file
@ -0,0 +1,135 @@
|
||||
|
||||
===============================================
|
||||
XFRM device - offloading the IPsec computations
|
||||
===============================================
|
||||
Shannon Nelson <shannon.nelson@oracle.com>
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
IPsec is a useful feature for securing network traffic, but the
|
||||
computational cost is high: a 10Gbps link can easily be brought down
|
||||
to under 1Gbps, depending on the traffic and link configuration.
|
||||
Luckily, there are NICs that offer a hardware based IPsec offload which
|
||||
can radically increase throughput and decrease CPU utilization. The XFRM
|
||||
Device interface allows NIC drivers to offer to the stack access to the
|
||||
hardware offload.
|
||||
|
||||
Userland access to the offload is typically through a system such as
|
||||
libreswan or KAME/raccoon, but the iproute2 'ip xfrm' command set can
|
||||
be handy when experimenting. An example command might look something
|
||||
like this:
|
||||
|
||||
ip x s add proto esp dst 14.0.0.70 src 14.0.0.52 spi 0x07 mode transport \
|
||||
reqid 0x07 replay-window 32 \
|
||||
aead 'rfc4106(gcm(aes))' 0x44434241343332312423222114131211f4f3f2f1 128 \
|
||||
sel src 14.0.0.52/24 dst 14.0.0.70/24 proto tcp \
|
||||
offload dev eth4 dir in
|
||||
|
||||
Yes, that's ugly, but that's what shell scripts and/or libreswan are for.
|
||||
|
||||
|
||||
|
||||
Callbacks to implement
|
||||
======================
|
||||
|
||||
/* from include/linux/netdevice.h */
|
||||
struct xfrmdev_ops {
|
||||
int (*xdo_dev_state_add) (struct xfrm_state *x);
|
||||
void (*xdo_dev_state_delete) (struct xfrm_state *x);
|
||||
void (*xdo_dev_state_free) (struct xfrm_state *x);
|
||||
bool (*xdo_dev_offload_ok) (struct sk_buff *skb,
|
||||
struct xfrm_state *x);
|
||||
void (*xdo_dev_state_advance_esn) (struct xfrm_state *x);
|
||||
};
|
||||
|
||||
The NIC driver offering ipsec offload will need to implement these
|
||||
callbacks to make the offload available to the network stack's
|
||||
XFRM subsytem. Additionally, the feature bits NETIF_F_HW_ESP and
|
||||
NETIF_F_HW_ESP_TX_CSUM will signal the availability of the offload.
|
||||
|
||||
|
||||
|
||||
Flow
|
||||
====
|
||||
|
||||
At probe time and before the call to register_netdev(), the driver should
|
||||
set up local data structures and XFRM callbacks, and set the feature bits.
|
||||
The XFRM code's listener will finish the setup on NETDEV_REGISTER.
|
||||
|
||||
adapter->netdev->xfrmdev_ops = &ixgbe_xfrmdev_ops;
|
||||
adapter->netdev->features |= NETIF_F_HW_ESP;
|
||||
adapter->netdev->hw_enc_features |= NETIF_F_HW_ESP;
|
||||
|
||||
When new SAs are set up with a request for "offload" feature, the
|
||||
driver's xdo_dev_state_add() will be given the new SA to be offloaded
|
||||
and an indication of whether it is for Rx or Tx. The driver should
|
||||
- verify the algorithm is supported for offloads
|
||||
- store the SA information (key, salt, target-ip, protocol, etc)
|
||||
- enable the HW offload of the SA
|
||||
|
||||
The driver can also set an offload_handle in the SA, an opaque void pointer
|
||||
that can be used to convey context into the fast-path offload requests.
|
||||
|
||||
xs->xso.offload_handle = context;
|
||||
|
||||
|
||||
When the network stack is preparing an IPsec packet for an SA that has
|
||||
been setup for offload, it first calls into xdo_dev_offload_ok() with
|
||||
the skb and the intended offload state to ask the driver if the offload
|
||||
will serviceable. This can check the packet information to be sure the
|
||||
offload can be supported (e.g. IPv4 or IPv6, no IPv4 options, etc) and
|
||||
return true of false to signify its support.
|
||||
|
||||
When ready to send, the driver needs to inspect the Tx packet for the
|
||||
offload information, including the opaque context, and set up the packet
|
||||
send accordingly.
|
||||
|
||||
xs = xfrm_input_state(skb);
|
||||
context = xs->xso.offload_handle;
|
||||
set up HW for send
|
||||
|
||||
The stack has already inserted the appropriate IPsec headers in the
|
||||
packet data, the offload just needs to do the encryption and fix up the
|
||||
header values.
|
||||
|
||||
|
||||
When a packet is received and the HW has indicated that it offloaded a
|
||||
decryption, the driver needs to add a reference to the decoded SA into
|
||||
the packet's skb. At this point the data should be decrypted but the
|
||||
IPsec headers are still in the packet data; they are removed later up
|
||||
the stack in xfrm_input().
|
||||
|
||||
find and hold the SA that was used to the Rx skb
|
||||
get spi, protocol, and destination IP from packet headers
|
||||
xs = find xs from (spi, protocol, dest_IP)
|
||||
xfrm_state_hold(xs);
|
||||
|
||||
store the state information into the skb
|
||||
skb->sp = secpath_dup(skb->sp);
|
||||
skb->sp->xvec[skb->sp->len++] = xs;
|
||||
skb->sp->olen++;
|
||||
|
||||
indicate the success and/or error status of the offload
|
||||
xo = xfrm_offload(skb);
|
||||
xo->flags = CRYPTO_DONE;
|
||||
xo->status = crypto_status;
|
||||
|
||||
hand the packet to napi_gro_receive() as usual
|
||||
|
||||
In ESN mode, xdo_dev_state_advance_esn() is called from xfrm_replay_advance_esn().
|
||||
Driver will check packet seq number and update HW ESN state machine if needed.
|
||||
|
||||
When the SA is removed by the user, the driver's xdo_dev_state_delete()
|
||||
is asked to disable the offload. Later, xdo_dev_state_free() is called
|
||||
from a garbage collection routine after all reference counts to the state
|
||||
have been removed and any remaining resources can be cleared for the
|
||||
offload state. How these are used by the driver will depend on specific
|
||||
hardware needs.
|
||||
|
||||
As a netdev is set to DOWN the XFRM stack's netdev listener will call
|
||||
xdo_dev_state_delete() and xdo_dev_state_free() on any remaining offloaded
|
||||
states.
|
||||
|
||||
|
@ -5,13 +5,15 @@ Masahide NAKAMURA <nakam@linux-ipv6.org>
|
||||
|
||||
Transformation Statistics
|
||||
-------------------------
|
||||
xfrm_proc is a statistics shown factor dropped by transformation
|
||||
for developer.
|
||||
It is a counter designed from current transformation source code
|
||||
and defined like linux private MIB.
|
||||
|
||||
Inbound statistics
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The xfrm_proc code is a set of statistics showing numbers of packets
|
||||
dropped by the transformation code and why. These counters are defined
|
||||
as part of the linux private MIB. These counters can be viewed in
|
||||
/proc/net/xfrm_stat.
|
||||
|
||||
|
||||
Inbound errors
|
||||
~~~~~~~~~~~~~~
|
||||
XfrmInError:
|
||||
All errors which is not matched others
|
||||
XfrmInBufferError:
|
||||
@ -46,6 +48,10 @@ XfrmInPolBlock:
|
||||
Policy discards
|
||||
XfrmInPolError:
|
||||
Policy error
|
||||
XfrmAcquireError:
|
||||
State hasn't been fully acquired before use
|
||||
XfrmFwdHdrError:
|
||||
Forward routing of a packet is not allowed
|
||||
|
||||
Outbound errors
|
||||
~~~~~~~~~~~~~~~
|
||||
@ -72,3 +78,5 @@ XfrmOutPolDead:
|
||||
Policy is dead
|
||||
XfrmOutPolError:
|
||||
Policy error
|
||||
XfrmOutStateInvalid:
|
||||
State is invalid, perhaps expired
|
||||
|
@ -95,7 +95,9 @@ dev_weight
|
||||
--------------
|
||||
|
||||
The maximum number of packets that kernel can handle on a NAPI interrupt,
|
||||
it's a Per-CPU variable.
|
||||
it's a Per-CPU variable. For drivers that support LRO or GRO_HW, a hardware
|
||||
aggregated packet is counted as one packet in this context.
|
||||
|
||||
Default: 64
|
||||
|
||||
dev_weight_rx_bias
|
||||
|
45
MAINTAINERS
45
MAINTAINERS
@ -1348,8 +1348,10 @@ T: git git://github.com/ulli-kroll/linux.git
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/arm/gemini.txt
|
||||
F: Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt
|
||||
F: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt
|
||||
F: Documentation/devicetree/bindings/rtc/faraday,ftrtc010.txt
|
||||
F: arch/arm/mach-gemini/
|
||||
F: drivers/net/ethernet/cortina/gemini/*
|
||||
F: drivers/pinctrl/pinctrl-gemini.c
|
||||
F: drivers/rtc/rtc-ftrtc010.c
|
||||
|
||||
@ -2579,6 +2581,7 @@ S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-class-net-batman-adv
|
||||
F: Documentation/ABI/testing/sysfs-class-net-mesh
|
||||
F: Documentation/networking/batman-adv.rst
|
||||
F: include/uapi/linux/batadv_packet.h
|
||||
F: include/uapi/linux/batman_adv.h
|
||||
F: net/batman-adv/
|
||||
|
||||
@ -2702,7 +2705,6 @@ F: drivers/mtd/devices/block2mtd.c
|
||||
|
||||
BLUETOOTH DRIVERS
|
||||
M: Marcel Holtmann <marcel@holtmann.org>
|
||||
M: Gustavo Padovan <gustavo@padovan.org>
|
||||
M: Johan Hedberg <johan.hedberg@gmail.com>
|
||||
L: linux-bluetooth@vger.kernel.org
|
||||
W: http://www.bluez.org/
|
||||
@ -2713,7 +2715,6 @@ F: drivers/bluetooth/
|
||||
|
||||
BLUETOOTH SUBSYSTEM
|
||||
M: Marcel Holtmann <marcel@holtmann.org>
|
||||
M: Gustavo Padovan <gustavo@padovan.org>
|
||||
M: Johan Hedberg <johan.hedberg@gmail.com>
|
||||
L: linux-bluetooth@vger.kernel.org
|
||||
W: http://www.bluez.org/
|
||||
@ -2738,12 +2739,16 @@ M: Alexei Starovoitov <ast@kernel.org>
|
||||
M: Daniel Borkmann <daniel@iogearbox.net>
|
||||
L: netdev@vger.kernel.org
|
||||
L: linux-kernel@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
|
||||
S: Supported
|
||||
F: arch/x86/net/bpf_jit*
|
||||
F: Documentation/networking/filter.txt
|
||||
F: Documentation/bpf/
|
||||
F: include/linux/bpf*
|
||||
F: include/linux/filter.h
|
||||
F: include/trace/events/bpf.h
|
||||
F: include/trace/events/xdp.h
|
||||
F: include/uapi/linux/bpf*
|
||||
F: include/uapi/linux/filter.h
|
||||
F: kernel/bpf/
|
||||
@ -3208,7 +3213,7 @@ W: https://github.com/linux-can
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
|
||||
S: Maintained
|
||||
F: Documentation/networking/can.txt
|
||||
F: Documentation/networking/can.rst
|
||||
F: net/can/
|
||||
F: include/linux/can/core.h
|
||||
F: include/uapi/linux/can.h
|
||||
@ -4956,6 +4961,11 @@ S: Maintained
|
||||
F: lib/dynamic_debug.c
|
||||
F: include/linux/dynamic_debug.h
|
||||
|
||||
DYNAMIC INTERRUPT MODERATION
|
||||
M: Tal Gilboa <talgi@mellanox.com>
|
||||
S: Maintained
|
||||
F: include/linux/net_dim.h
|
||||
|
||||
DZ DECSTATION DZ11 SERIAL DRIVER
|
||||
M: "Maciej W. Rozycki" <macro@linux-mips.org>
|
||||
S: Maintained
|
||||
@ -8743,6 +8753,13 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/mediatek/
|
||||
|
||||
MEDIATEK SWITCH DRIVER
|
||||
M: Sean Wang <sean.wang@mediatek.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/dsa/mt7530.*
|
||||
F: net/dsa/tag_mtk.c
|
||||
|
||||
MEDIATEK JPEG DRIVER
|
||||
M: Rick Chang <rick.chang@mediatek.com>
|
||||
M: Bin Liu <bin.liu@mediatek.com>
|
||||
@ -9628,6 +9645,11 @@ NETWORKING [WIRELESS]
|
||||
L: linux-wireless@vger.kernel.org
|
||||
Q: http://patchwork.kernel.org/project/linux-wireless/list/
|
||||
|
||||
NETDEVSIM
|
||||
M: Jakub Kicinski <jakub.kicinski@netronome.com>
|
||||
S: Maintained
|
||||
F: drivers/net/netdevsim/*
|
||||
|
||||
NETXEN (1/10) GbE SUPPORT
|
||||
M: Manish Chopra <manish.chopra@cavium.com>
|
||||
M: Rahul Verma <rahul.verma@cavium.com>
|
||||
@ -11792,15 +11814,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/realtek/rtl818x/rtl8187/
|
||||
|
||||
RTL8192CE WIRELESS DRIVER
|
||||
M: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
M: Chaoming Li <chaoming_li@realsil.com.cn>
|
||||
REALTEK WIRELESS DRIVER (rtlwifi family)
|
||||
M: Ping-Ke Shih <pkshih@realtek.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/realtek/rtlwifi/
|
||||
F: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/
|
||||
|
||||
RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
|
||||
M: Jes Sorensen <Jes.Sorensen@gmail.com>
|
||||
@ -12684,6 +12704,13 @@ F: drivers/md/raid*
|
||||
F: include/linux/raid/
|
||||
F: include/uapi/linux/raid/
|
||||
|
||||
SOCIONEXT (SNI) NETSEC NETWORK DRIVER
|
||||
M: Jassi Brar <jaswinder.singh@linaro.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/socionext/netsec.c
|
||||
F: Documentation/devicetree/bindings/net/socionext-netsec.txt
|
||||
|
||||
SONIC NETWORK DRIVER
|
||||
M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
|
||||
L: netdev@vger.kernel.org
|
||||
@ -14822,9 +14849,9 @@ S: Maintained
|
||||
F: drivers/hid/hid-wiimote*
|
||||
|
||||
WILOCITY WIL6210 WIRELESS DRIVER
|
||||
M: Maya Erez <qca_merez@qca.qualcomm.com>
|
||||
M: Maya Erez <merez@codeaurora.org>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: wil6210@qca.qualcomm.com
|
||||
L: wil6210@qti.qualcomm.com
|
||||
S: Supported
|
||||
W: http://wireless.kernel.org/en/users/Drivers/wil6210
|
||||
F: drivers/net/wireless/ath/wil6210/
|
||||
|
@ -196,6 +196,9 @@ config HAVE_OPTPROBES
|
||||
config HAVE_KPROBES_ON_FTRACE
|
||||
bool
|
||||
|
||||
config HAVE_FUNCTION_ERROR_INJECTION
|
||||
bool
|
||||
|
||||
config HAVE_NMI
|
||||
bool
|
||||
|
||||
|
@ -122,7 +122,7 @@
|
||||
};
|
||||
|
||||
can1: can@43f88000 {
|
||||
compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx25-flexcan";
|
||||
reg = <0x43f88000 0x4000>;
|
||||
interrupts = <43>;
|
||||
clocks = <&clks 75>, <&clks 75>;
|
||||
@ -131,7 +131,7 @@
|
||||
};
|
||||
|
||||
can2: can@43f8c000 {
|
||||
compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx25-flexcan";
|
||||
reg = <0x43f8c000 0x4000>;
|
||||
interrupts = <44>;
|
||||
clocks = <&clks 76>, <&clks 76>;
|
||||
|
@ -1038,7 +1038,7 @@
|
||||
};
|
||||
|
||||
can0: can@80032000 {
|
||||
compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx28-flexcan";
|
||||
reg = <0x80032000 0x2000>;
|
||||
interrupts = <8>;
|
||||
clocks = <&clks 58>, <&clks 58>;
|
||||
@ -1047,7 +1047,7 @@
|
||||
};
|
||||
|
||||
can1: can@80034000 {
|
||||
compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx28-flexcan";
|
||||
reg = <0x80034000 0x2000>;
|
||||
interrupts = <9>;
|
||||
clocks = <&clks 59>, <&clks 59>;
|
||||
|
@ -303,7 +303,7 @@
|
||||
};
|
||||
|
||||
can1: can@53fe4000 {
|
||||
compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx35-flexcan";
|
||||
reg = <0x53fe4000 0x1000>;
|
||||
clocks = <&clks 33>, <&clks 33>;
|
||||
clock-names = "ipg", "per";
|
||||
@ -312,7 +312,7 @@
|
||||
};
|
||||
|
||||
can2: can@53fe8000 {
|
||||
compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx35-flexcan";
|
||||
reg = <0x53fe8000 0x1000>;
|
||||
clocks = <&clks 34>, <&clks 34>;
|
||||
clock-names = "ipg", "per";
|
||||
|
@ -536,7 +536,7 @@
|
||||
};
|
||||
|
||||
can1: can@53fc8000 {
|
||||
compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx53-flexcan";
|
||||
reg = <0x53fc8000 0x4000>;
|
||||
interrupts = <82>;
|
||||
clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>,
|
||||
@ -546,7 +546,7 @@
|
||||
};
|
||||
|
||||
can2: can@53fcc000 {
|
||||
compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
|
||||
compatible = "fsl,imx53-flexcan";
|
||||
reg = <0x53fcc000 0x4000>;
|
||||
interrupts = <83>;
|
||||
clocks = <&clks IMX5_CLK_CAN2_IPG_GATE>,
|
||||
|
@ -112,3 +112,55 @@
|
||||
line-name = "PCA9539-P07";
|
||||
};
|
||||
};
|
||||
|
||||
&pci_root {
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
switch_nic: ethernet@3,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00010000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
&switch_ports {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "enacq";
|
||||
phy-handle = <&switchphy0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "eneport1";
|
||||
phy-handle = <&switchphy1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "enix";
|
||||
phy-handle = <&switchphy2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "enid";
|
||||
phy-handle = <&switchphy3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "cpu";
|
||||
ethernet = <&switch_nic>;
|
||||
phy-handle = <&switchphy4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "enembc";
|
||||
|
||||
/* connected to Ethernet MAC of AT91RM9200 in MII mode */
|
||||
fixed-link {
|
||||
speed = <100>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -111,3 +111,55 @@
|
||||
fsl,tx-cal-45-dp-ohms = <55>;
|
||||
fsl,tx-d-cal = <100>;
|
||||
};
|
||||
|
||||
&pci_root {
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
switch_nic: ethernet@3,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00010000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
&switch_ports {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "enacq";
|
||||
phy-handle = <&switchphy0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "eneport1";
|
||||
phy-handle = <&switchphy1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "enix";
|
||||
phy-handle = <&switchphy2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "enid";
|
||||
phy-handle = <&switchphy3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "cpu";
|
||||
ethernet = <&switch_nic>;
|
||||
phy-handle = <&switchphy4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "enembc";
|
||||
|
||||
/* connected to Ethernet MAC of AT91RM9200 in MII mode */
|
||||
fixed-link {
|
||||
speed = <100>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -212,3 +212,78 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pci_root {
|
||||
/* PLX Technology, Inc. PEX 8605 PCI Express 4-port Gen2 Switch */
|
||||
bridge@1,0 {
|
||||
compatible = "pci10b5,8605";
|
||||
reg = <0x00010000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
bridge@2,1 {
|
||||
compatible = "pci10b5,8605";
|
||||
reg = <0x00020800 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
ethernet@3,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00030000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
bridge@2,2 {
|
||||
compatible = "pci10b5,8605";
|
||||
reg = <0x00021000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
switch_nic: ethernet@4,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00040000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&switch_ports {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "eneport1";
|
||||
phy-handle = <&switchphy0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "eneport2";
|
||||
phy-handle = <&switchphy1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "enix";
|
||||
phy-handle = <&switchphy2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "enid";
|
||||
phy-handle = <&switchphy3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "cpu";
|
||||
ethernet = <&switch_nic>;
|
||||
phy-handle = <&switchphy4>;
|
||||
};
|
||||
};
|
||||
|
@ -92,6 +92,56 @@
|
||||
mux-int-port = <1>;
|
||||
mux-ext-port = <4>;
|
||||
};
|
||||
|
||||
aliases {
|
||||
mdio-gpio0 = &mdio0;
|
||||
};
|
||||
|
||||
mdio0: mdio-gpio {
|
||||
compatible = "virtual,mdio-gpio";
|
||||
gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>, /* mdc */
|
||||
<&gpio2 7 GPIO_ACTIVE_HIGH>; /* mdio */
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch@0 {
|
||||
compatible = "marvell,mv88e6085"; /* 88e6240*/
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
switch_ports: ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switchphy0: switchphy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
switchphy1: switchphy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
switchphy2: switchphy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
switchphy3: switchphy@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
|
||||
switchphy4: switchphy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ecspi5 {
|
||||
@ -326,3 +376,15 @@
|
||||
tcxo-clock-frequency = <26000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie {
|
||||
/* Synopsys, Inc. Device */
|
||||
pci_root: root@0,0 {
|
||||
compatible = "pci16c3,abcd";
|
||||
reg = <0x00000000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
@ -331,3 +331,19 @@
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&can0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&can1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&can2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&can3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -243,3 +243,19 @@
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&can0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&can1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&can2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&can3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -730,5 +730,41 @@
|
||||
<0000 0 0 3 &gic GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0000 0 0 4 &gic GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
can0: can@2a70000 {
|
||||
compatible = "fsl,ls1021ar2-flexcan";
|
||||
reg = <0x0 0x2a70000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clockgen 4 1>, <&clockgen 4 1>;
|
||||
clock-names = "ipg", "per";
|
||||
big-endian;
|
||||
};
|
||||
|
||||
can1: can@2a80000 {
|
||||
compatible = "fsl,ls1021ar2-flexcan";
|
||||
reg = <0x0 0x2a80000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clockgen 4 1>, <&clockgen 4 1>;
|
||||
clock-names = "ipg", "per";
|
||||
big-endian;
|
||||
};
|
||||
|
||||
can2: can@2a90000 {
|
||||
compatible = "fsl,ls1021ar2-flexcan";
|
||||
reg = <0x0 0x2a90000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clockgen 4 1>, <&clockgen 4 1>;
|
||||
clock-names = "ipg", "per";
|
||||
big-endian;
|
||||
};
|
||||
|
||||
can3: can@2aa0000 {
|
||||
compatible = "fsl,ls1021ar2-flexcan";
|
||||
reg = <0x0 0x2aa0000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clockgen 4 1>, <&clockgen 4 1>;
|
||||
clock-names = "ipg", "per";
|
||||
big-endian;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
#include "bpf_jit_32.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
/*
|
||||
* eBPF prog stack layout:
|
||||
*
|
||||
@ -365,15 +363,7 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
|
||||
static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
|
||||
{
|
||||
const u8 *tmp = bpf2a32[TMP_REG_1];
|
||||
s32 jmp_offset;
|
||||
|
||||
/* checks if divisor is zero or not. If it is, then
|
||||
* exit directly.
|
||||
*/
|
||||
emit(ARM_CMP_I(rn, 0), ctx);
|
||||
_emit(ARM_COND_EQ, ARM_MOV_I(ARM_R0, 0), ctx);
|
||||
jmp_offset = epilogue_offset(ctx);
|
||||
_emit(ARM_COND_EQ, ARM_B(jmp_offset), ctx);
|
||||
#if __LINUX_ARM_ARCH__ == 7
|
||||
if (elf_hwcap & HWCAP_IDIVA) {
|
||||
if (op == BPF_DIV)
|
||||
@ -1821,7 +1811,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
/* If BPF JIT was not enabled then we must fall back to
|
||||
* the interpreter.
|
||||
*/
|
||||
if (!bpf_jit_enable)
|
||||
if (!prog->jit_requested)
|
||||
return orig_prog;
|
||||
|
||||
/* If constant blinding was enabled and we failed during blinding
|
||||
|
@ -31,8 +31,6 @@
|
||||
|
||||
#include "bpf_jit.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
#define TMP_REG_1 (MAX_BPF_JIT_REG + 0)
|
||||
#define TMP_REG_2 (MAX_BPF_JIT_REG + 1)
|
||||
#define TCALL_CNT (MAX_BPF_JIT_REG + 2)
|
||||
@ -99,6 +97,20 @@ static inline void emit_a64_mov_i64(const int reg, const u64 val,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void emit_addr_mov_i64(const int reg, const u64 val,
|
||||
struct jit_ctx *ctx)
|
||||
{
|
||||
u64 tmp = val;
|
||||
int shift = 0;
|
||||
|
||||
emit(A64_MOVZ(1, reg, tmp & 0xffff, shift), ctx);
|
||||
for (;shift < 48;) {
|
||||
tmp >>= 16;
|
||||
shift += 16;
|
||||
emit(A64_MOVK(1, reg, tmp & 0xffff, shift), ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void emit_a64_mov_i(const int is64, const int reg,
|
||||
const s32 val, struct jit_ctx *ctx)
|
||||
{
|
||||
@ -378,18 +390,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X:
|
||||
case BPF_ALU | BPF_MOD | BPF_X:
|
||||
case BPF_ALU64 | BPF_MOD | BPF_X:
|
||||
{
|
||||
const u8 r0 = bpf2a64[BPF_REG_0];
|
||||
|
||||
/* if (src == 0) return 0 */
|
||||
jmp_offset = 3; /* skip ahead to else path */
|
||||
check_imm19(jmp_offset);
|
||||
emit(A64_CBNZ(is64, src, jmp_offset), ctx);
|
||||
emit(A64_MOVZ(1, r0, 0, 0), ctx);
|
||||
jmp_offset = epilogue_offset(ctx);
|
||||
check_imm26(jmp_offset);
|
||||
emit(A64_B(jmp_offset), ctx);
|
||||
/* else */
|
||||
switch (BPF_OP(code)) {
|
||||
case BPF_DIV:
|
||||
emit(A64_UDIV(is64, dst, dst, src), ctx);
|
||||
@ -401,7 +401,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BPF_ALU | BPF_LSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_LSH | BPF_X:
|
||||
emit(A64_LSLV(is64, dst, dst, src), ctx);
|
||||
@ -605,7 +604,10 @@ emit_cond_jmp:
|
||||
const u8 r0 = bpf2a64[BPF_REG_0];
|
||||
const u64 func = (u64)__bpf_call_base + imm;
|
||||
|
||||
emit_a64_mov_i64(tmp, func, ctx);
|
||||
if (ctx->prog->is_func)
|
||||
emit_addr_mov_i64(tmp, func, ctx);
|
||||
else
|
||||
emit_a64_mov_i64(tmp, func, ctx);
|
||||
emit(A64_BLR(tmp), ctx);
|
||||
emit(A64_MOV(1, r0, A64_R(0)), ctx);
|
||||
break;
|
||||
@ -837,16 +839,24 @@ static inline void bpf_flush_icache(void *start, void *end)
|
||||
flush_icache_range((unsigned long)start, (unsigned long)end);
|
||||
}
|
||||
|
||||
struct arm64_jit_data {
|
||||
struct bpf_binary_header *header;
|
||||
u8 *image;
|
||||
struct jit_ctx ctx;
|
||||
};
|
||||
|
||||
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_prog *tmp, *orig_prog = prog;
|
||||
struct bpf_binary_header *header;
|
||||
struct arm64_jit_data *jit_data;
|
||||
bool tmp_blinded = false;
|
||||
bool extra_pass = false;
|
||||
struct jit_ctx ctx;
|
||||
int image_size;
|
||||
u8 *image_ptr;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
if (!prog->jit_requested)
|
||||
return orig_prog;
|
||||
|
||||
tmp = bpf_jit_blind_constants(prog);
|
||||
@ -860,13 +870,30 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
prog = tmp;
|
||||
}
|
||||
|
||||
jit_data = prog->aux->jit_data;
|
||||
if (!jit_data) {
|
||||
jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL);
|
||||
if (!jit_data) {
|
||||
prog = orig_prog;
|
||||
goto out;
|
||||
}
|
||||
prog->aux->jit_data = jit_data;
|
||||
}
|
||||
if (jit_data->ctx.offset) {
|
||||
ctx = jit_data->ctx;
|
||||
image_ptr = jit_data->image;
|
||||
header = jit_data->header;
|
||||
extra_pass = true;
|
||||
image_size = sizeof(u32) * ctx.idx;
|
||||
goto skip_init_ctx;
|
||||
}
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.prog = prog;
|
||||
|
||||
ctx.offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
|
||||
if (ctx.offset == NULL) {
|
||||
prog = orig_prog;
|
||||
goto out;
|
||||
goto out_off;
|
||||
}
|
||||
|
||||
/* 1. Initial fake pass to compute ctx->idx. */
|
||||
@ -897,6 +924,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
/* 2. Now, the actual pass. */
|
||||
|
||||
ctx.image = (__le32 *)image_ptr;
|
||||
skip_init_ctx:
|
||||
ctx.idx = 0;
|
||||
|
||||
build_prologue(&ctx);
|
||||
@ -922,13 +950,31 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
|
||||
bpf_flush_icache(header, ctx.image + ctx.idx);
|
||||
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
if (!prog->is_func || extra_pass) {
|
||||
if (extra_pass && ctx.idx != jit_data->ctx.idx) {
|
||||
pr_err_once("multi-func JIT bug %d != %d\n",
|
||||
ctx.idx, jit_data->ctx.idx);
|
||||
bpf_jit_binary_free(header);
|
||||
prog->bpf_func = NULL;
|
||||
prog->jited = 0;
|
||||
goto out_off;
|
||||
}
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
} else {
|
||||
jit_data->ctx = ctx;
|
||||
jit_data->image = image_ptr;
|
||||
jit_data->header = header;
|
||||
}
|
||||
prog->bpf_func = (void *)ctx.image;
|
||||
prog->jited = 1;
|
||||
prog->jited_len = image_size;
|
||||
|
||||
if (!prog->is_func || extra_pass) {
|
||||
out_off:
|
||||
kfree(ctx.offset);
|
||||
kfree(ctx.offset);
|
||||
kfree(jit_data);
|
||||
prog->aux->jit_data = NULL;
|
||||
}
|
||||
out:
|
||||
if (tmp_blinded)
|
||||
bpf_jit_prog_release_other(prog, prog == orig_prog ?
|
||||
|
@ -265,6 +265,14 @@ int __init bcm63xx_enet_register(int unit,
|
||||
dpd->dma_chan_width = ENETDMA_CHAN_WIDTH;
|
||||
}
|
||||
|
||||
if (unit == 0) {
|
||||
dpd->rx_chan = 0;
|
||||
dpd->tx_chan = 1;
|
||||
} else {
|
||||
dpd->rx_chan = 2;
|
||||
dpd->tx_chan = 3;
|
||||
}
|
||||
|
||||
ret = platform_device_register(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -55,6 +55,10 @@ struct bcm63xx_enet_platform_data {
|
||||
|
||||
/* DMA descriptor shift */
|
||||
unsigned int dma_desc_shift;
|
||||
|
||||
/* dma channel ids */
|
||||
int rx_chan;
|
||||
int tx_chan;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1207,8 +1207,6 @@ jmp_cmp:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
void bpf_jit_compile(struct bpf_prog *fp)
|
||||
{
|
||||
struct jit_ctx ctx;
|
||||
|
@ -177,8 +177,6 @@ static u32 b_imm(unsigned int tgt, struct jit_ctx *ctx)
|
||||
(ctx->idx * 4) - 4;
|
||||
}
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
enum which_ebpf_reg {
|
||||
src_reg,
|
||||
src_reg_no_fp,
|
||||
@ -743,16 +741,11 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
break;
|
||||
case BPF_ALU | BPF_DIV | BPF_K: /* ALU_IMM */
|
||||
case BPF_ALU | BPF_MOD | BPF_K: /* ALU_IMM */
|
||||
if (insn->imm == 0)
|
||||
return -EINVAL;
|
||||
dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
|
||||
if (dst < 0)
|
||||
return dst;
|
||||
if (insn->imm == 0) { /* Div by zero */
|
||||
b_off = b_imm(exit_idx, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
emit_instr(ctx, beq, MIPS_R_ZERO, MIPS_R_ZERO, b_off);
|
||||
emit_instr(ctx, addu, MIPS_R_V0, MIPS_R_ZERO, MIPS_R_ZERO);
|
||||
}
|
||||
td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
|
||||
if (td == REG_64BIT || td == REG_32BIT_ZERO_EX)
|
||||
/* sign extend */
|
||||
@ -772,19 +765,13 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
break;
|
||||
case BPF_ALU64 | BPF_DIV | BPF_K: /* ALU_IMM */
|
||||
case BPF_ALU64 | BPF_MOD | BPF_K: /* ALU_IMM */
|
||||
if (insn->imm == 0)
|
||||
return -EINVAL;
|
||||
dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
|
||||
if (dst < 0)
|
||||
return dst;
|
||||
if (insn->imm == 0) { /* Div by zero */
|
||||
b_off = b_imm(exit_idx, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
emit_instr(ctx, beq, MIPS_R_ZERO, MIPS_R_ZERO, b_off);
|
||||
emit_instr(ctx, addu, MIPS_R_V0, MIPS_R_ZERO, MIPS_R_ZERO);
|
||||
}
|
||||
if (get_reg_val_type(ctx, this_idx, insn->dst_reg) == REG_32BIT)
|
||||
emit_instr(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32);
|
||||
|
||||
if (insn->imm == 1) {
|
||||
/* div by 1 is a nop, mod by 1 is zero */
|
||||
if (bpf_op == BPF_MOD)
|
||||
@ -862,11 +849,6 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
break;
|
||||
case BPF_DIV:
|
||||
case BPF_MOD:
|
||||
b_off = b_imm(exit_idx, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
emit_instr(ctx, beq, src, MIPS_R_ZERO, b_off);
|
||||
emit_instr(ctx, movz, MIPS_R_V0, MIPS_R_ZERO, src);
|
||||
emit_instr(ctx, ddivu, dst, src);
|
||||
if (bpf_op == BPF_DIV)
|
||||
emit_instr(ctx, mflo, dst);
|
||||
@ -945,11 +927,6 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
break;
|
||||
case BPF_DIV:
|
||||
case BPF_MOD:
|
||||
b_off = b_imm(exit_idx, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
emit_instr(ctx, beq, src, MIPS_R_ZERO, b_off);
|
||||
emit_instr(ctx, movz, MIPS_R_V0, MIPS_R_ZERO, src);
|
||||
emit_instr(ctx, divu, dst, src);
|
||||
if (bpf_op == BPF_DIV)
|
||||
emit_instr(ctx, mflo, dst);
|
||||
@ -1869,7 +1846,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
unsigned int image_size;
|
||||
u8 *image_ptr;
|
||||
|
||||
if (!bpf_jit_enable || !cpu_has_mips64r2)
|
||||
if (!prog->jit_requested || !cpu_has_mips64r2)
|
||||
return prog;
|
||||
|
||||
tmp = bpf_jit_blind_constants(prog);
|
||||
|
@ -137,12 +137,14 @@
|
||||
compatible = "fsl,p1010-flexcan";
|
||||
reg = <0x1c000 0x1000>;
|
||||
interrupts = <48 0x2 0 0>;
|
||||
big-endian;
|
||||
};
|
||||
|
||||
can1: can@1d000 {
|
||||
compatible = "fsl,p1010-flexcan";
|
||||
reg = <0x1d000 0x1000>;
|
||||
interrupts = <61 0x2 0 0>;
|
||||
big-endian;
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
|
@ -18,8 +18,6 @@
|
||||
|
||||
#include "bpf_jit32.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
static inline void bpf_flush_icache(void *start, void *end)
|
||||
{
|
||||
smp_wmb();
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
#include "bpf_jit64.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
static void bpf_jit_fill_ill_insns(void *area, unsigned int size)
|
||||
{
|
||||
memset32(area, BREAKPOINT_INSTRUCTION, size/4);
|
||||
@ -383,10 +381,6 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
||||
goto bpf_alu32_trunc;
|
||||
case BPF_ALU | BPF_DIV | BPF_X: /* (u32) dst /= (u32) src */
|
||||
case BPF_ALU | BPF_MOD | BPF_X: /* (u32) dst %= (u32) src */
|
||||
PPC_CMPWI(src_reg, 0);
|
||||
PPC_BCC_SHORT(COND_NE, (ctx->idx * 4) + 12);
|
||||
PPC_LI(b2p[BPF_REG_0], 0);
|
||||
PPC_JMP(exit_addr);
|
||||
if (BPF_OP(code) == BPF_MOD) {
|
||||
PPC_DIVWU(b2p[TMP_REG_1], dst_reg, src_reg);
|
||||
PPC_MULW(b2p[TMP_REG_1], src_reg,
|
||||
@ -397,10 +391,6 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
||||
goto bpf_alu32_trunc;
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */
|
||||
case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */
|
||||
PPC_CMPDI(src_reg, 0);
|
||||
PPC_BCC_SHORT(COND_NE, (ctx->idx * 4) + 12);
|
||||
PPC_LI(b2p[BPF_REG_0], 0);
|
||||
PPC_JMP(exit_addr);
|
||||
if (BPF_OP(code) == BPF_MOD) {
|
||||
PPC_DIVD(b2p[TMP_REG_1], dst_reg, src_reg);
|
||||
PPC_MULD(b2p[TMP_REG_1], src_reg,
|
||||
@ -995,7 +985,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
||||
struct bpf_prog *tmp_fp;
|
||||
bool bpf_blinded = false;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
if (!fp->jit_requested)
|
||||
return org_fp;
|
||||
|
||||
tmp_fp = bpf_jit_blind_constants(org_fp);
|
||||
|
@ -229,13 +229,55 @@ struct diag204_x_phys_block {
|
||||
} __packed;
|
||||
|
||||
enum diag26c_sc {
|
||||
DIAG26C_PORT_VNIC = 0x00000024,
|
||||
DIAG26C_MAC_SERVICES = 0x00000030
|
||||
};
|
||||
|
||||
enum diag26c_version {
|
||||
DIAG26C_VERSION2 = 0x00000002 /* z/VM 5.4.0 */
|
||||
DIAG26C_VERSION2 = 0x00000002, /* z/VM 5.4.0 */
|
||||
DIAG26C_VERSION6_VM65918 = 0x00020006 /* z/VM 6.4.0 + VM65918 */
|
||||
};
|
||||
|
||||
#define DIAG26C_VNIC_INFO 0x0002
|
||||
struct diag26c_vnic_req {
|
||||
u32 resp_buf_len;
|
||||
u32 resp_version;
|
||||
u16 req_format;
|
||||
u16 vlan_id;
|
||||
u64 sys_name;
|
||||
u8 res[2];
|
||||
u16 devno;
|
||||
} __packed __aligned(8);
|
||||
|
||||
#define VNIC_INFO_PROT_L3 1
|
||||
#define VNIC_INFO_PROT_L2 2
|
||||
/* Note: this is the bare minimum, use it for uninitialized VNICs only. */
|
||||
struct diag26c_vnic_resp {
|
||||
u32 version;
|
||||
u32 entry_cnt;
|
||||
/* VNIC info: */
|
||||
u32 next_entry;
|
||||
u64 owner;
|
||||
u16 devno;
|
||||
u8 status;
|
||||
u8 type;
|
||||
u64 lan_owner;
|
||||
u64 lan_name;
|
||||
u64 port_name;
|
||||
u8 port_type;
|
||||
u8 ext_status:6;
|
||||
u8 protocol:2;
|
||||
u16 base_devno;
|
||||
u32 port_num;
|
||||
u32 ifindex;
|
||||
u32 maxinfo;
|
||||
u32 dev_count;
|
||||
/* 3x device info: */
|
||||
u8 dev_info1[28];
|
||||
u8 dev_info2[28];
|
||||
u8 dev_info3[28];
|
||||
} __packed __aligned(8);
|
||||
|
||||
#define DIAG26C_GET_MAC 0x0000
|
||||
struct diag26c_mac_req {
|
||||
u32 resp_buf_len;
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include <asm/set_memory.h>
|
||||
#include "bpf_jit.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
struct bpf_jit {
|
||||
u32 seen; /* Flags to remember seen eBPF instructions */
|
||||
u32 seen_reg[16]; /* Array to remember which registers are used */
|
||||
@ -612,11 +610,6 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
jit->seen |= SEEN_RET0;
|
||||
/* ltr %src,%src (if src == 0 goto fail) */
|
||||
EMIT2(0x1200, src_reg, src_reg);
|
||||
/* jz <ret0> */
|
||||
EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg);
|
||||
/* lhi %w0,0 */
|
||||
EMIT4_IMM(0xa7080000, REG_W0, 0);
|
||||
/* lr %w1,%dst */
|
||||
@ -632,11 +625,6 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
|
||||
{
|
||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||
|
||||
jit->seen |= SEEN_RET0;
|
||||
/* ltgr %src,%src (if src == 0 goto fail) */
|
||||
EMIT4(0xb9020000, src_reg, src_reg);
|
||||
/* jz <ret0> */
|
||||
EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg);
|
||||
/* lghi %w0,0 */
|
||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||
/* lgr %w1,%dst */
|
||||
@ -1299,7 +1287,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
||||
struct bpf_jit jit;
|
||||
int pass;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
if (!fp->jit_requested)
|
||||
return orig_fp;
|
||||
|
||||
tmp = bpf_jit_blind_constants(fp);
|
||||
|
@ -79,7 +79,6 @@ static struct resource sh_eth_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh7763_eth_pdata = {
|
||||
.phy = 0,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
|
@ -76,7 +76,6 @@ static struct resource sh_eth0_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh7757_eth0_pdata = {
|
||||
.phy = 1,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.set_mdio_gate = sh7757_eth_set_mdio_gate,
|
||||
};
|
||||
|
||||
@ -104,7 +103,6 @@ static struct resource sh_eth1_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh7757_eth1_pdata = {
|
||||
.phy = 1,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.set_mdio_gate = sh7757_eth_set_mdio_gate,
|
||||
};
|
||||
|
||||
@ -148,7 +146,6 @@ static struct resource sh_eth_giga0_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh7757_eth_giga0_pdata = {
|
||||
.phy = 18,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
|
||||
.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
|
||||
};
|
||||
@ -182,7 +179,6 @@ static struct resource sh_eth_giga1_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh7757_eth_giga1_pdata = {
|
||||
.phy = 19,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
|
||||
.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
|
||||
};
|
||||
|
@ -159,7 +159,6 @@ static struct resource sh_eth_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh_eth_plat = {
|
||||
.phy = 0x1f, /* SMSC LAN8700 */
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
.ether_link_active_low = 1
|
||||
};
|
||||
|
@ -374,7 +374,6 @@ static struct resource sh_eth_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh_eth_plat = {
|
||||
.phy = 0x1f, /* SMSC LAN8187 */
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
|
@ -87,7 +87,6 @@ static struct resource sh_eth_resources[] = {
|
||||
|
||||
static struct sh_eth_plat_data sh7763_eth_pdata = {
|
||||
.phy = 1,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
|
@ -122,7 +122,6 @@ static struct platform_device scif2_device = {
|
||||
|
||||
static struct sh_eth_plat_data eth_platform_data = {
|
||||
.phy = 1,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
#include "bpf_jit_32.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
static inline bool is_simm13(unsigned int value)
|
||||
{
|
||||
return value + 0x1000 < 0x2000;
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include "bpf_jit_64.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
static inline bool is_simm13(unsigned int value)
|
||||
{
|
||||
return value + 0x1000 < 0x2000;
|
||||
@ -969,31 +967,17 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
emit_alu(MULX, src, dst, ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_DIV | BPF_X:
|
||||
emit_cmp(src, G0, ctx);
|
||||
emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx);
|
||||
emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx);
|
||||
|
||||
emit_write_y(G0, ctx);
|
||||
emit_alu(DIV, src, dst, ctx);
|
||||
break;
|
||||
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X:
|
||||
emit_cmp(src, G0, ctx);
|
||||
emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx);
|
||||
emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx);
|
||||
|
||||
emit_alu(UDIVX, src, dst, ctx);
|
||||
break;
|
||||
|
||||
case BPF_ALU | BPF_MOD | BPF_X: {
|
||||
const u8 tmp = bpf2sparc[TMP_REG_1];
|
||||
|
||||
ctx->tmp_1_used = true;
|
||||
|
||||
emit_cmp(src, G0, ctx);
|
||||
emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx);
|
||||
emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx);
|
||||
|
||||
emit_write_y(G0, ctx);
|
||||
emit_alu3(DIV, dst, src, tmp, ctx);
|
||||
emit_alu3(MULX, tmp, src, tmp, ctx);
|
||||
@ -1005,10 +989,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
|
||||
ctx->tmp_1_used = true;
|
||||
|
||||
emit_cmp(src, G0, ctx);
|
||||
emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx);
|
||||
emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx);
|
||||
|
||||
emit_alu3(UDIVX, dst, src, tmp, ctx);
|
||||
emit_alu3(MULX, tmp, src, tmp, ctx);
|
||||
emit_alu3(SUB, dst, tmp, dst, ctx);
|
||||
@ -1509,17 +1489,25 @@ static void jit_fill_hole(void *area, unsigned int size)
|
||||
*ptr++ = 0x91d02005; /* ta 5 */
|
||||
}
|
||||
|
||||
struct sparc64_jit_data {
|
||||
struct bpf_binary_header *header;
|
||||
u8 *image;
|
||||
struct jit_ctx ctx;
|
||||
};
|
||||
|
||||
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_prog *tmp, *orig_prog = prog;
|
||||
struct sparc64_jit_data *jit_data;
|
||||
struct bpf_binary_header *header;
|
||||
bool tmp_blinded = false;
|
||||
bool extra_pass = false;
|
||||
struct jit_ctx ctx;
|
||||
u32 image_size;
|
||||
u8 *image_ptr;
|
||||
int pass;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
if (!prog->jit_requested)
|
||||
return orig_prog;
|
||||
|
||||
tmp = bpf_jit_blind_constants(prog);
|
||||
@ -1533,13 +1521,31 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
prog = tmp;
|
||||
}
|
||||
|
||||
jit_data = prog->aux->jit_data;
|
||||
if (!jit_data) {
|
||||
jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL);
|
||||
if (!jit_data) {
|
||||
prog = orig_prog;
|
||||
goto out;
|
||||
}
|
||||
prog->aux->jit_data = jit_data;
|
||||
}
|
||||
if (jit_data->ctx.offset) {
|
||||
ctx = jit_data->ctx;
|
||||
image_ptr = jit_data->image;
|
||||
header = jit_data->header;
|
||||
extra_pass = true;
|
||||
image_size = sizeof(u32) * ctx.idx;
|
||||
goto skip_init_ctx;
|
||||
}
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.prog = prog;
|
||||
|
||||
ctx.offset = kcalloc(prog->len, sizeof(unsigned int), GFP_KERNEL);
|
||||
if (ctx.offset == NULL) {
|
||||
prog = orig_prog;
|
||||
goto out;
|
||||
goto out_off;
|
||||
}
|
||||
|
||||
/* Fake pass to detect features used, and get an accurate assessment
|
||||
@ -1562,7 +1568,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
}
|
||||
|
||||
ctx.image = (u32 *)image_ptr;
|
||||
|
||||
skip_init_ctx:
|
||||
for (pass = 1; pass < 3; pass++) {
|
||||
ctx.idx = 0;
|
||||
|
||||
@ -1593,14 +1599,24 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
|
||||
bpf_flush_icache(header, (u8 *)header + (header->pages * PAGE_SIZE));
|
||||
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
if (!prog->is_func || extra_pass) {
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
} else {
|
||||
jit_data->ctx = ctx;
|
||||
jit_data->image = image_ptr;
|
||||
jit_data->header = header;
|
||||
}
|
||||
|
||||
prog->bpf_func = (void *)ctx.image;
|
||||
prog->jited = 1;
|
||||
prog->jited_len = image_size;
|
||||
|
||||
if (!prog->is_func || extra_pass) {
|
||||
out_off:
|
||||
kfree(ctx.offset);
|
||||
kfree(ctx.offset);
|
||||
kfree(jit_data);
|
||||
prog->aux->jit_data = NULL;
|
||||
}
|
||||
out:
|
||||
if (tmp_blinded)
|
||||
bpf_jit_prog_release_other(prog, prog == orig_prog ?
|
||||
|
@ -155,6 +155,7 @@ config X86
|
||||
select HAVE_KERNEL_XZ
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KPROBES_ON_FTRACE
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_KVM
|
||||
select HAVE_LIVEPATCH if X86_64
|
||||
|
13
arch/x86/include/asm/error-injection.h
Normal file
13
arch/x86/include/asm/error-injection.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_ERROR_INJECTION_H
|
||||
#define _ASM_ERROR_INJECTION_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm-generic/error-injection.h>
|
||||
|
||||
asmlinkage void just_return_func(void);
|
||||
void override_function_with_return(struct pt_regs *regs);
|
||||
|
||||
#endif /* _ASM_ERROR_INJECTION_H */
|
@ -67,6 +67,8 @@ extern const int kretprobe_blacklist_size;
|
||||
void arch_remove_kprobe(struct kprobe *p);
|
||||
asmlinkage void kretprobe_trampoline(void);
|
||||
|
||||
extern void arch_kprobe_override_function(struct pt_regs *regs);
|
||||
|
||||
/* Architecture specific copy of original instruction*/
|
||||
struct arch_specific_insn {
|
||||
/* copy of the original instruction */
|
||||
|
@ -109,6 +109,11 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
|
||||
return regs->ax;
|
||||
}
|
||||
|
||||
static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
|
||||
{
|
||||
regs->ax = rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* user_mode(regs) determines whether a register set came from user
|
||||
* mode. On x86_32, this is true if V8086 mode was enabled OR if the
|
||||
|
@ -26,6 +26,7 @@ lib-y += memcpy_$(BITS).o
|
||||
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
|
||||
lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o insn-eval.o
|
||||
lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
|
||||
lib-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
|
||||
lib-$(CONFIG_RETPOLINE) += retpoline.o
|
||||
OBJECT_FILES_NON_STANDARD_retpoline.o :=y
|
||||
|
||||
|
19
arch/x86/lib/error-inject.c
Normal file
19
arch/x86/lib/error-inject.c
Normal file
@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/error-injection.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
asmlinkage void just_return_func(void);
|
||||
|
||||
asm(
|
||||
".type just_return_func, @function\n"
|
||||
"just_return_func:\n"
|
||||
" ret\n"
|
||||
".size just_return_func, .-just_return_func\n"
|
||||
);
|
||||
|
||||
void override_function_with_return(struct pt_regs *regs)
|
||||
{
|
||||
regs->ip = (unsigned long)&just_return_func;
|
||||
}
|
||||
NOKPROBE_SYMBOL(override_function_with_return);
|
@ -15,8 +15,6 @@
|
||||
#include <asm/set_memory.h>
|
||||
#include <linux/bpf.h>
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
/*
|
||||
* assembly code in arch/x86/net/bpf_jit.S
|
||||
*/
|
||||
@ -154,6 +152,11 @@ static bool is_ereg(u32 reg)
|
||||
BIT(BPF_REG_AX));
|
||||
}
|
||||
|
||||
static bool is_axreg(u32 reg)
|
||||
{
|
||||
return reg == BPF_REG_0;
|
||||
}
|
||||
|
||||
/* add modifiers if 'reg' maps to x64 registers r8..r15 */
|
||||
static u8 add_1mod(u8 byte, u32 reg)
|
||||
{
|
||||
@ -447,16 +450,36 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
||||
else if (is_ereg(dst_reg))
|
||||
EMIT1(add_1mod(0x40, dst_reg));
|
||||
|
||||
/* b3 holds 'normal' opcode, b2 short form only valid
|
||||
* in case dst is eax/rax.
|
||||
*/
|
||||
switch (BPF_OP(insn->code)) {
|
||||
case BPF_ADD: b3 = 0xC0; break;
|
||||
case BPF_SUB: b3 = 0xE8; break;
|
||||
case BPF_AND: b3 = 0xE0; break;
|
||||
case BPF_OR: b3 = 0xC8; break;
|
||||
case BPF_XOR: b3 = 0xF0; break;
|
||||
case BPF_ADD:
|
||||
b3 = 0xC0;
|
||||
b2 = 0x05;
|
||||
break;
|
||||
case BPF_SUB:
|
||||
b3 = 0xE8;
|
||||
b2 = 0x2D;
|
||||
break;
|
||||
case BPF_AND:
|
||||
b3 = 0xE0;
|
||||
b2 = 0x25;
|
||||
break;
|
||||
case BPF_OR:
|
||||
b3 = 0xC8;
|
||||
b2 = 0x0D;
|
||||
break;
|
||||
case BPF_XOR:
|
||||
b3 = 0xF0;
|
||||
b2 = 0x35;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_imm8(imm32))
|
||||
EMIT3(0x83, add_1reg(b3, dst_reg), imm32);
|
||||
else if (is_axreg(dst_reg))
|
||||
EMIT1_off32(b2, imm32);
|
||||
else
|
||||
EMIT2_off32(0x81, add_1reg(b3, dst_reg), imm32);
|
||||
break;
|
||||
@ -545,26 +568,6 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
||||
*/
|
||||
EMIT2(0x31, 0xd2);
|
||||
|
||||
if (BPF_SRC(insn->code) == BPF_X) {
|
||||
/* if (src_reg == 0) return 0 */
|
||||
|
||||
/* cmp r11, 0 */
|
||||
EMIT4(0x49, 0x83, 0xFB, 0x00);
|
||||
|
||||
/* jne .+9 (skip over pop, pop, xor and jmp) */
|
||||
EMIT2(X86_JNE, 1 + 1 + 2 + 5);
|
||||
EMIT1(0x5A); /* pop rdx */
|
||||
EMIT1(0x58); /* pop rax */
|
||||
EMIT2(0x31, 0xc0); /* xor eax, eax */
|
||||
|
||||
/* jmp cleanup_addr
|
||||
* addrs[i] - 11, because there are 11 bytes
|
||||
* after this insn: div, mov, pop, pop, mov
|
||||
*/
|
||||
jmp_offset = ctx->cleanup_addr - (addrs[i] - 11);
|
||||
EMIT1_off32(0xE9, jmp_offset);
|
||||
}
|
||||
|
||||
if (BPF_CLASS(insn->code) == BPF_ALU64)
|
||||
/* div r11 */
|
||||
EMIT3(0x49, 0xF7, 0xF3);
|
||||
@ -1109,19 +1112,29 @@ common_load:
|
||||
return proglen;
|
||||
}
|
||||
|
||||
struct x64_jit_data {
|
||||
struct bpf_binary_header *header;
|
||||
int *addrs;
|
||||
u8 *image;
|
||||
int proglen;
|
||||
struct jit_context ctx;
|
||||
};
|
||||
|
||||
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_binary_header *header = NULL;
|
||||
struct bpf_prog *tmp, *orig_prog = prog;
|
||||
struct x64_jit_data *jit_data;
|
||||
int proglen, oldproglen = 0;
|
||||
struct jit_context ctx = {};
|
||||
bool tmp_blinded = false;
|
||||
bool extra_pass = false;
|
||||
u8 *image = NULL;
|
||||
int *addrs;
|
||||
int pass;
|
||||
int i;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
if (!prog->jit_requested)
|
||||
return orig_prog;
|
||||
|
||||
tmp = bpf_jit_blind_constants(prog);
|
||||
@ -1135,10 +1148,28 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
prog = tmp;
|
||||
}
|
||||
|
||||
jit_data = prog->aux->jit_data;
|
||||
if (!jit_data) {
|
||||
jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL);
|
||||
if (!jit_data) {
|
||||
prog = orig_prog;
|
||||
goto out;
|
||||
}
|
||||
prog->aux->jit_data = jit_data;
|
||||
}
|
||||
addrs = jit_data->addrs;
|
||||
if (addrs) {
|
||||
ctx = jit_data->ctx;
|
||||
oldproglen = jit_data->proglen;
|
||||
image = jit_data->image;
|
||||
header = jit_data->header;
|
||||
extra_pass = true;
|
||||
goto skip_init_addrs;
|
||||
}
|
||||
addrs = kmalloc(prog->len * sizeof(*addrs), GFP_KERNEL);
|
||||
if (!addrs) {
|
||||
prog = orig_prog;
|
||||
goto out;
|
||||
goto out_addrs;
|
||||
}
|
||||
|
||||
/* Before first pass, make a rough estimation of addrs[]
|
||||
@ -1149,6 +1180,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
addrs[i] = proglen;
|
||||
}
|
||||
ctx.cleanup_addr = proglen;
|
||||
skip_init_addrs:
|
||||
|
||||
/* JITed image shrinks with every pass and the loop iterates
|
||||
* until the image stops shrinking. Very large bpf programs
|
||||
@ -1189,7 +1221,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
|
||||
if (image) {
|
||||
bpf_flush_icache(header, image + proglen);
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
if (!prog->is_func || extra_pass) {
|
||||
bpf_jit_binary_lock_ro(header);
|
||||
} else {
|
||||
jit_data->addrs = addrs;
|
||||
jit_data->ctx = ctx;
|
||||
jit_data->proglen = proglen;
|
||||
jit_data->image = image;
|
||||
jit_data->header = header;
|
||||
}
|
||||
prog->bpf_func = (void *)image;
|
||||
prog->jited = 1;
|
||||
prog->jited_len = proglen;
|
||||
@ -1197,8 +1237,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
prog = orig_prog;
|
||||
}
|
||||
|
||||
if (!prog->is_func || extra_pass) {
|
||||
out_addrs:
|
||||
kfree(addrs);
|
||||
kfree(addrs);
|
||||
kfree(jit_data);
|
||||
prog->aux->jit_data = NULL;
|
||||
}
|
||||
out:
|
||||
if (tmp_blinded)
|
||||
bpf_jit_prog_release_other(prog, prog == orig_prog ?
|
||||
|
@ -473,7 +473,7 @@ static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb,
|
||||
ENI_PRV_POS(skb) = eni_vcc->descr+size+1;
|
||||
skb_queue_tail(&eni_dev->rx_queue,skb);
|
||||
eni_vcc->last = skb;
|
||||
rx_enqueued++;
|
||||
rx_enqueued++;
|
||||
}
|
||||
eni_vcc->descr = here;
|
||||
eni_out(dma_wr,MID_DMA_WR_RX);
|
||||
@ -715,7 +715,7 @@ static void get_service(struct atm_dev *dev)
|
||||
else eni_dev->slow = vcc;
|
||||
eni_dev->last_slow = vcc;
|
||||
}
|
||||
putting++;
|
||||
putting++;
|
||||
ENI_VCC(vcc)->servicing++;
|
||||
}
|
||||
}
|
||||
@ -744,7 +744,7 @@ static void dequeue_rx(struct atm_dev *dev)
|
||||
}
|
||||
EVENT("dequeued (size=%ld,pos=0x%lx)\n",ENI_PRV_SIZE(skb),
|
||||
ENI_PRV_POS(skb));
|
||||
rx_dequeued++;
|
||||
rx_dequeued++;
|
||||
vcc = ATM_SKB(skb)->vcc;
|
||||
eni_vcc = ENI_VCC(vcc);
|
||||
first = 0;
|
||||
@ -1174,7 +1174,7 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
|
||||
DPRINTK("dma_wr set to %d, tx_pos is now %ld\n",dma_wr,tx->tx_pos);
|
||||
eni_out(dma_wr,MID_DMA_WR_TX);
|
||||
skb_queue_tail(&eni_dev->tx_queue,skb);
|
||||
queued++;
|
||||
queued++;
|
||||
return enq_ok;
|
||||
}
|
||||
|
||||
@ -1195,7 +1195,7 @@ static void poll_tx(struct atm_dev *dev)
|
||||
if (res == enq_ok) continue;
|
||||
DPRINTK("re-queuing TX PDU\n");
|
||||
skb_queue_head(&tx->backlog,skb);
|
||||
requeued++;
|
||||
requeued++;
|
||||
if (res == enq_jam) return;
|
||||
break;
|
||||
}
|
||||
@ -1232,7 +1232,7 @@ static void dequeue_tx(struct atm_dev *dev)
|
||||
else dev_kfree_skb_irq(skb);
|
||||
atomic_inc(&vcc->stats->tx);
|
||||
wake_up(&eni_dev->tx_wait);
|
||||
dma_complete++;
|
||||
dma_complete++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1555,7 +1555,7 @@ static void eni_tasklet(unsigned long data)
|
||||
}
|
||||
if (events & MID_TX_COMPLETE) {
|
||||
EVENT("INT: TX COMPLETE\n",0,0);
|
||||
tx_complete++;
|
||||
tx_complete++;
|
||||
wake_up(&eni_dev->tx_wait);
|
||||
/* poll_rx ? */
|
||||
}
|
||||
@ -2069,14 +2069,14 @@ static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb)
|
||||
}
|
||||
*(u32 *) skb->data = htonl(*(u32 *) skb->data);
|
||||
}
|
||||
submitted++;
|
||||
submitted++;
|
||||
ATM_SKB(skb)->vcc = vcc;
|
||||
tasklet_disable(&ENI_DEV(vcc->dev)->task);
|
||||
res = do_tx(skb);
|
||||
tasklet_enable(&ENI_DEV(vcc->dev)->task);
|
||||
if (res == enq_ok) return 0;
|
||||
skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
|
||||
backlogged++;
|
||||
backlogged++;
|
||||
tasklet_schedule(&ENI_DEV(vcc->dev)->task);
|
||||
return 0;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/phy.h>
|
||||
@ -996,6 +997,32 @@ fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
|
||||
|
||||
/**
|
||||
* fwnode_get_next_available_child_node - Return the next
|
||||
* available child node handle for a node
|
||||
* @fwnode: Firmware node to find the next child node for.
|
||||
* @child: Handle to one of the node's child nodes or a %NULL handle.
|
||||
*/
|
||||
struct fwnode_handle *
|
||||
fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
|
||||
struct fwnode_handle *child)
|
||||
{
|
||||
struct fwnode_handle *next_child = child;
|
||||
|
||||
if (!fwnode)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
next_child = fwnode_get_next_child_node(fwnode, next_child);
|
||||
|
||||
if (!next_child || fwnode_device_is_available(next_child))
|
||||
break;
|
||||
} while (next_child);
|
||||
|
||||
return next_child;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
|
||||
|
||||
/**
|
||||
* device_get_next_child_node - Return the next child node handle for a device
|
||||
* @dev: Device to find the next child node for.
|
||||
@ -1126,21 +1153,21 @@ enum dev_dma_attr device_get_dma_attr(struct device *dev)
|
||||
EXPORT_SYMBOL_GPL(device_get_dma_attr);
|
||||
|
||||
/**
|
||||
* device_get_phy_mode - Get phy mode for given device
|
||||
* @dev: Pointer to the given device
|
||||
* fwnode_get_phy_mode - Get phy mode for given firmware node
|
||||
* @fwnode: Pointer to the given node
|
||||
*
|
||||
* The function gets phy interface string from property 'phy-mode' or
|
||||
* 'phy-connection-type', and return its index in phy_modes table, or errno in
|
||||
* error case.
|
||||
*/
|
||||
int device_get_phy_mode(struct device *dev)
|
||||
int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
|
||||
{
|
||||
const char *pm;
|
||||
int err, i;
|
||||
|
||||
err = device_property_read_string(dev, "phy-mode", &pm);
|
||||
err = fwnode_property_read_string(fwnode, "phy-mode", &pm);
|
||||
if (err < 0)
|
||||
err = device_property_read_string(dev,
|
||||
err = fwnode_property_read_string(fwnode,
|
||||
"phy-connection-type", &pm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -1151,13 +1178,27 @@ int device_get_phy_mode(struct device *dev)
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
|
||||
|
||||
/**
|
||||
* device_get_phy_mode - Get phy mode for given device
|
||||
* @dev: Pointer to the given device
|
||||
*
|
||||
* The function gets phy interface string from property 'phy-mode' or
|
||||
* 'phy-connection-type', and return its index in phy_modes table, or errno in
|
||||
* error case.
|
||||
*/
|
||||
int device_get_phy_mode(struct device *dev)
|
||||
{
|
||||
return fwnode_get_phy_mode(dev_fwnode(dev));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_get_phy_mode);
|
||||
|
||||
static void *device_get_mac_addr(struct device *dev,
|
||||
static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
|
||||
const char *name, char *addr,
|
||||
int alen)
|
||||
{
|
||||
int ret = device_property_read_u8_array(dev, name, addr, alen);
|
||||
int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
|
||||
|
||||
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
|
||||
return addr;
|
||||
@ -1165,8 +1206,8 @@ static void *device_get_mac_addr(struct device *dev,
|
||||
}
|
||||
|
||||
/**
|
||||
* device_get_mac_address - Get the MAC for a given device
|
||||
* @dev: Pointer to the device
|
||||
* fwnode_get_mac_address - Get the MAC from the firmware node
|
||||
* @fwnode: Pointer to the firmware node
|
||||
* @addr: Address of buffer to store the MAC in
|
||||
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
|
||||
*
|
||||
@ -1187,22 +1228,59 @@ static void *device_get_mac_addr(struct device *dev,
|
||||
* In this case, the real MAC is in 'local-mac-address', and 'mac-address'
|
||||
* exists but is all zeros.
|
||||
*/
|
||||
void *device_get_mac_address(struct device *dev, char *addr, int alen)
|
||||
void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int alen)
|
||||
{
|
||||
char *res;
|
||||
|
||||
res = device_get_mac_addr(dev, "mac-address", addr, alen);
|
||||
res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
|
||||
res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
return device_get_mac_addr(dev, "address", addr, alen);
|
||||
return fwnode_get_mac_addr(fwnode, "address", addr, alen);
|
||||
}
|
||||
EXPORT_SYMBOL(fwnode_get_mac_address);
|
||||
|
||||
/**
|
||||
* device_get_mac_address - Get the MAC for a given device
|
||||
* @dev: Pointer to the device
|
||||
* @addr: Address of buffer to store the MAC in
|
||||
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
|
||||
*/
|
||||
void *device_get_mac_address(struct device *dev, char *addr, int alen)
|
||||
{
|
||||
return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
|
||||
}
|
||||
EXPORT_SYMBOL(device_get_mac_address);
|
||||
|
||||
/**
|
||||
* fwnode_irq_get - Get IRQ directly from a fwnode
|
||||
* @fwnode: Pointer to the firmware node
|
||||
* @index: Zero-based index of the IRQ
|
||||
*
|
||||
* Returns Linux IRQ number on success. Other values are determined
|
||||
* accordingly to acpi_/of_ irq_get() operation.
|
||||
*/
|
||||
int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index)
|
||||
{
|
||||
struct device_node *of_node = to_of_node(fwnode);
|
||||
struct resource res;
|
||||
int ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF) && of_node)
|
||||
return of_irq_get(of_node, index);
|
||||
|
||||
ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return res.start;
|
||||
}
|
||||
EXPORT_SYMBOL(fwnode_irq_get);
|
||||
|
||||
/**
|
||||
* device_graph_get_next_endpoint - Get next endpoint firmware node
|
||||
* @fwnode: Pointer to the parent firmware node
|
||||
|
@ -83,7 +83,8 @@ static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2)
|
||||
bcma_core_pcie2_set_ltr_vals(pcie2);
|
||||
|
||||
/* TODO:
|
||||
si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */
|
||||
*si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0);
|
||||
*/
|
||||
|
||||
/* enable the LTR */
|
||||
devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB;
|
||||
|
@ -31,6 +31,16 @@ config BT_HCIBTUSB
|
||||
Say Y here to compile support for Bluetooth USB devices into the
|
||||
kernel or say M to compile it as module (btusb).
|
||||
|
||||
config BT_HCIBTUSB_AUTOSUSPEND
|
||||
bool "Enable USB autosuspend for Bluetooth USB devices by default"
|
||||
depends on BT_HCIBTUSB
|
||||
help
|
||||
Say Y here to enable USB autosuspend for Bluetooth USB devices by
|
||||
default.
|
||||
|
||||
This can be overridden by passing btusb.enable_autosuspend=[y|n]
|
||||
on the kernel commandline.
|
||||
|
||||
config BT_HCIBTUSB_BCM
|
||||
bool "Broadcom protocol support"
|
||||
depends on BT_HCIBTUSB
|
||||
@ -67,6 +77,7 @@ config BT_HCIBTSDIO
|
||||
config BT_HCIUART
|
||||
tristate "HCI UART driver"
|
||||
depends on SERIAL_DEV_BUS || !SERIAL_DEV_BUS
|
||||
depends on NVMEM || !NVMEM
|
||||
depends on TTY
|
||||
help
|
||||
Bluetooth HCI UART driver.
|
||||
@ -97,6 +108,7 @@ config BT_HCIUART_NOKIA
|
||||
tristate "UART Nokia H4+ protocol support"
|
||||
depends on BT_HCIUART
|
||||
depends on BT_HCIUART_SERDEV
|
||||
depends on GPIOLIB
|
||||
depends on PM
|
||||
select BT_HCIUART_H4
|
||||
select BT_BCM
|
||||
@ -158,6 +170,7 @@ config BT_HCIUART_3WIRE
|
||||
config BT_HCIUART_INTEL
|
||||
bool "Intel protocol support"
|
||||
depends on BT_HCIUART
|
||||
depends on GPIOLIB
|
||||
select BT_HCIUART_H4
|
||||
select BT_INTEL
|
||||
help
|
||||
@ -171,6 +184,7 @@ config BT_HCIUART_BCM
|
||||
depends on BT_HCIUART
|
||||
depends on BT_HCIUART_SERDEV
|
||||
depends on (!ACPI || SERIAL_DEV_CTRL_TTYPORT)
|
||||
depends on GPIOLIB
|
||||
select BT_HCIUART_H4
|
||||
select BT_BCM
|
||||
help
|
||||
|
@ -302,9 +302,7 @@ static void bluecard_write_wakeup(struct bluecard_info *info)
|
||||
}
|
||||
|
||||
/* Wait until the command reaches the baseband */
|
||||
prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ/10);
|
||||
finish_wait(&wq, &wait);
|
||||
mdelay(100);
|
||||
|
||||
/* Set baud on baseband */
|
||||
info->ctrl_reg &= ~0x03;
|
||||
@ -316,9 +314,7 @@ static void bluecard_write_wakeup(struct bluecard_info *info)
|
||||
outb(info->ctrl_reg, iobase + REG_CONTROL);
|
||||
|
||||
/* Wait before the next HCI packet can be send */
|
||||
prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ);
|
||||
finish_wait(&wq, &wait);
|
||||
mdelay(1000);
|
||||
}
|
||||
|
||||
if (len == skb->len) {
|
||||
|
@ -259,7 +259,7 @@ static int bpa10x_flush(struct hci_dev *hdev)
|
||||
|
||||
static int bpa10x_setup(struct hci_dev *hdev)
|
||||
{
|
||||
const u8 req[] = { 0x07 };
|
||||
static const u8 req[] = { 0x07 };
|
||||
struct sk_buff *skb;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
@ -323,6 +323,7 @@ static const struct {
|
||||
{ 0x410e, "BCM43341B0" }, /* 002.001.014 */
|
||||
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */
|
||||
{ 0x610c, "BCM4354" }, /* 003.001.012 */
|
||||
{ 0x2122, "BCM4343A0" }, /* 001.001.034 */
|
||||
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */
|
||||
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */
|
||||
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
|
||||
|
@ -44,8 +44,8 @@ struct bcm_set_sleep_mode {
|
||||
__u8 tristate_control;
|
||||
__u8 usb_auto_sleep;
|
||||
__u8 usb_resume_timeout;
|
||||
__u8 pulsed_host_wake;
|
||||
__u8 break_to_host;
|
||||
__u8 pulsed_host_wake;
|
||||
} __packed;
|
||||
|
||||
struct bcm_set_pcm_int_params {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
@ -75,7 +76,7 @@ EXPORT_SYMBOL_GPL(btintel_check_bdaddr);
|
||||
|
||||
int btintel_enter_mfg(struct hci_dev *hdev)
|
||||
{
|
||||
const u8 param[] = { 0x01, 0x00 };
|
||||
static const u8 param[] = { 0x01, 0x00 };
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT);
|
||||
@ -569,6 +570,160 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_regmap_init);
|
||||
|
||||
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param)
|
||||
{
|
||||
struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 };
|
||||
struct sk_buff *skb;
|
||||
|
||||
params.boot_param = cpu_to_le32(boot_param);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), ¶ms,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Failed to send Intel Reset command");
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_send_intel_reset);
|
||||
|
||||
int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
struct intel_boot_params *params)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*params)) {
|
||||
bt_dev_err(hdev, "Intel boot parameters size mismatch");
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
memcpy(params, skb->data, sizeof(*params));
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
if (params->status) {
|
||||
bt_dev_err(hdev, "Intel boot parameters command failed (%02x)",
|
||||
params->status);
|
||||
return -bt_to_errno(params->status);
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "Device revision is %u",
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
bt_dev_info(hdev, "Secure boot is %s",
|
||||
params->secure_boot ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "OTP lock is %s",
|
||||
params->otp_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "API lock is %s",
|
||||
params->api_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Debug lock is %s",
|
||||
params->debug_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
|
||||
params->min_fw_build_nn, params->min_fw_build_cw,
|
||||
2000 + params->min_fw_build_yy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_read_boot_params);
|
||||
|
||||
int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
|
||||
u32 *boot_param)
|
||||
{
|
||||
int err;
|
||||
const u8 *fw_ptr;
|
||||
u32 frag_len;
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of signature information from the firmware
|
||||
* as the Sign fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware signature (%d)", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
frag_len = 0;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
/* Each SKU has a different reset parameter to use in the
|
||||
* HCI_Intel_Reset command and it is embedded in the firmware
|
||||
* data. So, instead of using static value per SKU, check
|
||||
* the firmware data and save it for later use.
|
||||
*/
|
||||
if (le16_to_cpu(cmd->opcode) == 0xfc0e) {
|
||||
/* The boot parameter is the first 32-bit value
|
||||
* and rest of 3 octets are reserved.
|
||||
*/
|
||||
*boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
|
||||
|
||||
bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param);
|
||||
}
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
/* The parameter length of the secure send command requires
|
||||
* a 4 byte alignment. It happens so that the firmware file
|
||||
* contains proper Intel_NOP commands to align the fragments
|
||||
* as needed.
|
||||
*
|
||||
* Send set of commands with 4 byte alignment from the
|
||||
* firmware data buffer as a single Data fragement.
|
||||
*/
|
||||
if (!(frag_len % 4)) {
|
||||
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev,
|
||||
"Failed to send firmware data (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr += frag_len;
|
||||
frag_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_download_firmware);
|
||||
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
|
@ -69,6 +69,14 @@ struct intel_secure_send_result {
|
||||
__u8 status;
|
||||
} __packed;
|
||||
|
||||
struct intel_reset {
|
||||
__u8 reset_type;
|
||||
__u8 patch_enable;
|
||||
__u8 ddc_reload;
|
||||
__u8 boot_option;
|
||||
__le32 boot_param;
|
||||
} __packed;
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_INTEL)
|
||||
|
||||
int btintel_check_bdaddr(struct hci_dev *hdev);
|
||||
@ -89,7 +97,11 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
|
||||
|
||||
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
|
||||
u16 opcode_write);
|
||||
|
||||
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
|
||||
int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
struct intel_boot_params *params);
|
||||
int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
|
||||
u32 *boot_param);
|
||||
#else
|
||||
|
||||
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
|
||||
@ -165,4 +177,23 @@ static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline int btintel_send_intel_reset(struct hci_dev *hdev,
|
||||
u32 reset_param)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btintel_read_boot_params(struct hci_dev *hdev,
|
||||
struct intel_boot_params *params)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btintel_download_firmware(struct hci_dev *dev,
|
||||
const struct firmware *fw,
|
||||
u32 *boot_param)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
@ -88,7 +88,8 @@ static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
if (!ret)
|
||||
kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
@ -292,6 +293,14 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
tuple = tuple->next;
|
||||
}
|
||||
|
||||
/* BCM43341 devices soldered onto the PCB (non-removable) use an
|
||||
* uart connection for bluetooth, ignore the BT SDIO interface.
|
||||
*/
|
||||
if (func->vendor == SDIO_VENDOR_ID_BROADCOM &&
|
||||
func->device == SDIO_DEVICE_ID_BROADCOM_43341 &&
|
||||
!mmc_card_is_removable(func->card->host))
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/quirks.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
@ -40,6 +41,7 @@
|
||||
|
||||
static bool disable_scofix;
|
||||
static bool force_scofix;
|
||||
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
|
||||
|
||||
static bool reset = true;
|
||||
|
||||
@ -263,6 +265,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
/* QCA ROME chipset */
|
||||
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME },
|
||||
@ -270,6 +273,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
@ -387,9 +391,8 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
#define BTUSB_FIRMWARE_LOADED 7
|
||||
#define BTUSB_FIRMWARE_FAILED 8
|
||||
#define BTUSB_BOOTING 9
|
||||
#define BTUSB_RESET_RESUME 10
|
||||
#define BTUSB_DIAG_RUNNING 11
|
||||
#define BTUSB_OOB_WAKE_ENABLED 12
|
||||
#define BTUSB_DIAG_RUNNING 10
|
||||
#define BTUSB_OOB_WAKE_ENABLED 11
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
@ -2006,15 +2009,11 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
{
|
||||
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x08, 0x04, 0x00 };
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct sk_buff *skb;
|
||||
struct intel_version ver;
|
||||
struct intel_boot_params *params;
|
||||
struct intel_boot_params params;
|
||||
const struct firmware *fw;
|
||||
const u8 *fw_ptr;
|
||||
u32 frag_len;
|
||||
u32 boot_param;
|
||||
char fwname[64];
|
||||
ktime_t calltime, delta, rettime;
|
||||
unsigned long long duration;
|
||||
@ -2022,6 +2021,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
/* Set the default boot parameter to 0x0 and it is updated to
|
||||
* SKU specific boot parameter after reading Intel_Write_Boot_Params
|
||||
* command while downloading the firmware.
|
||||
*/
|
||||
boot_param = 0x00000000;
|
||||
|
||||
calltime = ktime_get();
|
||||
|
||||
/* Read the Intel version information to determine if the device
|
||||
@ -2092,55 +2097,24 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
/* Read the secure boot parameters to identify the operating
|
||||
* details of the bootloader.
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: Reading Intel boot parameters failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*params)) {
|
||||
BT_ERR("%s: Intel boot parameters size mismatch", hdev->name);
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
params = (struct intel_boot_params *)skb->data;
|
||||
|
||||
bt_dev_info(hdev, "Device revision is %u",
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
bt_dev_info(hdev, "Secure boot is %s",
|
||||
params->secure_boot ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "OTP lock is %s",
|
||||
params->otp_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "API lock is %s",
|
||||
params->api_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Debug lock is %s",
|
||||
params->debug_lock ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
|
||||
params->min_fw_build_nn, params->min_fw_build_cw,
|
||||
2000 + params->min_fw_build_yy);
|
||||
err = btintel_read_boot_params(hdev, ¶ms);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* It is required that every single firmware fragment is acknowledged
|
||||
* with a command complete event. If the boot parameters indicate
|
||||
* that this bootloader does not send them, then abort the setup.
|
||||
*/
|
||||
if (params->limited_cce != 0x00) {
|
||||
if (params.limited_cce != 0x00) {
|
||||
BT_ERR("%s: Unsupported Intel firmware loading method (%u)",
|
||||
hdev->name, params->limited_cce);
|
||||
kfree_skb(skb);
|
||||
hdev->name, params.limited_cce);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If the OTP has no valid Bluetooth device address, then there will
|
||||
* also be no valid address for the operational firmware.
|
||||
*/
|
||||
if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
|
||||
if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) {
|
||||
bt_dev_info(hdev, "No device address configured");
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
}
|
||||
@ -2171,7 +2145,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
@ -2189,7 +2163,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to load Intel firmware file (%d)",
|
||||
hdev->name, err);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2203,7 +2176,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
@ -2217,8 +2190,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
if (fw->size < 644) {
|
||||
BT_ERR("%s: Invalid size of firmware file (%zu)",
|
||||
hdev->name, fw->size);
|
||||
@ -2228,64 +2199,10 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
|
||||
set_bit(BTUSB_DOWNLOADING, &data->flags);
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware header (%d)",
|
||||
hdev->name, err);
|
||||
/* Start firmware downloading and get boot parameter */
|
||||
err = btintel_download_firmware(hdev, fw, &boot_param);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware public key (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of signature information from the firmware
|
||||
* as the Sign fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware signature (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
frag_len = 0;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
/* The parameter length of the secure send command requires
|
||||
* a 4 byte alignment. It happens so that the firmware file
|
||||
* contains proper Intel_NOP commands to align the fragments
|
||||
* as needed.
|
||||
*
|
||||
* Send set of commands with 4 byte alignment from the
|
||||
* firmware data buffer as a single Data fragement.
|
||||
*/
|
||||
if (!(frag_len % 4)) {
|
||||
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
|
||||
if (err < 0) {
|
||||
BT_ERR("%s: Failed to send firmware data (%d)",
|
||||
hdev->name, err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr += frag_len;
|
||||
frag_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
|
||||
|
||||
@ -2338,12 +2255,9 @@ done:
|
||||
|
||||
set_bit(BTUSB_BOOTING, &data->flags);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
err = btintel_send_intel_reset(hdev, boot_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The bootloader will not indicate when the device is ready. This
|
||||
* is done by the operational firmware sending bootup notification.
|
||||
@ -3120,9 +3034,9 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
|
||||
/* QCA Rome devices lose their updated firmware over suspend,
|
||||
* but the USB hub doesn't notice any status change.
|
||||
* Explicitly request a device reset on resume.
|
||||
* explicitly request a device reset on resume.
|
||||
*/
|
||||
set_bit(BTUSB_RESET_RESUME, &data->flags);
|
||||
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BT_HCIBTUSB_RTL
|
||||
@ -3133,7 +3047,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
* but the USB hub doesn't notice any status change.
|
||||
* Explicitly request a device reset on resume.
|
||||
*/
|
||||
set_bit(BTUSB_RESET_RESUME, &data->flags);
|
||||
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3213,6 +3127,9 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (enable_autosuspend)
|
||||
usb_enable_autosuspend(data->udev);
|
||||
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0)
|
||||
goto out_free_dev;
|
||||
@ -3299,14 +3216,6 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
enable_irq(data->oob_wake_irq);
|
||||
}
|
||||
|
||||
/* Optionally request a device reset on resume, but only when
|
||||
* wakeups are disabled. If wakeups are enabled we assume the
|
||||
* device will stay powered up throughout suspend.
|
||||
*/
|
||||
if (test_bit(BTUSB_RESET_RESUME, &data->flags) &&
|
||||
!device_may_wakeup(&data->udev->dev))
|
||||
data->udev->reset_resume = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3425,6 +3334,9 @@ MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
|
||||
module_param(force_scofix, bool, 0644);
|
||||
MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
|
||||
|
||||
module_param(enable_autosuspend, bool, 0644);
|
||||
MODULE_PARM_DESC(enable_autosuspend, "Enable USB autosuspend by default");
|
||||
|
||||
module_param(reset, bool, 0644);
|
||||
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/platform_data/x86/apple.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
@ -52,7 +53,37 @@
|
||||
|
||||
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
|
||||
|
||||
/* device driver resources */
|
||||
/**
|
||||
* struct bcm_device - device driver resources
|
||||
* @serdev_hu: HCI UART controller struct
|
||||
* @list: bcm_device_list node
|
||||
* @dev: physical UART slave
|
||||
* @name: device name logged by bt_dev_*() functions
|
||||
* @device_wakeup: BT_WAKE pin,
|
||||
* assert = Bluetooth device must wake up or remain awake,
|
||||
* deassert = Bluetooth device may sleep when sleep criteria are met
|
||||
* @shutdown: BT_REG_ON pin,
|
||||
* power up or power down Bluetooth device internal regulators
|
||||
* @set_device_wakeup: callback to toggle BT_WAKE pin
|
||||
* either by accessing @device_wakeup or by calling @btlp
|
||||
* @set_shutdown: callback to toggle BT_REG_ON pin
|
||||
* either by accessing @shutdown or by calling @btpu/@btpd
|
||||
* @btlp: Apple ACPI method to toggle BT_WAKE pin ("Bluetooth Low Power")
|
||||
* @btpu: Apple ACPI method to drive BT_REG_ON pin high ("Bluetooth Power Up")
|
||||
* @btpd: Apple ACPI method to drive BT_REG_ON pin low ("Bluetooth Power Down")
|
||||
* @clk: clock used by Bluetooth device
|
||||
* @clk_enabled: whether @clk is prepared and enabled
|
||||
* @init_speed: default baudrate of Bluetooth device;
|
||||
* the host UART is initially set to this baudrate so that
|
||||
* it can configure the Bluetooth device for @oper_speed
|
||||
* @oper_speed: preferred baudrate of Bluetooth device;
|
||||
* set to 0 if @init_speed is already the preferred baudrate
|
||||
* @irq: interrupt triggered by HOST_WAKE_BT pin
|
||||
* @irq_active_low: whether @irq is active low
|
||||
* @hu: pointer to HCI UART controller struct,
|
||||
* used to disable flow control during runtime suspend and system sleep
|
||||
* @is_suspended: whether flow control is currently disabled
|
||||
*/
|
||||
struct bcm_device {
|
||||
/* Must be the first member, hci_serdev.c expects this. */
|
||||
struct hci_uart serdev_hu;
|
||||
@ -63,6 +94,11 @@ struct bcm_device {
|
||||
const char *name;
|
||||
struct gpio_desc *device_wakeup;
|
||||
struct gpio_desc *shutdown;
|
||||
int (*set_device_wakeup)(struct bcm_device *, bool);
|
||||
int (*set_shutdown)(struct bcm_device *, bool);
|
||||
#ifdef CONFIG_ACPI
|
||||
acpi_handle btlp, btpu, btpd;
|
||||
#endif
|
||||
|
||||
struct clk *clk;
|
||||
bool clk_enabled;
|
||||
@ -74,7 +110,7 @@ struct bcm_device {
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
struct hci_uart *hu;
|
||||
bool is_suspended; /* suspend/resume flag */
|
||||
bool is_suspended;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -170,11 +206,21 @@ static bool bcm_device_exists(struct bcm_device *device)
|
||||
|
||||
static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
|
||||
{
|
||||
if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled)
|
||||
clk_prepare_enable(dev->clk);
|
||||
int err;
|
||||
|
||||
gpiod_set_value(dev->shutdown, powered);
|
||||
gpiod_set_value(dev->device_wakeup, powered);
|
||||
if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) {
|
||||
err = clk_prepare_enable(dev->clk);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = dev->set_shutdown(dev, powered);
|
||||
if (err)
|
||||
goto err_clk_disable;
|
||||
|
||||
err = dev->set_device_wakeup(dev, powered);
|
||||
if (err)
|
||||
goto err_revert_shutdown;
|
||||
|
||||
if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled)
|
||||
clk_disable_unprepare(dev->clk);
|
||||
@ -182,6 +228,13 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
|
||||
dev->clk_enabled = powered;
|
||||
|
||||
return 0;
|
||||
|
||||
err_revert_shutdown:
|
||||
dev->set_shutdown(dev, !powered);
|
||||
err_clk_disable:
|
||||
if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled)
|
||||
clk_disable_unprepare(dev->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@ -191,9 +244,7 @@ static irqreturn_t bcm_host_wake(int irq, void *data)
|
||||
|
||||
bt_dev_dbg(bdev, "Host wake IRQ");
|
||||
|
||||
pm_runtime_get(bdev->dev);
|
||||
pm_runtime_mark_last_busy(bdev->dev);
|
||||
pm_runtime_put_autosuspend(bdev->dev);
|
||||
pm_request_resume(bdev->dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -218,8 +269,10 @@ static int bcm_request_irq(struct bcm_data *bcm)
|
||||
bdev->irq_active_low ? IRQF_TRIGGER_FALLING :
|
||||
IRQF_TRIGGER_RISING,
|
||||
"host_wake", bdev);
|
||||
if (err)
|
||||
if (err) {
|
||||
bdev->irq = err;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
device_init_wakeup(bdev->dev, true);
|
||||
|
||||
@ -247,8 +300,8 @@ static const struct bcm_set_sleep_mode default_sleep_params = {
|
||||
/* Irrelevant USB flags */
|
||||
.usb_auto_sleep = 0,
|
||||
.usb_resume_timeout = 0,
|
||||
.break_to_host = 0,
|
||||
.pulsed_host_wake = 0,
|
||||
.break_to_host = 0
|
||||
};
|
||||
|
||||
static int bcm_setup_sleep(struct hci_uart *hu)
|
||||
@ -304,6 +357,7 @@ static int bcm_open(struct hci_uart *hu)
|
||||
{
|
||||
struct bcm_data *bcm;
|
||||
struct list_head *p;
|
||||
int err;
|
||||
|
||||
bt_dev_dbg(hu->hdev, "hu %p", hu);
|
||||
|
||||
@ -318,7 +372,10 @@ static int bcm_open(struct hci_uart *hu)
|
||||
mutex_lock(&bcm_device_lock);
|
||||
|
||||
if (hu->serdev) {
|
||||
serdev_device_open(hu->serdev);
|
||||
err = serdev_device_open(hu->serdev);
|
||||
if (err)
|
||||
goto err_free;
|
||||
|
||||
bcm->dev = serdev_device_get_drvdata(hu->serdev);
|
||||
goto out;
|
||||
}
|
||||
@ -346,17 +403,33 @@ out:
|
||||
if (bcm->dev) {
|
||||
hu->init_speed = bcm->dev->init_speed;
|
||||
hu->oper_speed = bcm->dev->oper_speed;
|
||||
bcm_gpio_set_power(bcm->dev, true);
|
||||
err = bcm_gpio_set_power(bcm->dev, true);
|
||||
if (err)
|
||||
goto err_unset_hu;
|
||||
}
|
||||
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
return 0;
|
||||
|
||||
err_unset_hu:
|
||||
if (hu->serdev)
|
||||
serdev_device_close(hu->serdev);
|
||||
#ifdef CONFIG_PM
|
||||
else
|
||||
bcm->dev->hu = NULL;
|
||||
#endif
|
||||
err_free:
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
hu->priv = NULL;
|
||||
kfree(bcm);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm_close(struct hci_uart *hu)
|
||||
{
|
||||
struct bcm_data *bcm = hu->priv;
|
||||
struct bcm_device *bdev = NULL;
|
||||
int err;
|
||||
|
||||
bt_dev_dbg(hu->hdev, "hu %p", hu);
|
||||
|
||||
@ -374,16 +447,17 @@ static int bcm_close(struct hci_uart *hu)
|
||||
}
|
||||
|
||||
if (bdev) {
|
||||
bcm_gpio_set_power(bdev, false);
|
||||
#ifdef CONFIG_PM
|
||||
pm_runtime_disable(bdev->dev);
|
||||
pm_runtime_set_suspended(bdev->dev);
|
||||
|
||||
if (device_can_wakeup(bdev->dev)) {
|
||||
if (IS_ENABLED(CONFIG_PM) && bdev->irq > 0) {
|
||||
devm_free_irq(bdev->dev, bdev->irq, bdev);
|
||||
device_init_wakeup(bdev->dev, false);
|
||||
pm_runtime_disable(bdev->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
err = bcm_gpio_set_power(bdev, false);
|
||||
if (err)
|
||||
bt_dev_err(hu->hdev, "Failed to power down");
|
||||
else
|
||||
pm_runtime_set_suspended(bdev->dev);
|
||||
}
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
|
||||
@ -512,11 +586,8 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
|
||||
} else if (!bcm->rx_skb) {
|
||||
/* Delay auto-suspend when receiving completed packet */
|
||||
mutex_lock(&bcm_device_lock);
|
||||
if (bcm->dev && bcm_device_exists(bcm->dev)) {
|
||||
pm_runtime_get(bcm->dev->dev);
|
||||
pm_runtime_mark_last_busy(bcm->dev->dev);
|
||||
pm_runtime_put_autosuspend(bcm->dev->dev);
|
||||
}
|
||||
if (bcm->dev && bcm_device_exists(bcm->dev))
|
||||
pm_request_resume(bcm->dev->dev);
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
}
|
||||
|
||||
@ -566,6 +637,7 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
|
||||
static int bcm_suspend_device(struct device *dev)
|
||||
{
|
||||
struct bcm_device *bdev = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
bt_dev_dbg(bdev, "");
|
||||
|
||||
@ -577,27 +649,37 @@ static int bcm_suspend_device(struct device *dev)
|
||||
}
|
||||
|
||||
/* Suspend the device */
|
||||
if (bdev->device_wakeup) {
|
||||
gpiod_set_value(bdev->device_wakeup, false);
|
||||
bt_dev_dbg(bdev, "suspend, delaying 15 ms");
|
||||
mdelay(15);
|
||||
err = bdev->set_device_wakeup(bdev, false);
|
||||
if (err) {
|
||||
if (bdev->is_suspended && bdev->hu) {
|
||||
bdev->is_suspended = false;
|
||||
hci_uart_set_flow_control(bdev->hu, false);
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
bt_dev_dbg(bdev, "suspend, delaying 15 ms");
|
||||
msleep(15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_resume_device(struct device *dev)
|
||||
{
|
||||
struct bcm_device *bdev = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
bt_dev_dbg(bdev, "");
|
||||
|
||||
if (bdev->device_wakeup) {
|
||||
gpiod_set_value(bdev->device_wakeup, true);
|
||||
bt_dev_dbg(bdev, "resume, delaying 15 ms");
|
||||
mdelay(15);
|
||||
err = bdev->set_device_wakeup(bdev, true);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to power up\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_dbg(bdev, "resume, delaying 15 ms");
|
||||
msleep(15);
|
||||
|
||||
/* When this executes, the device has woken up already */
|
||||
if (bdev->is_suspended && bdev->hu) {
|
||||
bdev->is_suspended = false;
|
||||
@ -632,7 +714,7 @@ static int bcm_suspend(struct device *dev)
|
||||
if (pm_runtime_active(dev))
|
||||
bcm_suspend_device(dev);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
if (device_may_wakeup(dev) && bdev->irq > 0) {
|
||||
error = enable_irq_wake(bdev->irq);
|
||||
if (!error)
|
||||
bt_dev_dbg(bdev, "BCM irq: enabled");
|
||||
@ -648,6 +730,7 @@ unlock:
|
||||
static int bcm_resume(struct device *dev)
|
||||
{
|
||||
struct bcm_device *bdev = dev_get_drvdata(dev);
|
||||
int err = 0;
|
||||
|
||||
bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
|
||||
|
||||
@ -662,19 +745,21 @@ static int bcm_resume(struct device *dev)
|
||||
if (!bdev->hu)
|
||||
goto unlock;
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
if (device_may_wakeup(dev) && bdev->irq > 0) {
|
||||
disable_irq_wake(bdev->irq);
|
||||
bt_dev_dbg(bdev, "BCM irq: disabled");
|
||||
}
|
||||
|
||||
bcm_resume_device(dev);
|
||||
err = bcm_resume_device(dev);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
if (!err) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -771,25 +856,84 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_apple_set_device_wakeup(struct bcm_device *dev, bool awake)
|
||||
{
|
||||
if (ACPI_FAILURE(acpi_execute_simple_method(dev->btlp, NULL, !awake)))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_apple_set_shutdown(struct bcm_device *dev, bool powered)
|
||||
{
|
||||
if (ACPI_FAILURE(acpi_evaluate_object(powered ? dev->btpu : dev->btpd,
|
||||
NULL, NULL, NULL)))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_apple_get_resources(struct bcm_device *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev->dev);
|
||||
const union acpi_object *obj;
|
||||
|
||||
if (!adev ||
|
||||
ACPI_FAILURE(acpi_get_handle(adev->handle, "BTLP", &dev->btlp)) ||
|
||||
ACPI_FAILURE(acpi_get_handle(adev->handle, "BTPU", &dev->btpu)) ||
|
||||
ACPI_FAILURE(acpi_get_handle(adev->handle, "BTPD", &dev->btpd)))
|
||||
return -ENODEV;
|
||||
|
||||
if (!acpi_dev_get_property(adev, "baud", ACPI_TYPE_BUFFER, &obj) &&
|
||||
obj->buffer.length == 8)
|
||||
dev->init_speed = *(u64 *)obj->buffer.pointer;
|
||||
|
||||
dev->set_device_wakeup = bcm_apple_set_device_wakeup;
|
||||
dev->set_shutdown = bcm_apple_set_shutdown;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int bcm_apple_get_resources(struct bcm_device *dev)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static int bcm_gpio_set_device_wakeup(struct bcm_device *dev, bool awake)
|
||||
{
|
||||
gpiod_set_value(dev->device_wakeup, awake);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_gpio_set_shutdown(struct bcm_device *dev, bool powered)
|
||||
{
|
||||
gpiod_set_value(dev->shutdown, powered);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_get_resources(struct bcm_device *dev)
|
||||
{
|
||||
dev->name = dev_name(dev->dev);
|
||||
|
||||
if (x86_apple_machine && !bcm_apple_get_resources(dev))
|
||||
return 0;
|
||||
|
||||
dev->clk = devm_clk_get(dev->dev, NULL);
|
||||
|
||||
dev->device_wakeup = devm_gpiod_get_optional(dev->dev,
|
||||
"device-wakeup",
|
||||
GPIOD_OUT_LOW);
|
||||
dev->device_wakeup = devm_gpiod_get(dev->dev, "device-wakeup",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(dev->device_wakeup))
|
||||
return PTR_ERR(dev->device_wakeup);
|
||||
|
||||
dev->shutdown = devm_gpiod_get_optional(dev->dev, "shutdown",
|
||||
GPIOD_OUT_LOW);
|
||||
dev->shutdown = devm_gpiod_get(dev->dev, "shutdown", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(dev->shutdown))
|
||||
return PTR_ERR(dev->shutdown);
|
||||
|
||||
dev->set_device_wakeup = bcm_gpio_set_device_wakeup;
|
||||
dev->set_shutdown = bcm_gpio_set_shutdown;
|
||||
|
||||
/* IRQ can be declared in ACPI table as Interrupt or GpioInt */
|
||||
if (dev->irq <= 0) {
|
||||
struct gpio_desc *gpio;
|
||||
@ -802,7 +946,7 @@ static int bcm_get_resources(struct bcm_device *dev)
|
||||
dev->irq = gpiod_to_irq(gpio);
|
||||
}
|
||||
|
||||
dev_info(dev->dev, "BCM irq: %d\n", dev->irq);
|
||||
dev_dbg(dev->dev, "BCM irq: %d\n", dev->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -892,7 +1036,9 @@ static int bcm_probe(struct platform_device *pdev)
|
||||
list_add_tail(&dev->list, &bcm_device_list);
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
|
||||
bcm_gpio_set_power(dev, false);
|
||||
ret = bcm_gpio_set_power(dev, false);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to power down\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -939,6 +1085,7 @@ static const struct acpi_device_id bcm_acpi_match[] = {
|
||||
{ "BCM2E65", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
|
||||
{ "BCM2E67", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
|
||||
{ "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
|
||||
{ "BCM2E72", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
|
||||
{ "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
|
||||
{ "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
|
||||
{ "BCM2E7E", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
|
||||
@ -993,7 +1140,9 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
bcm_gpio_set_power(bcmdev, false);
|
||||
err = bcm_gpio_set_power(bcmdev, false);
|
||||
if (err)
|
||||
dev_err(&serdev->dev, "Failed to power down\n");
|
||||
|
||||
return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
|
||||
}
|
||||
|
@ -540,18 +540,15 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
|
||||
|
||||
static int intel_setup(struct hci_uart *hu)
|
||||
{
|
||||
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x08, 0x04, 0x00 };
|
||||
struct intel_data *intel = hu->priv;
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
struct sk_buff *skb;
|
||||
struct intel_version ver;
|
||||
struct intel_boot_params *params;
|
||||
struct intel_boot_params params;
|
||||
struct list_head *p;
|
||||
const struct firmware *fw;
|
||||
const u8 *fw_ptr;
|
||||
char fwname[64];
|
||||
u32 frag_len;
|
||||
u32 boot_param;
|
||||
ktime_t calltime, delta, rettime;
|
||||
unsigned long long duration;
|
||||
unsigned int init_speed, oper_speed;
|
||||
@ -563,6 +560,12 @@ static int intel_setup(struct hci_uart *hu)
|
||||
hu->hdev->set_diag = btintel_set_diag;
|
||||
hu->hdev->set_bdaddr = btintel_set_bdaddr;
|
||||
|
||||
/* Set the default boot parameter to 0x0 and it is updated to
|
||||
* SKU specific boot parameter after reading Intel_Write_Boot_Params
|
||||
* command while downloading the firmware.
|
||||
*/
|
||||
boot_param = 0x00000000;
|
||||
|
||||
calltime = ktime_get();
|
||||
|
||||
if (hu->init_speed)
|
||||
@ -656,85 +659,95 @@ static int intel_setup(struct hci_uart *hu)
|
||||
/* Read the secure boot parameters to identify the operating
|
||||
* details of the bootloader.
|
||||
*/
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
|
||||
PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*params)) {
|
||||
bt_dev_err(hdev, "Intel boot parameters size mismatch");
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
params = (struct intel_boot_params *)skb->data;
|
||||
if (params->status) {
|
||||
bt_dev_err(hdev, "Intel boot parameters command failure (%02x)",
|
||||
params->status);
|
||||
err = -bt_to_errno(params->status);
|
||||
kfree_skb(skb);
|
||||
err = btintel_read_boot_params(hdev, ¶ms);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "Device revision is %u",
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
bt_dev_info(hdev, "Secure boot is %s",
|
||||
params->secure_boot ? "enabled" : "disabled");
|
||||
|
||||
bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
|
||||
params->min_fw_build_nn, params->min_fw_build_cw,
|
||||
2000 + params->min_fw_build_yy);
|
||||
|
||||
/* It is required that every single firmware fragment is acknowledged
|
||||
* with a command complete event. If the boot parameters indicate
|
||||
* that this bootloader does not send them, then abort the setup.
|
||||
*/
|
||||
if (params->limited_cce != 0x00) {
|
||||
if (params.limited_cce != 0x00) {
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
|
||||
params->limited_cce);
|
||||
kfree_skb(skb);
|
||||
params.limited_cce);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If the OTP has no valid Bluetooth device address, then there will
|
||||
* also be no valid address for the operational firmware.
|
||||
*/
|
||||
if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
|
||||
if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) {
|
||||
bt_dev_info(hdev, "No device address configured");
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
}
|
||||
|
||||
/* With this Intel bootloader only the hardware variant and device
|
||||
* revision information are used to select the right firmware.
|
||||
* revision information are used to select the right firmware for SfP
|
||||
* and WsP.
|
||||
*
|
||||
* The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
|
||||
*
|
||||
* Currently the supported hardware variants are:
|
||||
* 11 (0x0b) for iBT 3.0 (LnP/SfP)
|
||||
* 12 (0x0c) for iBT 3.5 (WsP)
|
||||
*
|
||||
* For ThP/JfP and for future SKU's, the FW name varies based on HW
|
||||
* variant, HW revision and FW revision, as these are dependent on CNVi
|
||||
* and RF Combination.
|
||||
*
|
||||
* 18 (0x12) for iBT3.5 (ThP/JfP)
|
||||
*
|
||||
* The firmware file name for these will be
|
||||
* ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
|
||||
*
|
||||
*/
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
switch (ver.hw_variant) {
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x12: /* ThP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
ver.hw_variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = request_firmware(&fw, fwname, &hdev->dev);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to load Intel firmware file (%d)",
|
||||
err);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_dev_info(hdev, "Found device firmware: %s", fwname);
|
||||
|
||||
/* Save the DDC file name for later */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
kfree_skb(skb);
|
||||
switch (ver.hw_variant) {
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x12: /* ThP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
ver.hw_variant);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fw->size < 644) {
|
||||
bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
|
||||
@ -745,70 +758,10 @@ static int intel_setup(struct hci_uart *hu)
|
||||
|
||||
set_bit(STATE_DOWNLOADING, &intel->flags);
|
||||
|
||||
/* Start the firmware download transaction with the Init fragment
|
||||
* represented by the 128 bytes of CSS header.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x00, 128, fw->data);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
|
||||
/* Start firmware downloading and get boot parameter */
|
||||
err = btintel_download_firmware(hdev, fw, &boot_param);
|
||||
if (err < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of public key information from the firmware
|
||||
* as the PKey fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware public key (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Send the 256 bytes of signature information from the firmware
|
||||
* as the Sign fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware signature (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr = fw->data + 644;
|
||||
frag_len = 0;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data),
|
||||
fw->size);
|
||||
|
||||
/* The parameter length of the secure send command requires
|
||||
* a 4 byte alignment. It happens so that the firmware file
|
||||
* contains proper Intel_NOP commands to align the fragments
|
||||
* as needed.
|
||||
*
|
||||
* Send set of commands with 4 byte alignment from the
|
||||
* firmware data buffer as a single Data fragement.
|
||||
*/
|
||||
if (frag_len % 4)
|
||||
continue;
|
||||
|
||||
/* Send each command from the firmware data buffer as
|
||||
* a single Data fragment.
|
||||
*/
|
||||
err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send firmware data (%d)",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_ptr += frag_len;
|
||||
frag_len = 0;
|
||||
}
|
||||
|
||||
set_bit(STATE_FIRMWARE_LOADED, &intel->flags);
|
||||
|
||||
@ -869,12 +822,9 @@ done:
|
||||
|
||||
set_bit(STATE_BOOTING, &intel->flags);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
|
||||
HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
err = btintel_send_intel_reset(hdev, boot_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The bootloader will not indicate when the device is ready. This
|
||||
* is done by the operational firmware sending bootup notification.
|
||||
|
@ -53,9 +53,14 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
|
||||
#include "hci_uart.h"
|
||||
|
||||
/* Vendor-specific HCI commands */
|
||||
#define HCI_VS_WRITE_BD_ADDR 0xfc06
|
||||
#define HCI_VS_UPDATE_UART_HCI_BAUDRATE 0xff36
|
||||
|
||||
/* HCILL commands */
|
||||
#define HCILL_GO_TO_SLEEP_IND 0x30
|
||||
#define HCILL_GO_TO_SLEEP_ACK 0x31
|
||||
@ -86,6 +91,7 @@ struct ll_device {
|
||||
struct serdev_device *serdev;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct clk *ext_clk;
|
||||
bdaddr_t bdaddr;
|
||||
};
|
||||
|
||||
struct ll_struct {
|
||||
@ -620,7 +626,7 @@ static int download_firmware(struct ll_device *lldev)
|
||||
case ACTION_SEND_COMMAND: /* action send */
|
||||
bt_dev_dbg(lldev->hu.hdev, "S");
|
||||
cmd = (struct hci_command *)action_ptr;
|
||||
if (cmd->opcode == 0xff36) {
|
||||
if (cmd->opcode == HCI_VS_UPDATE_UART_HCI_BAUDRATE) {
|
||||
/* ignore remote change
|
||||
* baud rate HCI VS command
|
||||
*/
|
||||
@ -628,11 +634,11 @@ static int download_firmware(struct ll_device *lldev)
|
||||
break;
|
||||
}
|
||||
if (cmd->prefix != 1)
|
||||
bt_dev_dbg(lldev->hu.hdev, "command type %d\n", cmd->prefix);
|
||||
bt_dev_dbg(lldev->hu.hdev, "command type %d", cmd->prefix);
|
||||
|
||||
skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen, &cmd->speed, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(lldev->hu.hdev, "send command failed\n");
|
||||
bt_dev_err(lldev->hu.hdev, "send command failed");
|
||||
err = PTR_ERR(skb);
|
||||
goto out_rel_fw;
|
||||
}
|
||||
@ -659,6 +665,24 @@ out_rel_fw:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ll_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
{
|
||||
bdaddr_t bdaddr_swapped;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* HCI_VS_WRITE_BD_ADDR (at least on a CC2560A chip) expects the BD
|
||||
* address to be MSB first, but bdaddr_t has the convention of being
|
||||
* LSB first.
|
||||
*/
|
||||
baswap(&bdaddr_swapped, bdaddr);
|
||||
skb = __hci_cmd_sync(hdev, HCI_VS_WRITE_BD_ADDR, sizeof(bdaddr_t),
|
||||
&bdaddr_swapped, HCI_INIT_TIMEOUT);
|
||||
if (!IS_ERR(skb))
|
||||
kfree_skb(skb);
|
||||
|
||||
return PTR_ERR_OR_ZERO(skb);
|
||||
}
|
||||
|
||||
static int ll_setup(struct hci_uart *hu)
|
||||
{
|
||||
int err, retry = 3;
|
||||
@ -671,14 +695,20 @@ static int ll_setup(struct hci_uart *hu)
|
||||
|
||||
lldev = serdev_device_get_drvdata(serdev);
|
||||
|
||||
hu->hdev->set_bdaddr = ll_set_bdaddr;
|
||||
|
||||
serdev_device_set_flow_control(serdev, true);
|
||||
|
||||
do {
|
||||
/* Configure BT_EN to HIGH state */
|
||||
/* Reset the Bluetooth device */
|
||||
gpiod_set_value_cansleep(lldev->enable_gpio, 0);
|
||||
msleep(5);
|
||||
gpiod_set_value_cansleep(lldev->enable_gpio, 1);
|
||||
msleep(100);
|
||||
err = serdev_device_wait_for_cts(serdev, true, 200);
|
||||
if (err) {
|
||||
bt_dev_err(hu->hdev, "Failed to get CTS");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = download_firmware(lldev);
|
||||
if (!err)
|
||||
@ -691,6 +721,18 @@ static int ll_setup(struct hci_uart *hu)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Set BD address if one was specified at probe */
|
||||
if (!bacmp(&lldev->bdaddr, BDADDR_NONE)) {
|
||||
/* This means that there was an error getting the BD address
|
||||
* during probe, so mark the device as having a bad address.
|
||||
*/
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks);
|
||||
} else if (bacmp(&lldev->bdaddr, BDADDR_ANY)) {
|
||||
err = ll_set_bdaddr(hu->hdev, &lldev->bdaddr);
|
||||
if (err)
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks);
|
||||
}
|
||||
|
||||
/* Operational speed if any */
|
||||
if (hu->oper_speed)
|
||||
speed = hu->oper_speed;
|
||||
@ -700,7 +742,12 @@ static int ll_setup(struct hci_uart *hu)
|
||||
speed = 0;
|
||||
|
||||
if (speed) {
|
||||
struct sk_buff *skb = __hci_cmd_sync(hu->hdev, 0xff36, sizeof(speed), &speed, HCI_INIT_TIMEOUT);
|
||||
__le32 speed_le = cpu_to_le32(speed);
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hu->hdev, HCI_VS_UPDATE_UART_HCI_BAUDRATE,
|
||||
sizeof(speed_le), &speed_le,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (!IS_ERR(skb)) {
|
||||
kfree_skb(skb);
|
||||
serdev_device_set_baudrate(serdev, speed);
|
||||
@ -716,6 +763,7 @@ static int hci_ti_probe(struct serdev_device *serdev)
|
||||
{
|
||||
struct hci_uart *hu;
|
||||
struct ll_device *lldev;
|
||||
struct nvmem_cell *bdaddr_cell;
|
||||
u32 max_speed = 3000000;
|
||||
|
||||
lldev = devm_kzalloc(&serdev->dev, sizeof(struct ll_device), GFP_KERNEL);
|
||||
@ -737,6 +785,52 @@ static int hci_ti_probe(struct serdev_device *serdev)
|
||||
of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed);
|
||||
hci_uart_set_speeds(hu, 115200, max_speed);
|
||||
|
||||
/* optional BD address from nvram */
|
||||
bdaddr_cell = nvmem_cell_get(&serdev->dev, "bd-address");
|
||||
if (IS_ERR(bdaddr_cell)) {
|
||||
int err = PTR_ERR(bdaddr_cell);
|
||||
|
||||
if (err == -EPROBE_DEFER)
|
||||
return err;
|
||||
|
||||
/* ENOENT means there is no matching nvmem cell and ENOSYS
|
||||
* means that nvmem is not enabled in the kernel configuration.
|
||||
*/
|
||||
if (err != -ENOENT && err != -ENOSYS) {
|
||||
/* If there was some other error, give userspace a
|
||||
* chance to fix the problem instead of failing to load
|
||||
* the driver. Using BDADDR_NONE as a flag that is
|
||||
* tested later in the setup function.
|
||||
*/
|
||||
dev_warn(&serdev->dev,
|
||||
"Failed to get \"bd-address\" nvmem cell (%d)\n",
|
||||
err);
|
||||
bacpy(&lldev->bdaddr, BDADDR_NONE);
|
||||
}
|
||||
} else {
|
||||
bdaddr_t *bdaddr;
|
||||
size_t len;
|
||||
|
||||
bdaddr = nvmem_cell_read(bdaddr_cell, &len);
|
||||
nvmem_cell_put(bdaddr_cell);
|
||||
if (IS_ERR(bdaddr)) {
|
||||
dev_err(&serdev->dev, "Failed to read nvmem bd-address\n");
|
||||
return PTR_ERR(bdaddr);
|
||||
}
|
||||
if (len != sizeof(bdaddr_t)) {
|
||||
dev_err(&serdev->dev, "Invalid nvmem bd-address length\n");
|
||||
kfree(bdaddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* As per the device tree bindings, the value from nvmem is
|
||||
* expected to be MSB first, but in the kernel it is expected
|
||||
* that bdaddr_t is LSB first.
|
||||
*/
|
||||
baswap(&lldev->bdaddr, bdaddr);
|
||||
kfree(bdaddr);
|
||||
}
|
||||
|
||||
return hci_uart_register_device(hu, &llp);
|
||||
}
|
||||
|
||||
@ -748,6 +842,7 @@ static void hci_ti_remove(struct serdev_device *serdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id hci_ti_of_match[] = {
|
||||
{ .compatible = "ti,cc2560" },
|
||||
{ .compatible = "ti,wl1271-st" },
|
||||
{ .compatible = "ti,wl1273-st" },
|
||||
{ .compatible = "ti,wl1281-st" },
|
||||
|
@ -932,6 +932,9 @@ static int qca_setup(struct hci_uart *hu)
|
||||
if (!ret) {
|
||||
set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
|
||||
qca_debugfs_init(hdev);
|
||||
} else if (ret == -ENOENT) {
|
||||
/* No patch/nvm-config found, run with original fw/config */
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* Setup bdaddr */
|
||||
|
@ -303,6 +303,7 @@ int hci_uart_register_device(struct hci_uart *hu,
|
||||
hci_set_drvdata(hdev, hu);
|
||||
|
||||
INIT_WORK(&hu->write_work, hci_uart_write_work);
|
||||
percpu_init_rwsem(&hu->proto_lock);
|
||||
|
||||
/* Only when vendor specific setup callback is provided, consider
|
||||
* the manufacturer information valid. This avoids filling in the
|
||||
|
@ -140,6 +140,29 @@ static u32 hv_copyto_ringbuffer(
|
||||
return start_write_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* hv_get_ringbuffer_availbytes()
|
||||
*
|
||||
* Get number of bytes available to read and to write to
|
||||
* for the specified ring buffer
|
||||
*/
|
||||
static void
|
||||
hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
|
||||
u32 *read, u32 *write)
|
||||
{
|
||||
u32 read_loc, write_loc, dsize;
|
||||
|
||||
/* Capture the read/write indices before they changed */
|
||||
read_loc = READ_ONCE(rbi->ring_buffer->read_index);
|
||||
write_loc = READ_ONCE(rbi->ring_buffer->write_index);
|
||||
dsize = rbi->ring_datasize;
|
||||
|
||||
*write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
|
||||
read_loc - write_loc;
|
||||
*read = dsize - *write;
|
||||
}
|
||||
|
||||
/* Get various debug metrics for the specified ring buffer. */
|
||||
void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info)
|
||||
|
@ -264,7 +264,7 @@ static int qedr_register_device(struct qedr_dev *dev)
|
||||
static int qedr_alloc_mem_sb(struct qedr_dev *dev,
|
||||
struct qed_sb_info *sb_info, u16 sb_id)
|
||||
{
|
||||
struct status_block *sb_virt;
|
||||
struct status_block_e4 *sb_virt;
|
||||
dma_addr_t sb_phys;
|
||||
int rc;
|
||||
|
||||
|
@ -164,6 +164,13 @@ struct rdma_srq_sge {
|
||||
__le32 l_key;
|
||||
};
|
||||
|
||||
/* Rdma doorbell data for flags update */
|
||||
struct rdma_pwm_flags_data {
|
||||
__le16 icid; /* internal CID */
|
||||
u8 agg_flags; /* aggregative flags */
|
||||
u8 reserved;
|
||||
};
|
||||
|
||||
/* Rdma doorbell data for SQ and RQ */
|
||||
struct rdma_pwm_val16_data {
|
||||
__le16 icid;
|
||||
@ -180,12 +187,16 @@ struct rdma_pwm_val32_data {
|
||||
__le16 icid;
|
||||
u8 agg_flags;
|
||||
u8 params;
|
||||
#define RDMA_PWM_VAL32_DATA_AGG_CMD_MASK 0x3
|
||||
#define RDMA_PWM_VAL32_DATA_AGG_CMD_SHIFT 0
|
||||
#define RDMA_PWM_VAL32_DATA_BYPASS_EN_MASK 0x1
|
||||
#define RDMA_PWM_VAL32_DATA_BYPASS_EN_SHIFT 2
|
||||
#define RDMA_PWM_VAL32_DATA_RESERVED_MASK 0x1F
|
||||
#define RDMA_PWM_VAL32_DATA_RESERVED_SHIFT 3
|
||||
#define RDMA_PWM_VAL32_DATA_AGG_CMD_MASK 0x3
|
||||
#define RDMA_PWM_VAL32_DATA_AGG_CMD_SHIFT 0
|
||||
#define RDMA_PWM_VAL32_DATA_BYPASS_EN_MASK 0x1
|
||||
#define RDMA_PWM_VAL32_DATA_BYPASS_EN_SHIFT 2
|
||||
#define RDMA_PWM_VAL32_DATA_CONN_TYPE_IS_IWARP_MASK 0x1
|
||||
#define RDMA_PWM_VAL32_DATA_CONN_TYPE_IS_IWARP_SHIFT 3
|
||||
#define RDMA_PWM_VAL32_DATA_SET_16B_VAL_MASK 0x1
|
||||
#define RDMA_PWM_VAL32_DATA_SET_16B_VAL_SHIFT 4
|
||||
#define RDMA_PWM_VAL32_DATA_RESERVED_MASK 0x7
|
||||
#define RDMA_PWM_VAL32_DATA_RESERVED_SHIFT 5
|
||||
__le32 value;
|
||||
};
|
||||
|
||||
@ -478,23 +489,25 @@ struct rdma_sq_fmr_wqe {
|
||||
__le16 dif_app_tag_mask;
|
||||
__le16 dif_runt_crc_value;
|
||||
__le16 dif_flags;
|
||||
#define RDMA_SQ_FMR_WQE_DIF_IO_DIRECTION_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_IO_DIRECTION_FLG_SHIFT 0
|
||||
#define RDMA_SQ_FMR_WQE_DIF_BLOCK_SIZE_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_BLOCK_SIZE_SHIFT 1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_RUNT_VALID_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_RUNT_VALID_FLG_SHIFT 2
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_CRC_GUARD_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_CRC_GUARD_SHIFT 3
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_REF_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_REF_TAG_SHIFT 4
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_APP_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_APP_TAG_SHIFT 5
|
||||
#define RDMA_SQ_FMR_WQE_DIF_CRC_SEED_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_CRC_SEED_SHIFT 6
|
||||
#define RDMA_SQ_FMR_WQE_RESERVED4_MASK 0x1FF
|
||||
#define RDMA_SQ_FMR_WQE_RESERVED4_SHIFT 7
|
||||
__le32 Reserved5;
|
||||
#define RDMA_SQ_FMR_WQE_DIF_IO_DIRECTION_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_IO_DIRECTION_FLG_SHIFT 0
|
||||
#define RDMA_SQ_FMR_WQE_DIF_BLOCK_SIZE_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_BLOCK_SIZE_SHIFT 1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_RUNT_VALID_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_RUNT_VALID_FLG_SHIFT 2
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_CRC_GUARD_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_CRC_GUARD_SHIFT 3
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_REF_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_REF_TAG_SHIFT 4
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_APP_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_VALIDATE_APP_TAG_SHIFT 5
|
||||
#define RDMA_SQ_FMR_WQE_DIF_CRC_SEED_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_CRC_SEED_SHIFT 6
|
||||
#define RDMA_SQ_FMR_WQE_DIF_RX_REF_TAG_CONST_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_DIF_RX_REF_TAG_CONST_SHIFT 7
|
||||
#define RDMA_SQ_FMR_WQE_RESERVED4_MASK 0xFF
|
||||
#define RDMA_SQ_FMR_WQE_RESERVED4_SHIFT 8
|
||||
__le32 reserved5;
|
||||
};
|
||||
|
||||
/* First element (16 bytes) of fmr wqe */
|
||||
@ -558,23 +571,25 @@ struct rdma_sq_fmr_wqe_3rd {
|
||||
__le16 dif_app_tag_mask;
|
||||
__le16 dif_runt_crc_value;
|
||||
__le16 dif_flags;
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_IO_DIRECTION_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_IO_DIRECTION_FLG_SHIFT 0
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_BLOCK_SIZE_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_BLOCK_SIZE_SHIFT 1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_RUNT_VALID_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_RUNT_VALID_FLG_SHIFT 2
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_CRC_GUARD_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_CRC_GUARD_SHIFT 3
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_REF_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_REF_TAG_SHIFT 4
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_APP_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_APP_TAG_SHIFT 5
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_CRC_SEED_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_CRC_SEED_SHIFT 6
|
||||
#define RDMA_SQ_FMR_WQE_3RD_RESERVED4_MASK 0x1FF
|
||||
#define RDMA_SQ_FMR_WQE_3RD_RESERVED4_SHIFT 7
|
||||
__le32 Reserved5;
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_IO_DIRECTION_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_IO_DIRECTION_FLG_SHIFT 0
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_BLOCK_SIZE_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_BLOCK_SIZE_SHIFT 1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_RUNT_VALID_FLG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_RUNT_VALID_FLG_SHIFT 2
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_CRC_GUARD_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_CRC_GUARD_SHIFT 3
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_REF_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_REF_TAG_SHIFT 4
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_APP_TAG_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_VALIDATE_APP_TAG_SHIFT 5
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_CRC_SEED_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_CRC_SEED_SHIFT 6
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_RX_REF_TAG_CONST_MASK 0x1
|
||||
#define RDMA_SQ_FMR_WQE_3RD_DIF_RX_REF_TAG_CONST_SHIFT 7
|
||||
#define RDMA_SQ_FMR_WQE_3RD_RESERVED4_MASK 0xFF
|
||||
#define RDMA_SQ_FMR_WQE_RESERVED4_SHIFT 8
|
||||
__le32 reserved5;
|
||||
};
|
||||
|
||||
struct rdma_sq_local_inv_wqe {
|
||||
@ -606,20 +621,22 @@ struct rdma_sq_rdma_wqe {
|
||||
__le32 xrc_srq;
|
||||
u8 req_type;
|
||||
u8 flags;
|
||||
#define RDMA_SQ_RDMA_WQE_COMP_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_COMP_FLG_SHIFT 0
|
||||
#define RDMA_SQ_RDMA_WQE_RD_FENCE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_RD_FENCE_FLG_SHIFT 1
|
||||
#define RDMA_SQ_RDMA_WQE_INV_FENCE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_INV_FENCE_FLG_SHIFT 2
|
||||
#define RDMA_SQ_RDMA_WQE_SE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_SE_FLG_SHIFT 3
|
||||
#define RDMA_SQ_RDMA_WQE_INLINE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_INLINE_FLG_SHIFT 4
|
||||
#define RDMA_SQ_RDMA_WQE_DIF_ON_HOST_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_DIF_ON_HOST_FLG_SHIFT 5
|
||||
#define RDMA_SQ_RDMA_WQE_RESERVED0_MASK 0x3
|
||||
#define RDMA_SQ_RDMA_WQE_RESERVED0_SHIFT 6
|
||||
#define RDMA_SQ_RDMA_WQE_COMP_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_COMP_FLG_SHIFT 0
|
||||
#define RDMA_SQ_RDMA_WQE_RD_FENCE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_RD_FENCE_FLG_SHIFT 1
|
||||
#define RDMA_SQ_RDMA_WQE_INV_FENCE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_INV_FENCE_FLG_SHIFT 2
|
||||
#define RDMA_SQ_RDMA_WQE_SE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_SE_FLG_SHIFT 3
|
||||
#define RDMA_SQ_RDMA_WQE_INLINE_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_INLINE_FLG_SHIFT 4
|
||||
#define RDMA_SQ_RDMA_WQE_DIF_ON_HOST_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_DIF_ON_HOST_FLG_SHIFT 5
|
||||
#define RDMA_SQ_RDMA_WQE_READ_INV_FLG_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_READ_INV_FLG_SHIFT 6
|
||||
#define RDMA_SQ_RDMA_WQE_RESERVED0_MASK 0x1
|
||||
#define RDMA_SQ_RDMA_WQE_RESERVED0_SHIFT 7
|
||||
u8 wqe_size;
|
||||
u8 prev_wqe_size;
|
||||
struct regpair remote_va;
|
||||
|
@ -497,4 +497,15 @@ config THUNDERBOLT_NET
|
||||
|
||||
source "drivers/net/hyperv/Kconfig"
|
||||
|
||||
config NETDEVSIM
|
||||
tristate "Simulated networking device"
|
||||
depends on DEBUG_FS
|
||||
help
|
||||
This driver is a developer testing tool and software model that can
|
||||
be used to test various control path networking APIs, especially
|
||||
HW-offload related.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called netdevsim.
|
||||
|
||||
endif # NETDEVICES
|
||||
|
@ -78,3 +78,4 @@ obj-$(CONFIG_FUJITSU_ES) += fjes/
|
||||
|
||||
thunderbolt-net-y += thunderbolt.o
|
||||
obj-$(CONFIG_THUNDERBOLT_NET) += thunderbolt-net.o
|
||||
obj-$(CONFIG_NETDEVSIM) += netdevsim/
|
||||
|
@ -1431,13 +1431,9 @@ static int bond_option_ad_actor_system_set(struct bonding *bond,
|
||||
{
|
||||
u8 macaddr[ETH_ALEN];
|
||||
u8 *mac;
|
||||
int i;
|
||||
|
||||
if (newval->string) {
|
||||
i = sscanf(newval->string, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&macaddr[0], &macaddr[1], &macaddr[2],
|
||||
&macaddr[3], &macaddr[4], &macaddr[5]);
|
||||
if (i != ETH_ALEN)
|
||||
if (!mac_pton(newval->string, macaddr))
|
||||
goto err;
|
||||
mac = macaddr;
|
||||
} else {
|
||||
|
@ -264,7 +264,6 @@ static int cfhsi_tx_frm(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
|
||||
}
|
||||
|
||||
/* Create payload CAIF frames. */
|
||||
pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
|
||||
while (nfrms < CFHSI_MAX_PKTS) {
|
||||
struct caif_payload_info *info;
|
||||
int hpad;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user