mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) Support ipv6 checksum offload in sunvnet driver, from Shannon Nelson. 2) Move to RB-tree instead of custom AVL code in inetpeer, from Eric Dumazet. 3) Allow generic XDP to work on virtual devices, from John Fastabend. 4) Add bpf device maps and XDP_REDIRECT, which can be used to build arbitrary switching frameworks using XDP. From John Fastabend. 5) Remove UFO offloads from the tree, gave us little other than bugs. 6) Remove the IPSEC flow cache, from Florian Westphal. 7) Support ipv6 route offload in mlxsw driver. 8) Support VF representors in bnxt_en, from Sathya Perla. 9) Add support for forward error correction modes to ethtool, from Vidya Sagar Ravipati. 10) Add time filter for packet scheduler action dumping, from Jamal Hadi Salim. 11) Extend the zerocopy sendmsg() used by virtio and tap to regular sockets via MSG_ZEROCOPY. From Willem de Bruijn. 12) Significantly rework value tracking in the BPF verifier, from Edward Cree. 13) Add new jump instructions to eBPF, from Daniel Borkmann. 14) Rework rtnetlink plumbing so that operations can be run without taking the RTNL semaphore. From Florian Westphal. 15) Support XDP in tap driver, from Jason Wang. 16) Add 32-bit eBPF JIT for ARM, from Shubham Bansal. 17) Add Huawei hinic ethernet driver. 18) Allow to report MD5 keys in TCP inet_diag dumps, from Ivan Delalande. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1780 commits) i40e: point wb_desc at the nvm_wb_desc during i40e_read_nvm_aq i40e: avoid NVM acquire deadlock during NVM update drivers: net: xgene: Remove return statement from void function drivers: net: xgene: Configure tx/rx delay for ACPI drivers: net: xgene: Read tx/rx delay for ACPI rocker: fix kcalloc parameter order rds: Fix non-atomic operation on shared flag variable net: sched: don't use GFP_KERNEL under spin lock vhost_net: correctly check tx avail during rx busy polling net: mdio-mux: add mdio_mux parameter to mdio_mux_init() rxrpc: Make service connection lookup always check for retry net: stmmac: Delete dead code for MDIO registration gianfar: Fix Tx flow control deactivation cxgb4: Ignore MPS_TX_INT_CAUSE[Bubble] for T6 cxgb4: Fix pause frame count in t4_get_port_stats cxgb4: fix memory leak tun: rename generic_xdp to skb_xdp tun: reserve extra headroom only when XDP is set net: dsa: bcm_sf2: Configure IMP port TC2QOS mapping net: dsa: bcm_sf2: Advertise number of egress queues ...
This commit is contained in:
commit
aae3dbb477
25
Documentation/devicetree/bindings/net/anarion-gmac.txt
Normal file
25
Documentation/devicetree/bindings/net/anarion-gmac.txt
Normal file
@ -0,0 +1,25 @@
|
||||
* Adaptrum Anarion ethernet controller
|
||||
|
||||
This device is a platform glue layer for stmmac.
|
||||
Please see stmmac.txt for the other unchanged properties.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "adaptrum,anarion-gmac", "snps,dwmac"
|
||||
- phy-mode: Should be "rgmii". Other modes are not currently supported.
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
gmac1: ethernet@f2014000 {
|
||||
compatible = "adaptrum,anarion-gmac", "snps,dwmac";
|
||||
reg = <0xf2014000 0x4000>, <0xf2018100 8>;
|
||||
|
||||
interrupt-parent = <&core_intc>;
|
||||
interrupts = <21>;
|
||||
interrupt-names = "macirq";
|
||||
|
||||
clocks = <&core_clk>;
|
||||
clock-names = "stmmaceth";
|
||||
|
||||
phy-mode = "rgmii";
|
||||
};
|
35
Documentation/devicetree/bindings/net/broadcom-bluetooth.txt
Normal file
35
Documentation/devicetree/bindings/net/broadcom-bluetooth.txt
Normal file
@ -0,0 +1,35 @@
|
||||
Broadcom Bluetooth Chips
|
||||
---------------------
|
||||
|
||||
This documents the binding structure and common properties for serial
|
||||
attached Broadcom devices.
|
||||
|
||||
Serial attached Broadcom devices shall be a child node of the host UART
|
||||
device the slave device is attached to.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should contain one of the following:
|
||||
* "brcm,bcm43438-bt"
|
||||
|
||||
Optional properties:
|
||||
|
||||
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
|
||||
- shutdown-gpios: GPIO specifier, used to enable the BT module
|
||||
- device-wakeup-gpios: GPIO specifier, used to wakeup the controller
|
||||
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor
|
||||
- clocks: clock specifier if external clock provided to the controller
|
||||
- clock-names: should be "extclk"
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
&uart2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2_pins>;
|
||||
|
||||
bluetooth {
|
||||
compatible = "brcm,bcm43438-bt";
|
||||
max-speed = <921600>;
|
||||
};
|
||||
};
|
@ -41,6 +41,11 @@ Optional properties (port):
|
||||
- marvell,loopback: port is loopback mode
|
||||
- phy: a phandle to a phy node defining the PHY address (as the reg
|
||||
property, a single integer).
|
||||
- interrupt-names: if more than a single interrupt for rx is given, must
|
||||
be the name associated to the interrupts listed. Valid
|
||||
names are: "tx-cpu0", "tx-cpu1", "tx-cpu2", "tx-cpu3",
|
||||
"rx-shared", "link".
|
||||
- marvell,system-controller: a phandle to the system controller.
|
||||
|
||||
Example for marvell,armada-375-pp2:
|
||||
|
||||
@ -80,19 +85,37 @@ cpm_ethernet: ethernet@0 {
|
||||
clock-names = "pp_clk", "gop_clk", "gp_clk";
|
||||
|
||||
eth0: eth0 {
|
||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 43 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 47 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 51 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 55 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "tx-cpu0", "tx-cpu1", "tx-cpu2",
|
||||
"tx-cpu3", "rx-shared";
|
||||
port-id = <0>;
|
||||
gop-port-id = <0>;
|
||||
};
|
||||
|
||||
eth1: eth1 {
|
||||
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 44 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 48 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 52 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 56 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "tx-cpu0", "tx-cpu1", "tx-cpu2",
|
||||
"tx-cpu3", "rx-shared";
|
||||
port-id = <1>;
|
||||
gop-port-id = <2>;
|
||||
};
|
||||
|
||||
eth2: eth2 {
|
||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 45 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 49 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 53 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<ICU_GRP_NSR 57 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "tx-cpu0", "tx-cpu1", "tx-cpu2",
|
||||
"tx-cpu3", "rx-shared";
|
||||
port-id = <2>;
|
||||
gop-port-id = <3>;
|
||||
};
|
||||
|
@ -7,24 +7,30 @@ have dual GMAC each represented by a child node..
|
||||
* Ethernet controller node
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "mediatek,mt2701-eth"
|
||||
- compatible: Should be
|
||||
"mediatek,mt2701-eth": for MT2701 SoC
|
||||
"mediatek,mt7623-eth", "mediatek,mt2701-eth": for MT7623 SoC
|
||||
"mediatek,mt7622-eth": for MT7622 SoC
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupts: Should contain the three frame engines interrupts in numeric
|
||||
order. These are fe_int0, fe_int1 and fe_int2.
|
||||
- clocks: the clock used by the core
|
||||
- clock-names: the names of the clock listed in the clocks property. These are
|
||||
"ethif", "esw", "gp2", "gp1"
|
||||
"ethif", "esw", "gp2", "gp1" : For MT2701 and MT7623 SoC
|
||||
"ethif", "esw", "gp0", "gp1", "gp2", "sgmii_tx250m", "sgmii_rx250m",
|
||||
"sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll" : For MT7622 SoC
|
||||
- power-domains: phandle to the power domain that the ethernet is part of
|
||||
- resets: Should contain a phandle to the ethsys reset signal
|
||||
- reset-names: Should contain the reset signal name "eth"
|
||||
- mediatek,ethsys: phandle to the syscon node that handles the port setup
|
||||
- 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
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
|
||||
* Ethernet MAC node
|
||||
|
||||
Required properties:
|
||||
|
@ -52,6 +52,11 @@ Optional Properties:
|
||||
Mark the corresponding energy efficient ethernet mode as broken and
|
||||
request the ethernet to stop advertising it.
|
||||
|
||||
- phy-is-integrated: If set, indicates that the PHY is integrated into the same
|
||||
physical package as the Ethernet MAC. If needed, muxers should be configured
|
||||
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.
|
||||
|
||||
Example:
|
||||
|
||||
ethernet-phy@0 {
|
||||
|
@ -4,19 +4,25 @@ This file provides information on what the device node for the Ethernet AVB
|
||||
interface contains.
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,etheravb-r8a7790" if the device is a part of R8A7790 SoC.
|
||||
"renesas,etheravb-r8a7791" if the device is a part of R8A7791 SoC.
|
||||
"renesas,etheravb-r8a7792" if the device is a part of R8A7792 SoC.
|
||||
"renesas,etheravb-r8a7793" if the device is a part of R8A7793 SoC.
|
||||
"renesas,etheravb-r8a7794" if the device is a part of R8A7794 SoC.
|
||||
"renesas,etheravb-r8a7795" if the device is a part of R8A7795 SoC.
|
||||
"renesas,etheravb-r8a7796" if the device is a part of R8A7796 SoC.
|
||||
"renesas,etheravb-rcar-gen2" for generic R-Car Gen 2 compatible interface.
|
||||
"renesas,etheravb-rcar-gen3" for generic R-Car Gen 3 compatible interface.
|
||||
- compatible: Must contain one or more of the following:
|
||||
- "renesas,etheravb-r8a7743" for the R8A7743 SoC.
|
||||
- "renesas,etheravb-r8a7745" for the R8A7745 SoC.
|
||||
- "renesas,etheravb-r8a7790" for the R8A7790 SoC.
|
||||
- "renesas,etheravb-r8a7791" for the R8A7791 SoC.
|
||||
- "renesas,etheravb-r8a7792" for the R8A7792 SoC.
|
||||
- "renesas,etheravb-r8a7793" for the R8A7793 SoC.
|
||||
- "renesas,etheravb-r8a7794" for the R8A7794 SoC.
|
||||
- "renesas,etheravb-rcar-gen2" as a fallback for the above
|
||||
R-Car Gen2 and RZ/G1 devices.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first
|
||||
followed by the generic version.
|
||||
- "renesas,etheravb-r8a7795" for the R8A7795 SoC.
|
||||
- "renesas,etheravb-r8a7796" for the R8A7796 SoC.
|
||||
- "renesas,etheravb-rcar-gen3" as a fallback for the above
|
||||
R-Car Gen3 devices.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first followed by
|
||||
the generic version.
|
||||
|
||||
- reg: offset and length of (1) the register block and (2) the stream buffer.
|
||||
- interrupts: A list of interrupt-specifiers, one for each entry in
|
||||
|
@ -10,6 +10,7 @@ Required properties:
|
||||
"rockchip,rk3366-gmac": found on RK3366 SoCs
|
||||
"rockchip,rk3368-gmac": found on RK3368 SoCs
|
||||
"rockchip,rk3399-gmac": found on RK3399 SoCs
|
||||
"rockchip,rv1108-gmac": found on RV1108 SoCs
|
||||
- reg: addresses and length of the register sets for the device.
|
||||
- interrupts: Should contain the GMAC interrupts.
|
||||
- interrupt-names: Should contain the interrupt names "macirq".
|
||||
|
55
Documentation/devicetree/bindings/net/xilinx_axienet.txt
Normal file
55
Documentation/devicetree/bindings/net/xilinx_axienet.txt
Normal file
@ -0,0 +1,55 @@
|
||||
XILINX AXI ETHERNET Device Tree Bindings
|
||||
--------------------------------------------------------
|
||||
|
||||
Also called AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core
|
||||
provides connectivity to an external ethernet PHY supporting different
|
||||
interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two
|
||||
segments of memory for buffering TX and RX, as well as the capability of
|
||||
offloading TX/RX checksum calculation off the processor.
|
||||
|
||||
Management configuration is done through the AXI interface, while payload is
|
||||
sent and received through means of an AXI DMA controller. This driver
|
||||
includes the DMA driver code, so this driver is incompatible with AXI DMA
|
||||
driver.
|
||||
|
||||
For more details about mdio please refer phy.txt file in the same directory.
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be one of "xlnx,axi-ethernet-1.00.a",
|
||||
"xlnx,axi-ethernet-1.01.a", "xlnx,axi-ethernet-2.01.a"
|
||||
- reg : Address and length of the IO space.
|
||||
- interrupts : Should be a list of two interrupt, TX and RX.
|
||||
- phy-handle : Should point to the external phy device.
|
||||
See ethernet.txt file in the same directory.
|
||||
- xlnx,rxmem : Set to allocated memory buffer for Rx/Tx in the hardware
|
||||
|
||||
Optional properties:
|
||||
- phy-mode : See ethernet.txt
|
||||
- xlnx,phy-type : Deprecated, do not use, but still accepted in preference
|
||||
to phy-mode.
|
||||
- xlnx,txcsum : 0 or empty for disabling TX checksum offload,
|
||||
1 to enable partial TX checksum offload,
|
||||
2 to enable full TX checksum offload
|
||||
- xlnx,rxcsum : Same values as xlnx,txcsum but for RX checksum offload
|
||||
|
||||
Example:
|
||||
axi_ethernet_eth: ethernet@40c00000 {
|
||||
compatible = "xlnx,axi-ethernet-1.00.a";
|
||||
device_type = "network";
|
||||
interrupt-parent = <µblaze_0_axi_intc>;
|
||||
interrupts = <2 0>;
|
||||
phy-mode = "mii";
|
||||
reg = <0x40c00000 0x40000>;
|
||||
xlnx,rxcsum = <0x2>;
|
||||
xlnx,rxmem = <0x800>;
|
||||
xlnx,txcsum = <0x2>;
|
||||
phy-handle = <&phy0>;
|
||||
axi_ethernetlite_0_mdio: mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: phy@0 {
|
||||
device_type = "ethernet-phy";
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
};
|
43
Documentation/devicetree/bindings/phy/phy-mvebu-comphy.txt
Normal file
43
Documentation/devicetree/bindings/phy/phy-mvebu-comphy.txt
Normal file
@ -0,0 +1,43 @@
|
||||
mvebu comphy driver
|
||||
-------------------
|
||||
|
||||
A comphy controller can be found on Marvell Armada 7k/8k on the CP110. It
|
||||
provides a number of shared PHYs used by various interfaces (network, sata,
|
||||
usb, PCIe...).
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be "marvell,comphy-cp110"
|
||||
- reg: should contain the comphy register location and length.
|
||||
- marvell,system-controller: should contain a phandle to the
|
||||
system controller node.
|
||||
- #address-cells: should be 1.
|
||||
- #size-cells: should be 0.
|
||||
|
||||
A sub-node is required for each comphy lane provided by the comphy.
|
||||
|
||||
Required properties (child nodes):
|
||||
|
||||
- reg: comphy lane number.
|
||||
- #phy-cells : from the generic phy bindings, must be 1. Defines the
|
||||
input port to use for a given comphy lane.
|
||||
|
||||
Example:
|
||||
|
||||
cpm_comphy: phy@120000 {
|
||||
compatible = "marvell,comphy-cp110";
|
||||
reg = <0x120000 0x6000>;
|
||||
marvell,system-controller = <&cpm_syscon0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpm_comphy0: phy@0 {
|
||||
reg = <0>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
cpm_comphy1: phy@1 {
|
||||
reg = <1>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
};
|
@ -30,8 +30,6 @@ atm.txt
|
||||
- info on where to get ATM programs and support for Linux.
|
||||
ax25.txt
|
||||
- info on using AX.25 and NET/ROM code for Linux
|
||||
batman-adv.txt
|
||||
- B.A.T.M.A.N routing protocol on top of layer 2 Ethernet Frames.
|
||||
baycom.txt
|
||||
- info on the driver for Baycom style amateur radio modems
|
||||
bonding.txt
|
||||
|
220
Documentation/networking/batman-adv.rst
Normal file
220
Documentation/networking/batman-adv.rst
Normal file
@ -0,0 +1,220 @@
|
||||
==========
|
||||
batman-adv
|
||||
==========
|
||||
|
||||
Batman advanced is a new approach to wireless networking which does no longer
|
||||
operate on the IP basis. Unlike the batman daemon, which exchanges information
|
||||
using UDP packets and sets routing tables, batman-advanced operates on ISO/OSI
|
||||
Layer 2 only and uses and routes (or better: bridges) Ethernet Frames. It
|
||||
emulates a virtual network switch of all nodes participating. Therefore all
|
||||
nodes appear to be link local, thus all higher operating protocols won't be
|
||||
affected by any changes within the network. You can run almost any protocol
|
||||
above batman advanced, prominent examples are: IPv4, IPv6, DHCP, IPX.
|
||||
|
||||
Batman advanced was implemented as a Linux kernel driver to reduce the overhead
|
||||
to a minimum. It does not depend on any (other) network driver, and can be used
|
||||
on wifi as well as ethernet lan, vpn, etc ... (anything with ethernet-style
|
||||
layer 2).
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Load the batman-adv module into your kernel::
|
||||
|
||||
$ insmod batman-adv.ko
|
||||
|
||||
The module is now waiting for activation. You must add some interfaces on which
|
||||
batman can operate. After loading the module batman advanced will scan your
|
||||
systems interfaces to search for compatible interfaces. Once found, it will
|
||||
create subfolders in the ``/sys`` directories of each supported interface,
|
||||
e.g.::
|
||||
|
||||
$ ls /sys/class/net/eth0/batman_adv/
|
||||
elp_interval iface_status mesh_iface throughput_override
|
||||
|
||||
If an interface does not have the ``batman_adv`` subfolder, it probably is not
|
||||
supported. Not supported interfaces are: loopback, non-ethernet and batman's
|
||||
own interfaces.
|
||||
|
||||
Note: After the module was loaded it will continuously watch for new
|
||||
interfaces to verify the compatibility. There is no need to reload the module
|
||||
if you plug your USB wifi adapter into your machine after batman advanced was
|
||||
initially loaded.
|
||||
|
||||
The batman-adv soft-interface can be created using the iproute2 tool ``ip``::
|
||||
|
||||
$ ip link add name bat0 type batadv
|
||||
|
||||
To activate a given interface simply attach it to the ``bat0`` interface::
|
||||
|
||||
$ ip link set dev eth0 master bat0
|
||||
|
||||
Repeat this step for all interfaces you wish to add. Now batman starts
|
||||
using/broadcasting on this/these interface(s).
|
||||
|
||||
By reading the "iface_status" file you can check its status::
|
||||
|
||||
$ cat /sys/class/net/eth0/batman_adv/iface_status
|
||||
active
|
||||
|
||||
To deactivate an interface you have to detach it from the "bat0" interface::
|
||||
|
||||
$ ip link set dev eth0 nomaster
|
||||
|
||||
|
||||
All mesh wide settings can be found in batman's own interface folder::
|
||||
|
||||
$ ls /sys/class/net/bat0/mesh/
|
||||
aggregated_ogms fragmentation isolation_mark routing_algo
|
||||
ap_isolation gw_bandwidth log_level vlan0
|
||||
bonding gw_mode multicast_mode
|
||||
bridge_loop_avoidance gw_sel_class network_coding
|
||||
distributed_arp_table hop_penalty orig_interval
|
||||
|
||||
There is a special folder for debugging information::
|
||||
|
||||
$ ls /sys/kernel/debug/batman_adv/bat0/
|
||||
bla_backbone_table log neighbors transtable_local
|
||||
bla_claim_table mcast_flags originators
|
||||
dat_cache nc socket
|
||||
gateways nc_nodes transtable_global
|
||||
|
||||
Some of the files contain all sort of status information regarding the mesh
|
||||
network. For example, you can view the table of originators (mesh
|
||||
participants) with::
|
||||
|
||||
$ cat /sys/kernel/debug/batman_adv/bat0/originators
|
||||
|
||||
Other files allow to change batman's behaviour to better fit your requirements.
|
||||
For instance, you can check the current originator interval (value in
|
||||
milliseconds which determines how often batman sends its broadcast packets)::
|
||||
|
||||
$ cat /sys/class/net/bat0/mesh/orig_interval
|
||||
1000
|
||||
|
||||
and also change its value::
|
||||
|
||||
$ echo 3000 > /sys/class/net/bat0/mesh/orig_interval
|
||||
|
||||
In very mobile scenarios, you might want to adjust the originator interval to a
|
||||
lower value. This will make the mesh more responsive to topology changes, but
|
||||
will also increase the overhead.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To make use of your newly created mesh, batman advanced provides a new
|
||||
interface "bat0" which you should use from this point on. All interfaces added
|
||||
to batman advanced are not relevant any longer because batman handles them for
|
||||
you. Basically, one "hands over" the data by using the batman interface and
|
||||
batman will make sure it reaches its destination.
|
||||
|
||||
The "bat0" interface can be used like any other regular interface. It needs an
|
||||
IP address which can be either statically configured or dynamically (by using
|
||||
DHCP or similar services)::
|
||||
|
||||
NodeA: ip link set up dev bat0
|
||||
NodeA: ip addr add 192.168.0.1/24 dev bat0
|
||||
|
||||
NodeB: ip link set up dev bat0
|
||||
NodeB: ip addr add 192.168.0.2/24 dev bat0
|
||||
NodeB: ping 192.168.0.1
|
||||
|
||||
Note: In order to avoid problems remove all IP addresses previously assigned to
|
||||
interfaces now used by batman advanced, e.g.::
|
||||
|
||||
$ ip addr flush dev eth0
|
||||
|
||||
|
||||
Logging/Debugging
|
||||
=================
|
||||
|
||||
All error messages, warnings and information messages are sent to the kernel
|
||||
log. Depending on your operating system distribution this can be read in one of
|
||||
a number of ways. Try using the commands: ``dmesg``, ``logread``, or looking in
|
||||
the files ``/var/log/kern.log`` or ``/var/log/syslog``. All batman-adv messages
|
||||
are prefixed with "batman-adv:" So to see just these messages try::
|
||||
|
||||
$ dmesg | grep batman-adv
|
||||
|
||||
When investigating problems with your mesh network, it is sometimes necessary to
|
||||
see more detail debug messages. This must be enabled when compiling the
|
||||
batman-adv module. When building batman-adv as part of kernel, use "make
|
||||
menuconfig" and enable the option ``B.A.T.M.A.N. debugging``
|
||||
(``CONFIG_BATMAN_ADV_DEBUG=y``).
|
||||
|
||||
Those additional debug messages can be accessed using a special file in
|
||||
debugfs::
|
||||
|
||||
$ cat /sys/kernel/debug/batman_adv/bat0/log
|
||||
|
||||
The additional debug output is by default disabled. It can be enabled during
|
||||
run time. Following log_levels are defined:
|
||||
|
||||
.. flat-table::
|
||||
|
||||
* - 0
|
||||
- All debug output disabled
|
||||
* - 1
|
||||
- Enable messages related to routing / flooding / broadcasting
|
||||
* - 2
|
||||
- Enable messages related to route added / changed / deleted
|
||||
* - 4
|
||||
- Enable messages related to translation table operations
|
||||
* - 8
|
||||
- Enable messages related to bridge loop avoidance
|
||||
* - 16
|
||||
- Enable messages related to DAT, ARP snooping and parsing
|
||||
* - 32
|
||||
- Enable messages related to network coding
|
||||
* - 64
|
||||
- Enable messages related to multicast
|
||||
* - 128
|
||||
- Enable messages related to throughput meter
|
||||
* - 255
|
||||
- Enable all messages
|
||||
|
||||
The debug output can be changed at runtime using the file
|
||||
``/sys/class/net/bat0/mesh/log_level``. e.g.::
|
||||
|
||||
$ echo 6 > /sys/class/net/bat0/mesh/log_level
|
||||
|
||||
will enable debug messages for when routes change.
|
||||
|
||||
Counters for different types of packets entering and leaving the batman-adv
|
||||
module are available through ethtool::
|
||||
|
||||
$ ethtool --statistics bat0
|
||||
|
||||
|
||||
batctl
|
||||
======
|
||||
|
||||
As batman advanced operates on layer 2, all hosts participating in the virtual
|
||||
switch are completely transparent for all protocols above layer 2. Therefore
|
||||
the common diagnosis tools do not work as expected. To overcome these problems,
|
||||
batctl was created. At the moment the batctl contains ping, traceroute, tcpdump
|
||||
and interfaces to the kernel module settings.
|
||||
|
||||
For more information, please see the manpage (``man batctl``).
|
||||
|
||||
batctl is available on https://www.open-mesh.org/
|
||||
|
||||
|
||||
Contact
|
||||
=======
|
||||
|
||||
Please send us comments, experiences, questions, anything :)
|
||||
|
||||
IRC:
|
||||
#batman on irc.freenode.org
|
||||
Mailing-list:
|
||||
b.a.t.m.a.n@open-mesh.org (optional subscription at
|
||||
https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
|
||||
|
||||
You can also contact the Authors:
|
||||
|
||||
* Marek Lindner <mareklindner@neomailbox.ch>
|
||||
* Simon Wunderlich <sw@simonwunderlich.de>
|
@ -1,215 +0,0 @@
|
||||
BATMAN-ADV
|
||||
----------
|
||||
|
||||
Batman advanced is a new approach to wireless networking which
|
||||
does no longer operate on the IP basis. Unlike the batman daemon,
|
||||
which exchanges information using UDP packets and sets routing
|
||||
tables, batman-advanced operates on ISO/OSI Layer 2 only and uses
|
||||
and routes (or better: bridges) Ethernet Frames. It emulates a
|
||||
virtual network switch of all nodes participating. Therefore all
|
||||
nodes appear to be link local, thus all higher operating proto-
|
||||
cols won't be affected by any changes within the network. You can
|
||||
run almost any protocol above batman advanced, prominent examples
|
||||
are: IPv4, IPv6, DHCP, IPX.
|
||||
|
||||
Batman advanced was implemented as a Linux kernel driver to re-
|
||||
duce the overhead to a minimum. It does not depend on any (other)
|
||||
network driver, and can be used on wifi as well as ethernet lan,
|
||||
vpn, etc ... (anything with ethernet-style layer 2).
|
||||
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
Load the batman-adv module into your kernel:
|
||||
|
||||
# insmod batman-adv.ko
|
||||
|
||||
The module is now waiting for activation. You must add some in-
|
||||
terfaces on which batman can operate. After loading the module
|
||||
batman advanced will scan your systems interfaces to search for
|
||||
compatible interfaces. Once found, it will create subfolders in
|
||||
the /sys directories of each supported interface, e.g.
|
||||
|
||||
# ls /sys/class/net/eth0/batman_adv/
|
||||
# elp_interval iface_status mesh_iface throughput_override
|
||||
|
||||
If an interface does not have the "batman_adv" subfolder it prob-
|
||||
ably is not supported. Not supported interfaces are: loopback,
|
||||
non-ethernet and batman's own interfaces.
|
||||
|
||||
Note: After the module was loaded it will continuously watch for
|
||||
new interfaces to verify the compatibility. There is no need to
|
||||
reload the module if you plug your USB wifi adapter into your ma-
|
||||
chine after batman advanced was initially loaded.
|
||||
|
||||
The batman-adv soft-interface can be created using the iproute2
|
||||
tool "ip"
|
||||
|
||||
# ip link add name bat0 type batadv
|
||||
|
||||
To activate a given interface simply attach it to the "bat0"
|
||||
interface
|
||||
|
||||
# ip link set dev eth0 master bat0
|
||||
|
||||
Repeat this step for all interfaces you wish to add. Now batman
|
||||
starts using/broadcasting on this/these interface(s).
|
||||
|
||||
By reading the "iface_status" file you can check its status:
|
||||
|
||||
# cat /sys/class/net/eth0/batman_adv/iface_status
|
||||
# active
|
||||
|
||||
To deactivate an interface you have to detach it from the
|
||||
"bat0" interface:
|
||||
|
||||
# ip link set dev eth0 nomaster
|
||||
|
||||
|
||||
All mesh wide settings can be found in batman's own interface
|
||||
folder:
|
||||
|
||||
# ls /sys/class/net/bat0/mesh/
|
||||
# aggregated_ogms fragmentation isolation_mark routing_algo
|
||||
# ap_isolation gw_bandwidth log_level vlan0
|
||||
# bonding gw_mode multicast_mode
|
||||
# bridge_loop_avoidance gw_sel_class network_coding
|
||||
# distributed_arp_table hop_penalty orig_interval
|
||||
|
||||
There is a special folder for debugging information:
|
||||
|
||||
# ls /sys/kernel/debug/batman_adv/bat0/
|
||||
# bla_backbone_table log neighbors transtable_local
|
||||
# bla_claim_table mcast_flags originators
|
||||
# dat_cache nc socket
|
||||
# gateways nc_nodes transtable_global
|
||||
|
||||
Some of the files contain all sort of status information regard-
|
||||
ing the mesh network. For example, you can view the table of
|
||||
originators (mesh participants) with:
|
||||
|
||||
# cat /sys/kernel/debug/batman_adv/bat0/originators
|
||||
|
||||
Other files allow to change batman's behaviour to better fit your
|
||||
requirements. For instance, you can check the current originator
|
||||
interval (value in milliseconds which determines how often batman
|
||||
sends its broadcast packets):
|
||||
|
||||
# cat /sys/class/net/bat0/mesh/orig_interval
|
||||
# 1000
|
||||
|
||||
and also change its value:
|
||||
|
||||
# echo 3000 > /sys/class/net/bat0/mesh/orig_interval
|
||||
|
||||
In very mobile scenarios, you might want to adjust the originator
|
||||
interval to a lower value. This will make the mesh more respon-
|
||||
sive to topology changes, but will also increase the overhead.
|
||||
|
||||
|
||||
USAGE
|
||||
-----
|
||||
|
||||
To make use of your newly created mesh, batman advanced provides
|
||||
a new interface "bat0" which you should use from this point on.
|
||||
All interfaces added to batman advanced are not relevant any
|
||||
longer because batman handles them for you. Basically, one "hands
|
||||
over" the data by using the batman interface and batman will make
|
||||
sure it reaches its destination.
|
||||
|
||||
The "bat0" interface can be used like any other regular inter-
|
||||
face. It needs an IP address which can be either statically con-
|
||||
figured or dynamically (by using DHCP or similar services):
|
||||
|
||||
# NodeA: ip link set up dev bat0
|
||||
# NodeA: ip addr add 192.168.0.1/24 dev bat0
|
||||
|
||||
# NodeB: ip link set up dev bat0
|
||||
# NodeB: ip addr add 192.168.0.2/24 dev bat0
|
||||
# NodeB: ping 192.168.0.1
|
||||
|
||||
Note: In order to avoid problems remove all IP addresses previ-
|
||||
ously assigned to interfaces now used by batman advanced, e.g.
|
||||
|
||||
# ip addr flush dev eth0
|
||||
|
||||
|
||||
LOGGING/DEBUGGING
|
||||
-----------------
|
||||
|
||||
All error messages, warnings and information messages are sent to
|
||||
the kernel log. Depending on your operating system distribution
|
||||
this can be read in one of a number of ways. Try using the com-
|
||||
mands: dmesg, logread, or looking in the files /var/log/kern.log
|
||||
or /var/log/syslog. All batman-adv messages are prefixed with
|
||||
"batman-adv:" So to see just these messages try
|
||||
|
||||
# dmesg | grep batman-adv
|
||||
|
||||
When investigating problems with your mesh network it is some-
|
||||
times necessary to see more detail debug messages. This must be
|
||||
enabled when compiling the batman-adv module. When building bat-
|
||||
man-adv as part of kernel, use "make menuconfig" and enable the
|
||||
option "B.A.T.M.A.N. debugging".
|
||||
|
||||
Those additional debug messages can be accessed using a special
|
||||
file in debugfs
|
||||
|
||||
# cat /sys/kernel/debug/batman_adv/bat0/log
|
||||
|
||||
The additional debug output is by default disabled. It can be en-
|
||||
abled during run time. Following log_levels are defined:
|
||||
|
||||
0 - All debug output disabled
|
||||
1 - Enable messages related to routing / flooding / broadcasting
|
||||
2 - Enable messages related to route added / changed / deleted
|
||||
4 - Enable messages related to translation table operations
|
||||
8 - Enable messages related to bridge loop avoidance
|
||||
16 - Enable messages related to DAT, ARP snooping and parsing
|
||||
32 - Enable messages related to network coding
|
||||
64 - Enable messages related to multicast
|
||||
128 - Enable messages related to throughput meter
|
||||
255 - Enable all messages
|
||||
|
||||
The debug output can be changed at runtime using the file
|
||||
/sys/class/net/bat0/mesh/log_level. e.g.
|
||||
|
||||
# echo 6 > /sys/class/net/bat0/mesh/log_level
|
||||
|
||||
will enable debug messages for when routes change.
|
||||
|
||||
Counters for different types of packets entering and leaving the
|
||||
batman-adv module are available through ethtool:
|
||||
|
||||
# ethtool --statistics bat0
|
||||
|
||||
|
||||
BATCTL
|
||||
------
|
||||
|
||||
As batman advanced operates on layer 2 all hosts participating in
|
||||
the virtual switch are completely transparent for all protocols
|
||||
above layer 2. Therefore the common diagnosis tools do not work
|
||||
as expected. To overcome these problems batctl was created. At
|
||||
the moment the batctl contains ping, traceroute, tcpdump and
|
||||
interfaces to the kernel module settings.
|
||||
|
||||
For more information, please see the manpage (man batctl).
|
||||
|
||||
batctl is available on https://www.open-mesh.org/
|
||||
|
||||
|
||||
CONTACT
|
||||
-------
|
||||
|
||||
Please send us comments, experiences, questions, anything :)
|
||||
|
||||
IRC: #batman on irc.freenode.org
|
||||
Mailing-list: b.a.t.m.a.n@open-mesh.org (optional subscription
|
||||
at https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
|
||||
|
||||
You can also contact the Authors:
|
||||
|
||||
Marek Lindner <mareklindner@neomailbox.ch>
|
||||
Simon Wunderlich <sw@simonwunderlich.de>
|
@ -13,6 +13,7 @@ Contents
|
||||
- Configuring DPAA Ethernet in your kernel
|
||||
- DPAA Ethernet Frame Processing
|
||||
- DPAA Ethernet Features
|
||||
- DPAA IRQ Affinity and Receive Side Scaling
|
||||
- Debugging
|
||||
|
||||
DPAA Ethernet Overview
|
||||
@ -147,7 +148,10 @@ gradually.
|
||||
|
||||
The driver has Rx and Tx checksum offloading for UDP and TCP. Currently the Rx
|
||||
checksum offload feature is enabled by default and cannot be controlled through
|
||||
ethtool.
|
||||
ethtool. Also, rx-flow-hash and rx-hashing was added. The addition of RSS
|
||||
provides a big performance boost for the forwarding scenarios, allowing
|
||||
different traffic flows received by one interface to be processed by different
|
||||
CPUs in parallel.
|
||||
|
||||
The driver has support for multiple prioritized Tx traffic classes. Priorities
|
||||
range from 0 (lowest) to 3 (highest). These are mapped to HW workqueues with
|
||||
@ -166,6 +170,68 @@ classes as follows:
|
||||
tc qdisc add dev <int> root handle 1: \
|
||||
mqprio num_tc 4 map 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 hw 1
|
||||
|
||||
DPAA IRQ Affinity and Receive Side Scaling
|
||||
==========================================
|
||||
|
||||
Traffic coming on the DPAA Rx queues or on the DPAA Tx confirmation
|
||||
queues is seen by the CPU as ingress traffic on a certain portal.
|
||||
The DPAA QMan portal interrupts are affined each to a certain CPU.
|
||||
The same portal interrupt services all the QMan portal consumers.
|
||||
|
||||
By default the DPAA Ethernet driver enables RSS, making use of the
|
||||
DPAA FMan Parser and Keygen blocks to distribute traffic on 128
|
||||
hardware frame queues using a hash on IP v4/v6 source and destination
|
||||
and L4 source and destination ports, in present in the received frame.
|
||||
When RSS is disabled, all traffic received by a certain interface is
|
||||
received on the default Rx frame queue. The default DPAA Rx frame
|
||||
queues are configured to put the received traffic into a pool channel
|
||||
that allows any available CPU portal to dequeue the ingress traffic.
|
||||
The default frame queues have the HOLDACTIVE option set, ensuring that
|
||||
traffic bursts from a certain queue are serviced by the same CPU.
|
||||
This ensures a very low rate of frame reordering. A drawback of this
|
||||
is that only one CPU at a time can service the traffic received by a
|
||||
certain interface when RSS is not enabled.
|
||||
|
||||
To implement RSS, the DPAA Ethernet driver allocates an extra set of
|
||||
128 Rx frame queues that are configured to dedicated channels, in a
|
||||
round-robin manner. The mapping of the frame queues to CPUs is now
|
||||
hardcoded, there is no indirection table to move traffic for a certain
|
||||
FQ (hash result) to another CPU. The ingress traffic arriving on one
|
||||
of these frame queues will arrive at the same portal and will always
|
||||
be processed by the same CPU. This ensures intra-flow order preservation
|
||||
and workload distribution for multiple traffic flows.
|
||||
|
||||
RSS can be turned off for a certain interface using ethtool, i.e.
|
||||
|
||||
# ethtool -N fm1-mac9 rx-flow-hash tcp4 ""
|
||||
|
||||
To turn it back on, one needs to set rx-flow-hash for tcp4/6 or udp4/6:
|
||||
|
||||
# ethtool -N fm1-mac9 rx-flow-hash udp4 sfdn
|
||||
|
||||
There is no independent control for individual protocols, any command
|
||||
run for one of tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6 is
|
||||
going to control the rx-flow-hashing for all protocols on that interface.
|
||||
|
||||
Besides using the FMan Keygen computed hash for spreading traffic on the
|
||||
128 Rx FQs, the DPAA Ethernet driver also sets the skb hash value when
|
||||
the NETIF_F_RXHASH feature is on (active by default). This can be turned
|
||||
on or off through ethtool, i.e.:
|
||||
|
||||
# ethtool -K fm1-mac9 rx-hashing off
|
||||
# ethtool -k fm1-mac9 | grep hash
|
||||
receive-hashing: off
|
||||
# ethtool -K fm1-mac9 rx-hashing on
|
||||
Actual changes:
|
||||
receive-hashing: on
|
||||
# ethtool -k fm1-mac9 | grep hash
|
||||
receive-hashing: on
|
||||
|
||||
Please note that Rx hashing depends upon the rx-flow-hashing being on
|
||||
for that interface - turning off rx-flow-hashing will also disable the
|
||||
rx-hashing (without ethtool reporting it as off as that depends on the
|
||||
NETIF_F_RXHASH feature flag).
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
|
@ -596,8 +596,8 @@ skb pointer). All constraints and restrictions from bpf_check_classic() apply
|
||||
before a conversion to the new layout is being done behind the scenes!
|
||||
|
||||
Currently, the classic BPF format is being used for JITing on most 32-bit
|
||||
architectures, whereas x86-64, aarch64, s390x, powerpc64, sparc64 perform JIT
|
||||
compilation from eBPF instruction set.
|
||||
architectures, whereas x86-64, aarch64, s390x, powerpc64, sparc64, arm32 perform
|
||||
JIT compilation from eBPF instruction set.
|
||||
|
||||
Some core changes of the new internal format:
|
||||
|
||||
@ -793,7 +793,7 @@ Some core changes of the new internal format:
|
||||
bpf_exit
|
||||
|
||||
After the call the registers R1-R5 contain junk values and cannot be read.
|
||||
In the future an eBPF verifier can be used to validate internal BPF programs.
|
||||
An in-kernel eBPF verifier is used to validate internal BPF programs.
|
||||
|
||||
Also in the new design, eBPF is limited to 4096 insns, which means that any
|
||||
program will terminate quickly and will only call a fixed number of kernel
|
||||
@ -906,6 +906,10 @@ If BPF_CLASS(code) == BPF_JMP, BPF_OP(code) is one of:
|
||||
BPF_JSGE 0x70 /* eBPF only: signed '>=' */
|
||||
BPF_CALL 0x80 /* eBPF only: function call */
|
||||
BPF_EXIT 0x90 /* eBPF only: function return */
|
||||
BPF_JLT 0xa0 /* eBPF only: unsigned '<' */
|
||||
BPF_JLE 0xb0 /* eBPF only: unsigned '<=' */
|
||||
BPF_JSLT 0xc0 /* eBPF only: signed '<' */
|
||||
BPF_JSLE 0xd0 /* eBPF only: signed '<=' */
|
||||
|
||||
So BPF_ADD | BPF_X | BPF_ALU means 32-bit addition in both classic BPF
|
||||
and eBPF. There are only two registers in classic BPF, so it means A += X.
|
||||
@ -1017,7 +1021,7 @@ At the start of the program the register R1 contains a pointer to context
|
||||
and has type PTR_TO_CTX.
|
||||
If verifier sees an insn that does R2=R1, then R2 has now type
|
||||
PTR_TO_CTX as well and can be used on the right hand side of expression.
|
||||
If R1=PTR_TO_CTX and insn is R2=R1+R1, then R2=UNKNOWN_VALUE,
|
||||
If R1=PTR_TO_CTX and insn is R2=R1+R1, then R2=SCALAR_VALUE,
|
||||
since addition of two valid pointers makes invalid pointer.
|
||||
(In 'secure' mode verifier will reject any type of pointer arithmetic to make
|
||||
sure that kernel addresses don't leak to unprivileged users)
|
||||
@ -1039,7 +1043,7 @@ is a correct program. If there was R1 instead of R6, it would have
|
||||
been rejected.
|
||||
|
||||
load/store instructions are allowed only with registers of valid types, which
|
||||
are PTR_TO_CTX, PTR_TO_MAP, FRAME_PTR. They are bounds and alignment checked.
|
||||
are PTR_TO_CTX, PTR_TO_MAP, PTR_TO_STACK. They are bounds and alignment checked.
|
||||
For example:
|
||||
bpf_mov R1 = 1
|
||||
bpf_mov R2 = 2
|
||||
@ -1058,7 +1062,7 @@ intends to load a word from address R6 + 8 and store it into R0
|
||||
If R6=PTR_TO_CTX, via is_valid_access() callback the verifier will know
|
||||
that offset 8 of size 4 bytes can be accessed for reading, otherwise
|
||||
the verifier will reject the program.
|
||||
If R6=FRAME_PTR, then access should be aligned and be within
|
||||
If R6=PTR_TO_STACK, then access should be aligned and be within
|
||||
stack bounds, which are [-MAX_BPF_STACK, 0). In this example offset is 8,
|
||||
so it will fail verification, since it's out of bounds.
|
||||
|
||||
@ -1069,7 +1073,7 @@ For example:
|
||||
bpf_ld R0 = *(u32 *)(R10 - 4)
|
||||
bpf_exit
|
||||
is invalid program.
|
||||
Though R10 is correct read-only register and has type FRAME_PTR
|
||||
Though R10 is correct read-only register and has type PTR_TO_STACK
|
||||
and R10 - 4 is within stack bounds, there were no stores into that location.
|
||||
|
||||
Pointer register spill/fill is tracked as well, since four (R6-R9)
|
||||
@ -1094,6 +1098,71 @@ all use cases.
|
||||
|
||||
See details of eBPF verifier in kernel/bpf/verifier.c
|
||||
|
||||
Register value tracking
|
||||
-----------------------
|
||||
In order to determine the safety of an eBPF program, the verifier must track
|
||||
the range of possible values in each register and also in each stack slot.
|
||||
This is done with 'struct bpf_reg_state', defined in include/linux/
|
||||
bpf_verifier.h, which unifies tracking of scalar and pointer values. Each
|
||||
register state has a type, which is either NOT_INIT (the register has not been
|
||||
written to), SCALAR_VALUE (some value which is not usable as a pointer), or a
|
||||
pointer type. The types of pointers describe their base, as follows:
|
||||
PTR_TO_CTX Pointer to bpf_context.
|
||||
CONST_PTR_TO_MAP Pointer to struct bpf_map. "Const" because arithmetic
|
||||
on these pointers is forbidden.
|
||||
PTR_TO_MAP_VALUE Pointer to the value stored in a map element.
|
||||
PTR_TO_MAP_VALUE_OR_NULL
|
||||
Either a pointer to a map value, or NULL; map accesses
|
||||
(see section 'eBPF maps', below) return this type,
|
||||
which becomes a PTR_TO_MAP_VALUE when checked != NULL.
|
||||
Arithmetic on these pointers is forbidden.
|
||||
PTR_TO_STACK Frame pointer.
|
||||
PTR_TO_PACKET skb->data.
|
||||
PTR_TO_PACKET_END skb->data + headlen; arithmetic forbidden.
|
||||
However, a pointer may be offset from this base (as a result of pointer
|
||||
arithmetic), and this is tracked in two parts: the 'fixed offset' and 'variable
|
||||
offset'. The former is used when an exactly-known value (e.g. an immediate
|
||||
operand) is added to a pointer, while the latter is used for values which are
|
||||
not exactly known. The variable offset is also used in SCALAR_VALUEs, to track
|
||||
the range of possible values in the register.
|
||||
The verifier's knowledge about the variable offset consists of:
|
||||
* minimum and maximum values as unsigned
|
||||
* minimum and maximum values as signed
|
||||
* knowledge of the values of individual bits, in the form of a 'tnum': a u64
|
||||
'mask' and a u64 'value'. 1s in the mask represent bits whose value is unknown;
|
||||
1s in the value represent bits known to be 1. Bits known to be 0 have 0 in both
|
||||
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;
|
||||
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
|
||||
it will have a umin_value (unsigned minimum value) of 9, whereas in the 'false'
|
||||
branch it will have a umax_value of 8. A signed compare (with BPF_JSGT or
|
||||
BPF_JSGE) would instead update the signed minimum/maximum values. Information
|
||||
from the signed and unsigned bounds can be combined; for instance if a value is
|
||||
first tested < 8 and then tested s> 4, the verifier will conclude that the value
|
||||
is also > 4 and s< 8, since the bounds prevent crossing the sign boundary.
|
||||
PTR_TO_PACKETs with a variable offset part have an 'id', which is common to all
|
||||
pointers sharing that same variable offset. This is important for packet range
|
||||
checks: after adding some variable to a packet pointer, if you then copy it to
|
||||
another register and (say) add a constant 4, both registers will share the same
|
||||
'id' but one will have a fixed offset of +4. Then if it is bounds-checked and
|
||||
found to be less than a PTR_TO_PACKET_END, the other register is now known to
|
||||
have a safe range of at least 4 bytes. See 'Direct packet access', below, for
|
||||
more on PTR_TO_PACKET ranges.
|
||||
The 'id' field is also used on PTR_TO_MAP_VALUE_OR_NULL, common to all copies of
|
||||
the pointer returned from a map lookup. This means that when one copy is
|
||||
checked and found to be non-NULL, all copies can become PTR_TO_MAP_VALUEs.
|
||||
As well as range-checking, the tracked information is also used for enforcing
|
||||
alignment of pointer accesses. For instance, on most systems the packet pointer
|
||||
is 2 bytes after a 4-byte alignment. If a program adds 14 bytes to that to jump
|
||||
over the Ethernet header, then reads IHL and addes (IHL * 4), the resulting
|
||||
pointer will have a variable offset known to be 4n+2 for some n, so adding the 2
|
||||
bytes (NET_IP_ALIGN) gives a 4-byte alignment and so word-sized accesses through
|
||||
that pointer are safe.
|
||||
|
||||
Direct packet access
|
||||
--------------------
|
||||
In cls_bpf and act_bpf programs the verifier allows direct access to the packet
|
||||
@ -1121,7 +1190,7 @@ it now points to 'skb->data + 14' and accessible range is [R5, R5 + 14 - 14)
|
||||
which is zero bytes.
|
||||
|
||||
More complex packet access may look like:
|
||||
R0=imm1 R1=ctx R3=pkt(id=0,off=0,r=14) R4=pkt_end R5=pkt(id=0,off=14,r=14) R10=fp
|
||||
R0=inv1 R1=ctx R3=pkt(id=0,off=0,r=14) R4=pkt_end R5=pkt(id=0,off=14,r=14) R10=fp
|
||||
6: r0 = *(u8 *)(r3 +7) /* load 7th byte from the packet */
|
||||
7: r4 = *(u8 *)(r3 +12)
|
||||
8: r4 *= 14
|
||||
@ -1135,26 +1204,31 @@ More complex packet access may look like:
|
||||
16: r2 += 8
|
||||
17: r1 = *(u32 *)(r1 +80) /* load skb->data_end */
|
||||
18: if r2 > r1 goto pc+2
|
||||
R0=inv56 R1=pkt_end R2=pkt(id=2,off=8,r=8) R3=pkt(id=2,off=0,r=8) R4=inv52 R5=pkt(id=0,off=14,r=14) R10=fp
|
||||
R0=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R1=pkt_end R2=pkt(id=2,off=8,r=8) R3=pkt(id=2,off=0,r=8) R4=inv(id=0,umax_value=3570,var_off=(0x0; 0xfffe)) R5=pkt(id=0,off=14,r=14) R10=fp
|
||||
19: r1 = *(u8 *)(r3 +4)
|
||||
The state of the register R3 is R3=pkt(id=2,off=0,r=8)
|
||||
id=2 means that two 'r3 += rX' instructions were seen, so r3 points to some
|
||||
offset within a packet and since the program author did
|
||||
'if (r3 + 8 > r1) goto err' at insn #18, the safe range is [R3, R3 + 8).
|
||||
The verifier only allows 'add' operation on packet registers. Any other
|
||||
operation will set the register state to 'unknown_value' and it won't be
|
||||
The verifier only allows 'add'/'sub' operations on packet registers. Any other
|
||||
operation will set the register state to 'SCALAR_VALUE' and it won't be
|
||||
available for direct packet access.
|
||||
Operation 'r3 += rX' may overflow and become less than original skb->data,
|
||||
therefore the verifier has to prevent that. So it tracks the number of
|
||||
upper zero bits in all 'uknown_value' registers, so when it sees
|
||||
'r3 += rX' instruction and rX is more than 16-bit value, it will error as:
|
||||
"cannot add integer value with N upper zero bits to ptr_to_packet"
|
||||
therefore the verifier has to prevent that. So when it sees 'r3 += rX'
|
||||
instruction and rX is more than 16-bit value, any subsequent bounds-check of r3
|
||||
against skb->data_end will not give us 'range' information, so attempts to read
|
||||
through the pointer will give "invalid access to packet" error.
|
||||
Ex. after insn 'r4 = *(u8 *)(r3 +12)' (insn #7 above) the state of r4 is
|
||||
R4=inv56 which means that upper 56 bits on the register are guaranteed
|
||||
to be zero. After insn 'r4 *= 14' the state becomes R4=inv52, since
|
||||
multiplying 8-bit value by constant 14 will keep upper 52 bits as zero.
|
||||
Similarly 'r2 >>= 48' will make R2=inv48, since the shift is not sign
|
||||
extending. This logic is implemented in evaluate_reg_alu() function.
|
||||
R4=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) which means that upper 56 bits
|
||||
of the register are guaranteed to be zero, and nothing is known about the lower
|
||||
8 bits. After insn 'r4 *= 14' the state becomes
|
||||
R4=inv(id=0,umax_value=3570,var_off=(0x0; 0xfffe)), since multiplying an 8-bit
|
||||
value by constant 14 will keep upper 52 bits as zero, also the least significant
|
||||
bit will be zero as 14 is even. Similarly 'r2 >>= 48' will make
|
||||
R2=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)), since the shift is not sign
|
||||
extending. This logic is implemented in adjust_reg_min_max_vals() function,
|
||||
which calls adjust_ptr_min_max_vals() for adding pointer to scalar (or vice
|
||||
versa) and adjust_scalar_min_max_vals() for operations on two scalars.
|
||||
|
||||
The end result is that bpf program author can access packet directly
|
||||
using normal C code as:
|
||||
@ -1214,6 +1288,22 @@ The map is defined by:
|
||||
. key size in bytes
|
||||
. value size in bytes
|
||||
|
||||
Pruning
|
||||
-------
|
||||
The verifier does not actually walk all possible paths through the program. For
|
||||
each new branch to analyse, the verifier looks at all the states it's previously
|
||||
been in when at this instruction. If any of them contain the current state as a
|
||||
subset, the branch is 'pruned' - that is, the fact that the previous state was
|
||||
accepted implies the current state would be as well. For instance, if in the
|
||||
previous state, r1 held a packet-pointer, and in the current state, r1 holds a
|
||||
packet-pointer with a range as long or longer and at least as strict an
|
||||
alignment, then r1 is safe. Similarly, if r2 was NOT_INIT before then it can't
|
||||
have been used by any path from that point, so any value in r2 (including
|
||||
another NOT_INIT) is safe. The implementation is in the function regsafe().
|
||||
Pruning considers not only the registers but also the stack (and any spilled
|
||||
registers it may hold). They must all be safe for the branch to be pruned.
|
||||
This is implemented in states_equal().
|
||||
|
||||
Understanding eBPF verifier messages
|
||||
------------------------------------
|
||||
|
||||
|
125
Documentation/networking/hinic.txt
Normal file
125
Documentation/networking/hinic.txt
Normal file
@ -0,0 +1,125 @@
|
||||
Linux Kernel Driver for Huawei Intelligent NIC(HiNIC) family
|
||||
============================================================
|
||||
|
||||
Overview:
|
||||
=========
|
||||
HiNIC is a network interface card for the Data Center Area.
|
||||
|
||||
The driver supports a range of link-speed devices (10GbE, 25GbE, 40GbE, etc.).
|
||||
The driver supports also a negotiated and extendable feature set.
|
||||
|
||||
Some HiNIC devices support SR-IOV. This driver is used for Physical Function
|
||||
(PF).
|
||||
|
||||
HiNIC devices support MSI-X interrupt vector for each Tx/Rx queue and
|
||||
adaptive interrupt moderation.
|
||||
|
||||
HiNIC devices support also various offload features such as checksum offload,
|
||||
TCP Transmit Segmentation Offload(TSO), Receive-Side Scaling(RSS) and
|
||||
LRO(Large Receive Offload).
|
||||
|
||||
|
||||
Supported PCI vendor ID/device IDs:
|
||||
===================================
|
||||
|
||||
19e5:1822 - HiNIC PF
|
||||
|
||||
|
||||
Driver Architecture and Source Code:
|
||||
====================================
|
||||
|
||||
hinic_dev - Implement a Logical Network device that is independent from
|
||||
specific HW details about HW data structure formats.
|
||||
|
||||
hinic_hwdev - Implement the HW details of the device and include the components
|
||||
for accessing the PCI NIC.
|
||||
|
||||
hinic_hwdev contains the following components:
|
||||
===============================================
|
||||
|
||||
HW Interface:
|
||||
=============
|
||||
|
||||
The interface for accessing the pci device (DMA memory and PCI BARs).
|
||||
(hinic_hw_if.c, hinic_hw_if.h)
|
||||
|
||||
Configuration Status Registers Area that describes the HW Registers on the
|
||||
configuration and status BAR0. (hinic_hw_csr.h)
|
||||
|
||||
MGMT components:
|
||||
================
|
||||
|
||||
Asynchronous Event Queues(AEQs) - The event queues for receiving messages from
|
||||
the MGMT modules on the cards. (hinic_hw_eqs.c, hinic_hw_eqs.h)
|
||||
|
||||
Application Programmable Interface commands(API CMD) - Interface for sending
|
||||
MGMT commands to the card. (hinic_hw_api_cmd.c, hinic_hw_api_cmd.h)
|
||||
|
||||
Management (MGMT) - the PF to MGMT channel that uses API CMD for sending MGMT
|
||||
commands to the card and receives notifications from the MGMT modules on the
|
||||
card by AEQs. Also set the addresses of the IO CMDQs in HW.
|
||||
(hinic_hw_mgmt.c, hinic_hw_mgmt.h)
|
||||
|
||||
IO components:
|
||||
==============
|
||||
|
||||
Completion Event Queues(CEQs) - The completion Event Queues that describe IO
|
||||
tasks that are finished. (hinic_hw_eqs.c, hinic_hw_eqs.h)
|
||||
|
||||
Work Queues(WQ) - Contain the memory and operations for use by CMD queues and
|
||||
the Queue Pairs. The WQ is a Memory Block in a Page. The Block contains
|
||||
pointers to Memory Areas that are the Memory for the Work Queue Elements(WQEs).
|
||||
(hinic_hw_wq.c, hinic_hw_wq.h)
|
||||
|
||||
Command Queues(CMDQ) - The queues for sending commands for IO management and is
|
||||
used to set the QPs addresses in HW. The commands completion events are
|
||||
accumulated on the CEQ that is configured to receive the CMDQ completion events.
|
||||
(hinic_hw_cmdq.c, hinic_hw_cmdq.h)
|
||||
|
||||
Queue Pairs(QPs) - The HW Receive and Send queues for Receiving and Transmitting
|
||||
Data. (hinic_hw_qp.c, hinic_hw_qp.h, hinic_hw_qp_ctxt.h)
|
||||
|
||||
IO - de/constructs all the IO components. (hinic_hw_io.c, hinic_hw_io.h)
|
||||
|
||||
HW device:
|
||||
==========
|
||||
|
||||
HW device - de/constructs the HW Interface, the MGMT components on the
|
||||
initialization of the driver and the IO components on the case of Interface
|
||||
UP/DOWN Events. (hinic_hw_dev.c, hinic_hw_dev.h)
|
||||
|
||||
|
||||
hinic_dev contains the following components:
|
||||
===============================================
|
||||
|
||||
PCI ID table - Contains the supported PCI Vendor/Device IDs.
|
||||
(hinic_pci_tbl.h)
|
||||
|
||||
Port Commands - Send commands to the HW device for port management
|
||||
(MAC, Vlan, MTU, ...). (hinic_port.c, hinic_port.h)
|
||||
|
||||
Tx Queues - Logical Tx Queues that use the HW Send Queues for transmit.
|
||||
The Logical Tx queue is not dependent on the format of the HW Send Queue.
|
||||
(hinic_tx.c, hinic_tx.h)
|
||||
|
||||
Rx Queues - Logical Rx Queues that use the HW Receive Queues for receive.
|
||||
The Logical Rx queue is not dependent on the format of the HW Receive Queue.
|
||||
(hinic_rx.c, hinic_rx.h)
|
||||
|
||||
hinic_dev - de/constructs the Logical Tx and Rx Queues.
|
||||
(hinic_main.c, hinic_dev.h)
|
||||
|
||||
|
||||
Miscellaneous:
|
||||
=============
|
||||
|
||||
Common functions that are used by HW and Logical Device.
|
||||
(hinic_common.c, hinic_common.h)
|
||||
|
||||
|
||||
Support
|
||||
=======
|
||||
|
||||
If an issue is identified with the released source code on the supported kernel
|
||||
with a supported adapter, email the specific information related to the issue to
|
||||
aviad.krawczyk@huawei.com.
|
@ -6,6 +6,7 @@ Contents:
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
batman-adv
|
||||
kapi
|
||||
z8530book
|
||||
|
||||
|
@ -109,7 +109,10 @@ neigh/default/unres_qlen_bytes - INTEGER
|
||||
queued for each unresolved address by other network layers.
|
||||
(added in linux 3.3)
|
||||
Setting negative value is meaningless and will return error.
|
||||
Default: 65536 Bytes(64KB)
|
||||
Default: SK_WMEM_MAX, (same as net.core.wmem_default).
|
||||
Exact value depends on architecture and kernel options,
|
||||
but should be enough to allow queuing 256 packets
|
||||
of medium size.
|
||||
|
||||
neigh/default/unres_qlen - INTEGER
|
||||
The maximum number of packets which may be queued for each
|
||||
@ -119,7 +122,7 @@ neigh/default/unres_qlen - INTEGER
|
||||
unexpected packet loss. The current default value is calculated
|
||||
according to default value of unres_qlen_bytes and true size of
|
||||
packet.
|
||||
Default: 31
|
||||
Default: 101
|
||||
|
||||
mtu_expires - INTEGER
|
||||
Time, in seconds, that cached PMTU information is kept.
|
||||
@ -353,12 +356,7 @@ tcp_l3mdev_accept - BOOLEAN
|
||||
compiled with CONFIG_NET_L3_MASTER_DEV.
|
||||
|
||||
tcp_low_latency - BOOLEAN
|
||||
If set, the TCP stack makes decisions that prefer lower
|
||||
latency as opposed to higher throughput. By default, this
|
||||
option is not set meaning that higher throughput is preferred.
|
||||
An example of an application where this default should be
|
||||
changed would be a Beowulf compute cluster.
|
||||
Default: 0
|
||||
This is a legacy option, it has no effect anymore.
|
||||
|
||||
tcp_max_orphans - INTEGER
|
||||
Maximal number of TCP sockets not attached to any user file handle,
|
||||
@ -1291,8 +1289,7 @@ tag - INTEGER
|
||||
xfrm4_gc_thresh - INTEGER
|
||||
The threshold at which we will start garbage collecting for IPv4
|
||||
destination cache entries. At twice this value the system will
|
||||
refuse new allocations. The value must be set below the flowcache
|
||||
limit (4096 * number of online cpus) to take effect.
|
||||
refuse new allocations.
|
||||
|
||||
igmp_link_local_mcast_reports - BOOLEAN
|
||||
Enable IGMP reports for link local multicast groups in the
|
||||
@ -1356,6 +1353,15 @@ flowlabel_state_ranges - BOOLEAN
|
||||
FALSE: disabled
|
||||
Default: true
|
||||
|
||||
flowlabel_reflect - BOOLEAN
|
||||
Automatically reflect the flow label. Needed for Path MTU
|
||||
Discovery to work with Equal Cost Multipath Routing in anycast
|
||||
environments. See RFC 7690 and:
|
||||
https://tools.ietf.org/html/draft-wang-6man-flow-label-reflection-01
|
||||
TRUE: enabled
|
||||
FALSE: disabled
|
||||
Default: FALSE
|
||||
|
||||
anycast_src_echo_reply - BOOLEAN
|
||||
Controls the use of anycast addresses as source addresses for ICMPv6
|
||||
echo reply
|
||||
@ -1778,8 +1784,7 @@ ratelimit - INTEGER
|
||||
xfrm6_gc_thresh - INTEGER
|
||||
The threshold at which we will start garbage collecting for IPv6
|
||||
destination cache entries. At twice this value the system will
|
||||
refuse new allocations. The value must be set below the flowcache
|
||||
limit (4096 * number of online cpus) to take effect.
|
||||
refuse new allocations.
|
||||
|
||||
|
||||
IPv6 Update by:
|
||||
|
257
Documentation/networking/msg_zerocopy.rst
Normal file
257
Documentation/networking/msg_zerocopy.rst
Normal file
@ -0,0 +1,257 @@
|
||||
|
||||
============
|
||||
MSG_ZEROCOPY
|
||||
============
|
||||
|
||||
Intro
|
||||
=====
|
||||
|
||||
The MSG_ZEROCOPY flag enables copy avoidance for socket send calls.
|
||||
The feature is currently implemented for TCP sockets.
|
||||
|
||||
|
||||
Opportunity and Caveats
|
||||
-----------------------
|
||||
|
||||
Copying large buffers between user process and kernel can be
|
||||
expensive. Linux supports various interfaces that eschew copying,
|
||||
such as sendpage and splice. The MSG_ZEROCOPY flag extends the
|
||||
underlying copy avoidance mechanism to common socket send calls.
|
||||
|
||||
Copy avoidance is not a free lunch. As implemented, with page pinning,
|
||||
it replaces per byte copy cost with page accounting and completion
|
||||
notification overhead. As a result, MSG_ZEROCOPY is generally only
|
||||
effective at writes over around 10 KB.
|
||||
|
||||
Page pinning also changes system call semantics. It temporarily shares
|
||||
the buffer between process and network stack. Unlike with copying, the
|
||||
process cannot immediately overwrite the buffer after system call
|
||||
return without possibly modifying the data in flight. Kernel integrity
|
||||
is not affected, but a buggy program can possibly corrupt its own data
|
||||
stream.
|
||||
|
||||
The kernel returns a notification when it is safe to modify data.
|
||||
Converting an existing application to MSG_ZEROCOPY is not always as
|
||||
trivial as just passing the flag, then.
|
||||
|
||||
|
||||
More Info
|
||||
---------
|
||||
|
||||
Much of this document was derived from a longer paper presented at
|
||||
netdev 2.1. For more in-depth information see that paper and talk,
|
||||
the excellent reporting over at LWN.net or read the original code.
|
||||
|
||||
paper, slides, video
|
||||
https://netdevconf.org/2.1/session.html?debruijn
|
||||
|
||||
LWN article
|
||||
https://lwn.net/Articles/726917/
|
||||
|
||||
patchset
|
||||
[PATCH net-next v4 0/9] socket sendmsg MSG_ZEROCOPY
|
||||
http://lkml.kernel.org/r/20170803202945.70750-1-willemdebruijn.kernel@gmail.com
|
||||
|
||||
|
||||
Interface
|
||||
=========
|
||||
|
||||
Passing the MSG_ZEROCOPY flag is the most obvious step to enable copy
|
||||
avoidance, but not the only one.
|
||||
|
||||
Socket Setup
|
||||
------------
|
||||
|
||||
The kernel is permissive when applications pass undefined flags to the
|
||||
send system call. By default it simply ignores these. To avoid enabling
|
||||
copy avoidance mode for legacy processes that accidentally already pass
|
||||
this flag, a process must first signal intent by setting a socket option:
|
||||
|
||||
::
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &one, sizeof(one)))
|
||||
error(1, errno, "setsockopt zerocopy");
|
||||
|
||||
|
||||
Transmission
|
||||
------------
|
||||
|
||||
The change to send (or sendto, sendmsg, sendmmsg) itself is trivial.
|
||||
Pass the new flag.
|
||||
|
||||
::
|
||||
|
||||
ret = send(fd, buf, sizeof(buf), MSG_ZEROCOPY);
|
||||
|
||||
A zerocopy failure will return -1 with errno ENOBUFS. This happens if
|
||||
the socket option was not set, the socket exceeds its optmem limit or
|
||||
the user exceeds its ulimit on locked pages.
|
||||
|
||||
|
||||
Mixing copy avoidance and copying
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Many workloads have a mixture of large and small buffers. Because copy
|
||||
avoidance is more expensive than copying for small packets, the
|
||||
feature is implemented as a flag. It is safe to mix calls with the flag
|
||||
with those without.
|
||||
|
||||
|
||||
Notifications
|
||||
-------------
|
||||
|
||||
The kernel has to notify the process when it is safe to reuse a
|
||||
previously passed buffer. It queues completion notifications on the
|
||||
socket error queue, akin to the transmit timestamping interface.
|
||||
|
||||
The notification itself is a simple scalar value. Each socket
|
||||
maintains an internal unsigned 32-bit counter. Each send call with
|
||||
MSG_ZEROCOPY that successfully sends data increments the counter. The
|
||||
counter is not incremented on failure or if called with length zero.
|
||||
The counter counts system call invocations, not bytes. It wraps after
|
||||
UINT_MAX calls.
|
||||
|
||||
|
||||
Notification Reception
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The below snippet demonstrates the API. In the simplest case, each
|
||||
send syscall is followed by a poll and recvmsg on the error queue.
|
||||
|
||||
Reading from the error queue is always a non-blocking operation. The
|
||||
poll call is there to block until an error is outstanding. It will set
|
||||
POLLERR in its output flags. That flag does not have to be set in the
|
||||
events field. Errors are signaled unconditionally.
|
||||
|
||||
::
|
||||
|
||||
pfd.fd = fd;
|
||||
pfd.events = 0;
|
||||
if (poll(&pfd, 1, -1) != 1 || pfd.revents & POLLERR == 0)
|
||||
error(1, errno, "poll");
|
||||
|
||||
ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
|
||||
if (ret == -1)
|
||||
error(1, errno, "recvmsg");
|
||||
|
||||
read_notification(msg);
|
||||
|
||||
The example is for demonstration purpose only. In practice, it is more
|
||||
efficient to not wait for notifications, but read without blocking
|
||||
every couple of send calls.
|
||||
|
||||
Notifications can be processed out of order with other operations on
|
||||
the socket. A socket that has an error queued would normally block
|
||||
other operations until the error is read. Zerocopy notifications have
|
||||
a zero error code, however, to not block send and recv calls.
|
||||
|
||||
|
||||
Notification Batching
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Multiple outstanding packets can be read at once using the recvmmsg
|
||||
call. This is often not needed. In each message the kernel returns not
|
||||
a single value, but a range. It coalesces consecutive notifications
|
||||
while one is outstanding for reception on the error queue.
|
||||
|
||||
When a new notification is about to be queued, it checks whether the
|
||||
new value extends the range of the notification at the tail of the
|
||||
queue. If so, it drops the new notification packet and instead increases
|
||||
the range upper value of the outstanding notification.
|
||||
|
||||
For protocols that acknowledge data in-order, like TCP, each
|
||||
notification can be squashed into the previous one, so that no more
|
||||
than one notification is outstanding at any one point.
|
||||
|
||||
Ordered delivery is the common case, but not guaranteed. Notifications
|
||||
may arrive out of order on retransmission and socket teardown.
|
||||
|
||||
|
||||
Notification Parsing
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The below snippet demonstrates how to parse the control message: the
|
||||
read_notification() call in the previous snippet. A notification
|
||||
is encoded in the standard error format, sock_extended_err.
|
||||
|
||||
The level and type fields in the control data are protocol family
|
||||
specific, IP_RECVERR or IPV6_RECVERR.
|
||||
|
||||
Error origin is the new type SO_EE_ORIGIN_ZEROCOPY. ee_errno is zero,
|
||||
as explained before, to avoid blocking read and write system calls on
|
||||
the socket.
|
||||
|
||||
The 32-bit notification range is encoded as [ee_info, ee_data]. This
|
||||
range is inclusive. Other fields in the struct must be treated as
|
||||
undefined, bar for ee_code, as discussed below.
|
||||
|
||||
::
|
||||
|
||||
struct sock_extended_err *serr;
|
||||
struct cmsghdr *cm;
|
||||
|
||||
cm = CMSG_FIRSTHDR(msg);
|
||||
if (cm->cmsg_level != SOL_IP &&
|
||||
cm->cmsg_type != IP_RECVERR)
|
||||
error(1, 0, "cmsg");
|
||||
|
||||
serr = (void *) CMSG_DATA(cm);
|
||||
if (serr->ee_errno != 0 ||
|
||||
serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY)
|
||||
error(1, 0, "serr");
|
||||
|
||||
printf("completed: %u..%u\n", serr->ee_info, serr->ee_data);
|
||||
|
||||
|
||||
Deferred copies
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Passing flag MSG_ZEROCOPY is a hint to the kernel to apply copy
|
||||
avoidance, and a contract that the kernel will queue a completion
|
||||
notification. It is not a guarantee that the copy is elided.
|
||||
|
||||
Copy avoidance is not always feasible. Devices that do not support
|
||||
scatter-gather I/O cannot send packets made up of kernel generated
|
||||
protocol headers plus zerocopy user data. A packet may need to be
|
||||
converted to a private copy of data deep in the stack, say to compute
|
||||
a checksum.
|
||||
|
||||
In all these cases, the kernel returns a completion notification when
|
||||
it releases its hold on the shared pages. That notification may arrive
|
||||
before the (copied) data is fully transmitted. A zerocopy completion
|
||||
notification is not a transmit completion notification, therefore.
|
||||
|
||||
Deferred copies can be more expensive than a copy immediately in the
|
||||
system call, if the data is no longer warm in the cache. The process
|
||||
also incurs notification processing cost for no benefit. For this
|
||||
reason, the kernel signals if data was completed with a copy, by
|
||||
setting flag SO_EE_CODE_ZEROCOPY_COPIED in field ee_code on return.
|
||||
A process may use this signal to stop passing flag MSG_ZEROCOPY on
|
||||
subsequent requests on the same socket.
|
||||
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
Loopback
|
||||
--------
|
||||
|
||||
Data sent to local sockets can be queued indefinitely if the receive
|
||||
process does not read its socket. Unbound notification latency is not
|
||||
acceptable. For this reason all packets generated with MSG_ZEROCOPY
|
||||
that are looped to a local socket will incur a deferred copy. This
|
||||
includes looping onto packet sockets (e.g., tcpdump) and tun devices.
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
More realistic example code can be found in the kernel source under
|
||||
tools/testing/selftests/net/msg_zerocopy.c.
|
||||
|
||||
Be cognizant of the loopback constraint. The test can be run between
|
||||
a pair of hosts. But if run between a local pair of processes, for
|
||||
instance when run with msg_zerocopy.sh between a veth pair across
|
||||
namespaces, the test will not show any improvement. For testing, the
|
||||
loopback restriction can be temporarily relaxed by making
|
||||
skb_orphan_frags_rx identical to skb_orphan_frags.
|
@ -111,6 +111,14 @@ A: Generally speaking, the patches get triaged quickly (in less than 48h).
|
||||
patch is a good way to ensure your patch is ignored or pushed to
|
||||
the bottom of the priority list.
|
||||
|
||||
Q: I submitted multiple versions of the patch series, should I directly update
|
||||
patchwork for the previous versions of these patch series?
|
||||
|
||||
A: No, please don't interfere with the patch status on patchwork, leave it to
|
||||
the maintainer to figure out what is the most recent and current version that
|
||||
should be applied. If there is any doubt, the maintainer will reply and ask
|
||||
what should be done.
|
||||
|
||||
Q: How can I tell what patches are queued up for backporting to the
|
||||
various stable releases?
|
||||
|
||||
|
75
Documentation/networking/netvsc.txt
Normal file
75
Documentation/networking/netvsc.txt
Normal file
@ -0,0 +1,75 @@
|
||||
Hyper-V network driver
|
||||
======================
|
||||
|
||||
Compatibility
|
||||
=============
|
||||
|
||||
This driver is compatible with Windows Server 2012 R2, 2016 and
|
||||
Windows 10.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
Checksum offload
|
||||
----------------
|
||||
The netvsc driver supports checksum offload as long as the
|
||||
Hyper-V host version does. Windows Server 2016 and Azure
|
||||
support checksum offload for TCP and UDP for both IPv4 and
|
||||
IPv6. Windows Server 2012 only supports checksum offload for TCP.
|
||||
|
||||
Receive Side Scaling
|
||||
--------------------
|
||||
Hyper-V supports receive side scaling. For TCP, packets are
|
||||
distributed among available queues based on IP address and port
|
||||
number.
|
||||
|
||||
For UDP, we can switch UDP hash level between L3 and L4 by ethtool
|
||||
command. UDP over IPv4 and v6 can be set differently. The default
|
||||
hash level is L4. We currently only allow switching TX hash level
|
||||
from within the guests.
|
||||
|
||||
On Azure, fragmented UDP packets have high loss rate with L4
|
||||
hashing. Using L3 hashing is recommended in this case.
|
||||
|
||||
For example, for UDP over IPv4 on eth0:
|
||||
To include UDP port numbers in hashing:
|
||||
ethtool -N eth0 rx-flow-hash udp4 sdfn
|
||||
To exclude UDP port numbers in hashing:
|
||||
ethtool -N eth0 rx-flow-hash udp4 sd
|
||||
To show UDP hash level:
|
||||
ethtool -n eth0 rx-flow-hash udp4
|
||||
|
||||
Generic Receive Offload, aka GRO
|
||||
--------------------------------
|
||||
The driver supports GRO and it is enabled by default. GRO coalesces
|
||||
like packets and significantly reduces CPU usage under heavy Rx
|
||||
load.
|
||||
|
||||
SR-IOV support
|
||||
--------------
|
||||
Hyper-V supports SR-IOV as a hardware acceleration option. If SR-IOV
|
||||
is enabled in both the vSwitch and the guest configuration, then the
|
||||
Virtual Function (VF) device is passed to the guest as a PCI
|
||||
device. In this case, both a synthetic (netvsc) and VF device are
|
||||
visible in the guest OS and both NIC's have the same MAC address.
|
||||
|
||||
The VF is enslaved by netvsc device. The netvsc driver will transparently
|
||||
switch the data path to the VF when it is available and up.
|
||||
Network state (addresses, firewall, etc) should be applied only to the
|
||||
netvsc device; the slave device should not be accessed directly in
|
||||
most cases. The exceptions are if some special queue discipline or
|
||||
flow direction is desired, these should be applied directly to the
|
||||
VF slave device.
|
||||
|
||||
Receive Buffer
|
||||
--------------
|
||||
Packets are received into a receive area which is created when device
|
||||
is probed. The receive area is broken into MTU sized chunks and each may
|
||||
contain one or more packets. The number of receive sections may be changed
|
||||
via ethtool Rx ring parameters.
|
||||
|
||||
There is a similar send buffer which is used to aggregate packets for sending.
|
||||
The send area is broken into chunks of 6144 bytes, each of section may
|
||||
contain one or more packets. The send buffer is an optimization, the driver
|
||||
will use slower method to handle very large packets or if the send buffer
|
||||
area is exhausted.
|
@ -96,17 +96,6 @@ nf_conntrack_max - INTEGER
|
||||
Size of connection tracking table. Default value is
|
||||
nf_conntrack_buckets value * 4.
|
||||
|
||||
nf_conntrack_default_on - BOOLEAN
|
||||
0 - don't register conntrack in new net namespaces
|
||||
1 - register conntrack in new net namespaces (default)
|
||||
|
||||
This controls wheter newly created network namespaces have connection
|
||||
tracking enabled by default. It will be enabled automatically
|
||||
regardless of this setting if the new net namespace requires
|
||||
connection tracking, e.g. when NAT rules are created.
|
||||
This setting is only visible in initial user namespace, it has no
|
||||
effect on existing namespaces.
|
||||
|
||||
nf_conntrack_tcp_be_liberal - BOOLEAN
|
||||
0 - disabled (default)
|
||||
not 0 - enabled
|
||||
|
82
Documentation/networking/rmnet.txt
Normal file
82
Documentation/networking/rmnet.txt
Normal file
@ -0,0 +1,82 @@
|
||||
1. Introduction
|
||||
|
||||
rmnet driver is used for supporting the Multiplexing and aggregation
|
||||
Protocol (MAP). This protocol is used by all recent chipsets using Qualcomm
|
||||
Technologies, Inc. modems.
|
||||
|
||||
This driver can be used to register onto any physical network device in
|
||||
IP mode. Physical transports include USB, HSIC, PCIe and IP accelerator.
|
||||
|
||||
Multiplexing allows for creation of logical netdevices (rmnet devices) to
|
||||
handle multiple private data networks (PDN) like a default internet, tethering,
|
||||
multimedia messaging service (MMS) or IP media subsystem (IMS). Hardware sends
|
||||
packets with MAP headers to rmnet. Based on the multiplexer id, rmnet
|
||||
routes to the appropriate PDN after removing the MAP header.
|
||||
|
||||
Aggregation is required to achieve high data rates. This involves hardware
|
||||
sending aggregated bunch of MAP frames. rmnet driver will de-aggregate
|
||||
these MAP frames and send them to appropriate PDN's.
|
||||
|
||||
2. Packet format
|
||||
|
||||
a. MAP packet (data / control)
|
||||
|
||||
MAP header has the same endianness of the IP packet.
|
||||
|
||||
Packet format -
|
||||
|
||||
Bit 0 1 2-7 8 - 15 16 - 31
|
||||
Function Command / Data Reserved Pad Multiplexer ID Payload length
|
||||
Bit 32 - x
|
||||
Function Raw Bytes
|
||||
|
||||
Command (1)/ Data (0) bit value is to indicate if the packet is a MAP command
|
||||
or data packet. Control packet is used for transport level flow control. Data
|
||||
packets are standard IP packets.
|
||||
|
||||
Reserved bits are usually zeroed out and to be ignored by receiver.
|
||||
|
||||
Padding is number of bytes to be added for 4 byte alignment if required by
|
||||
hardware.
|
||||
|
||||
Multiplexer ID is to indicate the PDN on which data has to be sent.
|
||||
|
||||
Payload length includes the padding length but does not include MAP header
|
||||
length.
|
||||
|
||||
b. MAP packet (command specific)
|
||||
|
||||
Bit 0 1 2-7 8 - 15 16 - 31
|
||||
Function Command Reserved Pad Multiplexer ID Payload length
|
||||
Bit 32 - 39 40 - 45 46 - 47 48 - 63
|
||||
Function Command name Reserved Command Type Reserved
|
||||
Bit 64 - 95
|
||||
Function Transaction ID
|
||||
Bit 96 - 127
|
||||
Function Command data
|
||||
|
||||
Command 1 indicates disabling flow while 2 is enabling flow
|
||||
|
||||
Command types -
|
||||
0 for MAP command request
|
||||
1 is to acknowledge the receipt of a command
|
||||
2 is for unsupported commands
|
||||
3 is for error during processing of commands
|
||||
|
||||
c. Aggregation
|
||||
|
||||
Aggregation is multiple MAP packets (can be data or command) delivered to
|
||||
rmnet in a single linear skb. rmnet will process the individual
|
||||
packets and either ACK the MAP command or deliver the IP packet to the
|
||||
network stack as needed
|
||||
|
||||
MAP header|IP Packet|Optional padding|MAP header|IP Packet|Optional padding....
|
||||
MAP header|IP Packet|Optional padding|MAP header|Command Packet|Optional pad...
|
||||
|
||||
3. Userspace configuration
|
||||
|
||||
rmnet userspace configuration is done through netlink library librmnetctl
|
||||
and command line utility rmnetcli. Utility is hosted in codeaurora forum git.
|
||||
The driver uses rtnl_link_ops for communication.
|
||||
|
||||
https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/dataservices/tree/rmnetctl
|
@ -818,10 +818,15 @@ The kernel interface functions are as follows:
|
||||
|
||||
(*) Send data through a call.
|
||||
|
||||
typedef void (*rxrpc_notify_end_tx_t)(struct sock *sk,
|
||||
unsigned long user_call_ID,
|
||||
struct sk_buff *skb);
|
||||
|
||||
int rxrpc_kernel_send_data(struct socket *sock,
|
||||
struct rxrpc_call *call,
|
||||
struct msghdr *msg,
|
||||
size_t len);
|
||||
size_t len,
|
||||
rxrpc_notify_end_tx_t notify_end_rx);
|
||||
|
||||
This is used to supply either the request part of a client call or the
|
||||
reply part of a server call. msg.msg_iovlen and msg.msg_iov specify the
|
||||
@ -832,6 +837,11 @@ The kernel interface functions are as follows:
|
||||
The msg must not specify a destination address, control data or any flags
|
||||
other than MSG_MORE. len is the total amount of data to transmit.
|
||||
|
||||
notify_end_rx can be NULL or it can be used to specify a function to be
|
||||
called when the call changes state to end the Tx phase. This function is
|
||||
called with the call-state spinlock held to prevent any reply or final ACK
|
||||
from being delivered first.
|
||||
|
||||
(*) Receive data from a call.
|
||||
|
||||
int rxrpc_kernel_recv_data(struct socket *sock,
|
||||
@ -965,6 +975,51 @@ The kernel interface functions are as follows:
|
||||
size should be set when the call is begun. tx_total_len may not be less
|
||||
than zero.
|
||||
|
||||
(*) Check to see the completion state of a call so that the caller can assess
|
||||
whether it needs to be retried.
|
||||
|
||||
enum rxrpc_call_completion {
|
||||
RXRPC_CALL_SUCCEEDED,
|
||||
RXRPC_CALL_REMOTELY_ABORTED,
|
||||
RXRPC_CALL_LOCALLY_ABORTED,
|
||||
RXRPC_CALL_LOCAL_ERROR,
|
||||
RXRPC_CALL_NETWORK_ERROR,
|
||||
};
|
||||
|
||||
int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
|
||||
enum rxrpc_call_completion *_compl,
|
||||
u32 *_abort_code);
|
||||
|
||||
On return, -EINPROGRESS will be returned if the call is still ongoing; if
|
||||
it is finished, *_compl will be set to indicate the manner of completion,
|
||||
*_abort_code will be set to any abort code that occurred. 0 will be
|
||||
returned on a successful completion, -ECONNABORTED will be returned if the
|
||||
client failed due to a remote abort and anything else will return an
|
||||
appropriate error code.
|
||||
|
||||
The caller should look at this information to decide if it's worth
|
||||
retrying the call.
|
||||
|
||||
(*) Retry a client call.
|
||||
|
||||
int rxrpc_kernel_retry_call(struct socket *sock,
|
||||
struct rxrpc_call *call,
|
||||
struct sockaddr_rxrpc *srx,
|
||||
struct key *key);
|
||||
|
||||
This attempts to partially reinitialise a call and submit it again whilst
|
||||
reusing the original call's Tx queue to avoid the need to repackage and
|
||||
re-encrypt the data to be sent. call indicates the call to retry, srx the
|
||||
new address to send it to and key the encryption key to use for signing or
|
||||
encrypting the packets.
|
||||
|
||||
For this to work, the first Tx data packet must still be in the transmit
|
||||
queue, and currently this is only permitted for local and network errors
|
||||
and the call must not have been aborted. Any partially constructed Tx
|
||||
packet is left as is and can continue being filled afterwards.
|
||||
|
||||
It returns 0 if the call was requeued and an error otherwise.
|
||||
|
||||
|
||||
=======================
|
||||
CONFIGURABLE PARAMETERS
|
||||
|
@ -1,45 +1,107 @@
|
||||
Stream Parser
|
||||
-------------
|
||||
Stream Parser (strparser)
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The stream parser (strparser) is a utility that parses messages of an
|
||||
application layer protocol running over a TCP connection. The stream
|
||||
application layer protocol running over a data stream. The stream
|
||||
parser works in conjunction with an upper layer in the kernel to provide
|
||||
kernel support for application layer messages. For instance, Kernel
|
||||
Connection Multiplexor (KCM) uses the Stream Parser to parse messages
|
||||
using a BPF program.
|
||||
|
||||
The strparser works in one of two modes: receive callback or general
|
||||
mode.
|
||||
|
||||
In receive callback mode, the strparser is called from the data_ready
|
||||
callback of a TCP socket. Messages are parsed and delivered as they are
|
||||
received on the socket.
|
||||
|
||||
In general mode, a sequence of skbs are fed to strparser from an
|
||||
outside source. Message are parsed and delivered as the sequence is
|
||||
processed. This modes allows strparser to be applied to arbitrary
|
||||
streams of data.
|
||||
|
||||
Interface
|
||||
---------
|
||||
=========
|
||||
|
||||
The API includes a context structure, a set of callbacks, utility
|
||||
functions, and a data_ready function. The callbacks include
|
||||
a parse_msg function that is called to perform parsing (e.g.
|
||||
BPF parsing in case of KCM), and a rcv_msg function that is called
|
||||
when a full message has been completed.
|
||||
functions, and a data_ready function for receive callback mode. The
|
||||
callbacks include a parse_msg function that is called to perform
|
||||
parsing (e.g. BPF parsing in case of KCM), and a rcv_msg function
|
||||
that is called when a full message has been completed.
|
||||
|
||||
A stream parser can be instantiated for a TCP connection. This is done
|
||||
by:
|
||||
Functions
|
||||
=========
|
||||
|
||||
strp_init(struct strparser *strp, struct sock *csk,
|
||||
struct strp_callbacks *cb)
|
||||
strp_init(struct strparser *strp, struct sock *sk,
|
||||
const struct strp_callbacks *cb)
|
||||
|
||||
strp is a struct of type strparser that is allocated by the upper layer.
|
||||
csk is the TCP socket associated with the stream parser. Callbacks are
|
||||
called by the stream parser.
|
||||
Called to initialize a stream parser. strp is a struct of type
|
||||
strparser that is allocated by the upper layer. sk is the TCP
|
||||
socket associated with the stream parser for use with receive
|
||||
callback mode; in general mode this is set to NULL. Callbacks
|
||||
are called by the stream parser (the callbacks are listed below).
|
||||
|
||||
void strp_pause(struct strparser *strp)
|
||||
|
||||
Temporarily pause a stream parser. Message parsing is suspended
|
||||
and no new messages are delivered to the upper layer.
|
||||
|
||||
void strp_pause(struct strparser *strp)
|
||||
|
||||
Unpause a paused stream parser.
|
||||
|
||||
void strp_stop(struct strparser *strp);
|
||||
|
||||
strp_stop is called to completely stop stream parser operations.
|
||||
This is called internally when the stream parser encounters an
|
||||
error, and it is called from the upper layer to stop parsing
|
||||
operations.
|
||||
|
||||
void strp_done(struct strparser *strp);
|
||||
|
||||
strp_done is called to release any resources held by the stream
|
||||
parser instance. This must be called after the stream processor
|
||||
has been stopped.
|
||||
|
||||
int strp_process(struct strparser *strp, struct sk_buff *orig_skb,
|
||||
unsigned int orig_offset, size_t orig_len,
|
||||
size_t max_msg_size, long timeo)
|
||||
|
||||
strp_process is called in general mode for a stream parser to
|
||||
parse an sk_buff. The number of bytes processed or a negative
|
||||
error number is returned. Note that strp_process does not
|
||||
consume the sk_buff. max_msg_size is maximum size the stream
|
||||
parser will parse. timeo is timeout for completing a message.
|
||||
|
||||
void strp_data_ready(struct strparser *strp);
|
||||
|
||||
The upper layer calls strp_tcp_data_ready when data is ready on
|
||||
the lower socket for strparser to process. This should be called
|
||||
from a data_ready callback that is set on the socket. Note that
|
||||
maximum messages size is the limit of the receive socket
|
||||
buffer and message timeout is the receive timeout for the socket.
|
||||
|
||||
void strp_check_rcv(struct strparser *strp);
|
||||
|
||||
strp_check_rcv is called to check for new messages on the socket.
|
||||
This is normally called at initialization of a stream parser
|
||||
instance or after strp_unpause.
|
||||
|
||||
Callbacks
|
||||
---------
|
||||
=========
|
||||
|
||||
There are four callbacks:
|
||||
There are six callbacks:
|
||||
|
||||
int (*parse_msg)(struct strparser *strp, struct sk_buff *skb);
|
||||
|
||||
parse_msg is called to determine the length of the next message
|
||||
in the stream. The upper layer must implement this function. It
|
||||
should parse the sk_buff as containing the headers for the
|
||||
next application layer messages in the stream.
|
||||
next application layer message in the stream.
|
||||
|
||||
The skb->cb in the input skb is a struct strp_rx_msg. Only
|
||||
The skb->cb in the input skb is a struct strp_msg. Only
|
||||
the offset field is relevant in parse_msg and gives the offset
|
||||
where the message starts in the skb.
|
||||
|
||||
@ -50,26 +112,41 @@ int (*parse_msg)(struct strparser *strp, struct sk_buff *skb);
|
||||
-ESTRPIPE : current message should not be processed by the
|
||||
kernel, return control of the socket to userspace which
|
||||
can proceed to read the messages itself
|
||||
other < 0 : Error is parsing, give control back to userspace
|
||||
other < 0 : Error in parsing, give control back to userspace
|
||||
assuming that synchronization is lost and the stream
|
||||
is unrecoverable (application expected to close TCP socket)
|
||||
|
||||
In the case that an error is returned (return value is less than
|
||||
zero) the stream parser will set the error on TCP socket and wake
|
||||
it up. If parse_msg returned -ESTRPIPE and the stream parser had
|
||||
previously read some bytes for the current message, then the error
|
||||
set on the attached socket is ENODATA since the stream is
|
||||
unrecoverable in that case.
|
||||
zero) and the parser is in receive callback mode, then it will set
|
||||
the error on TCP socket and wake it up. If parse_msg returned
|
||||
-ESTRPIPE and the stream parser had previously read some bytes for
|
||||
the current message, then the error set on the attached socket is
|
||||
ENODATA since the stream is unrecoverable in that case.
|
||||
|
||||
void (*lock)(struct strparser *strp)
|
||||
|
||||
The lock callback is called to lock the strp structure when
|
||||
the strparser is performing an asynchronous operation (such as
|
||||
processing a timeout). In receive callback mode the default
|
||||
function is to lock_sock for the associated socket. In general
|
||||
mode the callback must be set appropriately.
|
||||
|
||||
void (*unlock)(struct strparser *strp)
|
||||
|
||||
The unlock callback is called to release the lock obtained
|
||||
by the lock callback. In receive callback mode the default
|
||||
function is release_sock for the associated socket. In general
|
||||
mode the callback must be set appropriately.
|
||||
|
||||
void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
|
||||
|
||||
rcv_msg is called when a full message has been received and
|
||||
is queued. The callee must consume the sk_buff; it can
|
||||
call strp_pause to prevent any further messages from being
|
||||
received in rcv_msg (see strp_pause below). This callback
|
||||
received in rcv_msg (see strp_pause above). This callback
|
||||
must be set.
|
||||
|
||||
The skb->cb in the input skb is a struct strp_rx_msg. This
|
||||
The skb->cb in the input skb is a struct strp_msg. This
|
||||
struct contains two fields: offset and full_len. Offset is
|
||||
where the message starts in the skb, and full_len is the
|
||||
the length of the message. skb->len - offset may be greater
|
||||
@ -78,59 +155,53 @@ void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
|
||||
int (*read_sock_done)(struct strparser *strp, int err);
|
||||
|
||||
read_sock_done is called when the stream parser is done reading
|
||||
the TCP socket. The stream parser may read multiple messages
|
||||
in a loop and this function allows cleanup to occur when existing
|
||||
the loop. If the callback is not set (NULL in strp_init) a
|
||||
default function is used.
|
||||
the TCP socket in receive callback mode. The stream parser may
|
||||
read multiple messages in a loop and this function allows cleanup
|
||||
to occur when exiting the loop. If the callback is not set (NULL
|
||||
in strp_init) a default function is used.
|
||||
|
||||
void (*abort_parser)(struct strparser *strp, int err);
|
||||
|
||||
This function is called when stream parser encounters an error
|
||||
in parsing. The default function stops the stream parser for the
|
||||
TCP socket and sets the error in the socket. The default function
|
||||
can be changed by setting the callback to non-NULL in strp_init.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
The upper layer calls strp_tcp_data_ready when data is ready on the lower
|
||||
socket for strparser to process. This should be called from a data_ready
|
||||
callback that is set on the socket.
|
||||
|
||||
strp_stop is called to completely stop stream parser operations. This
|
||||
is called internally when the stream parser encounters an error, and
|
||||
it is called from the upper layer when unattaching a TCP socket.
|
||||
|
||||
strp_done is called to unattach the stream parser from the TCP socket.
|
||||
This must be called after the stream processor has be stopped.
|
||||
|
||||
strp_check_rcv is called to check for new messages on the socket. This
|
||||
is normally called at initialization of the a stream parser instance
|
||||
of after strp_unpause.
|
||||
in parsing. The default function stops the stream parser and
|
||||
sets the error in the socket if the parser is in receive callback
|
||||
mode. The default function can be changed by setting the callback
|
||||
to non-NULL in strp_init.
|
||||
|
||||
Statistics
|
||||
----------
|
||||
==========
|
||||
|
||||
Various counters are kept for each stream parser for a TCP socket.
|
||||
These are in the strp_stats structure. strp_aggr_stats is a convenience
|
||||
structure for accumulating statistics for multiple stream parser
|
||||
instances. save_strp_stats and aggregate_strp_stats are helper functions
|
||||
to save and aggregate statistics.
|
||||
Various counters are kept for each stream parser instance. These are in
|
||||
the strp_stats structure. strp_aggr_stats is a convenience structure for
|
||||
accumulating statistics for multiple stream parser instances.
|
||||
save_strp_stats and aggregate_strp_stats are helper functions to save
|
||||
and aggregate statistics.
|
||||
|
||||
Message assembly limits
|
||||
-----------------------
|
||||
=======================
|
||||
|
||||
The stream parser provide mechanisms to limit the resources consumed by
|
||||
message assembly.
|
||||
|
||||
A timer is set when assembly starts for a new message. The message
|
||||
timeout is taken from rcvtime for the associated TCP socket. If the
|
||||
timer fires before assembly completes the stream parser is aborted
|
||||
and the ETIMEDOUT error is set on the TCP socket.
|
||||
A timer is set when assembly starts for a new message. In receive
|
||||
callback mode the message timeout is taken from rcvtime for the
|
||||
associated TCP socket. In general mode, the timeout is passed as an
|
||||
argument in strp_process. If the timer fires before assembly completes
|
||||
the stream parser is aborted and the ETIMEDOUT error is set on the TCP
|
||||
socket if in receive callback mode.
|
||||
|
||||
In receive callback mode, message length is limited to the receive
|
||||
buffer size of the associated TCP socket. If the length returned by
|
||||
parse_msg is greater than the socket buffer size then the stream parser
|
||||
is aborted with EMSGSIZE error set on the TCP socket. Note that this
|
||||
makes the maximum size of receive skbuffs for a socket with a stream
|
||||
parser to be 2*sk_rcvbuf of the TCP socket.
|
||||
|
||||
In general mode the message length limit is passed in as an argument
|
||||
to strp_process.
|
||||
|
||||
Author
|
||||
======
|
||||
|
||||
Tom Herbert (tom@quantonium.net)
|
||||
|
||||
Message length is limited to the receive buffer size of the associated
|
||||
TCP socket. If the length returned by parse_msg is greater than
|
||||
the socket buffer size then the stream parser is aborted with
|
||||
EMSGSIZE error set on the TCP socket. Note that this makes the
|
||||
maximum size of receive skbuffs for a socket with a stream parser
|
||||
to be 2*sk_rcvbuf of the TCP socket.
|
||||
|
@ -46,13 +46,13 @@ translate these BPF proglets into native CPU instructions. There are
|
||||
two flavors of JITs, the newer eBPF JIT currently supported on:
|
||||
- x86_64
|
||||
- arm64
|
||||
- arm32
|
||||
- ppc64
|
||||
- sparc64
|
||||
- mips64
|
||||
- s390x
|
||||
|
||||
And the older cBPF JIT supported on the following archs:
|
||||
- arm
|
||||
- mips
|
||||
- ppc
|
||||
- sparc
|
||||
|
28
MAINTAINERS
28
MAINTAINERS
@ -2492,7 +2492,7 @@ Q: https://patchwork.open-mesh.org/project/batman/list/
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-class-net-batman-adv
|
||||
F: Documentation/ABI/testing/sysfs-class-net-mesh
|
||||
F: Documentation/networking/batman-adv.txt
|
||||
F: Documentation/networking/batman-adv.rst
|
||||
F: include/uapi/linux/batman_adv.h
|
||||
F: net/batman-adv/
|
||||
|
||||
@ -5136,6 +5136,7 @@ F: include/linux/of_net.h
|
||||
F: include/linux/phy.h
|
||||
F: include/linux/phy_fixed.h
|
||||
F: include/linux/platform_data/mdio-gpio.h
|
||||
F: include/linux/platform_data/mdio-bcm-unimac.h
|
||||
F: include/trace/events/mdio.h
|
||||
F: include/uapi/linux/mdio.h
|
||||
F: include/uapi/linux/mii.h
|
||||
@ -6183,6 +6184,14 @@ S: Maintained
|
||||
F: drivers/net/ethernet/hisilicon/
|
||||
F: Documentation/devicetree/bindings/net/hisilicon*.txt
|
||||
|
||||
HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
|
||||
M: Yisen Zhuang <yisen.zhuang@huawei.com>
|
||||
M: Salil Mehta <salil.mehta@huawei.com>
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://www.hisilicon.com
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/hisilicon/hns3/
|
||||
|
||||
HISILICON ROCE DRIVER
|
||||
M: Lijun Ou <oulijun@huawei.com>
|
||||
M: Wei Hu(Xavier) <xavier.huwei@huawei.com>
|
||||
@ -6267,6 +6276,13 @@ L: linux-input@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/input/touchscreen/htcpen.c
|
||||
|
||||
HUAWEI ETHERNET DRIVER
|
||||
M: Aviad Krawczyk <aviad.krawczyk@huawei.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/networking/hinic.txt
|
||||
F: drivers/net/ethernet/huawei/hinic/
|
||||
|
||||
HUGETLB FILESYSTEM
|
||||
M: Nadia Yvette Chambers <nyc@holomorphy.com>
|
||||
S: Maintained
|
||||
@ -6293,6 +6309,7 @@ M: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
M: Stephen Hemminger <sthemmin@microsoft.com>
|
||||
L: devel@linuxdriverproject.org
|
||||
S: Maintained
|
||||
F: Documentation/networking/netvsc.txt
|
||||
F: arch/x86/include/asm/mshyperv.h
|
||||
F: arch/x86/include/uapi/asm/hyperv.h
|
||||
F: arch/x86/kernel/cpu/mshyperv.c
|
||||
@ -6305,6 +6322,7 @@ F: drivers/net/hyperv/
|
||||
F: drivers/scsi/storvsc_drv.c
|
||||
F: drivers/uio/uio_hv_generic.c
|
||||
F: drivers/video/fbdev/hyperv_fb.c
|
||||
F: net/vmw_vsock/hyperv_transport.c
|
||||
F: include/linux/hyperv.h
|
||||
F: tools/hv/
|
||||
F: Documentation/ABI/stable/sysfs-bus-vmbus
|
||||
@ -7120,9 +7138,7 @@ W: http://irda.sourceforge.net/
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git
|
||||
F: Documentation/networking/irda.txt
|
||||
F: drivers/net/irda/
|
||||
F: include/net/irda/
|
||||
F: net/irda/
|
||||
F: drivers/staging/irda/
|
||||
|
||||
IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
|
||||
M: Marc Zyngier <marc.zyngier@arm.com>
|
||||
@ -8449,7 +8465,9 @@ F: include/uapi/linux/uvcvideo.h
|
||||
|
||||
MEDIATEK ETHERNET DRIVER
|
||||
M: Felix Fietkau <nbd@openwrt.org>
|
||||
M: John Crispin <blogic@openwrt.org>
|
||||
M: John Crispin <john@phrozen.org>
|
||||
M: Sean Wang <sean.wang@mediatek.com>
|
||||
M: Nelson Chang <nelson.chang@mediatek.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/mediatek/
|
||||
|
@ -109,4 +109,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _UAPI_ASM_SOCKET_H */
|
||||
|
@ -50,7 +50,7 @@ config ARM
|
||||
select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARM_SMCCC if CPU_V7
|
||||
select HAVE_CBPF_JIT
|
||||
select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32
|
||||
select HAVE_CC_STACKPROTECTOR
|
||||
select HAVE_CONTEXT_TRACKING
|
||||
select HAVE_C_RECORDMCOUNT
|
||||
|
@ -50,6 +50,16 @@
|
||||
device_type = "memory";
|
||||
reg = <0x60000000 0x40000000>;
|
||||
};
|
||||
|
||||
vcc_phy: vcc-phy-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-high;
|
||||
regulator-name = "vcc_phy";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
|
||||
&emmc {
|
||||
@ -60,6 +70,30 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gmac {
|
||||
assigned-clocks = <&cru SCLK_MAC_SRC>;
|
||||
assigned-clock-rates = <50000000>;
|
||||
clock_in_out = "output";
|
||||
phy-supply = <&vcc_phy>;
|
||||
phy-mode = "rmii";
|
||||
phy-handle = <&phy>;
|
||||
status = "okay";
|
||||
|
||||
mdio {
|
||||
compatible = "snps,dwmac-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy: phy@0 {
|
||||
compatible = "ethernet-phy-id1234.d400", "ethernet-phy-ieee802.3-c22";
|
||||
reg = <0>;
|
||||
clocks = <&cru SCLK_MAC_PHY>;
|
||||
resets = <&cru SRST_MACPHY>;
|
||||
phy-is-integrated;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&tsadc {
|
||||
status = "okay";
|
||||
|
||||
|
@ -270,6 +270,7 @@ CONFIG_ICPLUS_PHY=y
|
||||
CONFIG_REALTEK_PHY=y
|
||||
CONFIG_MICREL_PHY=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
CONFIG_ROCKCHIP_PHY=y
|
||||
CONFIG_USB_PEGASUS=y
|
||||
CONFIG_USB_RTL8152=m
|
||||
CONFIG_USB_USBNET=y
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,6 +11,7 @@
|
||||
#ifndef PFILTER_OPCODES_ARM_H
|
||||
#define PFILTER_OPCODES_ARM_H
|
||||
|
||||
/* ARM 32bit Registers */
|
||||
#define ARM_R0 0
|
||||
#define ARM_R1 1
|
||||
#define ARM_R2 2
|
||||
@ -22,38 +23,43 @@
|
||||
#define ARM_R8 8
|
||||
#define ARM_R9 9
|
||||
#define ARM_R10 10
|
||||
#define ARM_FP 11
|
||||
#define ARM_IP 12
|
||||
#define ARM_SP 13
|
||||
#define ARM_LR 14
|
||||
#define ARM_PC 15
|
||||
#define ARM_FP 11 /* Frame Pointer */
|
||||
#define ARM_IP 12 /* Intra-procedure scratch register */
|
||||
#define ARM_SP 13 /* Stack pointer: as load/store base reg */
|
||||
#define ARM_LR 14 /* Link Register */
|
||||
#define ARM_PC 15 /* Program counter */
|
||||
|
||||
#define ARM_COND_EQ 0x0
|
||||
#define ARM_COND_NE 0x1
|
||||
#define ARM_COND_CS 0x2
|
||||
#define ARM_COND_EQ 0x0 /* == */
|
||||
#define ARM_COND_NE 0x1 /* != */
|
||||
#define ARM_COND_CS 0x2 /* unsigned >= */
|
||||
#define ARM_COND_HS ARM_COND_CS
|
||||
#define ARM_COND_CC 0x3
|
||||
#define ARM_COND_CC 0x3 /* unsigned < */
|
||||
#define ARM_COND_LO ARM_COND_CC
|
||||
#define ARM_COND_MI 0x4
|
||||
#define ARM_COND_PL 0x5
|
||||
#define ARM_COND_VS 0x6
|
||||
#define ARM_COND_VC 0x7
|
||||
#define ARM_COND_HI 0x8
|
||||
#define ARM_COND_LS 0x9
|
||||
#define ARM_COND_GE 0xa
|
||||
#define ARM_COND_LT 0xb
|
||||
#define ARM_COND_GT 0xc
|
||||
#define ARM_COND_LE 0xd
|
||||
#define ARM_COND_AL 0xe
|
||||
#define ARM_COND_MI 0x4 /* < 0 */
|
||||
#define ARM_COND_PL 0x5 /* >= 0 */
|
||||
#define ARM_COND_VS 0x6 /* Signed Overflow */
|
||||
#define ARM_COND_VC 0x7 /* No Signed Overflow */
|
||||
#define ARM_COND_HI 0x8 /* unsigned > */
|
||||
#define ARM_COND_LS 0x9 /* unsigned <= */
|
||||
#define ARM_COND_GE 0xa /* Signed >= */
|
||||
#define ARM_COND_LT 0xb /* Signed < */
|
||||
#define ARM_COND_GT 0xc /* Signed > */
|
||||
#define ARM_COND_LE 0xd /* Signed <= */
|
||||
#define ARM_COND_AL 0xe /* None */
|
||||
|
||||
/* register shift types */
|
||||
#define SRTYPE_LSL 0
|
||||
#define SRTYPE_LSR 1
|
||||
#define SRTYPE_ASR 2
|
||||
#define SRTYPE_ROR 3
|
||||
#define SRTYPE_ASL (SRTYPE_LSL)
|
||||
|
||||
#define ARM_INST_ADD_R 0x00800000
|
||||
#define ARM_INST_ADDS_R 0x00900000
|
||||
#define ARM_INST_ADC_R 0x00a00000
|
||||
#define ARM_INST_ADC_I 0x02a00000
|
||||
#define ARM_INST_ADD_I 0x02800000
|
||||
#define ARM_INST_ADDS_I 0x02900000
|
||||
|
||||
#define ARM_INST_AND_R 0x00000000
|
||||
#define ARM_INST_AND_I 0x02000000
|
||||
@ -76,8 +82,10 @@
|
||||
#define ARM_INST_LDRH_I 0x01d000b0
|
||||
#define ARM_INST_LDRH_R 0x019000b0
|
||||
#define ARM_INST_LDR_I 0x05900000
|
||||
#define ARM_INST_LDR_R 0x07900000
|
||||
|
||||
#define ARM_INST_LDM 0x08900000
|
||||
#define ARM_INST_LDM_IA 0x08b00000
|
||||
|
||||
#define ARM_INST_LSL_I 0x01a00000
|
||||
#define ARM_INST_LSL_R 0x01a00010
|
||||
@ -86,6 +94,7 @@
|
||||
#define ARM_INST_LSR_R 0x01a00030
|
||||
|
||||
#define ARM_INST_MOV_R 0x01a00000
|
||||
#define ARM_INST_MOVS_R 0x01b00000
|
||||
#define ARM_INST_MOV_I 0x03a00000
|
||||
#define ARM_INST_MOVW 0x03000000
|
||||
#define ARM_INST_MOVT 0x03400000
|
||||
@ -96,17 +105,28 @@
|
||||
#define ARM_INST_PUSH 0x092d0000
|
||||
|
||||
#define ARM_INST_ORR_R 0x01800000
|
||||
#define ARM_INST_ORRS_R 0x01900000
|
||||
#define ARM_INST_ORR_I 0x03800000
|
||||
|
||||
#define ARM_INST_REV 0x06bf0f30
|
||||
#define ARM_INST_REV16 0x06bf0fb0
|
||||
|
||||
#define ARM_INST_RSB_I 0x02600000
|
||||
#define ARM_INST_RSBS_I 0x02700000
|
||||
#define ARM_INST_RSC_I 0x02e00000
|
||||
|
||||
#define ARM_INST_SUB_R 0x00400000
|
||||
#define ARM_INST_SUBS_R 0x00500000
|
||||
#define ARM_INST_RSB_R 0x00600000
|
||||
#define ARM_INST_SUB_I 0x02400000
|
||||
#define ARM_INST_SUBS_I 0x02500000
|
||||
#define ARM_INST_SBC_I 0x02c00000
|
||||
#define ARM_INST_SBC_R 0x00c00000
|
||||
#define ARM_INST_SBCS_R 0x00d00000
|
||||
|
||||
#define ARM_INST_STR_I 0x05800000
|
||||
#define ARM_INST_STRB_I 0x05c00000
|
||||
#define ARM_INST_STRH_I 0x01c000b0
|
||||
|
||||
#define ARM_INST_TST_R 0x01100000
|
||||
#define ARM_INST_TST_I 0x03100000
|
||||
@ -117,6 +137,8 @@
|
||||
|
||||
#define ARM_INST_MLS 0x00600090
|
||||
|
||||
#define ARM_INST_UXTH 0x06ff0070
|
||||
|
||||
/*
|
||||
* Use a suitable undefined instruction to use for ARM/Thumb2 faulting.
|
||||
* We need to be careful not to conflict with those used by other modules
|
||||
@ -135,9 +157,15 @@
|
||||
#define _AL3_R(op, rd, rn, rm) ((op ## _R) | (rd) << 12 | (rn) << 16 | (rm))
|
||||
/* immediate */
|
||||
#define _AL3_I(op, rd, rn, imm) ((op ## _I) | (rd) << 12 | (rn) << 16 | (imm))
|
||||
/* register with register-shift */
|
||||
#define _AL3_SR(inst) (inst | (1 << 4))
|
||||
|
||||
#define ARM_ADD_R(rd, rn, rm) _AL3_R(ARM_INST_ADD, rd, rn, rm)
|
||||
#define ARM_ADDS_R(rd, rn, rm) _AL3_R(ARM_INST_ADDS, rd, rn, rm)
|
||||
#define ARM_ADD_I(rd, rn, imm) _AL3_I(ARM_INST_ADD, rd, rn, imm)
|
||||
#define ARM_ADDS_I(rd, rn, imm) _AL3_I(ARM_INST_ADDS, rd, rn, imm)
|
||||
#define ARM_ADC_R(rd, rn, rm) _AL3_R(ARM_INST_ADC, rd, rn, rm)
|
||||
#define ARM_ADC_I(rd, rn, imm) _AL3_I(ARM_INST_ADC, rd, rn, imm)
|
||||
|
||||
#define ARM_AND_R(rd, rn, rm) _AL3_R(ARM_INST_AND, rd, rn, rm)
|
||||
#define ARM_AND_I(rd, rn, imm) _AL3_I(ARM_INST_AND, rd, rn, imm)
|
||||
@ -156,7 +184,9 @@
|
||||
#define ARM_EOR_I(rd, rn, imm) _AL3_I(ARM_INST_EOR, rd, rn, imm)
|
||||
|
||||
#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
|
||||
| (off))
|
||||
| ((off) & 0xfff))
|
||||
#define ARM_LDR_R(rt, rn, rm) (ARM_INST_LDR_R | (rt) << 12 | (rn) << 16 \
|
||||
| (rm))
|
||||
#define ARM_LDRB_I(rt, rn, off) (ARM_INST_LDRB_I | (rt) << 12 | (rn) << 16 \
|
||||
| (off))
|
||||
#define ARM_LDRB_R(rt, rn, rm) (ARM_INST_LDRB_R | (rt) << 12 | (rn) << 16 \
|
||||
@ -167,15 +197,23 @@
|
||||
| (rm))
|
||||
|
||||
#define ARM_LDM(rn, regs) (ARM_INST_LDM | (rn) << 16 | (regs))
|
||||
#define ARM_LDM_IA(rn, regs) (ARM_INST_LDM_IA | (rn) << 16 | (regs))
|
||||
|
||||
#define ARM_LSL_R(rd, rn, rm) (_AL3_R(ARM_INST_LSL, rd, 0, rn) | (rm) << 8)
|
||||
#define ARM_LSL_I(rd, rn, imm) (_AL3_I(ARM_INST_LSL, rd, 0, rn) | (imm) << 7)
|
||||
|
||||
#define ARM_LSR_R(rd, rn, rm) (_AL3_R(ARM_INST_LSR, rd, 0, rn) | (rm) << 8)
|
||||
#define ARM_LSR_I(rd, rn, imm) (_AL3_I(ARM_INST_LSR, rd, 0, rn) | (imm) << 7)
|
||||
#define ARM_ASR_R(rd, rn, rm) (_AL3_R(ARM_INST_ASR, rd, 0, rn) | (rm) << 8)
|
||||
#define ARM_ASR_I(rd, rn, imm) (_AL3_I(ARM_INST_ASR, rd, 0, rn) | (imm) << 7)
|
||||
|
||||
#define ARM_MOV_R(rd, rm) _AL3_R(ARM_INST_MOV, rd, 0, rm)
|
||||
#define ARM_MOVS_R(rd, rm) _AL3_R(ARM_INST_MOVS, rd, 0, rm)
|
||||
#define ARM_MOV_I(rd, imm) _AL3_I(ARM_INST_MOV, rd, 0, imm)
|
||||
#define ARM_MOV_SR(rd, rm, type, rs) \
|
||||
(_AL3_SR(ARM_MOV_R(rd, rm)) | (type) << 5 | (rs) << 8)
|
||||
#define ARM_MOV_SI(rd, rm, type, imm6) \
|
||||
(ARM_MOV_R(rd, rm) | (type) << 5 | (imm6) << 7)
|
||||
|
||||
#define ARM_MOVW(rd, imm) \
|
||||
(ARM_INST_MOVW | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff))
|
||||
@ -190,19 +228,38 @@
|
||||
|
||||
#define ARM_ORR_R(rd, rn, rm) _AL3_R(ARM_INST_ORR, rd, rn, rm)
|
||||
#define ARM_ORR_I(rd, rn, imm) _AL3_I(ARM_INST_ORR, rd, rn, imm)
|
||||
#define ARM_ORR_S(rd, rn, rm, type, rs) \
|
||||
(ARM_ORR_R(rd, rn, rm) | (type) << 5 | (rs) << 7)
|
||||
#define ARM_ORR_SR(rd, rn, rm, type, rs) \
|
||||
(_AL3_SR(ARM_ORR_R(rd, rn, rm)) | (type) << 5 | (rs) << 8)
|
||||
#define ARM_ORRS_R(rd, rn, rm) _AL3_R(ARM_INST_ORRS, rd, rn, rm)
|
||||
#define ARM_ORRS_SR(rd, rn, rm, type, rs) \
|
||||
(_AL3_SR(ARM_ORRS_R(rd, rn, rm)) | (type) << 5 | (rs) << 8)
|
||||
#define ARM_ORR_SI(rd, rn, rm, type, imm6) \
|
||||
(ARM_ORR_R(rd, rn, rm) | (type) << 5 | (imm6) << 7)
|
||||
#define ARM_ORRS_SI(rd, rn, rm, type, imm6) \
|
||||
(ARM_ORRS_R(rd, rn, rm) | (type) << 5 | (imm6) << 7)
|
||||
|
||||
#define ARM_REV(rd, rm) (ARM_INST_REV | (rd) << 12 | (rm))
|
||||
#define ARM_REV16(rd, rm) (ARM_INST_REV16 | (rd) << 12 | (rm))
|
||||
|
||||
#define ARM_RSB_I(rd, rn, imm) _AL3_I(ARM_INST_RSB, rd, rn, imm)
|
||||
#define ARM_RSBS_I(rd, rn, imm) _AL3_I(ARM_INST_RSBS, rd, rn, imm)
|
||||
#define ARM_RSC_I(rd, rn, imm) _AL3_I(ARM_INST_RSC, rd, rn, imm)
|
||||
|
||||
#define ARM_SUB_R(rd, rn, rm) _AL3_R(ARM_INST_SUB, rd, rn, rm)
|
||||
#define ARM_SUBS_R(rd, rn, rm) _AL3_R(ARM_INST_SUBS, rd, rn, rm)
|
||||
#define ARM_RSB_R(rd, rn, rm) _AL3_R(ARM_INST_RSB, rd, rn, rm)
|
||||
#define ARM_SBC_R(rd, rn, rm) _AL3_R(ARM_INST_SBC, rd, rn, rm)
|
||||
#define ARM_SBCS_R(rd, rn, rm) _AL3_R(ARM_INST_SBCS, rd, rn, rm)
|
||||
#define ARM_SUB_I(rd, rn, imm) _AL3_I(ARM_INST_SUB, rd, rn, imm)
|
||||
#define ARM_SUBS_I(rd, rn, imm) _AL3_I(ARM_INST_SUBS, rd, rn, imm)
|
||||
#define ARM_SBC_I(rd, rn, imm) _AL3_I(ARM_INST_SBC, rd, rn, imm)
|
||||
|
||||
#define ARM_STR_I(rt, rn, off) (ARM_INST_STR_I | (rt) << 12 | (rn) << 16 \
|
||||
| (off))
|
||||
| ((off) & 0xfff))
|
||||
#define ARM_STRH_I(rt, rn, off) (ARM_INST_STRH_I | (rt) << 12 | (rn) << 16 \
|
||||
| (((off) & 0xf0) << 4) | ((off) & 0xf))
|
||||
#define ARM_STRB_I(rt, rn, off) (ARM_INST_STRB_I | (rt) << 12 | (rn) << 16 \
|
||||
| (((off) & 0xf0) << 4) | ((off) & 0xf))
|
||||
|
||||
#define ARM_TST_R(rn, rm) _AL3_R(ARM_INST_TST, 0, rn, rm)
|
||||
#define ARM_TST_I(rn, imm) _AL3_I(ARM_INST_TST, 0, rn, imm)
|
||||
@ -214,5 +271,6 @@
|
||||
|
||||
#define ARM_MLS(rd, rn, rm, ra) (ARM_INST_MLS | (rd) << 16 | (rn) | (rm) << 8 \
|
||||
| (ra) << 12)
|
||||
#define ARM_UXTH(rd, rm) (ARM_INST_UXTH | (rd) << 12 | (rm))
|
||||
|
||||
#endif /* PFILTER_OPCODES_ARM_H */
|
||||
|
@ -50,6 +50,23 @@
|
||||
chosen {
|
||||
stdout-path = "serial2:1500000n8";
|
||||
};
|
||||
|
||||
vcc_phy: vcc-phy-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_phy";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
|
||||
&gmac2phy {
|
||||
phy-supply = <&vcc_phy>;
|
||||
clock_in_out = "output";
|
||||
assigned-clocks = <&cru SCLK_MAC2PHY_SRC>;
|
||||
assigned-clock-rate = <50000000>;
|
||||
assigned-clocks = <&cru SCLK_MAC2PHY>;
|
||||
assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
|
@ -63,6 +63,8 @@
|
||||
i2c1 = &i2c1;
|
||||
i2c2 = &i2c2;
|
||||
i2c3 = &i2c3;
|
||||
ethernet0 = &gmac2io;
|
||||
ethernet1 = &gmac2phy;
|
||||
};
|
||||
|
||||
cpus {
|
||||
@ -424,6 +426,43 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac2phy: ethernet@ff550000 {
|
||||
compatible = "rockchip,rk3328-gmac";
|
||||
reg = <0x0 0xff550000 0x0 0x10000>;
|
||||
rockchip,grf = <&grf>;
|
||||
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "macirq";
|
||||
clocks = <&cru SCLK_MAC2PHY_SRC>, <&cru SCLK_MAC2PHY_RXTX>,
|
||||
<&cru SCLK_MAC2PHY_RXTX>, <&cru SCLK_MAC2PHY_REF>,
|
||||
<&cru ACLK_MAC2PHY>, <&cru PCLK_MAC2PHY>,
|
||||
<&cru SCLK_MAC2PHY_OUT>;
|
||||
clock-names = "stmmaceth", "mac_clk_rx",
|
||||
"mac_clk_tx", "clk_mac_ref",
|
||||
"aclk_mac", "pclk_mac",
|
||||
"clk_macphy";
|
||||
resets = <&cru SRST_GMAC2PHY_A>, <&cru SRST_MACPHY>;
|
||||
reset-names = "stmmaceth", "mac-phy";
|
||||
phy-mode = "rmii";
|
||||
phy-handle = <&phy>;
|
||||
status = "disabled";
|
||||
|
||||
mdio {
|
||||
compatible = "snps,dwmac-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy: phy@0 {
|
||||
compatible = "ethernet-phy-id1234.d400", "ethernet-phy-ieee802.3-c22";
|
||||
reg = <0>;
|
||||
clocks = <&cru SCLK_MAC2PHY_OUT>;
|
||||
resets = <&cru SRST_MACPHY>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&fephyled_rxm1 &fephyled_linkm1>;
|
||||
phy-is-integrated;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gic: interrupt-controller@ff811000 {
|
||||
compatible = "arm,gic-400";
|
||||
#interrupt-cells = <3>;
|
||||
|
@ -203,6 +203,7 @@ CONFIG_MARVELL_PHY=m
|
||||
CONFIG_MESON_GXL_PHY=m
|
||||
CONFIG_MICREL_PHY=y
|
||||
CONFIG_REALTEK_PHY=m
|
||||
CONFIG_ROCKCHIP_PHY=y
|
||||
CONFIG_USB_PEGASUS=m
|
||||
CONFIG_USB_RTL8150=m
|
||||
CONFIG_USB_RTL8152=m
|
||||
|
@ -44,8 +44,12 @@
|
||||
#define A64_COND_NE AARCH64_INSN_COND_NE /* != */
|
||||
#define A64_COND_CS AARCH64_INSN_COND_CS /* unsigned >= */
|
||||
#define A64_COND_HI AARCH64_INSN_COND_HI /* unsigned > */
|
||||
#define A64_COND_LS AARCH64_INSN_COND_LS /* unsigned <= */
|
||||
#define A64_COND_CC AARCH64_INSN_COND_CC /* unsigned < */
|
||||
#define A64_COND_GE AARCH64_INSN_COND_GE /* signed >= */
|
||||
#define A64_COND_GT AARCH64_INSN_COND_GT /* signed > */
|
||||
#define A64_COND_LE AARCH64_INSN_COND_LE /* signed <= */
|
||||
#define A64_COND_LT AARCH64_INSN_COND_LT /* signed < */
|
||||
#define A64_B_(cond, imm19) A64_COND_BRANCH(cond, (imm19) << 2)
|
||||
|
||||
/* Unconditional branch (immediate) */
|
||||
|
@ -527,10 +527,14 @@ emit_bswap_uxt:
|
||||
/* IF (dst COND src) JUMP off */
|
||||
case BPF_JMP | BPF_JEQ | BPF_X:
|
||||
case BPF_JMP | BPF_JGT | BPF_X:
|
||||
case BPF_JMP | BPF_JLT | BPF_X:
|
||||
case BPF_JMP | BPF_JGE | BPF_X:
|
||||
case BPF_JMP | BPF_JLE | BPF_X:
|
||||
case BPF_JMP | BPF_JNE | BPF_X:
|
||||
case BPF_JMP | BPF_JSGT | BPF_X:
|
||||
case BPF_JMP | BPF_JSLT | BPF_X:
|
||||
case BPF_JMP | BPF_JSGE | BPF_X:
|
||||
case BPF_JMP | BPF_JSLE | BPF_X:
|
||||
emit(A64_CMP(1, dst, src), ctx);
|
||||
emit_cond_jmp:
|
||||
jmp_offset = bpf2a64_offset(i + off, i, ctx);
|
||||
@ -542,9 +546,15 @@ emit_cond_jmp:
|
||||
case BPF_JGT:
|
||||
jmp_cond = A64_COND_HI;
|
||||
break;
|
||||
case BPF_JLT:
|
||||
jmp_cond = A64_COND_CC;
|
||||
break;
|
||||
case BPF_JGE:
|
||||
jmp_cond = A64_COND_CS;
|
||||
break;
|
||||
case BPF_JLE:
|
||||
jmp_cond = A64_COND_LS;
|
||||
break;
|
||||
case BPF_JSET:
|
||||
case BPF_JNE:
|
||||
jmp_cond = A64_COND_NE;
|
||||
@ -552,9 +562,15 @@ emit_cond_jmp:
|
||||
case BPF_JSGT:
|
||||
jmp_cond = A64_COND_GT;
|
||||
break;
|
||||
case BPF_JSLT:
|
||||
jmp_cond = A64_COND_LT;
|
||||
break;
|
||||
case BPF_JSGE:
|
||||
jmp_cond = A64_COND_GE;
|
||||
break;
|
||||
case BPF_JSLE:
|
||||
jmp_cond = A64_COND_LE;
|
||||
break;
|
||||
default:
|
||||
return -EFAULT;
|
||||
}
|
||||
@ -566,10 +582,14 @@ emit_cond_jmp:
|
||||
/* IF (dst COND imm) JUMP off */
|
||||
case BPF_JMP | BPF_JEQ | BPF_K:
|
||||
case BPF_JMP | BPF_JGT | BPF_K:
|
||||
case BPF_JMP | BPF_JLT | BPF_K:
|
||||
case BPF_JMP | BPF_JGE | BPF_K:
|
||||
case BPF_JMP | BPF_JLE | BPF_K:
|
||||
case BPF_JMP | BPF_JNE | BPF_K:
|
||||
case BPF_JMP | BPF_JSGT | BPF_K:
|
||||
case BPF_JMP | BPF_JSLT | BPF_K:
|
||||
case BPF_JMP | BPF_JSGE | BPF_K:
|
||||
case BPF_JMP | BPF_JSLE | BPF_K:
|
||||
emit_a64_mov_i(1, tmp, imm, ctx);
|
||||
emit(A64_CMP(1, dst, tmp), ctx);
|
||||
goto emit_cond_jmp;
|
||||
|
@ -102,5 +102,7 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
@ -111,4 +111,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _ASM_IA64_SOCKET_H */
|
||||
|
@ -102,4 +102,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _ASM_M32R_SOCKET_H */
|
||||
|
@ -120,4 +120,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _UAPI_ASM_SOCKET_H */
|
||||
|
@ -113,6 +113,7 @@ struct jit_ctx {
|
||||
u64 *reg_val_types;
|
||||
unsigned int long_b_conversion:1;
|
||||
unsigned int gen_b_offsets:1;
|
||||
unsigned int use_bbit_insns:1;
|
||||
};
|
||||
|
||||
static void set_reg_val_type(u64 *rvt, int reg, enum reg_val_type type)
|
||||
@ -655,19 +656,6 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int this_idx)
|
||||
return build_int_epilogue(ctx, MIPS_R_T9);
|
||||
}
|
||||
|
||||
static bool use_bbit_insns(void)
|
||||
{
|
||||
switch (current_cpu_type()) {
|
||||
case CPU_CAVIUM_OCTEON:
|
||||
case CPU_CAVIUM_OCTEON_PLUS:
|
||||
case CPU_CAVIUM_OCTEON2:
|
||||
case CPU_CAVIUM_OCTEON3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_bad_offset(int b_off)
|
||||
{
|
||||
return b_off > 0x1ffff || b_off < -0x20000;
|
||||
@ -682,6 +670,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
unsigned int target;
|
||||
u64 t64;
|
||||
s64 t64s;
|
||||
int bpf_op = BPF_OP(insn->code);
|
||||
|
||||
switch (insn->code) {
|
||||
case BPF_ALU64 | BPF_ADD | BPF_K: /* ALU64_IMM */
|
||||
@ -770,13 +759,13 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
emit_instr(ctx, sll, dst, dst, 0);
|
||||
if (insn->imm == 1) {
|
||||
/* div by 1 is a nop, mod by 1 is zero */
|
||||
if (BPF_OP(insn->code) == BPF_MOD)
|
||||
if (bpf_op == BPF_MOD)
|
||||
emit_instr(ctx, addu, dst, MIPS_R_ZERO, MIPS_R_ZERO);
|
||||
break;
|
||||
}
|
||||
gen_imm_to_reg(insn, MIPS_R_AT, ctx);
|
||||
emit_instr(ctx, divu, dst, MIPS_R_AT);
|
||||
if (BPF_OP(insn->code) == BPF_DIV)
|
||||
if (bpf_op == BPF_DIV)
|
||||
emit_instr(ctx, mflo, dst);
|
||||
else
|
||||
emit_instr(ctx, mfhi, dst);
|
||||
@ -798,13 +787,13 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
|
||||
if (insn->imm == 1) {
|
||||
/* div by 1 is a nop, mod by 1 is zero */
|
||||
if (BPF_OP(insn->code) == BPF_MOD)
|
||||
if (bpf_op == BPF_MOD)
|
||||
emit_instr(ctx, addu, dst, MIPS_R_ZERO, MIPS_R_ZERO);
|
||||
break;
|
||||
}
|
||||
gen_imm_to_reg(insn, MIPS_R_AT, ctx);
|
||||
emit_instr(ctx, ddivu, dst, MIPS_R_AT);
|
||||
if (BPF_OP(insn->code) == BPF_DIV)
|
||||
if (bpf_op == BPF_DIV)
|
||||
emit_instr(ctx, mflo, dst);
|
||||
else
|
||||
emit_instr(ctx, mfhi, dst);
|
||||
@ -829,7 +818,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
emit_instr(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32);
|
||||
did_move = false;
|
||||
if (insn->src_reg == BPF_REG_10) {
|
||||
if (BPF_OP(insn->code) == BPF_MOV) {
|
||||
if (bpf_op == BPF_MOV) {
|
||||
emit_instr(ctx, daddiu, dst, MIPS_R_SP, MAX_BPF_STACK);
|
||||
did_move = true;
|
||||
} else {
|
||||
@ -839,7 +828,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
} else if (get_reg_val_type(ctx, this_idx, insn->src_reg) == REG_32BIT) {
|
||||
int tmp_reg = MIPS_R_AT;
|
||||
|
||||
if (BPF_OP(insn->code) == BPF_MOV) {
|
||||
if (bpf_op == BPF_MOV) {
|
||||
tmp_reg = dst;
|
||||
did_move = true;
|
||||
}
|
||||
@ -847,7 +836,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
emit_instr(ctx, dinsu, tmp_reg, MIPS_R_ZERO, 32, 32);
|
||||
src = MIPS_R_AT;
|
||||
}
|
||||
switch (BPF_OP(insn->code)) {
|
||||
switch (bpf_op) {
|
||||
case BPF_MOV:
|
||||
if (!did_move)
|
||||
emit_instr(ctx, daddu, dst, src, MIPS_R_ZERO);
|
||||
@ -879,7 +868,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
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(insn->code) == BPF_DIV)
|
||||
if (bpf_op == BPF_DIV)
|
||||
emit_instr(ctx, mflo, dst);
|
||||
else
|
||||
emit_instr(ctx, mfhi, dst);
|
||||
@ -923,7 +912,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
if (ts == REG_64BIT || ts == REG_32BIT_ZERO_EX) {
|
||||
int tmp_reg = MIPS_R_AT;
|
||||
|
||||
if (BPF_OP(insn->code) == BPF_MOV) {
|
||||
if (bpf_op == BPF_MOV) {
|
||||
tmp_reg = dst;
|
||||
did_move = true;
|
||||
}
|
||||
@ -931,7 +920,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
emit_instr(ctx, sll, tmp_reg, src, 0);
|
||||
src = MIPS_R_AT;
|
||||
}
|
||||
switch (BPF_OP(insn->code)) {
|
||||
switch (bpf_op) {
|
||||
case BPF_MOV:
|
||||
if (!did_move)
|
||||
emit_instr(ctx, addu, dst, src, MIPS_R_ZERO);
|
||||
@ -962,7 +951,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
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(insn->code) == BPF_DIV)
|
||||
if (bpf_op == BPF_DIV)
|
||||
emit_instr(ctx, mflo, dst);
|
||||
else
|
||||
emit_instr(ctx, mfhi, dst);
|
||||
@ -989,7 +978,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
break;
|
||||
case BPF_JMP | BPF_JEQ | BPF_K: /* JMP_IMM */
|
||||
case BPF_JMP | BPF_JNE | BPF_K: /* JMP_IMM */
|
||||
cmp_eq = (BPF_OP(insn->code) == BPF_JEQ);
|
||||
cmp_eq = (bpf_op == BPF_JEQ);
|
||||
dst = ebpf_to_mips_reg(ctx, insn, dst_reg_fp_ok);
|
||||
if (dst < 0)
|
||||
return dst;
|
||||
@ -1002,8 +991,12 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
goto jeq_common;
|
||||
case BPF_JMP | BPF_JEQ | BPF_X: /* JMP_REG */
|
||||
case BPF_JMP | BPF_JNE | BPF_X:
|
||||
case BPF_JMP | BPF_JSLT | BPF_X:
|
||||
case BPF_JMP | BPF_JSLE | BPF_X:
|
||||
case BPF_JMP | BPF_JSGT | BPF_X:
|
||||
case BPF_JMP | BPF_JSGE | BPF_X:
|
||||
case BPF_JMP | BPF_JLT | BPF_X:
|
||||
case BPF_JMP | BPF_JLE | BPF_X:
|
||||
case BPF_JMP | BPF_JGT | BPF_X:
|
||||
case BPF_JMP | BPF_JGE | BPF_X:
|
||||
case BPF_JMP | BPF_JSET | BPF_X:
|
||||
@ -1020,33 +1013,39 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
emit_instr(ctx, sll, MIPS_R_AT, dst, 0);
|
||||
dst = MIPS_R_AT;
|
||||
}
|
||||
if (BPF_OP(insn->code) == BPF_JSET) {
|
||||
if (bpf_op == BPF_JSET) {
|
||||
emit_instr(ctx, and, MIPS_R_AT, dst, src);
|
||||
cmp_eq = false;
|
||||
dst = MIPS_R_AT;
|
||||
src = MIPS_R_ZERO;
|
||||
} else if (BPF_OP(insn->code) == BPF_JSGT) {
|
||||
} else if (bpf_op == BPF_JSGT || bpf_op == BPF_JSLE) {
|
||||
emit_instr(ctx, dsubu, MIPS_R_AT, dst, src);
|
||||
if ((insn + 1)->code == (BPF_JMP | BPF_EXIT) && insn->off == 1) {
|
||||
b_off = b_imm(exit_idx, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
emit_instr(ctx, blez, MIPS_R_AT, b_off);
|
||||
if (bpf_op == BPF_JSGT)
|
||||
emit_instr(ctx, blez, MIPS_R_AT, b_off);
|
||||
else
|
||||
emit_instr(ctx, bgtz, MIPS_R_AT, b_off);
|
||||
emit_instr(ctx, nop);
|
||||
return 2; /* We consumed the exit. */
|
||||
}
|
||||
b_off = b_imm(this_idx + insn->off + 1, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
emit_instr(ctx, bgtz, MIPS_R_AT, b_off);
|
||||
if (bpf_op == BPF_JSGT)
|
||||
emit_instr(ctx, bgtz, MIPS_R_AT, b_off);
|
||||
else
|
||||
emit_instr(ctx, blez, MIPS_R_AT, b_off);
|
||||
emit_instr(ctx, nop);
|
||||
break;
|
||||
} else if (BPF_OP(insn->code) == BPF_JSGE) {
|
||||
} else if (bpf_op == BPF_JSGE || bpf_op == BPF_JSLT) {
|
||||
emit_instr(ctx, slt, MIPS_R_AT, dst, src);
|
||||
cmp_eq = true;
|
||||
cmp_eq = bpf_op == BPF_JSGE;
|
||||
dst = MIPS_R_AT;
|
||||
src = MIPS_R_ZERO;
|
||||
} else if (BPF_OP(insn->code) == BPF_JGT) {
|
||||
} else if (bpf_op == BPF_JGT || bpf_op == BPF_JLE) {
|
||||
/* dst or src could be AT */
|
||||
emit_instr(ctx, dsubu, MIPS_R_T8, dst, src);
|
||||
emit_instr(ctx, sltu, MIPS_R_AT, dst, src);
|
||||
@ -1054,16 +1053,16 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
||||
emit_instr(ctx, movz, MIPS_R_T9, MIPS_R_SP, MIPS_R_T8);
|
||||
emit_instr(ctx, movn, MIPS_R_T9, MIPS_R_ZERO, MIPS_R_T8);
|
||||
emit_instr(ctx, or, MIPS_R_AT, MIPS_R_T9, MIPS_R_AT);
|
||||
cmp_eq = true;
|
||||
cmp_eq = bpf_op == BPF_JGT;
|
||||
dst = MIPS_R_AT;
|
||||
src = MIPS_R_ZERO;
|
||||
} else if (BPF_OP(insn->code) == BPF_JGE) {
|
||||
} else if (bpf_op == BPF_JGE || bpf_op == BPF_JLT) {
|
||||
emit_instr(ctx, sltu, MIPS_R_AT, dst, src);
|
||||
cmp_eq = true;
|
||||
cmp_eq = bpf_op == BPF_JGE;
|
||||
dst = MIPS_R_AT;
|
||||
src = MIPS_R_ZERO;
|
||||
} else { /* JNE/JEQ case */
|
||||
cmp_eq = (BPF_OP(insn->code) == BPF_JEQ);
|
||||
cmp_eq = (bpf_op == BPF_JEQ);
|
||||
}
|
||||
jeq_common:
|
||||
/*
|
||||
@ -1122,7 +1121,9 @@ jeq_common:
|
||||
break;
|
||||
case BPF_JMP | BPF_JSGT | BPF_K: /* JMP_IMM */
|
||||
case BPF_JMP | BPF_JSGE | BPF_K: /* JMP_IMM */
|
||||
cmp_eq = (BPF_OP(insn->code) == BPF_JSGE);
|
||||
case BPF_JMP | BPF_JSLT | BPF_K: /* JMP_IMM */
|
||||
case BPF_JMP | BPF_JSLE | BPF_K: /* JMP_IMM */
|
||||
cmp_eq = (bpf_op == BPF_JSGE);
|
||||
dst = ebpf_to_mips_reg(ctx, insn, dst_reg_fp_ok);
|
||||
if (dst < 0)
|
||||
return dst;
|
||||
@ -1132,65 +1133,92 @@ jeq_common:
|
||||
b_off = b_imm(exit_idx, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
if (cmp_eq)
|
||||
emit_instr(ctx, bltz, dst, b_off);
|
||||
else
|
||||
switch (bpf_op) {
|
||||
case BPF_JSGT:
|
||||
emit_instr(ctx, blez, dst, b_off);
|
||||
break;
|
||||
case BPF_JSGE:
|
||||
emit_instr(ctx, bltz, dst, b_off);
|
||||
break;
|
||||
case BPF_JSLT:
|
||||
emit_instr(ctx, bgez, dst, b_off);
|
||||
break;
|
||||
case BPF_JSLE:
|
||||
emit_instr(ctx, bgtz, dst, b_off);
|
||||
break;
|
||||
}
|
||||
emit_instr(ctx, nop);
|
||||
return 2; /* We consumed the exit. */
|
||||
}
|
||||
b_off = b_imm(this_idx + insn->off + 1, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
return -E2BIG;
|
||||
if (cmp_eq)
|
||||
emit_instr(ctx, bgez, dst, b_off);
|
||||
else
|
||||
switch (bpf_op) {
|
||||
case BPF_JSGT:
|
||||
emit_instr(ctx, bgtz, dst, b_off);
|
||||
break;
|
||||
case BPF_JSGE:
|
||||
emit_instr(ctx, bgez, dst, b_off);
|
||||
break;
|
||||
case BPF_JSLT:
|
||||
emit_instr(ctx, bltz, dst, b_off);
|
||||
break;
|
||||
case BPF_JSLE:
|
||||
emit_instr(ctx, blez, dst, b_off);
|
||||
break;
|
||||
}
|
||||
emit_instr(ctx, nop);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* only "LT" compare available, so we must use imm + 1
|
||||
* to generate "GT"
|
||||
* to generate "GT" and imm -1 to generate LE
|
||||
*/
|
||||
t64s = insn->imm + (cmp_eq ? 0 : 1);
|
||||
if (bpf_op == BPF_JSGT)
|
||||
t64s = insn->imm + 1;
|
||||
else if (bpf_op == BPF_JSLE)
|
||||
t64s = insn->imm + 1;
|
||||
else
|
||||
t64s = insn->imm;
|
||||
|
||||
cmp_eq = bpf_op == BPF_JSGT || bpf_op == BPF_JSGE;
|
||||
if (t64s >= S16_MIN && t64s <= S16_MAX) {
|
||||
emit_instr(ctx, slti, MIPS_R_AT, dst, (int)t64s);
|
||||
src = MIPS_R_AT;
|
||||
dst = MIPS_R_ZERO;
|
||||
cmp_eq = true;
|
||||
goto jeq_common;
|
||||
}
|
||||
emit_const_to_reg(ctx, MIPS_R_AT, (u64)t64s);
|
||||
emit_instr(ctx, slt, MIPS_R_AT, dst, MIPS_R_AT);
|
||||
src = MIPS_R_AT;
|
||||
dst = MIPS_R_ZERO;
|
||||
cmp_eq = true;
|
||||
goto jeq_common;
|
||||
|
||||
case BPF_JMP | BPF_JGT | BPF_K:
|
||||
case BPF_JMP | BPF_JGE | BPF_K:
|
||||
cmp_eq = (BPF_OP(insn->code) == BPF_JGE);
|
||||
case BPF_JMP | BPF_JLT | BPF_K:
|
||||
case BPF_JMP | BPF_JLE | BPF_K:
|
||||
cmp_eq = (bpf_op == BPF_JGE);
|
||||
dst = ebpf_to_mips_reg(ctx, insn, dst_reg_fp_ok);
|
||||
if (dst < 0)
|
||||
return dst;
|
||||
/*
|
||||
* only "LT" compare available, so we must use imm + 1
|
||||
* to generate "GT"
|
||||
* to generate "GT" and imm -1 to generate LE
|
||||
*/
|
||||
t64s = (u64)(u32)(insn->imm) + (cmp_eq ? 0 : 1);
|
||||
if (t64s >= 0 && t64s <= S16_MAX) {
|
||||
emit_instr(ctx, sltiu, MIPS_R_AT, dst, (int)t64s);
|
||||
src = MIPS_R_AT;
|
||||
dst = MIPS_R_ZERO;
|
||||
cmp_eq = true;
|
||||
goto jeq_common;
|
||||
}
|
||||
if (bpf_op == BPF_JGT)
|
||||
t64s = (u64)(u32)(insn->imm) + 1;
|
||||
else if (bpf_op == BPF_JLE)
|
||||
t64s = (u64)(u32)(insn->imm) + 1;
|
||||
else
|
||||
t64s = (u64)(u32)(insn->imm);
|
||||
|
||||
cmp_eq = bpf_op == BPF_JGT || bpf_op == BPF_JGE;
|
||||
|
||||
emit_const_to_reg(ctx, MIPS_R_AT, (u64)t64s);
|
||||
emit_instr(ctx, sltu, MIPS_R_AT, dst, MIPS_R_AT);
|
||||
src = MIPS_R_AT;
|
||||
dst = MIPS_R_ZERO;
|
||||
cmp_eq = true;
|
||||
goto jeq_common;
|
||||
|
||||
case BPF_JMP | BPF_JSET | BPF_K: /* JMP_IMM */
|
||||
@ -1198,7 +1226,7 @@ jeq_common:
|
||||
if (dst < 0)
|
||||
return dst;
|
||||
|
||||
if (use_bbit_insns() && hweight32((u32)insn->imm) == 1) {
|
||||
if (ctx->use_bbit_insns && hweight32((u32)insn->imm) == 1) {
|
||||
if ((insn + 1)->code == (BPF_JMP | BPF_EXIT) && insn->off == 1) {
|
||||
b_off = b_imm(exit_idx, ctx);
|
||||
if (is_bad_offset(b_off))
|
||||
@ -1724,10 +1752,14 @@ static int reg_val_propagate_range(struct jit_ctx *ctx, u64 initial_rvt,
|
||||
case BPF_JEQ:
|
||||
case BPF_JGT:
|
||||
case BPF_JGE:
|
||||
case BPF_JLT:
|
||||
case BPF_JLE:
|
||||
case BPF_JSET:
|
||||
case BPF_JNE:
|
||||
case BPF_JSGT:
|
||||
case BPF_JSGE:
|
||||
case BPF_JSLT:
|
||||
case BPF_JSLE:
|
||||
if (follow_taken) {
|
||||
rvt[idx] |= RVT_BRANCH_TAKEN;
|
||||
idx += insn->off;
|
||||
@ -1853,6 +1885,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
|
||||
preempt_disable();
|
||||
switch (current_cpu_type()) {
|
||||
case CPU_CAVIUM_OCTEON:
|
||||
case CPU_CAVIUM_OCTEON_PLUS:
|
||||
case CPU_CAVIUM_OCTEON2:
|
||||
case CPU_CAVIUM_OCTEON3:
|
||||
ctx.use_bbit_insns = 1;
|
||||
break;
|
||||
default:
|
||||
ctx.use_bbit_insns = 0;
|
||||
}
|
||||
preempt_enable();
|
||||
|
||||
ctx.offsets = kcalloc(prog->len + 1, sizeof(*ctx.offsets), GFP_KERNEL);
|
||||
if (ctx.offsets == NULL)
|
||||
goto out_err;
|
||||
|
@ -102,4 +102,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
@ -31,7 +31,6 @@ CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_INET6_IPCOMP=m
|
||||
CONFIG_IPV6_TUNNEL=m
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_NETFILTER_DEBUG=y
|
||||
CONFIG_NET_PKTGEN=m
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_DEVTMPFS=y
|
||||
|
@ -101,4 +101,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 0x4034
|
||||
|
||||
#define SO_ZEROCOPY 0x4035
|
||||
|
||||
#endif /* _UAPI_ASM_SOCKET_H */
|
||||
|
@ -263,6 +263,7 @@ static inline bool is_nearbranch(int offset)
|
||||
#define COND_EQ (CR0_EQ | COND_CMP_TRUE)
|
||||
#define COND_NE (CR0_EQ | COND_CMP_FALSE)
|
||||
#define COND_LT (CR0_LT | COND_CMP_TRUE)
|
||||
#define COND_LE (CR0_GT | COND_CMP_FALSE)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -795,12 +795,24 @@ emit_clear:
|
||||
case BPF_JMP | BPF_JSGT | BPF_X:
|
||||
true_cond = COND_GT;
|
||||
goto cond_branch;
|
||||
case BPF_JMP | BPF_JLT | BPF_K:
|
||||
case BPF_JMP | BPF_JLT | BPF_X:
|
||||
case BPF_JMP | BPF_JSLT | BPF_K:
|
||||
case BPF_JMP | BPF_JSLT | BPF_X:
|
||||
true_cond = COND_LT;
|
||||
goto cond_branch;
|
||||
case BPF_JMP | BPF_JGE | BPF_K:
|
||||
case BPF_JMP | BPF_JGE | BPF_X:
|
||||
case BPF_JMP | BPF_JSGE | BPF_K:
|
||||
case BPF_JMP | BPF_JSGE | BPF_X:
|
||||
true_cond = COND_GE;
|
||||
goto cond_branch;
|
||||
case BPF_JMP | BPF_JLE | BPF_K:
|
||||
case BPF_JMP | BPF_JLE | BPF_X:
|
||||
case BPF_JMP | BPF_JSLE | BPF_K:
|
||||
case BPF_JMP | BPF_JSLE | BPF_X:
|
||||
true_cond = COND_LE;
|
||||
goto cond_branch;
|
||||
case BPF_JMP | BPF_JEQ | BPF_K:
|
||||
case BPF_JMP | BPF_JEQ | BPF_X:
|
||||
true_cond = COND_EQ;
|
||||
@ -817,14 +829,18 @@ emit_clear:
|
||||
cond_branch:
|
||||
switch (code) {
|
||||
case BPF_JMP | BPF_JGT | BPF_X:
|
||||
case BPF_JMP | BPF_JLT | BPF_X:
|
||||
case BPF_JMP | BPF_JGE | BPF_X:
|
||||
case BPF_JMP | BPF_JLE | BPF_X:
|
||||
case BPF_JMP | BPF_JEQ | BPF_X:
|
||||
case BPF_JMP | BPF_JNE | BPF_X:
|
||||
/* unsigned comparison */
|
||||
PPC_CMPLD(dst_reg, src_reg);
|
||||
break;
|
||||
case BPF_JMP | BPF_JSGT | BPF_X:
|
||||
case BPF_JMP | BPF_JSLT | BPF_X:
|
||||
case BPF_JMP | BPF_JSGE | BPF_X:
|
||||
case BPF_JMP | BPF_JSLE | BPF_X:
|
||||
/* signed comparison */
|
||||
PPC_CMPD(dst_reg, src_reg);
|
||||
break;
|
||||
@ -834,7 +850,9 @@ cond_branch:
|
||||
case BPF_JMP | BPF_JNE | BPF_K:
|
||||
case BPF_JMP | BPF_JEQ | BPF_K:
|
||||
case BPF_JMP | BPF_JGT | BPF_K:
|
||||
case BPF_JMP | BPF_JLT | BPF_K:
|
||||
case BPF_JMP | BPF_JGE | BPF_K:
|
||||
case BPF_JMP | BPF_JLE | BPF_K:
|
||||
/*
|
||||
* Need sign-extended load, so only positive
|
||||
* values can be used as imm in cmpldi
|
||||
@ -849,7 +867,9 @@ cond_branch:
|
||||
}
|
||||
break;
|
||||
case BPF_JMP | BPF_JSGT | BPF_K:
|
||||
case BPF_JMP | BPF_JSLT | BPF_K:
|
||||
case BPF_JMP | BPF_JSGE | BPF_K:
|
||||
case BPF_JMP | BPF_JSLE | BPF_K:
|
||||
/*
|
||||
* signed comparison, so any 16-bit value
|
||||
* can be used in cmpdi
|
||||
|
@ -108,4 +108,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
@ -1093,15 +1093,27 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
|
||||
case BPF_JMP | BPF_JSGT | BPF_K: /* ((s64) dst > (s64) imm) */
|
||||
mask = 0x2000; /* jh */
|
||||
goto branch_ks;
|
||||
case BPF_JMP | BPF_JSLT | BPF_K: /* ((s64) dst < (s64) imm) */
|
||||
mask = 0x4000; /* jl */
|
||||
goto branch_ks;
|
||||
case BPF_JMP | BPF_JSGE | BPF_K: /* ((s64) dst >= (s64) imm) */
|
||||
mask = 0xa000; /* jhe */
|
||||
goto branch_ks;
|
||||
case BPF_JMP | BPF_JSLE | BPF_K: /* ((s64) dst <= (s64) imm) */
|
||||
mask = 0xc000; /* jle */
|
||||
goto branch_ks;
|
||||
case BPF_JMP | BPF_JGT | BPF_K: /* (dst_reg > imm) */
|
||||
mask = 0x2000; /* jh */
|
||||
goto branch_ku;
|
||||
case BPF_JMP | BPF_JLT | BPF_K: /* (dst_reg < imm) */
|
||||
mask = 0x4000; /* jl */
|
||||
goto branch_ku;
|
||||
case BPF_JMP | BPF_JGE | BPF_K: /* (dst_reg >= imm) */
|
||||
mask = 0xa000; /* jhe */
|
||||
goto branch_ku;
|
||||
case BPF_JMP | BPF_JLE | BPF_K: /* (dst_reg <= imm) */
|
||||
mask = 0xc000; /* jle */
|
||||
goto branch_ku;
|
||||
case BPF_JMP | BPF_JNE | BPF_K: /* (dst_reg != imm) */
|
||||
mask = 0x7000; /* jne */
|
||||
goto branch_ku;
|
||||
@ -1119,15 +1131,27 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
|
||||
case BPF_JMP | BPF_JSGT | BPF_X: /* ((s64) dst > (s64) src) */
|
||||
mask = 0x2000; /* jh */
|
||||
goto branch_xs;
|
||||
case BPF_JMP | BPF_JSLT | BPF_X: /* ((s64) dst < (s64) src) */
|
||||
mask = 0x4000; /* jl */
|
||||
goto branch_xs;
|
||||
case BPF_JMP | BPF_JSGE | BPF_X: /* ((s64) dst >= (s64) src) */
|
||||
mask = 0xa000; /* jhe */
|
||||
goto branch_xs;
|
||||
case BPF_JMP | BPF_JSLE | BPF_X: /* ((s64) dst <= (s64) src) */
|
||||
mask = 0xc000; /* jle */
|
||||
goto branch_xs;
|
||||
case BPF_JMP | BPF_JGT | BPF_X: /* (dst > src) */
|
||||
mask = 0x2000; /* jh */
|
||||
goto branch_xu;
|
||||
case BPF_JMP | BPF_JLT | BPF_X: /* (dst < src) */
|
||||
mask = 0x4000; /* jl */
|
||||
goto branch_xu;
|
||||
case BPF_JMP | BPF_JGE | BPF_X: /* (dst >= src) */
|
||||
mask = 0xa000; /* jhe */
|
||||
goto branch_xu;
|
||||
case BPF_JMP | BPF_JLE | BPF_X: /* (dst <= src) */
|
||||
mask = 0xc000; /* jle */
|
||||
goto branch_xu;
|
||||
case BPF_JMP | BPF_JNE | BPF_X: /* (dst != src) */
|
||||
mask = 0x7000; /* jne */
|
||||
goto branch_xu;
|
||||
|
@ -28,7 +28,6 @@ CONFIG_IP_PNP_RARP=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_NETFILTER_DEBUG=y
|
||||
CONFIG_IP_NF_QUEUE=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
|
@ -98,6 +98,8 @@
|
||||
|
||||
#define SO_PEERGROUPS 0x003d
|
||||
|
||||
#define SO_ZEROCOPY 0x003e
|
||||
|
||||
/* Security levels - as per NRL IPv6 - don't actually do anything */
|
||||
#define SO_SECURITY_AUTHENTICATION 0x5001
|
||||
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
|
||||
|
@ -128,6 +128,8 @@ static u32 WDISP10(u32 off)
|
||||
|
||||
#define BA (BRANCH | CONDA)
|
||||
#define BG (BRANCH | CONDG)
|
||||
#define BL (BRANCH | CONDL)
|
||||
#define BLE (BRANCH | CONDLE)
|
||||
#define BGU (BRANCH | CONDGU)
|
||||
#define BLEU (BRANCH | CONDLEU)
|
||||
#define BGE (BRANCH | CONDGE)
|
||||
@ -715,9 +717,15 @@ static int emit_compare_and_branch(const u8 code, const u8 dst, u8 src,
|
||||
case BPF_JGT:
|
||||
br_opcode = BGU;
|
||||
break;
|
||||
case BPF_JLT:
|
||||
br_opcode = BLU;
|
||||
break;
|
||||
case BPF_JGE:
|
||||
br_opcode = BGEU;
|
||||
break;
|
||||
case BPF_JLE:
|
||||
br_opcode = BLEU;
|
||||
break;
|
||||
case BPF_JSET:
|
||||
case BPF_JNE:
|
||||
br_opcode = BNE;
|
||||
@ -725,9 +733,15 @@ static int emit_compare_and_branch(const u8 code, const u8 dst, u8 src,
|
||||
case BPF_JSGT:
|
||||
br_opcode = BG;
|
||||
break;
|
||||
case BPF_JSLT:
|
||||
br_opcode = BL;
|
||||
break;
|
||||
case BPF_JSGE:
|
||||
br_opcode = BGE;
|
||||
break;
|
||||
case BPF_JSLE:
|
||||
br_opcode = BLE;
|
||||
break;
|
||||
default:
|
||||
/* Make sure we dont leak kernel information to the
|
||||
* user.
|
||||
@ -746,18 +760,30 @@ static int emit_compare_and_branch(const u8 code, const u8 dst, u8 src,
|
||||
case BPF_JGT:
|
||||
cbcond_opcode = CBCONDGU;
|
||||
break;
|
||||
case BPF_JLT:
|
||||
cbcond_opcode = CBCONDLU;
|
||||
break;
|
||||
case BPF_JGE:
|
||||
cbcond_opcode = CBCONDGEU;
|
||||
break;
|
||||
case BPF_JLE:
|
||||
cbcond_opcode = CBCONDLEU;
|
||||
break;
|
||||
case BPF_JNE:
|
||||
cbcond_opcode = CBCONDNE;
|
||||
break;
|
||||
case BPF_JSGT:
|
||||
cbcond_opcode = CBCONDG;
|
||||
break;
|
||||
case BPF_JSLT:
|
||||
cbcond_opcode = CBCONDL;
|
||||
break;
|
||||
case BPF_JSGE:
|
||||
cbcond_opcode = CBCONDGE;
|
||||
break;
|
||||
case BPF_JSLE:
|
||||
cbcond_opcode = CBCONDLE;
|
||||
break;
|
||||
default:
|
||||
/* Make sure we dont leak kernel information to the
|
||||
* user.
|
||||
@ -1176,10 +1202,14 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
/* IF (dst COND src) JUMP off */
|
||||
case BPF_JMP | BPF_JEQ | BPF_X:
|
||||
case BPF_JMP | BPF_JGT | BPF_X:
|
||||
case BPF_JMP | BPF_JLT | BPF_X:
|
||||
case BPF_JMP | BPF_JGE | BPF_X:
|
||||
case BPF_JMP | BPF_JLE | BPF_X:
|
||||
case BPF_JMP | BPF_JNE | BPF_X:
|
||||
case BPF_JMP | BPF_JSGT | BPF_X:
|
||||
case BPF_JMP | BPF_JSLT | BPF_X:
|
||||
case BPF_JMP | BPF_JSGE | BPF_X:
|
||||
case BPF_JMP | BPF_JSLE | BPF_X:
|
||||
case BPF_JMP | BPF_JSET | BPF_X: {
|
||||
int err;
|
||||
|
||||
@ -1191,10 +1221,14 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
/* IF (dst COND imm) JUMP off */
|
||||
case BPF_JMP | BPF_JEQ | BPF_K:
|
||||
case BPF_JMP | BPF_JGT | BPF_K:
|
||||
case BPF_JMP | BPF_JLT | BPF_K:
|
||||
case BPF_JMP | BPF_JGE | BPF_K:
|
||||
case BPF_JMP | BPF_JLE | BPF_K:
|
||||
case BPF_JMP | BPF_JNE | BPF_K:
|
||||
case BPF_JMP | BPF_JSGT | BPF_K:
|
||||
case BPF_JMP | BPF_JSLT | BPF_K:
|
||||
case BPF_JMP | BPF_JSGE | BPF_K:
|
||||
case BPF_JMP | BPF_JSLE | BPF_K:
|
||||
case BPF_JMP | BPF_JSET | BPF_K: {
|
||||
int err;
|
||||
|
||||
|
@ -94,7 +94,9 @@ static int bpf_size_to_x86_bytes(int bpf_size)
|
||||
#define X86_JNE 0x75
|
||||
#define X86_JBE 0x76
|
||||
#define X86_JA 0x77
|
||||
#define X86_JL 0x7C
|
||||
#define X86_JGE 0x7D
|
||||
#define X86_JLE 0x7E
|
||||
#define X86_JG 0x7F
|
||||
|
||||
static void bpf_flush_icache(void *start, void *end)
|
||||
@ -285,7 +287,7 @@ static void emit_bpf_tail_call(u8 **pprog)
|
||||
EMIT4(0x48, 0x8B, 0x46, /* mov rax, qword ptr [rsi + 16] */
|
||||
offsetof(struct bpf_array, map.max_entries));
|
||||
EMIT3(0x48, 0x39, 0xD0); /* cmp rax, rdx */
|
||||
#define OFFSET1 47 /* number of bytes to jump */
|
||||
#define OFFSET1 43 /* number of bytes to jump */
|
||||
EMIT2(X86_JBE, OFFSET1); /* jbe out */
|
||||
label1 = cnt;
|
||||
|
||||
@ -294,21 +296,20 @@ static void emit_bpf_tail_call(u8 **pprog)
|
||||
*/
|
||||
EMIT2_off32(0x8B, 0x85, 36); /* mov eax, dword ptr [rbp + 36] */
|
||||
EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */
|
||||
#define OFFSET2 36
|
||||
#define OFFSET2 32
|
||||
EMIT2(X86_JA, OFFSET2); /* ja out */
|
||||
label2 = cnt;
|
||||
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
|
||||
EMIT2_off32(0x89, 0x85, 36); /* mov dword ptr [rbp + 36], eax */
|
||||
|
||||
/* prog = array->ptrs[index]; */
|
||||
EMIT4_off32(0x48, 0x8D, 0x84, 0xD6, /* lea rax, [rsi + rdx * 8 + offsetof(...)] */
|
||||
EMIT4_off32(0x48, 0x8B, 0x84, 0xD6, /* mov rax, [rsi + rdx * 8 + offsetof(...)] */
|
||||
offsetof(struct bpf_array, ptrs));
|
||||
EMIT3(0x48, 0x8B, 0x00); /* mov rax, qword ptr [rax] */
|
||||
|
||||
/* if (prog == NULL)
|
||||
* goto out;
|
||||
*/
|
||||
EMIT4(0x48, 0x83, 0xF8, 0x00); /* cmp rax, 0 */
|
||||
EMIT3(0x48, 0x85, 0xC0); /* test rax,rax */
|
||||
#define OFFSET3 10
|
||||
EMIT2(X86_JE, OFFSET3); /* je out */
|
||||
label3 = cnt;
|
||||
@ -888,9 +889,13 @@ xadd: if (is_imm8(insn->off))
|
||||
case BPF_JMP | BPF_JEQ | BPF_X:
|
||||
case BPF_JMP | BPF_JNE | BPF_X:
|
||||
case BPF_JMP | BPF_JGT | BPF_X:
|
||||
case BPF_JMP | BPF_JLT | BPF_X:
|
||||
case BPF_JMP | BPF_JGE | BPF_X:
|
||||
case BPF_JMP | BPF_JLE | BPF_X:
|
||||
case BPF_JMP | BPF_JSGT | BPF_X:
|
||||
case BPF_JMP | BPF_JSLT | BPF_X:
|
||||
case BPF_JMP | BPF_JSGE | BPF_X:
|
||||
case BPF_JMP | BPF_JSLE | BPF_X:
|
||||
/* cmp dst_reg, src_reg */
|
||||
EMIT3(add_2mod(0x48, dst_reg, src_reg), 0x39,
|
||||
add_2reg(0xC0, dst_reg, src_reg));
|
||||
@ -911,9 +916,13 @@ xadd: if (is_imm8(insn->off))
|
||||
case BPF_JMP | BPF_JEQ | BPF_K:
|
||||
case BPF_JMP | BPF_JNE | BPF_K:
|
||||
case BPF_JMP | BPF_JGT | BPF_K:
|
||||
case BPF_JMP | BPF_JLT | BPF_K:
|
||||
case BPF_JMP | BPF_JGE | BPF_K:
|
||||
case BPF_JMP | BPF_JLE | BPF_K:
|
||||
case BPF_JMP | BPF_JSGT | BPF_K:
|
||||
case BPF_JMP | BPF_JSLT | BPF_K:
|
||||
case BPF_JMP | BPF_JSGE | BPF_K:
|
||||
case BPF_JMP | BPF_JSLE | BPF_K:
|
||||
/* cmp dst_reg, imm8/32 */
|
||||
EMIT1(add_1mod(0x48, dst_reg));
|
||||
|
||||
@ -935,18 +944,34 @@ emit_cond_jmp: /* convert BPF opcode to x86 */
|
||||
/* GT is unsigned '>', JA in x86 */
|
||||
jmp_cond = X86_JA;
|
||||
break;
|
||||
case BPF_JLT:
|
||||
/* LT is unsigned '<', JB in x86 */
|
||||
jmp_cond = X86_JB;
|
||||
break;
|
||||
case BPF_JGE:
|
||||
/* GE is unsigned '>=', JAE in x86 */
|
||||
jmp_cond = X86_JAE;
|
||||
break;
|
||||
case BPF_JLE:
|
||||
/* LE is unsigned '<=', JBE in x86 */
|
||||
jmp_cond = X86_JBE;
|
||||
break;
|
||||
case BPF_JSGT:
|
||||
/* signed '>', GT in x86 */
|
||||
jmp_cond = X86_JG;
|
||||
break;
|
||||
case BPF_JSLT:
|
||||
/* signed '<', LT in x86 */
|
||||
jmp_cond = X86_JL;
|
||||
break;
|
||||
case BPF_JSGE:
|
||||
/* signed '>=', GE in x86 */
|
||||
jmp_cond = X86_JGE;
|
||||
break;
|
||||
case BPF_JSLE:
|
||||
/* signed '<=', LE in x86 */
|
||||
jmp_cond = X86_JLE;
|
||||
break;
|
||||
default: /* to silence gcc warning */
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -113,4 +113,6 @@
|
||||
|
||||
#define SO_PEERGROUPS 59
|
||||
|
||||
#define SO_ZEROCOPY 60
|
||||
|
||||
#endif /* _XTENSA_SOCKET_H */
|
||||
|
@ -71,7 +71,7 @@ static struct attribute *adummy_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group adummy_group_attrs = {
|
||||
static const struct attribute_group adummy_group_attrs = {
|
||||
.name = NULL, /* We want them in dev's root folder */
|
||||
.attrs = adummy_attrs
|
||||
};
|
||||
@ -130,7 +130,7 @@ adummy_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct atmdev_ops adummy_ops =
|
||||
static const struct atmdev_ops adummy_ops =
|
||||
{
|
||||
.open = adummy_open,
|
||||
.close = adummy_close,
|
||||
|
@ -2374,7 +2374,7 @@ MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles");
|
||||
|
||||
/********** module entry **********/
|
||||
|
||||
static struct pci_device_id amb_pci_tbl[] = {
|
||||
static const struct pci_device_id amb_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR), 0 },
|
||||
{ PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD), 0 },
|
||||
{ 0, }
|
||||
|
@ -342,7 +342,7 @@ static struct atmdev_ops atmtcp_v_dev_ops = {
|
||||
*/
|
||||
|
||||
|
||||
static struct atmdev_ops atmtcp_c_dev_ops = {
|
||||
static const struct atmdev_ops atmtcp_c_dev_ops = {
|
||||
.close = atmtcp_c_close,
|
||||
.send = atmtcp_c_send
|
||||
};
|
||||
|
@ -2292,7 +2292,7 @@ err_disable:
|
||||
}
|
||||
|
||||
|
||||
static struct pci_device_id eni_pci_tbl[] = {
|
||||
static const struct pci_device_id eni_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_FPGA), 0 /* FPGA */ },
|
||||
{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_ASIC), 1 /* ASIC */ },
|
||||
{ 0, }
|
||||
|
@ -2030,7 +2030,7 @@ static void firestream_remove_one(struct pci_dev *pdev)
|
||||
func_exit ();
|
||||
}
|
||||
|
||||
static struct pci_device_id firestream_pci_tbl[] = {
|
||||
static const struct pci_device_id firestream_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50), FS_IS50},
|
||||
{ PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155), FS_IS155},
|
||||
{ 0, }
|
||||
|
@ -2757,7 +2757,7 @@ static void fore200e_pca_remove_one(struct pci_dev *pci_dev)
|
||||
}
|
||||
|
||||
|
||||
static struct pci_device_id fore200e_pca_tbl[] = {
|
||||
static const struct pci_device_id fore200e_pca_tbl[] = {
|
||||
{ PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID,
|
||||
0, 0, (unsigned long) &fore200e_bus[0] },
|
||||
{ 0, }
|
||||
|
@ -161,7 +161,7 @@ static unsigned int clocktab[] = {
|
||||
CLK_LOW
|
||||
};
|
||||
|
||||
static struct atmdev_ops he_ops =
|
||||
static const struct atmdev_ops he_ops =
|
||||
{
|
||||
.open = he_open,
|
||||
.close = he_close,
|
||||
@ -2851,7 +2851,7 @@ MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)");
|
||||
module_param(sdh, bool, 0);
|
||||
MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
|
||||
|
||||
static struct pci_device_id he_pci_tbl[] = {
|
||||
static const struct pci_device_id he_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(FORE, PCI_DEVICE_ID_FORE_HE), 0 },
|
||||
{ 0, }
|
||||
};
|
||||
|
@ -2867,7 +2867,7 @@ MODULE_PARM_DESC(max_tx_size, "maximum size of TX AAL5 frames");
|
||||
MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames");
|
||||
MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles");
|
||||
|
||||
static struct pci_device_id hrz_pci_tbl[] = {
|
||||
static const struct pci_device_id hrz_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, PCI_ANY_ID, PCI_ANY_ID,
|
||||
0, 0, 0 },
|
||||
{ 0, }
|
||||
|
@ -134,7 +134,7 @@ static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos,
|
||||
static void idt77252_softint(struct work_struct *work);
|
||||
|
||||
|
||||
static struct atmdev_ops idt77252_ops =
|
||||
static const struct atmdev_ops idt77252_ops =
|
||||
{
|
||||
.dev_close = idt77252_dev_close,
|
||||
.open = idt77252_open,
|
||||
@ -3725,7 +3725,7 @@ err_out_disable_pdev:
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct pci_device_id idt77252_pci_tbl[] =
|
||||
static const struct pci_device_id idt77252_pci_tbl[] =
|
||||
{
|
||||
{ PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77252), 0 },
|
||||
{ 0, }
|
||||
|
@ -3266,7 +3266,7 @@ static void ia_remove_one(struct pci_dev *pdev)
|
||||
kfree(iadev);
|
||||
}
|
||||
|
||||
static struct pci_device_id ia_pci_tbl[] = {
|
||||
static const struct pci_device_id ia_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_IPHASE, 0x0008, PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{ PCI_VENDOR_ID_IPHASE, 0x0009, PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{ 0,}
|
||||
|
@ -2589,7 +2589,7 @@ static int lanai_init_one(struct pci_dev *pci,
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct pci_device_id lanai_pci_tbl[] = {
|
||||
static const struct pci_device_id lanai_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAI2) },
|
||||
{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAIHB) },
|
||||
{ 0, } /* terminal entry */
|
||||
|
@ -154,7 +154,7 @@ static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr);
|
||||
|
||||
static struct ns_dev *cards[NS_MAX_CARDS];
|
||||
static unsigned num_cards;
|
||||
static struct atmdev_ops atm_ops = {
|
||||
static const struct atmdev_ops atm_ops = {
|
||||
.open = ns_open,
|
||||
.close = ns_close,
|
||||
.ioctl = ns_ioctl,
|
||||
@ -253,7 +253,7 @@ static void nicstar_remove_one(struct pci_dev *pcidev)
|
||||
kfree(card);
|
||||
}
|
||||
|
||||
static struct pci_device_id nicstar_pci_tbl[] = {
|
||||
static const struct pci_device_id nicstar_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77201), 0 },
|
||||
{0,} /* terminate list */
|
||||
};
|
||||
|
@ -611,7 +611,7 @@ static struct attribute *solos_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group solos_attr_group = {
|
||||
static const struct attribute_group solos_attr_group = {
|
||||
.attrs = solos_attrs,
|
||||
.name = "parameters",
|
||||
};
|
||||
@ -628,7 +628,7 @@ static struct attribute *gpio_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group gpio_attr_group = {
|
||||
static const struct attribute_group gpio_attr_group = {
|
||||
.attrs = gpio_attrs,
|
||||
.name = "gpio",
|
||||
};
|
||||
@ -1187,7 +1187,7 @@ static int psend(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct atmdev_ops fpga_ops = {
|
||||
static const struct atmdev_ops fpga_ops = {
|
||||
.open = popen,
|
||||
.close = pclose,
|
||||
.ioctl = NULL,
|
||||
@ -1476,7 +1476,7 @@ static void fpga_remove(struct pci_dev *dev)
|
||||
kfree(card);
|
||||
}
|
||||
|
||||
static struct pci_device_id fpga_pci_tbl[] = {
|
||||
static const struct pci_device_id fpga_pci_tbl[] = {
|
||||
{ 0x10ee, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
|
||||
{ 0, }
|
||||
};
|
||||
|
@ -1642,7 +1642,7 @@ out_free:
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct pci_device_id zatm_pci_tbl[] = {
|
||||
static const struct pci_device_id zatm_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1221), ZATM_COPPER },
|
||||
{ PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1225), 0 },
|
||||
{ 0, }
|
||||
|
@ -3,11 +3,8 @@ config BCMA_POSSIBLE
|
||||
depends on HAS_IOMEM && HAS_DMA
|
||||
default y
|
||||
|
||||
menu "Broadcom specific AMBA"
|
||||
depends on BCMA_POSSIBLE
|
||||
|
||||
config BCMA
|
||||
tristate "BCMA support"
|
||||
menuconfig BCMA
|
||||
tristate "Broadcom specific AMBA"
|
||||
depends on BCMA_POSSIBLE
|
||||
help
|
||||
Bus driver for Broadcom specific Advanced Microcontroller Bus
|
||||
@ -117,5 +114,3 @@ config BCMA_DEBUG
|
||||
This turns on additional debugging messages.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
endmenu
|
||||
|
@ -191,6 +191,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
case BCMA_CHIP_ID_BCM4707:
|
||||
case BCMA_CHIP_ID_BCM5357:
|
||||
case BCMA_CHIP_ID_BCM53572:
|
||||
case BCMA_CHIP_ID_BCM53573:
|
||||
case BCMA_CHIP_ID_BCM47094:
|
||||
chip->ngpio = 32;
|
||||
break;
|
||||
|
@ -98,6 +98,7 @@ config BT_HCIUART_NOKIA
|
||||
depends on BT_HCIUART_SERDEV
|
||||
depends on PM
|
||||
select BT_HCIUART_H4
|
||||
select BT_BCM
|
||||
help
|
||||
Nokia H4+ is serial protocol for communication between Bluetooth
|
||||
device and host. This protocol is required for Bluetooth devices
|
||||
@ -167,6 +168,7 @@ config BT_HCIUART_INTEL
|
||||
config BT_HCIUART_BCM
|
||||
bool "Broadcom protocol support"
|
||||
depends on BT_HCIUART
|
||||
depends on BT_HCIUART_SERDEV
|
||||
select BT_HCIUART_H4
|
||||
select BT_BCM
|
||||
help
|
||||
|
@ -140,7 +140,8 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
|
||||
|
||||
#define BTUSB_ATH3012 0x80
|
||||
/* This table is to load patch and sysconfig files
|
||||
* for AR3012 */
|
||||
* for AR3012
|
||||
*/
|
||||
static const struct usb_device_id ath3k_blist_tbl[] = {
|
||||
|
||||
/* Atheros AR3012 with sflash firmware*/
|
||||
|
@ -93,6 +93,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
|
||||
|
||||
/* Hardware states */
|
||||
#define CARD_READY 1
|
||||
#define CARD_ACTIVITY 2
|
||||
#define CARD_HAS_PCCARD_ID 4
|
||||
#define CARD_HAS_POWER_LED 5
|
||||
#define CARD_HAS_ACTIVITY_LED 6
|
||||
@ -160,16 +161,14 @@ static void bluecard_activity_led_timeout(u_long arg)
|
||||
struct bluecard_info *info = (struct bluecard_info *)arg;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||
return;
|
||||
|
||||
if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) {
|
||||
/* Disable activity LED */
|
||||
outb(0x08 | 0x20, iobase + 0x30);
|
||||
} else {
|
||||
/* Disable power LED */
|
||||
outb(0x00, iobase + 0x30);
|
||||
if (test_bit(CARD_ACTIVITY, &(info->hw_state))) {
|
||||
/* leave LED in inactive state for HZ/10 for blink effect */
|
||||
clear_bit(CARD_ACTIVITY, &(info->hw_state));
|
||||
mod_timer(&(info->timer), jiffies + HZ / 10);
|
||||
}
|
||||
|
||||
/* Disable activity LED, enable power LED */
|
||||
outb(0x08 | 0x20, iobase + 0x30);
|
||||
}
|
||||
|
||||
|
||||
@ -177,22 +176,22 @@ static void bluecard_enable_activity_led(struct bluecard_info *info)
|
||||
{
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||
/* don't disturb running blink timer */
|
||||
if (timer_pending(&(info->timer)))
|
||||
return;
|
||||
|
||||
set_bit(CARD_ACTIVITY, &(info->hw_state));
|
||||
|
||||
if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) {
|
||||
/* Enable activity LED */
|
||||
outb(0x10 | 0x40, iobase + 0x30);
|
||||
|
||||
/* Stop the LED after HZ/4 */
|
||||
mod_timer(&(info->timer), jiffies + HZ / 4);
|
||||
/* Enable activity LED, keep power LED enabled */
|
||||
outb(0x18 | 0x60, iobase + 0x30);
|
||||
} else {
|
||||
/* Enable power LED */
|
||||
outb(0x08 | 0x20, iobase + 0x30);
|
||||
|
||||
/* Stop the LED after HZ/2 */
|
||||
mod_timer(&(info->timer), jiffies + HZ / 2);
|
||||
/* Disable power LED */
|
||||
outb(0x00, iobase + 0x30);
|
||||
}
|
||||
|
||||
/* Stop the LED after HZ/10 */
|
||||
mod_timer(&(info->timer), jiffies + HZ / 10);
|
||||
}
|
||||
|
||||
|
||||
@ -625,16 +624,13 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
|
||||
static int bluecard_hci_open(struct hci_dev *hdev)
|
||||
{
|
||||
struct bluecard_info *info = hci_get_drvdata(hdev);
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
|
||||
|
||||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
/* Enable LED */
|
||||
outb(0x08 | 0x20, iobase + 0x30);
|
||||
}
|
||||
/* Enable power LED */
|
||||
outb(0x08 | 0x20, iobase + 0x30);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -643,15 +639,15 @@ static int bluecard_hci_open(struct hci_dev *hdev)
|
||||
static int bluecard_hci_close(struct hci_dev *hdev)
|
||||
{
|
||||
struct bluecard_info *info = hci_get_drvdata(hdev);
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
bluecard_hci_flush(hdev);
|
||||
|
||||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
/* Stop LED timer */
|
||||
del_timer_sync(&(info->timer));
|
||||
|
||||
/* Disable LED */
|
||||
outb(0x00, iobase + 0x30);
|
||||
}
|
||||
/* Disable power LED */
|
||||
outb(0x00, iobase + 0x30);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -684,14 +684,16 @@ static int bt3c_config(struct pcmcia_device *link)
|
||||
unsigned long try;
|
||||
|
||||
/* First pass: look for a config entry that looks normal.
|
||||
Two tries: without IO aliases, then with aliases */
|
||||
* Two tries: without IO aliases, then with aliases
|
||||
*/
|
||||
for (try = 0; try < 2; try++)
|
||||
if (!pcmcia_loop_config(link, bt3c_check_config, (void *) try))
|
||||
goto found_port;
|
||||
|
||||
/* Second pass: try to find an entry that isn't picky about
|
||||
its base address, then try to grab any standard serial port
|
||||
address, and finally try to get any free port. */
|
||||
* its base address, then try to grab any standard serial port
|
||||
* address, and finally try to get any free port.
|
||||
*/
|
||||
if (!pcmcia_loop_config(link, bt3c_check_config_notpicky, NULL))
|
||||
goto found_port;
|
||||
|
||||
|
@ -287,6 +287,37 @@ static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev)
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int btbcm_read_info(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Read Verbose Config Version Info */
|
||||
skb = btbcm_read_verbose_config(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read Controller Features */
|
||||
skb = btbcm_read_controller_features(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]);
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read Local Name */
|
||||
skb = btbcm_read_local_name(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
u16 subver;
|
||||
const char *name;
|
||||
@ -322,13 +353,10 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len)
|
||||
subver = le16_to_cpu(ver->lmp_subver);
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read Verbose Config Version Info */
|
||||
skb = btbcm_read_verbose_config(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
|
||||
kfree_skb(skb);
|
||||
/* Read controller information */
|
||||
err = btbcm_read_info(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch ((rev & 0xf000) >> 12) {
|
||||
case 0:
|
||||
@ -431,29 +459,10 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
|
||||
subver = le16_to_cpu(ver->lmp_subver);
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read Verbose Config Version Info */
|
||||
skb = btbcm_read_verbose_config(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read Controller Features */
|
||||
skb = btbcm_read_controller_features(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]);
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read Local Name */
|
||||
skb = btbcm_read_local_name(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
|
||||
kfree_skb(skb);
|
||||
/* Read controller information */
|
||||
err = btbcm_read_info(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch ((rev & 0xf000) >> 12) {
|
||||
case 0:
|
||||
|
@ -1455,7 +1455,8 @@ done:
|
||||
fw_dump_ptr = fw_dump_data;
|
||||
|
||||
/* Dump all the memory data into single file, a userspace script will
|
||||
be used to split all the memory data to multiple files*/
|
||||
* be used to split all the memory data to multiple files
|
||||
*/
|
||||
BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump start");
|
||||
for (idx = 0; idx < dump_num; idx++) {
|
||||
struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
|
||||
@ -1482,7 +1483,8 @@ done:
|
||||
}
|
||||
|
||||
/* fw_dump_data will be free in device coredump release function
|
||||
after 5 min*/
|
||||
* after 5 min
|
||||
*/
|
||||
dev_coredumpv(&card->func->dev, fw_dump_data, fw_dump_len, GFP_KERNEL);
|
||||
BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ static int rome_patch_ver_req(struct hci_dev *hdev, u32 *rome_version)
|
||||
* and lower 2 bytes from patch will be used.
|
||||
*/
|
||||
*rome_version = (le32_to_cpu(ver->soc_id) << 16) |
|
||||
(le16_to_cpu(ver->rome_ver) & 0x0000ffff);
|
||||
(le16_to_cpu(ver->rome_ver) & 0x0000ffff);
|
||||
|
||||
out:
|
||||
kfree_skb(skb);
|
||||
|
@ -279,6 +279,8 @@ static int rtl_load_config(struct hci_dev *hdev, const char *name, u8 **buff)
|
||||
return ret;
|
||||
ret = fw->size;
|
||||
*buff = kmemdup(fw->data, ret, GFP_KERNEL);
|
||||
if (!*buff)
|
||||
ret = -ENOMEM;
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
|
@ -144,7 +144,8 @@ static int btsdio_rx_packet(struct btsdio_data *data)
|
||||
if (!skb) {
|
||||
/* Out of memory. Prepare a read retry and just
|
||||
* return with the expectation that the next time
|
||||
* we're called we'll have more memory. */
|
||||
* we're called we'll have more memory.
|
||||
*/
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -614,14 +614,16 @@ static int btuart_config(struct pcmcia_device *link)
|
||||
int try;
|
||||
|
||||
/* First pass: look for a config entry that looks normal.
|
||||
Two tries: without IO aliases, then with aliases */
|
||||
* Two tries: without IO aliases, then with aliases
|
||||
*/
|
||||
for (try = 0; try < 2; try++)
|
||||
if (!pcmcia_loop_config(link, btuart_check_config, &try))
|
||||
goto found_port;
|
||||
|
||||
/* Second pass: try to find an entry that isn't picky about
|
||||
its base address, then try to grab any standard serial port
|
||||
address, and finally try to get any free port. */
|
||||
* its base address, then try to grab any standard serial port
|
||||
* address, and finally try to get any free port.
|
||||
*/
|
||||
if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL))
|
||||
goto found_port;
|
||||
|
||||
|
@ -66,6 +66,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_BCM2045 0x40000
|
||||
#define BTUSB_IFNUM_2 0x80000
|
||||
#define BTUSB_CW6622 0x100000
|
||||
#define BTUSB_BCM_NO_PRODID 0x200000
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@ -131,7 +132,8 @@ static const struct usb_device_id btusb_table[] = {
|
||||
{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Broadcom BCM43142A0 (Foxconn/Lenovo) */
|
||||
{ USB_DEVICE(0x105b, 0xe065), .driver_info = BTUSB_BCM_PATCHRAM },
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x105b, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Broadcom BCM920703 (HTC Vive) */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bb4, 0xff, 0x01, 0x01),
|
||||
@ -169,6 +171,10 @@ static const struct usb_device_id btusb_table[] = {
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Broadcom devices with missing product id */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0000, 0x0000, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM | BTUSB_BCM_NO_PRODID },
|
||||
|
||||
/* Intel Bluetooth USB Bootloader (RAM module) */
|
||||
{ USB_DEVICE(0x8087, 0x0a5a),
|
||||
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
|
||||
@ -268,6 +274,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0489, 0xe092), .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, 0x3016), .driver_info = BTUSB_QCA_ROME },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
|
||||
@ -357,6 +364,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
|
||||
{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
|
||||
|
||||
/* Additional Realtek 8821AE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
|
||||
@ -656,7 +664,8 @@ static void btusb_intr_complete(struct urb *urb)
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
/* -EPERM: urb is being killed;
|
||||
* -ENODEV: device got disconnected */
|
||||
* -ENODEV: device got disconnected
|
||||
*/
|
||||
if (err != -EPERM && err != -ENODEV)
|
||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||
hdev->name, urb, -err);
|
||||
@ -745,7 +754,8 @@ static void btusb_bulk_complete(struct urb *urb)
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
/* -EPERM: urb is being killed;
|
||||
* -ENODEV: device got disconnected */
|
||||
* -ENODEV: device got disconnected
|
||||
*/
|
||||
if (err != -EPERM && err != -ENODEV)
|
||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||
hdev->name, urb, -err);
|
||||
@ -840,7 +850,8 @@ static void btusb_isoc_complete(struct urb *urb)
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
/* -EPERM: urb is being killed;
|
||||
* -ENODEV: device got disconnected */
|
||||
* -ENODEV: device got disconnected
|
||||
*/
|
||||
if (err != -EPERM && err != -ENODEV)
|
||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||
hdev->name, urb, -err);
|
||||
@ -952,7 +963,8 @@ static void btusb_diag_complete(struct urb *urb)
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
/* -EPERM: urb is being killed;
|
||||
* -ENODEV: device got disconnected */
|
||||
* -ENODEV: device got disconnected
|
||||
*/
|
||||
if (err != -EPERM && err != -ENODEV)
|
||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||
hdev->name, urb, -err);
|
||||
@ -1076,6 +1088,10 @@ static int btusb_open(struct hci_dev *hdev)
|
||||
}
|
||||
|
||||
data->intf->needs_remote_wakeup = 1;
|
||||
/* device specific wakeup source enabled and required for USB
|
||||
* remote wakeup while host is suspended
|
||||
*/
|
||||
device_wakeup_enable(&data->udev->dev);
|
||||
|
||||
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
|
||||
goto done;
|
||||
@ -1139,6 +1155,7 @@ static int btusb_close(struct hci_dev *hdev)
|
||||
goto failed;
|
||||
|
||||
data->intf->needs_remote_wakeup = 0;
|
||||
device_wakeup_disable(&data->udev->dev);
|
||||
usb_autopm_put_interface(data->intf);
|
||||
|
||||
failed:
|
||||
@ -2892,11 +2909,25 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
if (id->driver_info == BTUSB_IGNORE)
|
||||
return -ENODEV;
|
||||
|
||||
if (id->driver_info & BTUSB_BCM_NO_PRODID) {
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
|
||||
/* For the broken Broadcom devices that show 0000:0000
|
||||
* as USB vendor and product information, check that the
|
||||
* manufacturer string identifies them as Broadcom based
|
||||
* devices.
|
||||
*/
|
||||
if (!udev->manufacturer ||
|
||||
strcmp(udev->manufacturer, "Broadcom Corp"))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_ATH3012) {
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
|
||||
/* Old firmware would otherwise let ath3k driver load
|
||||
* patch and sysconfig files */
|
||||
* patch and sysconfig files
|
||||
*/
|
||||
if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001)
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -3067,6 +3098,12 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
if (id->driver_info & BTUSB_QCA_ROME) {
|
||||
data->setup_on_usb = btusb_setup_qca;
|
||||
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
set_bit(BTUSB_RESET_RESUME, &data->flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BT_HCIBTUSB_RTL
|
||||
@ -3259,13 +3296,28 @@ static void play_deferred(struct btusb_data *data)
|
||||
int err;
|
||||
|
||||
while ((urb = usb_get_from_anchor(&data->deferred))) {
|
||||
usb_anchor_urb(urb, &data->tx_anchor);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
if (err != -EPERM && err != -ENODEV)
|
||||
BT_ERR("%s urb %p submission failed (%d)",
|
||||
data->hdev->name, urb, -err);
|
||||
kfree(urb->setup_packet);
|
||||
usb_unanchor_urb(urb);
|
||||
usb_free_urb(urb);
|
||||
break;
|
||||
}
|
||||
|
||||
data->tx_in_flight++;
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
|
||||
/* Cleanup the rest deferred urbs. */
|
||||
while ((urb = usb_get_from_anchor(&data->deferred))) {
|
||||
kfree(urb->setup_packet);
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
usb_scuttle_anchored_urbs(&data->deferred);
|
||||
}
|
||||
|
||||
static int btusb_resume(struct usb_interface *intf)
|
||||
|
@ -93,8 +93,7 @@ static void st_reg_completion_cb(void *priv_data, int data)
|
||||
complete(&lhst->wait_reg_completion);
|
||||
}
|
||||
|
||||
/* Called by Shared Transport layer when receive data is
|
||||
* available */
|
||||
/* Called by Shared Transport layer when receive data is available */
|
||||
static long st_receive(void *priv_data, struct sk_buff *skb)
|
||||
{
|
||||
struct ti_st *lhst = priv_data;
|
||||
@ -198,7 +197,8 @@ static int ti_st_open(struct hci_dev *hdev)
|
||||
}
|
||||
|
||||
/* Is ST registration callback
|
||||
* called with ERROR status? */
|
||||
* called with ERROR status?
|
||||
*/
|
||||
if (hst->reg_status != 0) {
|
||||
BT_ERR("ST registration completed with invalid "
|
||||
"status %d", hst->reg_status);
|
||||
@ -276,7 +276,7 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
static int bt_ti_probe(struct platform_device *pdev)
|
||||
{
|
||||
static struct ti_st *hst;
|
||||
struct ti_st *hst;
|
||||
struct hci_dev *hdev;
|
||||
int err;
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
@ -34,6 +36,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/serdev.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
@ -41,11 +44,15 @@
|
||||
#include "btbcm.h"
|
||||
#include "hci_uart.h"
|
||||
|
||||
#define BCM_NULL_PKT 0x00
|
||||
#define BCM_NULL_SIZE 0
|
||||
|
||||
#define BCM_LM_DIAG_PKT 0x07
|
||||
#define BCM_LM_DIAG_SIZE 63
|
||||
|
||||
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
|
||||
|
||||
/* platform device driver resources */
|
||||
struct bcm_device {
|
||||
struct list_head list;
|
||||
|
||||
@ -59,6 +66,7 @@ struct bcm_device {
|
||||
bool clk_enabled;
|
||||
|
||||
u32 init_speed;
|
||||
u32 oper_speed;
|
||||
int irq;
|
||||
u8 irq_polarity;
|
||||
|
||||
@ -68,6 +76,12 @@ struct bcm_device {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* serdev driver resources */
|
||||
struct bcm_serdev {
|
||||
struct hci_uart hu;
|
||||
};
|
||||
|
||||
/* generic bcm uart resources */
|
||||
struct bcm_data {
|
||||
struct sk_buff *rx_skb;
|
||||
struct sk_buff_head txq;
|
||||
@ -79,6 +93,14 @@ struct bcm_data {
|
||||
static DEFINE_MUTEX(bcm_device_lock);
|
||||
static LIST_HEAD(bcm_device_list);
|
||||
|
||||
static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
|
||||
{
|
||||
if (hu->serdev)
|
||||
serdev_device_set_baudrate(hu->serdev, speed);
|
||||
else
|
||||
hci_uart_set_baudrate(hu, speed);
|
||||
}
|
||||
|
||||
static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
|
||||
{
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
@ -176,7 +198,7 @@ static irqreturn_t bcm_host_wake(int irq, void *data)
|
||||
static int bcm_request_irq(struct bcm_data *bcm)
|
||||
{
|
||||
struct bcm_device *bdev = bcm->dev;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
/* If this is not a platform device, do not enable PM functionalities */
|
||||
mutex_lock(&bcm_device_lock);
|
||||
@ -185,22 +207,24 @@ static int bcm_request_irq(struct bcm_data *bcm)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (bdev->irq > 0) {
|
||||
err = devm_request_irq(&bdev->pdev->dev, bdev->irq,
|
||||
bcm_host_wake, IRQF_TRIGGER_RISING,
|
||||
"host_wake", bdev);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
device_init_wakeup(&bdev->pdev->dev, true);
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&bdev->pdev->dev,
|
||||
BCM_AUTOSUSPEND_DELAY);
|
||||
pm_runtime_use_autosuspend(&bdev->pdev->dev);
|
||||
pm_runtime_set_active(&bdev->pdev->dev);
|
||||
pm_runtime_enable(&bdev->pdev->dev);
|
||||
if (bdev->irq <= 0) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = devm_request_irq(&bdev->pdev->dev, bdev->irq, bcm_host_wake,
|
||||
IRQF_TRIGGER_RISING, "host_wake", bdev);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
device_init_wakeup(&bdev->pdev->dev, true);
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&bdev->pdev->dev,
|
||||
BCM_AUTOSUSPEND_DELAY);
|
||||
pm_runtime_use_autosuspend(&bdev->pdev->dev);
|
||||
pm_runtime_set_active(&bdev->pdev->dev);
|
||||
pm_runtime_enable(&bdev->pdev->dev);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
|
||||
@ -287,6 +311,14 @@ static int bcm_open(struct hci_uart *hu)
|
||||
|
||||
hu->priv = bcm;
|
||||
|
||||
/* If this is a serdev defined device, then only use
|
||||
* serdev open primitive and skip the rest.
|
||||
*/
|
||||
if (hu->serdev) {
|
||||
serdev_device_open(hu->serdev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!hu->tty->dev)
|
||||
goto out;
|
||||
|
||||
@ -301,6 +333,7 @@ static int bcm_open(struct hci_uart *hu)
|
||||
if (hu->tty->dev->parent == dev->pdev->dev.parent) {
|
||||
bcm->dev = dev;
|
||||
hu->init_speed = dev->init_speed;
|
||||
hu->oper_speed = dev->oper_speed;
|
||||
#ifdef CONFIG_PM
|
||||
dev->hu = hu;
|
||||
#endif
|
||||
@ -321,6 +354,12 @@ static int bcm_close(struct hci_uart *hu)
|
||||
|
||||
bt_dev_dbg(hu->hdev, "hu %p", hu);
|
||||
|
||||
/* If this is a serdev defined device, only use serdev
|
||||
* close primitive and then continue as usual.
|
||||
*/
|
||||
if (hu->serdev)
|
||||
serdev_device_close(hu->serdev);
|
||||
|
||||
/* Protect bcm->dev against removal of the device or driver */
|
||||
mutex_lock(&bcm_device_lock);
|
||||
if (bcm_device_exists(bdev)) {
|
||||
@ -396,7 +435,7 @@ static int bcm_setup(struct hci_uart *hu)
|
||||
speed = 0;
|
||||
|
||||
if (speed)
|
||||
hci_uart_set_baudrate(hu, speed);
|
||||
host_set_baudrate(hu, speed);
|
||||
|
||||
/* Operational speed if any */
|
||||
if (hu->oper_speed)
|
||||
@ -409,7 +448,7 @@ static int bcm_setup(struct hci_uart *hu)
|
||||
if (speed) {
|
||||
err = bcm_set_baudrate(hu, speed);
|
||||
if (!err)
|
||||
hci_uart_set_baudrate(hu, speed);
|
||||
host_set_baudrate(hu, speed);
|
||||
}
|
||||
|
||||
finalize:
|
||||
@ -432,11 +471,19 @@ finalize:
|
||||
.lsize = 0, \
|
||||
.maxlen = BCM_LM_DIAG_SIZE
|
||||
|
||||
#define BCM_RECV_NULL \
|
||||
.type = BCM_NULL_PKT, \
|
||||
.hlen = BCM_NULL_SIZE, \
|
||||
.loff = 0, \
|
||||
.lsize = 0, \
|
||||
.maxlen = BCM_NULL_SIZE
|
||||
|
||||
static const struct h4_recv_pkt bcm_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
|
||||
{ BCM_RECV_NULL, .recv = hci_recv_diag },
|
||||
};
|
||||
|
||||
static int bcm_recv(struct hci_uart *hu, const void *data, int count)
|
||||
@ -697,8 +744,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
|
||||
|
||||
case ACPI_RESOURCE_TYPE_SERIAL_BUS:
|
||||
sb = &ares->data.uart_serial_bus;
|
||||
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART)
|
||||
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART) {
|
||||
dev->init_speed = sb->default_baud_rate;
|
||||
dev->oper_speed = 4000000;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -851,7 +900,6 @@ static const struct hci_uart_proto bcm_proto = {
|
||||
.name = "Broadcom",
|
||||
.manufacturer = 15,
|
||||
.init_speed = 115200,
|
||||
.oper_speed = 4000000,
|
||||
.open = bcm_open,
|
||||
.close = bcm_close,
|
||||
.flush = bcm_flush,
|
||||
@ -901,9 +949,57 @@ static struct platform_driver bcm_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int bcm_serdev_probe(struct serdev_device *serdev)
|
||||
{
|
||||
struct bcm_serdev *bcmdev;
|
||||
u32 speed;
|
||||
int err;
|
||||
|
||||
bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL);
|
||||
if (!bcmdev)
|
||||
return -ENOMEM;
|
||||
|
||||
bcmdev->hu.serdev = serdev;
|
||||
serdev_device_set_drvdata(serdev, bcmdev);
|
||||
|
||||
err = device_property_read_u32(&serdev->dev, "max-speed", &speed);
|
||||
if (!err)
|
||||
bcmdev->hu.oper_speed = speed;
|
||||
|
||||
return hci_uart_register_device(&bcmdev->hu, &bcm_proto);
|
||||
}
|
||||
|
||||
static void bcm_serdev_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct bcm_serdev *bcmdev = serdev_device_get_drvdata(serdev);
|
||||
|
||||
hci_uart_unregister_device(&bcmdev->hu);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id bcm_bluetooth_of_match[] = {
|
||||
{ .compatible = "brcm,bcm43438-bt" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);
|
||||
#endif
|
||||
|
||||
static struct serdev_device_driver bcm_serdev_driver = {
|
||||
.probe = bcm_serdev_probe,
|
||||
.remove = bcm_serdev_remove,
|
||||
.driver = {
|
||||
.name = "hci_uart_bcm",
|
||||
.of_match_table = of_match_ptr(bcm_bluetooth_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm_init(void)
|
||||
{
|
||||
/* For now, we need to keep both platform device
|
||||
* driver (ACPI generated) and serdev driver (DT).
|
||||
*/
|
||||
platform_driver_register(&bcm_driver);
|
||||
serdev_device_driver_register(&bcm_serdev_driver);
|
||||
|
||||
return hci_uart_register_proto(&bcm_proto);
|
||||
}
|
||||
@ -911,6 +1007,7 @@ int __init bcm_init(void)
|
||||
int __exit bcm_deinit(void)
|
||||
{
|
||||
platform_driver_unregister(&bcm_driver);
|
||||
serdev_device_driver_unregister(&bcm_serdev_driver);
|
||||
|
||||
return hci_uart_unregister_proto(&bcm_proto);
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
const struct h4_recv_pkt *pkts, int pkts_count)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
u8 alignment = hu->alignment;
|
||||
u8 alignment = hu->alignment ? hu->alignment : 1;
|
||||
|
||||
while (count) {
|
||||
int i, len;
|
||||
|
@ -457,7 +457,8 @@ static int hci_uart_tty_open(struct tty_struct *tty)
|
||||
BT_DBG("tty %p", tty);
|
||||
|
||||
/* Error if the tty has no write op instead of leaving an exploitable
|
||||
hole */
|
||||
* hole
|
||||
*/
|
||||
if (tty->ops->write == NULL)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@ -622,7 +622,8 @@ static int download_firmware(struct ll_device *lldev)
|
||||
cmd = (struct hci_command *)action_ptr;
|
||||
if (cmd->opcode == 0xff36) {
|
||||
/* ignore remote change
|
||||
* baud rate HCI VS command */
|
||||
* baud rate HCI VS command
|
||||
*/
|
||||
bt_dev_warn(lldev->hu.hdev, "change remote baud rate command in firmware");
|
||||
break;
|
||||
}
|
||||
@ -742,14 +743,8 @@ static int hci_ti_probe(struct serdev_device *serdev)
|
||||
static void hci_ti_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct ll_device *lldev = serdev_device_get_drvdata(serdev);
|
||||
struct hci_uart *hu = &lldev->hu;
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
hu->proto->close(hu);
|
||||
hci_uart_unregister_device(&lldev->hu);
|
||||
}
|
||||
|
||||
static const struct of_device_id hci_ti_of_match[] = {
|
||||
|
@ -767,16 +767,8 @@ static int nokia_bluetooth_serdev_probe(struct serdev_device *serdev)
|
||||
static void nokia_bluetooth_serdev_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct nokia_bt_dev *btdev = serdev_device_get_drvdata(serdev);
|
||||
struct hci_uart *hu = &btdev->hu;
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
hu->proto->close(hu);
|
||||
|
||||
pm_runtime_disable(&btdev->serdev->dev);
|
||||
hci_uart_unregister_device(&btdev->hu);
|
||||
}
|
||||
|
||||
static int nokia_bluetooth_runtime_suspend(struct device *dev)
|
||||
|
@ -354,3 +354,16 @@ err_alloc:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hci_uart_register_device);
|
||||
|
||||
void hci_uart_unregister_device(struct hci_uart *hu)
|
||||
{
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
hu->proto->close(hu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hci_uart_unregister_device);
|
||||
|
@ -112,6 +112,7 @@ struct hci_uart {
|
||||
int hci_uart_register_proto(const struct hci_uart_proto *p);
|
||||
int hci_uart_unregister_proto(const struct hci_uart_proto *p);
|
||||
int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p);
|
||||
void hci_uart_unregister_device(struct hci_uart *hu);
|
||||
|
||||
int hci_uart_tx_wakeup(struct hci_uart *hu);
|
||||
int hci_uart_init_ready(struct hci_uart *hu);
|
||||
|
@ -661,9 +661,23 @@ void vmbus_close(struct vmbus_channel *channel)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_close);
|
||||
|
||||
int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
||||
u32 bufferlen, u64 requestid,
|
||||
enum vmbus_packet_type type, u32 flags)
|
||||
/**
|
||||
* vmbus_sendpacket() - Send the specified buffer on the given channel
|
||||
* @channel: Pointer to vmbus_channel structure.
|
||||
* @buffer: Pointer to the buffer you want to receive the data into.
|
||||
* @bufferlen: Maximum size of what the the buffer will hold
|
||||
* @requestid: Identifier of the request
|
||||
* @type: Type of packet that is being send e.g. negotiate, time
|
||||
* packet etc.
|
||||
*
|
||||
* Sends data in @buffer directly to hyper-v via the vmbus
|
||||
* This will send the data unparsed to hyper-v.
|
||||
*
|
||||
* Mainly used by Hyper-V drivers.
|
||||
*/
|
||||
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
|
||||
u32 bufferlen, u64 requestid,
|
||||
enum vmbus_packet_type type, u32 flags)
|
||||
{
|
||||
struct vmpacket_descriptor desc;
|
||||
u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
|
||||
@ -690,42 +704,19 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
|
||||
|
||||
return hv_ringbuffer_write(channel, bufferlist, num_vecs);
|
||||
}
|
||||
EXPORT_SYMBOL(vmbus_sendpacket_ctl);
|
||||
|
||||
/**
|
||||
* vmbus_sendpacket() - Send the specified buffer on the given channel
|
||||
* @channel: Pointer to vmbus_channel structure.
|
||||
* @buffer: Pointer to the buffer you want to receive the data into.
|
||||
* @bufferlen: Maximum size of what the the buffer will hold
|
||||
* @requestid: Identifier of the request
|
||||
* @type: Type of packet that is being send e.g. negotiate, time
|
||||
* packet etc.
|
||||
*
|
||||
* Sends data in @buffer directly to hyper-v via the vmbus
|
||||
* This will send the data unparsed to hyper-v.
|
||||
*
|
||||
* Mainly used by Hyper-V drivers.
|
||||
*/
|
||||
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
|
||||
u32 bufferlen, u64 requestid,
|
||||
enum vmbus_packet_type type, u32 flags)
|
||||
{
|
||||
return vmbus_sendpacket_ctl(channel, buffer, bufferlen, requestid,
|
||||
type, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(vmbus_sendpacket);
|
||||
|
||||
/*
|
||||
* vmbus_sendpacket_pagebuffer_ctl - Send a range of single-page buffer
|
||||
* vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
|
||||
* packets using a GPADL Direct packet type. This interface allows you
|
||||
* to control notifying the host. This will be useful for sending
|
||||
* batched data. Also the sender can control the send flags
|
||||
* explicitly.
|
||||
*/
|
||||
int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||
struct hv_page_buffer pagebuffers[],
|
||||
u32 pagecount, void *buffer, u32 bufferlen,
|
||||
u64 requestid, u32 flags)
|
||||
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
|
||||
struct hv_page_buffer pagebuffers[],
|
||||
u32 pagecount, void *buffer, u32 bufferlen,
|
||||
u64 requestid)
|
||||
{
|
||||
int i;
|
||||
struct vmbus_channel_packet_page_buffer desc;
|
||||
@ -750,7 +741,7 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||
|
||||
/* Setup the descriptor */
|
||||
desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
|
||||
desc.flags = flags;
|
||||
desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
|
||||
desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */
|
||||
desc.length8 = (u16)(packetlen_aligned >> 3);
|
||||
desc.transactionid = requestid;
|
||||
@ -771,24 +762,6 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
|
||||
|
||||
return hv_ringbuffer_write(channel, bufferlist, 3);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl);
|
||||
|
||||
/*
|
||||
* vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
|
||||
* packets using a GPADL Direct packet type.
|
||||
*/
|
||||
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
|
||||
struct hv_page_buffer pagebuffers[],
|
||||
u32 pagecount, void *buffer, u32 bufferlen,
|
||||
u64 requestid)
|
||||
{
|
||||
u32 flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
|
||||
|
||||
return vmbus_sendpacket_pagebuffer_ctl(channel, pagebuffers, pagecount,
|
||||
buffer, bufferlen,
|
||||
requestid, flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
|
||||
|
||||
/*
|
||||
@ -828,62 +801,6 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);
|
||||
|
||||
/*
|
||||
* vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
|
||||
* using a GPADL Direct packet type.
|
||||
*/
|
||||
int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
|
||||
struct hv_multipage_buffer *multi_pagebuffer,
|
||||
void *buffer, u32 bufferlen, u64 requestid)
|
||||
{
|
||||
struct vmbus_channel_packet_multipage_buffer desc;
|
||||
u32 descsize;
|
||||
u32 packetlen;
|
||||
u32 packetlen_aligned;
|
||||
struct kvec bufferlist[3];
|
||||
u64 aligned_data = 0;
|
||||
u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
|
||||
multi_pagebuffer->len);
|
||||
|
||||
if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Adjust the size down since vmbus_channel_packet_multipage_buffer is
|
||||
* the largest size we support
|
||||
*/
|
||||
descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
|
||||
((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
|
||||
sizeof(u64));
|
||||
packetlen = descsize + bufferlen;
|
||||
packetlen_aligned = ALIGN(packetlen, sizeof(u64));
|
||||
|
||||
|
||||
/* Setup the descriptor */
|
||||
desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
|
||||
desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
|
||||
desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */
|
||||
desc.length8 = (u16)(packetlen_aligned >> 3);
|
||||
desc.transactionid = requestid;
|
||||
desc.rangecount = 1;
|
||||
|
||||
desc.range.len = multi_pagebuffer->len;
|
||||
desc.range.offset = multi_pagebuffer->offset;
|
||||
|
||||
memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
|
||||
pfncount * sizeof(u64));
|
||||
|
||||
bufferlist[0].iov_base = &desc;
|
||||
bufferlist[0].iov_len = descsize;
|
||||
bufferlist[1].iov_base = buffer;
|
||||
bufferlist[1].iov_len = bufferlen;
|
||||
bufferlist[2].iov_base = &aligned_data;
|
||||
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
|
||||
|
||||
return hv_ringbuffer_write(channel, bufferlist, 3);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
|
||||
|
||||
/**
|
||||
* vmbus_recvpacket() - Retrieve the user packet on the specified channel
|
||||
* @channel: Pointer to vmbus_channel structure.
|
||||
|
@ -1,6 +1,7 @@
|
||||
config INFINIBAND_BNXT_RE
|
||||
tristate "Broadcom Netxtreme HCA support"
|
||||
depends on ETHERNET && NETDEVICES && PCI && INET && DCB
|
||||
depends on MAY_USE_DEVLINK
|
||||
select NET_VENDOR_BROADCOM
|
||||
select BNXT
|
||||
---help---
|
||||
|
@ -150,8 +150,8 @@ static int is_sqp(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
|
||||
/* VF or PF -- proxy SQP */
|
||||
if (mlx4_is_mfunc(dev->dev)) {
|
||||
for (i = 0; i < dev->dev->caps.num_ports; i++) {
|
||||
if (qp->mqp.qpn == dev->dev->caps.qp0_proxy[i] ||
|
||||
qp->mqp.qpn == dev->dev->caps.qp1_proxy[i]) {
|
||||
if (qp->mqp.qpn == dev->dev->caps.spec_qps[i].qp0_proxy ||
|
||||
qp->mqp.qpn == dev->dev->caps.spec_qps[i].qp1_proxy) {
|
||||
proxy_sqp = 1;
|
||||
break;
|
||||
}
|
||||
@ -178,7 +178,7 @@ static int is_qp0(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
|
||||
/* VF or PF -- proxy QP0 */
|
||||
if (mlx4_is_mfunc(dev->dev)) {
|
||||
for (i = 0; i < dev->dev->caps.num_ports; i++) {
|
||||
if (qp->mqp.qpn == dev->dev->caps.qp0_proxy[i]) {
|
||||
if (qp->mqp.qpn == dev->dev->caps.spec_qps[i].qp0_proxy) {
|
||||
proxy_qp0 = 1;
|
||||
break;
|
||||
}
|
||||
@ -632,8 +632,8 @@ static int qp0_enabled_vf(struct mlx4_dev *dev, int qpn)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dev->caps.num_ports; i++) {
|
||||
if (qpn == dev->caps.qp0_proxy[i])
|
||||
return !!dev->caps.qp0_qkey[i];
|
||||
if (qpn == dev->caps.spec_qps[i].qp0_proxy)
|
||||
return !!dev->caps.spec_qps[i].qp0_qkey;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1521,9 +1521,9 @@ static u32 get_sqp_num(struct mlx4_ib_dev *dev, struct ib_qp_init_attr *attr)
|
||||
}
|
||||
/* PF or VF -- creating proxies */
|
||||
if (attr->qp_type == IB_QPT_SMI)
|
||||
return dev->dev->caps.qp0_proxy[attr->port_num - 1];
|
||||
return dev->dev->caps.spec_qps[attr->port_num - 1].qp0_proxy;
|
||||
else
|
||||
return dev->dev->caps.qp1_proxy[attr->port_num - 1];
|
||||
return dev->dev->caps.spec_qps[attr->port_num - 1].qp1_proxy;
|
||||
}
|
||||
|
||||
static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,
|
||||
@ -2880,9 +2880,9 @@ static int vf_get_qp0_qkey(struct mlx4_dev *dev, int qpn, u32 *qkey)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dev->caps.num_ports; i++) {
|
||||
if (qpn == dev->caps.qp0_proxy[i] ||
|
||||
qpn == dev->caps.qp0_tunnel[i]) {
|
||||
*qkey = dev->caps.qp0_qkey[i];
|
||||
if (qpn == dev->caps.spec_qps[i].qp0_proxy ||
|
||||
qpn == dev->caps.spec_qps[i].qp0_tunnel) {
|
||||
*qkey = dev->caps.spec_qps[i].qp0_qkey;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -2943,7 +2943,7 @@ static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
|
||||
sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
|
||||
else
|
||||
sqp->ud_header.bth.destination_qpn =
|
||||
cpu_to_be32(mdev->dev->caps.qp0_tunnel[sqp->qp.port - 1]);
|
||||
cpu_to_be32(mdev->dev->caps.spec_qps[sqp->qp.port - 1].qp0_tunnel);
|
||||
|
||||
sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
|
||||
if (mlx4_is_master(mdev->dev)) {
|
||||
@ -3403,9 +3403,9 @@ static void set_tunnel_datagram_seg(struct mlx4_ib_dev *dev,
|
||||
|
||||
memcpy(dseg->av, &sqp_av, sizeof (struct mlx4_av));
|
||||
if (qpt == MLX4_IB_QPT_PROXY_GSI)
|
||||
dseg->dqpn = cpu_to_be32(dev->dev->caps.qp1_tunnel[port - 1]);
|
||||
dseg->dqpn = cpu_to_be32(dev->dev->caps.spec_qps[port - 1].qp1_tunnel);
|
||||
else
|
||||
dseg->dqpn = cpu_to_be32(dev->dev->caps.qp0_tunnel[port - 1]);
|
||||
dseg->dqpn = cpu_to_be32(dev->dev->caps.spec_qps[port - 1].qp0_tunnel);
|
||||
/* Use QKEY from the QP context, which is set by master */
|
||||
dseg->qkey = cpu_to_be32(IB_QP_SET_QKEY);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ struct capictr_event {
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_version driver_version = {2, 0, 1, 1 << 4};
|
||||
static const struct capi_version driver_version = {2, 0, 1, 1 << 4};
|
||||
static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
|
||||
static char capi_manufakturer[64] = "AVM Berlin";
|
||||
|
||||
|
@ -26,15 +26,7 @@
|
||||
|
||||
/*#define DEBUG */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define IMPLEMENT_DTMF 1
|
||||
#define IMPLEMENT_LINE_INTERCONNECT2 1
|
||||
@ -82,8 +74,6 @@
|
||||
#define CODEC_PERMANENT 0x02
|
||||
#define ADV_VOICE 0x03
|
||||
#define MAX_CIP_TYPES 5 /* kind of CIP types for group optimization */
|
||||
#define C_IND_MASK_DWORDS ((MAX_APPL + 32) >> 5)
|
||||
|
||||
|
||||
#define FAX_CONNECT_INFO_BUFFER_SIZE 256
|
||||
#define NCPI_BUFFER_SIZE 256
|
||||
@ -265,8 +255,8 @@ struct _PLCI {
|
||||
word ncci_ring_list;
|
||||
byte inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI];
|
||||
t_std_internal_command internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS];
|
||||
dword c_ind_mask_table[C_IND_MASK_DWORDS];
|
||||
dword group_optimization_mask_table[C_IND_MASK_DWORDS];
|
||||
DECLARE_BITMAP(c_ind_mask_table, MAX_APPL);
|
||||
DECLARE_BITMAP(group_optimization_mask_table, MAX_APPL);
|
||||
byte RBuffer[200];
|
||||
dword msg_in_queue[MSG_IN_QUEUE_SIZE/sizeof(dword)];
|
||||
API_SAVE saved_msg;
|
||||
|
@ -23,9 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "di_defs.h"
|
||||
@ -35,19 +33,9 @@
|
||||
#include "mdm_msg.h"
|
||||
#include "divasync.h"
|
||||
|
||||
|
||||
|
||||
#define FILE_ "MESSAGE.C"
|
||||
#define dprintf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* This is options supported for all adapters that are server by */
|
||||
/* XDI driver. Allo it is not necessary to ask it from every adapter*/
|
||||
@ -72,9 +60,6 @@ static dword diva_xdi_extended_features = 0;
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
|
||||
static void set_group_ind_mask(PLCI *plci);
|
||||
static void clear_group_ind_mask_bit(PLCI *plci, word b);
|
||||
static byte test_group_ind_mask_bit(PLCI *plci, word b);
|
||||
void AutomaticLaw(DIVA_CAPI_ADAPTER *);
|
||||
word CapiRelease(word);
|
||||
word CapiRegister(word);
|
||||
@ -1086,106 +1071,6 @@ static void plci_remove(PLCI *plci)
|
||||
plci->State = OUTG_DIS_PENDING;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Application Group function helpers */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static void set_group_ind_mask(PLCI *plci)
|
||||
{
|
||||
word i;
|
||||
|
||||
for (i = 0; i < C_IND_MASK_DWORDS; i++)
|
||||
plci->group_optimization_mask_table[i] = 0xffffffffL;
|
||||
}
|
||||
|
||||
static void clear_group_ind_mask_bit(PLCI *plci, word b)
|
||||
{
|
||||
plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
|
||||
}
|
||||
|
||||
static byte test_group_ind_mask_bit(PLCI *plci, word b)
|
||||
{
|
||||
return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* c_ind_mask operations for arbitrary MAX_APPL */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static void clear_c_ind_mask(PLCI *plci)
|
||||
{
|
||||
word i;
|
||||
|
||||
for (i = 0; i < C_IND_MASK_DWORDS; i++)
|
||||
plci->c_ind_mask_table[i] = 0;
|
||||
}
|
||||
|
||||
static byte c_ind_mask_empty(PLCI *plci)
|
||||
{
|
||||
word i;
|
||||
|
||||
i = 0;
|
||||
while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
|
||||
i++;
|
||||
return (i == C_IND_MASK_DWORDS);
|
||||
}
|
||||
|
||||
static void set_c_ind_mask_bit(PLCI *plci, word b)
|
||||
{
|
||||
plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
|
||||
}
|
||||
|
||||
static void clear_c_ind_mask_bit(PLCI *plci, word b)
|
||||
{
|
||||
plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
|
||||
}
|
||||
|
||||
static byte test_c_ind_mask_bit(PLCI *plci, word b)
|
||||
{
|
||||
return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
|
||||
}
|
||||
|
||||
static void dump_c_ind_mask(PLCI *plci)
|
||||
{
|
||||
word i, j, k;
|
||||
dword d;
|
||||
char *p;
|
||||
char buf[40];
|
||||
|
||||
for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
|
||||
{
|
||||
p = buf + 36;
|
||||
*p = '\0';
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (i + j < C_IND_MASK_DWORDS)
|
||||
{
|
||||
d = plci->c_ind_mask_table[i + j];
|
||||
for (k = 0; k < 8; k++)
|
||||
{
|
||||
*(--p) = hex_asc_lo(d);
|
||||
d >>= 4;
|
||||
}
|
||||
}
|
||||
else if (i != 0)
|
||||
{
|
||||
for (k = 0; k < 8; k++)
|
||||
*(--p) = ' ';
|
||||
}
|
||||
*(--p) = ' ';
|
||||
}
|
||||
dbug(1, dprintf("c_ind_mask =%s", (char *) p));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define dump_plcis(a)
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* translation function for each message */
|
||||
/*------------------------------------------------------------------*/
|
||||
@ -1457,13 +1342,13 @@ static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
||||
return 1;
|
||||
}
|
||||
else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
|
||||
clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
|
||||
dump_c_ind_mask(plci);
|
||||
__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
|
||||
dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
|
||||
Reject = GET_WORD(parms[0].info);
|
||||
dbug(1, dprintf("Reject=0x%x", Reject));
|
||||
if (Reject)
|
||||
{
|
||||
if (c_ind_mask_empty(plci))
|
||||
if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
|
||||
{
|
||||
if ((Reject & 0xff00) == 0x3400)
|
||||
{
|
||||
@ -1553,11 +1438,8 @@ static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
||||
sig_req(plci, CALL_RES, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < max_appl; i++) {
|
||||
if (test_c_ind_mask_bit(plci, i)) {
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
|
||||
}
|
||||
}
|
||||
for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@ -1584,13 +1466,10 @@ static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
||||
{
|
||||
if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
|
||||
{
|
||||
clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
|
||||
__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
|
||||
plci->appl = appl;
|
||||
for (i = 0; i < max_appl; i++)
|
||||
{
|
||||
if (test_c_ind_mask_bit(plci, i))
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
|
||||
}
|
||||
for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
|
||||
plci->State = OUTG_DIS_PENDING;
|
||||
}
|
||||
if (plci->Sig.Id && plci->appl)
|
||||
@ -1634,7 +1513,7 @@ static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
||||
{
|
||||
/* clear ind mask bit, just in case of collsion of */
|
||||
/* DISCONNECT_IND and CONNECT_RES */
|
||||
clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
|
||||
__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
|
||||
ncci_free_receive_buffers(plci, 0);
|
||||
if (plci_remove_check(plci))
|
||||
{
|
||||
@ -1642,7 +1521,7 @@ static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
||||
}
|
||||
if (plci->State == INC_DIS_PENDING
|
||||
|| plci->State == SUSPENDING) {
|
||||
if (c_ind_mask_empty(plci)) {
|
||||
if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
|
||||
if (plci->State != SUSPENDING) plci->State = IDLE;
|
||||
dbug(1, dprintf("chs=%d", plci->channels));
|
||||
if (!plci->channels) {
|
||||
@ -3351,13 +3230,11 @@ static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
||||
}
|
||||
plci->State = INC_CON_CONNECTED_ALERT;
|
||||
plci->appl = appl;
|
||||
clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
|
||||
dump_c_ind_mask(plci);
|
||||
for (i = 0; i < max_appl; i++) /* disconnect the other appls */
|
||||
{ /* its quasi a connect */
|
||||
if (test_c_ind_mask_bit(plci, i))
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
|
||||
}
|
||||
__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
|
||||
dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
|
||||
/* disconnect the other appls its quasi a connect */
|
||||
for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
|
||||
}
|
||||
|
||||
api_save_msg(msg, "s", &plci->saved_msg);
|
||||
@ -5692,19 +5569,17 @@ static void sig_ind(PLCI *plci)
|
||||
cip = find_cip(a, parms[4], parms[6]);
|
||||
cip_mask = 1L << cip;
|
||||
dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
|
||||
clear_c_ind_mask(plci);
|
||||
bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
|
||||
if (!remove_started && !a->adapter_disabled)
|
||||
{
|
||||
set_c_ind_mask_bit(plci, MAX_APPL);
|
||||
group_optimization(a, plci);
|
||||
for (i = 0; i < max_appl; i++) {
|
||||
for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
|
||||
if (application[i].Id
|
||||
&& (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
|
||||
&& CPN_filter_ok(parms[0], a, i)
|
||||
&& test_group_ind_mask_bit(plci, i)) {
|
||||
&& CPN_filter_ok(parms[0], a, i)) {
|
||||
dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
|
||||
set_c_ind_mask_bit(plci, i);
|
||||
dump_c_ind_mask(plci);
|
||||
__set_bit(i, plci->c_ind_mask_table);
|
||||
dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
|
||||
plci->State = INC_CON_PENDING;
|
||||
plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
|
||||
CALL_DIR_IN | CALL_DIR_ANSWER;
|
||||
@ -5750,10 +5625,9 @@ static void sig_ind(PLCI *plci)
|
||||
SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
|
||||
}
|
||||
}
|
||||
clear_c_ind_mask_bit(plci, MAX_APPL);
|
||||
dump_c_ind_mask(plci);
|
||||
dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
|
||||
}
|
||||
if (c_ind_mask_empty(plci)) {
|
||||
if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
|
||||
sig_req(plci, HANGUP, 0);
|
||||
send_req(plci);
|
||||
plci->State = IDLE;
|
||||
@ -5994,13 +5868,13 @@ static void sig_ind(PLCI *plci)
|
||||
break;
|
||||
|
||||
case RESUME:
|
||||
clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
|
||||
__clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
|
||||
PUT_WORD(&resume_cau[4], GOOD);
|
||||
sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
|
||||
break;
|
||||
|
||||
case SUSPEND:
|
||||
clear_c_ind_mask(plci);
|
||||
bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
|
||||
|
||||
if (plci->NL.Id && !plci->nl_remove_id) {
|
||||
mixer_remove(plci);
|
||||
@ -6037,15 +5911,12 @@ static void sig_ind(PLCI *plci)
|
||||
|
||||
if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
|
||||
{
|
||||
for (i = 0; i < max_appl; i++)
|
||||
{
|
||||
if (test_c_ind_mask_bit(plci, i))
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
|
||||
}
|
||||
for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
|
||||
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
clear_c_ind_mask(plci);
|
||||
bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
|
||||
}
|
||||
if (!plci->appl)
|
||||
{
|
||||
@ -6055,7 +5926,7 @@ static void sig_ind(PLCI *plci)
|
||||
a->listen_active--;
|
||||
}
|
||||
plci->State = INC_DIS_PENDING;
|
||||
if (c_ind_mask_empty(plci))
|
||||
if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
|
||||
{
|
||||
plci->State = IDLE;
|
||||
if (plci->NL.Id && !plci->nl_remove_id)
|
||||
@ -6341,14 +6212,10 @@ static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
|
||||
|| Info_Number == DSP
|
||||
|| Info_Number == UUI)
|
||||
{
|
||||
for (j = 0; j < max_appl; j++)
|
||||
{
|
||||
if (test_c_ind_mask_bit(plci, j))
|
||||
{
|
||||
dbug(1, dprintf("Ovl_Ind"));
|
||||
iesent = true;
|
||||
sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
|
||||
}
|
||||
for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
|
||||
dbug(1, dprintf("Ovl_Ind"));
|
||||
iesent = true;
|
||||
sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
|
||||
}
|
||||
}
|
||||
} /* all other signalling states */
|
||||
@ -6416,14 +6283,10 @@ static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
|
||||
}
|
||||
else if (!plci->appl && Info_Number)
|
||||
{ /* overlap receiving broadcast */
|
||||
for (j = 0; j < max_appl; j++)
|
||||
{
|
||||
if (test_c_ind_mask_bit(plci, j))
|
||||
{
|
||||
iesent = true;
|
||||
dbug(1, dprintf("Mlt_Ovl_Ind"));
|
||||
sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
|
||||
}
|
||||
for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
|
||||
iesent = true;
|
||||
dbug(1, dprintf("Mlt_Ovl_Ind"));
|
||||
sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
|
||||
}
|
||||
} /* all other signalling states */
|
||||
else if (Info_Number
|
||||
@ -7270,7 +7133,6 @@ static word get_plci(DIVA_CAPI_ADAPTER *a)
|
||||
word i, j;
|
||||
PLCI *plci;
|
||||
|
||||
dump_plcis(a);
|
||||
for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
|
||||
if (i == a->max_plci) {
|
||||
dbug(1, dprintf("get_plci: out of PLCIs"));
|
||||
@ -7321,8 +7183,8 @@ static word get_plci(DIVA_CAPI_ADAPTER *a)
|
||||
|
||||
plci->ncci_ring_list = 0;
|
||||
for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
|
||||
clear_c_ind_mask(plci);
|
||||
set_group_ind_mask(plci);
|
||||
bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
|
||||
bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
|
||||
plci->fax_connect_info_length = 0;
|
||||
plci->nsf_control_bits = 0;
|
||||
plci->ncpi_state = 0x00;
|
||||
@ -9373,10 +9235,10 @@ word CapiRelease(word Id)
|
||||
if (plci->State == INC_CON_PENDING
|
||||
|| plci->State == INC_CON_ALERT)
|
||||
{
|
||||
if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
|
||||
if (test_bit(Id - 1, plci->c_ind_mask_table))
|
||||
{
|
||||
clear_c_ind_mask_bit(plci, (word)(Id - 1));
|
||||
if (c_ind_mask_empty(plci))
|
||||
__clear_bit(Id - 1, plci->c_ind_mask_table);
|
||||
if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
|
||||
{
|
||||
sig_req(plci, HANGUP, 0);
|
||||
send_req(plci);
|
||||
@ -9384,10 +9246,10 @@ word CapiRelease(word Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
|
||||
if (test_bit(Id - 1, plci->c_ind_mask_table))
|
||||
{
|
||||
clear_c_ind_mask_bit(plci, (word)(Id - 1));
|
||||
if (c_ind_mask_empty(plci))
|
||||
__clear_bit(Id - 1, plci->c_ind_mask_table);
|
||||
if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
|
||||
{
|
||||
if (!plci->appl)
|
||||
{
|
||||
@ -9452,7 +9314,7 @@ word CapiRelease(word Id)
|
||||
static word plci_remove_check(PLCI *plci)
|
||||
{
|
||||
if (!plci) return true;
|
||||
if (!plci->NL.Id && c_ind_mask_empty(plci))
|
||||
if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
|
||||
{
|
||||
if (plci->Sig.Id == 0xff)
|
||||
plci->Sig.Id = 0;
|
||||
@ -14735,7 +14597,8 @@ static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
|
||||
word appl_number_group_type[MAX_APPL];
|
||||
PLCI *auxplci;
|
||||
|
||||
set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
|
||||
/* all APPLs within this inc. call are allowed to dial in */
|
||||
bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
|
||||
|
||||
if (!a->group_optimization_enabled)
|
||||
{
|
||||
@ -14771,13 +14634,12 @@ static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
|
||||
if (a->plci[k].Id)
|
||||
{
|
||||
auxplci = &a->plci[k];
|
||||
if (auxplci->appl == &application[i]) /* application has a busy PLCI */
|
||||
{
|
||||
if (auxplci->appl == &application[i]) {
|
||||
/* application has a busy PLCI */
|
||||
busy = true;
|
||||
dbug(1, dprintf("Appl 0x%x is busy", i + 1));
|
||||
}
|
||||
else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
|
||||
{
|
||||
} else if (test_bit(i, plci->c_ind_mask_table)) {
|
||||
/* application has an incoming call pending */
|
||||
busy = true;
|
||||
dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
|
||||
}
|
||||
@ -14826,7 +14688,8 @@ static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
|
||||
if (appl_number_group_type[i] == appl_number_group_type[j])
|
||||
{
|
||||
dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
|
||||
clear_group_ind_mask_bit(plci, j); /* disable call on other group members */
|
||||
/* disable call on other group members */
|
||||
__clear_bit(j, plci->group_optimization_mask_table);
|
||||
appl_number_group_type[j] = 0; /* remove disabled group member from group list */
|
||||
}
|
||||
}
|
||||
@ -14834,7 +14697,7 @@ static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
|
||||
}
|
||||
else /* application should not get a call */
|
||||
{
|
||||
clear_group_ind_mask_bit(plci, i);
|
||||
__clear_bit(i, plci->group_optimization_mask_table);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +337,7 @@ static const char *HFC_NT_LAYER1_STATES[HFC_MAX_NT_LAYER1_STATE + 1] = {
|
||||
};
|
||||
|
||||
/* supported devices */
|
||||
static struct usb_device_id hfcsusb_idtab[] = {
|
||||
static const struct usb_device_id hfcsusb_idtab[] = {
|
||||
{
|
||||
USB_DEVICE(0x0959, 0x2bd0),
|
||||
.driver_info = (unsigned long) &((struct hfcsusb_vdata)
|
||||
|
@ -65,7 +65,7 @@ typedef struct {
|
||||
} hfcsusb_vdata;
|
||||
|
||||
/* VID/PID device list */
|
||||
static struct usb_device_id hfcusb_idtab[] = {
|
||||
static const struct usb_device_id hfcusb_idtab[] = {
|
||||
{
|
||||
USB_DEVICE(0x0959, 0x2bd0),
|
||||
.driver_info = (unsigned long) &((hfcsusb_vdata)
|
||||
|
@ -45,7 +45,6 @@ obj-$(CONFIG_ETHERNET) += ethernet/
|
||||
obj-$(CONFIG_FDDI) += fddi/
|
||||
obj-$(CONFIG_HIPPI) += hippi/
|
||||
obj-$(CONFIG_HAMRADIO) += hamradio/
|
||||
obj-$(CONFIG_IRDA) += irda/
|
||||
obj-$(CONFIG_PLIP) += plip/
|
||||
obj-$(CONFIG_PPP) += ppp/
|
||||
obj-$(CONFIG_PPP_ASYNC) += ppp/
|
||||
|
@ -311,9 +311,7 @@ module_param(ipddp_mode, int, 0);
|
||||
static int __init ipddp_init_module(void)
|
||||
{
|
||||
dev_ipddp = ipddp_init();
|
||||
if (IS_ERR(dev_ipddp))
|
||||
return PTR_ERR(dev_ipddp);
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(dev_ipddp);
|
||||
}
|
||||
|
||||
static void __exit ipddp_cleanup_module(void)
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <linux/if_arcnet.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
/*
|
||||
* RECON_THRESHOLD is the maximum number of RECON messages to receive
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user