1
0
Fork 0

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
  ...
hifive-unleashed-5.1
Linus Torvalds 2018-01-31 14:31:10 -08:00
commit b2fe5fa686
1666 changed files with 120396 additions and 45479 deletions

View 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.

View File

@ -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

View 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!

View File

@ -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

View File

@ -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>;
};
...
};

View File

@ -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 {

View File

@ -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>;
};
};

View File

@ -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

View File

@ -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>;
};
};

View File

@ -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 = <&reg_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 = <&reg_fec_supply>;
phy-handle = <&ethphy>;

View File

@ -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.

View File

@ -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

View File

@ -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>;
};

View File

@ -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

View File

@ -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 = <&ethphy>;
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>;
};
};
};

View 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>;
};
};

View File

@ -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";
};
};

View File

@ -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>;
};
};
};
};

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,5 @@
.. SPDX-License-Identifier: GPL-2.0
==========
batman-adv
==========

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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
-------------------------------

View File

@ -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

View File

@ -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

View File

@ -7,6 +7,7 @@ Contents:
:maxdepth: 2
batman-adv
can
kapi
z8530book
msg_zerocopy

View File

@ -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

View File

@ -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:

View File

@ -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.

View File

@ -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

View 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.

View File

@ -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

View File

@ -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

View File

@ -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/

View File

@ -196,6 +196,9 @@ config HAVE_OPTPROBES
config HAVE_KPROBES_ON_FTRACE
bool
config HAVE_FUNCTION_ERROR_INJECTION
bool
config HAVE_NMI
bool

View File

@ -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>;

View File

@ -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>;

View File

@ -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";

View File

@ -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>,

View File

@ -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;
};
};
};

View File

@ -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;
};
};
};

View File

@ -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>;
};
};

View File

@ -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>;
};
};

View File

@ -331,3 +331,19 @@
&uart1 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&can2 {
status = "disabled";
};
&can3 {
status = "disabled";
};

View File

@ -243,3 +243,19 @@
&uart1 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&can2 {
status = "disabled";
};
&can3 {
status = "disabled";
};

View File

@ -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;
};
};
};

View File

@ -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

View File

@ -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 ?

View File

@ -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;

View File

@ -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;
};
/*

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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;

View File

@ -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 ?

View File

@ -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

View 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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View 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);

View File

@ -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 ?

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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 */

View File

@ -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 {

View File

@ -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), &params,
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);

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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, &params);
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(&params->otp_bdaddr, BDADDR_ANY)) {
if (!bacmp(&params.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");

View File

@ -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);
}

View File

@ -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, &params);
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(&params->otp_bdaddr, BDADDR_ANY)) {
if (!bacmp(&params.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.

View File

@ -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" },

View File

@ -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 */

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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/

View File

@ -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 {

View File

@ -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