Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next

Pull networking updates from David Millar:
 "Here are some highlights from the 2065 networking commits that
  happened this development cycle:

   1) XDP support for IXGBE (John Fastabend) and thunderx (Sunil Kowuri)

   2) Add a generic XDP driver, so that anyone can test XDP even if they
      lack a networking device whose driver has explicit XDP support
      (me).

   3) Sparc64 now has an eBPF JIT too (me)

   4) Add a BPF program testing framework via BPF_PROG_TEST_RUN (Alexei
      Starovoitov)

   5) Make netfitler network namespace teardown less expensive (Florian
      Westphal)

   6) Add symmetric hashing support to nft_hash (Laura Garcia Liebana)

   7) Implement NAPI and GRO in netvsc driver (Stephen Hemminger)

   8) Support TC flower offload statistics in mlxsw (Arkadi Sharshevsky)

   9) Multiqueue support in stmmac driver (Joao Pinto)

  10) Remove TCP timewait recycling, it never really could possibly work
      well in the real world and timestamp randomization really zaps any
      hint of usability this feature had (Soheil Hassas Yeganeh)

  11) Support level3 vs level4 ECMP route hashing in ipv4 (Nikolay
      Aleksandrov)

  12) Add socket busy poll support to epoll (Sridhar Samudrala)

  13) Netlink extended ACK support (Johannes Berg, Pablo Neira Ayuso,
      and several others)

  14) IPSEC hw offload infrastructure (Steffen Klassert)"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (2065 commits)
  tipc: refactor function tipc_sk_recv_stream()
  tipc: refactor function tipc_sk_recvmsg()
  net: thunderx: Optimize page recycling for XDP
  net: thunderx: Support for XDP header adjustment
  net: thunderx: Add support for XDP_TX
  net: thunderx: Add support for XDP_DROP
  net: thunderx: Add basic XDP support
  net: thunderx: Cleanup receive buffer allocation
  net: thunderx: Optimize CQE_TX handling
  net: thunderx: Optimize RBDR descriptor handling
  net: thunderx: Support for page recycling
  ipx: call ipxitf_put() in ioctl error path
  net: sched: add helpers to handle extended actions
  qed*: Fix issues in the ptp filter config implementation.
  qede: Fix concurrency issue in PTP Tx path processing.
  stmmac: Add support for SIMATIC IOT2000 platform
  net: hns: fix ethtool_get_strings overflow in hns driver
  tcp: fix wraparound issue in tcp_lp
  bpf, arm64: fix jit branch offset related to ldimm64
  bpf, arm64: implement jiting of BPF_XADD
  ...
This commit is contained in:
Linus Torvalds 2017-05-02 16:40:27 -07:00
commit 8d65b08deb
1690 changed files with 109196 additions and 46486 deletions

View File

@ -21,3 +21,30 @@ Description:
is responsible for coordination of driver and firmware
link framing mode, changing this setting to 'Y' if the
firmware is configured for 'raw-ip' mode.
What: /sys/class/net/<iface>/qmi/add_mux
Date: March 2017
KernelVersion: 4.11
Contact: Bjørn Mork <bjorn@mork.no>
Description:
Unsigned integer.
Write a number ranging from 1 to 127 to add a qmap mux
based network device, supported by recent Qualcomm based
modems.
The network device will be called qmimux.
Userspace is in charge of managing the qmux network device
activation and data stream setup on the modem side by
using the proper QMI protocol requests.
What: /sys/class/net/<iface>/qmi/del_mux
Date: March 2017
KernelVersion: 4.11
Contact: Bjørn Mork <bjorn@mork.no>
Description:
Unsigned integer.
Write a number ranging from 1 to 127 to delete a previously
created qmap mux based network device.

View File

@ -2,11 +2,14 @@
Required properties:
- compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2",
"brcm,genet-v3", "brcm,genet-v4".
"brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5".
- reg: address and length of the register set for the device
- interrupts: must be two cells, the first cell is the general purpose
interrupt line, while the second cell is the interrupt for the ring
RX and TX queues operating in ring mode
- interrupts and/or interrupts-extended: must be two cells, the first cell
is the general purpose interrupt line, while the second cell is the
interrupt for the ring RX and TX queues operating in ring mode. An
optional third interrupt cell for Wake-on-LAN can be specified.
See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
for information on the property specifics.
- phy-mode: see ethernet.txt file in the same directory
- #address-cells: should be 1
- #size-cells: should be 1
@ -29,15 +32,15 @@ Optional properties:
Required child nodes:
- mdio bus node: this node should always be present regarless of the PHY
- mdio bus node: this node should always be present regardless of the PHY
configuration of the GENET instance
MDIO bus node required properties:
- compatible: should contain one of "brcm,genet-mdio-v1", "brcm,genet-mdio-v2"
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4", the version has to match the
parent node compatible property (e.g: brcm,genet-v4 pairs with
brcm,genet-mdio-v4)
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4", "brcm,genet-mdio-v5", the version
has to match the parent node compatible property (e.g: brcm,genet-v4 pairs
with brcm,genet-mdio-v4)
- reg: address and length relative to the parent node base register address
- #address-cells: address cell for MDIO bus addressing, should be 1
- #size-cells: size of the cells for MDIO bus addressing, should be 0

View File

@ -2,8 +2,9 @@
Required properties:
- compatible: should one from "brcm,genet-mdio-v1", "brcm,genet-mdio-v2",
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4" or "brcm,unimac-mdio"
- reg: address and length of the regsiter set for the device, first one is the
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4", "brcm,genet-mdio-v5" or
"brcm,unimac-mdio"
- reg: address and length of the register set for the device, first one is the
base register, and the second one is optional and for indirect accesses to
larger than 16-bits MDIO transactions
- reg-names: name(s) of the register must be "mdio" and optional "mdio_indir_rw"

View File

@ -0,0 +1,24 @@
* Holt HI-311X stand-alone CAN controller device tree bindings
Required properties:
- compatible: Should be one of the following:
- "holt,hi3110" for HI-3110
- reg: SPI chip select.
- clocks: The clock feeding the CAN controller.
- interrupt-parent: The parent interrupt controller.
- interrupts: Should contain IRQ line for the CAN controller.
Optional properties:
- vdd-supply: Regulator that powers the CAN controller.
- xceiver-supply: Regulator that powers the CAN transceiver.
Example:
can0: can@1 {
compatible = "holt,hi3110";
reg = <1>;
clocks = <&clk32m>;
interrupt-parent = <&gpio4>;
interrupts = <13 IRQ_TYPE_EDGE_RISING>;
vdd-supply = <&reg5v0>;
xceiver-supply = <&reg5v0>;
};

View File

@ -0,0 +1,32 @@
Texas Instruments High End CAN Controller (HECC)
================================================
This file provides information, what the device node
for the hecc interface contains.
Required properties:
- compatible: "ti,am3517-hecc"
- reg: addresses and lengths of the register spaces for 'hecc', 'hecc-ram'
and 'mbx'
- reg-names :"hecc", "hecc-ram", "mbx"
- interrupts: interrupt mapping for the hecc interrupts sources
- clocks: clock phandles (see clock bindings for details)
Optional properties:
- ti,use-hecc1int: if provided configures HECC to produce all interrupts
on HECC1INT interrupt line. By default HECC0INT interrupt
line will be used.
- xceiver-supply: regulator that powers the CAN transceiver
Example:
For am3517evm board:
hecc: can@5c050000 {
compatible = "ti,am3517-hecc";
reg = <0x5c050000 0x80>,
<0x5c053000 0x180>,
<0x5c052000 0x200>;
reg-names = "hecc", "hecc-ram", "mbx";
interrupts = <24>;
clocks = <&hecc_ck>;
};

View File

@ -0,0 +1,105 @@
SMSC/MicroChip LAN9303 three port ethernet switch
-------------------------------------------------
Required properties:
- compatible: should be
- "smsc,lan9303-i2c" for I2C managed mode
or
- "smsc,lan9303-mdio" for mdio managed mode
Optional properties:
- reset-gpios: GPIO to be used to reset the whole device
- reset-duration: reset duration in milliseconds, defaults to 200 ms
Subnodes:
The integrated switch subnode should be specified according to the binding
described in dsa/dsa.txt. The CPU port of this switch is always port 0.
Note: always use 'reg = <0/1/2>;' for the three DSA ports, even if the device is
configured to use 1/2/3 instead. This hardware configuration will be
auto-detected and mapped accordingly.
Example:
I2C managed mode:
master: masterdevice@X {
status = "okay";
fixed-link { /* RMII fixed link to LAN9303 */
speed = <100>;
full-duplex;
};
};
switch: switch@a {
compatible = "smsc,lan9303-i2c";
reg = <0xa>;
status = "okay";
reset-gpios = <&gpio7 6 GPIO_ACTIVE_LOW>;
reset-duration = <200>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 { /* RMII fixed link to master */
reg = <0>;
label = "cpu";
ethernet = <&master>;
};
port@1 { /* external port 1 */
reg = <1>;
label = "lan1;
};
port@2 { /* external port 2 */
reg = <2>;
label = "lan2";
};
};
};
MDIO managed mode:
master: masterdevice@X {
status = "okay";
phy-handle = <&switch>;
mdio {
#address-cells = <1>;
#size-cells = <0>;
switch: switch-phy@0 {
compatible = "smsc,lan9303-mdio";
reg = <0>;
reset-gpios = <&gpio7 6 GPIO_ACTIVE_LOW>;
reset-duration = <100>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "cpu";
ethernet = <&master>;
};
port@1 { /* external port 1 */
reg = <1>;
label = "lan1;
};
port@2 { /* external port 2 */
reg = <2>;
label = "lan2";
};
};
};
};
};

View File

@ -0,0 +1,92 @@
Mediatek MT7530 Ethernet switch
================================
Required properties:
- compatible: Must be compatible = "mediatek,mt7530";
- #address-cells: Must be 1.
- #size-cells: Must be 0.
- mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part
on multi-chip module belong to MT7623A has or the remotely standalone
chip as the function MT7623N reference board provided for.
- core-supply: Phandle to the regulator node necessary for the core power.
- io-supply: Phandle to the regulator node necessary for the I/O power.
See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
for details for the regulator setup on these boards.
If the property mediatek,mcm isn't defined, following property is required
- reset-gpios: Should be a gpio specifier for a reset line.
Else, following properties are required
- resets : Phandle pointing to the system reset controller with
line index for the ethsys.
- reset-names : Should be set to "mcm".
Required properties for the child nodes within ports container:
- reg: Port address described must be 6 for CPU port and from 0 to 5 for
user ports.
- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled
"cpu".
See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
required, optional properties and how the integrated switch subnodes must
be specified.
Example:
&mdio0 {
switch@0 {
compatible = "mediatek,mt7530";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
core-supply = <&mt6323_vpa_reg>;
io-supply = <&mt6323_vemc3v3_reg>;
reset-gpios = <&pio 33 0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
port@3 {
reg = <3>;
label = "lan3";
};
port@4 {
reg = <4>;
label = "wan";
};
port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac0>;
phy-mode = "trgmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};
};

View File

@ -0,0 +1,35 @@
* Faraday Technology FTGMAC100 gigabit ethernet controller
Required properties:
- compatible: "faraday,ftgmac100"
Must also contain one of these if used as part of an Aspeed AST2400
or 2500 family SoC as they have some subtle tweaks to the
implementation:
- "aspeed,ast2400-mac"
- "aspeed,ast2500-mac"
- reg: Address and length of the register set for the device
- interrupts: Should contain ethernet controller interrupt
Optional properties:
- phy-mode: See ethernet.txt file in the same directory. If the property is
absent, "rgmii" is assumed. Supported values are "rgmii*" and "rmii" for
aspeed parts. Other (unknown) parts will accept any value.
- use-ncsi: Use the NC-SI stack instead of an MDIO PHY. Currently assumes
rmii (100bT) but kept as a separate property in case NC-SI grows support
for a gigabit link.
- no-hw-checksum: Used to disable HW checksum support. Here for backward
compatibility as the driver now should have correct defaults based on
the SoC.
Example:
mac0: ethernet@1e660000 {
compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
reg = <0x1e660000 0x180>;
interrupts = <2>;
status = "okay";
use-ncsi;
};

View File

@ -0,0 +1,28 @@
* CA8210 IEEE 802.15.4 *
Required properties:
- compatible: Should be "cascoda,ca8210"
- reg: Controlling chip select
- spi-max-frequency: Maximum clock speed, should be *less than*
4000000
- spi-cpol: Requires inverted clock polarity
- reset-gpio: GPIO attached to reset
- irq-gpio: GPIO attached to IRQ
Optional properties:
- extclock-enable: Include for the ca8210 to route its 16MHz clock
to an output
- extclock-freq: Frequency in Hz of the external clock
- extclock-gpio: GPIO of the ca8210 to output the clock on
Example:
ca8210@0 {
compatible = "cascoda,ca8210";
reg = <0>;
spi-max-frequency = <3000000>;
spi-cpol;
reset-gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
irq-gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
extclock-enable;
extclock-freq = 16000000;
extclock-gpio = 2;
};

View File

@ -7,17 +7,20 @@ interface.
Required properties:
- compatible: "marvell,orion-mdio"
- reg: address and length of the SMI register
- reg: address and length of the MDIO registers. When an interrupt is
not present, the length is the size of the SMI register (4 bytes)
otherwise it must be 0x84 bytes to cover the interrupt control
registers.
Optional properties:
- interrupts: interrupt line number for the SMI error/done interrupt
- clocks: Phandle to the clock control device and gate bit
- clocks: phandle for up to three required clocks for the MDIO instance
The child nodes of the MDIO driver are the individual PHY devices
connected to this MDIO bus. They must have a "reg" property given the
PHY address on the MDIO bus.
Example at the SoC level:
Example at the SoC level without an interrupt property:
mdio {
#address-cells = <1>;
@ -26,6 +29,16 @@ mdio {
reg = <0xd0072004 0x4>;
};
Example with an interrupt property:
mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0xd0072004 0x84>;
interrupts = <30>;
};
And at the board level:
mdio {

View File

@ -1,17 +1,28 @@
* Marvell Armada 375 Ethernet Controller (PPv2)
* Marvell Armada 375 Ethernet Controller (PPv2.1)
Marvell Armada 7K/8K Ethernet Controller (PPv2.2)
Required properties:
- compatible: should be "marvell,armada-375-pp2"
- compatible: should be one of:
"marvell,armada-375-pp2"
"marvell,armada-7k-pp2"
- reg: addresses and length of the register sets for the device.
Must contain the following register sets:
For "marvell,armada-375-pp2", must contain the following register
sets:
- common controller registers
- LMS registers
In addition, at least one port register set is required.
- clocks: a pointer to the reference clocks for this device, consequently:
- main controller clock
- GOP clock
- clock-names: names of used clocks, must be "pp_clk" and "gop_clk".
- one register area per Ethernet port
For "marvell,armada-7k-pp2", must contain the following register
sets:
- packet processor registers
- networking interfaces registers
- clocks: pointers to the reference clocks for this device, consequently:
- main controller clock (for both armada-375-pp2 and armada-7k-pp2)
- GOP clock (for both armada-375-pp2 and armada-7k-pp2)
- MG clock (only for armada-7k-pp2)
- clock-names: names of used clocks, must be "pp_clk", "gop_clk" and
"mg_clk" (the latter only for armada-7k-pp2).
The ethernet ports are represented by subnodes. At least one port is
required.
@ -19,8 +30,10 @@ required.
Required properties (port):
- interrupts: interrupt for the port
- port-id: should be '0' or '1' for ethernet ports, and '2' for the
loopback port
- port-id: ID of the port from the MAC point of view
- gop-port-id: only for marvell,armada-7k-pp2, ID of the port from the
GOP (Group Of Ports) point of view. This ID is used to index the
per-port registers in the second register area.
- phy-mode: See ethernet.txt file in the same directory
Optional properties (port):
@ -29,7 +42,7 @@ Optional properties (port):
- phy: a phandle to a phy node defining the PHY address (as the reg
property, a single integer).
Example:
Example for marvell,armada-375-pp2:
ethernet@f0000 {
compatible = "marvell,armada-375-pp2";
@ -57,3 +70,30 @@ ethernet@f0000 {
phy-mode = "gmii";
};
};
Example for marvell,armada-7k-pp2:
cpm_ethernet: ethernet@0 {
compatible = "marvell,armada-7k-pp22";
reg = <0x0 0x100000>, <0x129000 0xb000>;
clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
clock-names = "pp_clk", "gop_clk", "gp_clk";
eth0: eth0 {
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
port-id = <0>;
gop-port-id = <0>;
};
eth1: eth1 {
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
port-id = <1>;
gop-port-id = <2>;
};
eth2: eth2 {
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
port-id = <2>;
gop-port-id = <3>;
};
};

View File

@ -0,0 +1,37 @@
Common MDIO bus properties.
These are generic properties that can apply to any MDIO bus.
Optional properties:
- reset-gpios: One GPIO that control the RESET lines of all PHYs on that MDIO
bus.
- reset-delay-us: RESET pulse width in microseconds.
A list of child nodes, one per device on the bus is expected. These
should follow the generic phy.txt, or a device specific binding document.
The 'reset-delay-us' indicates the RESET signal pulse width in microseconds and
applies to all PHY devices. It must therefore be appropriately determined based
on all PHY requirements (maximum value of all per-PHY RESET pulse widths).
Example :
This example shows these optional properties, plus other properties
required for the TI Davinci MDIO driver.
davinci_mdio: ethernet@0x5c030000 {
compatible = "ti,davinci_mdio";
reg = <0x5c030000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
reset-delay-us = <2>;
ethphy0: ethernet-phy@1 {
reg = <1>;
};
ethphy1: ethernet-phy@3 {
reg = <3>;
};
};

View File

@ -5,8 +5,8 @@ Required properties:
- spi-max-frequency: Maximum SPI frequency (<= 2000000).
- interrupt-parent: phandle of parent interrupt handler.
- interrupts: A single interrupt specifier.
- ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on the
TRF7970A.
- ti,enable-gpios: One or two GPIO entries used for 'EN' and 'EN2' pins on the
TRF7970A. EN2 is optional.
- vin-supply: Regulator for supply voltage to VIN pin
Optional SoC Specific Properties:
@ -21,6 +21,8 @@ Optional SoC Specific Properties:
- t5t-rmb-extra-byte-quirk: Specify that the trf7970a has the erratum
where an extra byte is returned by Read Multiple Block commands issued
to Type 5 tags.
- vdd-io-supply: Regulator specifying voltage for vdd-io
- clock-frequency: Set to specify that the input frequency to the trf7970a is 13560000Hz or 27120000Hz
Example (for ARM-based BeagleBone with TRF7970A on SPI1):
@ -39,10 +41,12 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1):
<&gpio2 5 GPIO_ACTIVE_LOW>;
vin-supply = <&ldo3_reg>;
vin-voltage-override = <5000000>;
vdd-io-supply = <&ldo2_reg>;
autosuspend-delay = <30000>;
irq-status-read-quirk;
en2-rf-quirk;
t5t-rmb-extra-byte-quirk;
clock-frequency = <27120000>;
status = "okay";
};
};

View File

@ -0,0 +1,51 @@
Nokia Bluetooth Chips
---------------------
Nokia phones often come with UART connected bluetooth chips from different
vendors and modified device API. Those devices speak a protocol named H4+
(also known as h4p) by Nokia, which is similar to the H4 protocol from the
Bluetooth standard. In addition to the H4 protocol it specifies two more
UART status lines for wakeup of UART transceivers to improve power management
and a few new packet types used to negotiate uart speed.
Required properties:
- compatible: should contain "nokia,h4p-bluetooth" as well as one of the following:
* "brcm,bcm2048-nokia"
* "ti,wl1271-bluetooth-nokia"
- reset-gpios: GPIO specifier, used to reset the BT module (active low)
- bluetooth-wakeup-gpios: GPIO specifier, used to wakeup the BT module (active high)
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor (active high)
- clock-names: should be "sysclk"
- clocks: should contain a clock specifier for every name in clock-names
Optional properties:
- None
Example:
/ {
/* controlled (enabled/disabled) directly by BT module */
bluetooth_clk: vctcxo {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <38400000>;
};
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
bluetooth {
compatible = "ti,wl1271-bluetooth-nokia", "nokia,h4p-bluetooth";
reset-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>; /* gpio26 */
host-wakeup-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; /* gpio101 */
bluetooth-wakeup-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* gpio37 */
clocks = <&bluetooth_clk>;
clock-names = "sysclk";
};
};

View File

@ -7,9 +7,12 @@ Required properties:
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the STMMAC interrupts
- interrupt-names: Should contain the interrupt names "macirq"
"eth_wake_irq" if this interrupt is supported in the "interrupts"
property
- interrupt-names: Should contain a list of interrupt names corresponding to
the interrupts in the interrupts property, if available.
Valid interrupt names are:
- "macirq" (combined signal for various interrupt events)
- "eth_wake_irq" (the interrupt to manage the remote wake-up packet detection)
- "eth_lpi" (the interrupt that occurs when Tx or Rx enters/exits LPI state)
- phy-mode: See ethernet.txt file in the same directory.
- snps,reset-gpio gpio number for phy reset.
- snps,reset-active-low boolean flag to indicate if phy reset is active low.
@ -28,9 +31,9 @@ Optional properties:
clocks may be specified in derived bindings.
- clock-names: One name for each entry in the clocks property, the
first one should be "stmmaceth" and the second one should be "pclk".
- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
available this clock is used for programming the Timestamp Addend Register.
If not passed then the system clock will be used and this is fine on some
- ptp_ref: this is the PTP reference clock; in case of the PTP is available
this clock is used for programming the Timestamp Addend Register. If not
passed then the system clock will be used and this is fine on some
platforms.
- tx-fifo-depth: See ethernet.txt file in the same directory
- rx-fifo-depth: See ethernet.txt file in the same directory
@ -72,7 +75,45 @@ Optional properties:
- snps,mb: mixed-burst
- snps,rb: rebuild INCRx Burst
- mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus.
- Multiple RX Queues parameters: below the list of all the parameters to
configure the multiple RX queues:
- snps,rx-queues-to-use: number of RX queues to be used in the driver
- Choose one of these RX scheduling algorithms:
- snps,rx-sched-sp: Strict priority
- snps,rx-sched-wsp: Weighted Strict priority
- For each RX queue
- Choose one of these modes:
- snps,dcb-algorithm: Queue to be enabled as DCB
- snps,avb-algorithm: Queue to be enabled as AVB
- snps,map-to-dma-channel: Channel to map
- Specifiy specific packet routing:
- snps,route-avcp: AV Untagged Control packets
- snps,route-ptp: PTP Packets
- snps,route-dcbcp: DCB Control Packets
- snps,route-up: Untagged Packets
- snps,route-multi-broad: Multicast & Broadcast Packets
- snps,priority: RX queue priority (Range: 0x0 to 0xF)
- Multiple TX Queues parameters: below the list of all the parameters to
configure the multiple TX queues:
- snps,tx-queues-to-use: number of TX queues to be used in the driver
- Choose one of these TX scheduling algorithms:
- snps,tx-sched-wrr: Weighted Round Robin
- snps,tx-sched-wfq: Weighted Fair Queuing
- snps,tx-sched-dwrr: Deficit Weighted Round Robin
- snps,tx-sched-sp: Strict priority
- For each TX queue
- snps,weight: TX queue weight (if using a DCB weight algorithm)
- Choose one of these modes:
- snps,dcb-algorithm: TX queue will be working in DCB
- snps,avb-algorithm: TX queue will be working in AVB
[Attention] Queue 0 is reserved for legacy traffic
and so no AVB is available in this queue.
- Configure Credit Base Shaper (if AVB Mode selected):
- snps,send_slope: enable Low Power Interface
- snps,idle_slope: unlock on WoL
- snps,high_credit: max write outstanding req. limit
- snps,low_credit: max read outstanding req. limit
- snps,priority: TX queue priority (Range: 0x0 to 0xF)
Examples:
stmmac_axi_setup: stmmac-axi-config {
@ -81,12 +122,41 @@ Examples:
snps,blen = <256 128 64 32 0 0 0>;
};
mtl_rx_setup: rx-queues-config {
snps,rx-queues-to-use = <1>;
snps,rx-sched-sp;
queue0 {
snps,dcb-algorithm;
snps,map-to-dma-channel = <0x0>;
snps,priority = <0x0>;
};
};
mtl_tx_setup: tx-queues-config {
snps,tx-queues-to-use = <2>;
snps,tx-sched-wrr;
queue0 {
snps,weight = <0x10>;
snps,dcb-algorithm;
snps,priority = <0x0>;
};
queue1 {
snps,avb-algorithm;
snps,send_slope = <0x1000>;
snps,idle_slope = <0x1000>;
snps,high_credit = <0x3E800>;
snps,low_credit = <0xFFC18000>;
snps,priority = <0x1>;
};
};
gmac0: ethernet@e0800000 {
compatible = "st,spear600-gmac";
reg = <0xe0800000 0x8000>;
interrupt-parent = <&vic1>;
interrupts = <24 23>;
interrupt-names = "macirq", "eth_wake_irq";
interrupts = <24 23 22>;
interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
mac-address = [000000000000]; /* Filled in by U-Boot */
max-frame-size = <3800>;
phy-mode = "gmii";
@ -104,4 +174,6 @@ Examples:
phy1: ethernet-phy@0 {
};
};
snps,mtl-rx-config = <&mtl_rx_setup>;
snps,mtl-tx-config = <&mtl_tx_setup>;
};

View File

@ -0,0 +1,35 @@
TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
TI WiLink devices have a UART interface for providing Bluetooth, FM radio,
and GPS over what's called "shared transport". The shared transport is
standard BT HCI protocol with additional channels for the other functions.
These devices also have a separate WiFi interface as described in
wireless/ti,wlcore.txt.
This bindings follows the UART slave device binding in
../serial/slave-device.txt.
Required properties:
- compatible: should be one of the following:
"ti,wl1271-st"
"ti,wl1273-st"
"ti,wl1831-st"
"ti,wl1835-st"
"ti,wl1837-st"
Optional properties:
- enable-gpios : GPIO signal controlling enabling of BT. Active high.
- vio-supply : Vio input supply (1.8V)
- vbat-supply : Vbat input supply (2.9-4.8V)
Example:
&serial0 {
compatible = "ns16550a";
...
bluetooth {
compatible = "ti,wl1835-st";
enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
};

View File

@ -51,6 +51,7 @@ brcm Broadcom Corporation
buffalo Buffalo, Inc.
calxeda Calxeda
capella Capella Microsystems, Inc
cascoda Cascoda, Ltd.
cavium Cavium, Inc.
cdns Cadence Design Systems Inc.
ceva Ceva, Inc.

View File

@ -2,6 +2,9 @@
cfg80211 subsystem
==================
.. kernel-doc:: include/net/cfg80211.h
:doc: Introduction
Device registration
===================
@ -179,6 +182,12 @@ Actions and configuration
.. kernel-doc:: include/net/cfg80211.h
:functions: cfg80211_ibss_joined
.. kernel-doc:: include/net/cfg80211.h
:functions: cfg80211_connect_resp_params
.. kernel-doc:: include/net/cfg80211.h
:functions: cfg80211_connect_done
.. kernel-doc:: include/net/cfg80211.h
:functions: cfg80211_connect_result

View File

@ -595,10 +595,9 @@ got from bpf_prog_create(), and 'ctx' the given context (e.g.
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 of the
architectures. x86-64, aarch64 and s390x perform JIT compilation from eBPF
instruction set, however, future work will migrate other JIT compilers as well,
so that they will profit from the very same benefits.
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.
Some core changes of the new internal format:

View File

@ -63,6 +63,78 @@ Additional Configurations
The latest release of ethtool can be found from
https://www.kernel.org/pub/software/network/ethtool
Flow Director n-ntuple traffic filters (FDir)
---------------------------------------------
The driver utilizes the ethtool interface for configuring ntuple filters,
via "ethtool -N <device> <filter>".
The sctp4, ip4, udp4, and tcp4 flow types are supported with the standard
fields including src-ip, dst-ip, src-port and dst-port. The driver only
supports fully enabling or fully masking the fields, so use of the mask
fields for partial matches is not supported.
Additionally, the driver supports using the action to specify filters for a
Virtual Function. You can specify the action as a 64bit value, where the
lower 32 bits represents the queue number, while the next 8 bits represent
which VF. Note that 0 is the PF, so the VF identifier is offset by 1. For
example:
... action 0x800000002 ...
Would indicate to direct traffic for Virtual Function 7 (8 minus 1) on queue
2 of that VF.
The driver also supports using the user-defined field to specify 2 bytes of
arbitrary data to match within the packet payload in addition to the regular
fields. The data is specified in the lower 32bits of the user-def field in
the following way:
+----------------------------+---------------------------+
| 31 28 24 20 16 | 15 12 8 4 0|
+----------------------------+---------------------------+
| offset into packet payload | 2 bytes of flexible data |
+----------------------------+---------------------------+
As an example,
... user-def 0x4FFFF ....
means to match the value 0xFFFF 4 bytes into the packet payload. Note that
the offset is based on the beginning of the payload, and not the beginning
of the packet. Thus
flow-type tcp4 ... user-def 0x8BEAF ....
would match TCP/IPv4 packets which have the value 0xBEAF 8bytes into the
TCP/IPv4 payload.
For ICMP, the hardware parses the ICMP header as 4 bytes of header and 4
bytes of payload, so if you want to match an ICMP frames payload you may need
to add 4 to the offset in order to match the data.
Furthermore, the offset can only be up to a value of 64, as the hardware
will only read up to 64 bytes of data from the payload. It must also be even
as the flexible data is 2 bytes long and must be aligned to byte 0 of the
packet payload.
When programming filters, the hardware is limited to using a single input
set for each flow type. This means that it is an error to program two
different filters with the same type that don't match on the same fields.
Thus the second of the following two commands will fail:
ethtool -N <device> flow-type tcp4 src-ip 192.168.0.7 action 5
ethtool -N <device> flow-type tcp4 dst-ip 192.168.15.18 action 1
This is because the first filter will be accepted and reprogram the input
set for TCPv4 filters, but the second filter will be unable to reprogram the
input set until all the conflicting TCPv4 filters are first removed.
Note that the user-defined flexible offset is also considered part of the
input set and cannot be programmed separately for multiple filters of the
same type. However, the flexible data is not part of the input set and
multiple filters may use the same offset but match against different data.
Data Center Bridging (DCB)
--------------------------
DCB configuration is not currently supported.

View File

@ -73,6 +73,14 @@ fib_multipath_use_neigh - BOOLEAN
0 - disabled
1 - enabled
fib_multipath_hash_policy - INTEGER
Controls which hash policy to use for multipath routes. Only valid
for kernels built with CONFIG_IP_ROUTE_MULTIPATH enabled.
Default: 0 (Layer 3)
Possible values:
0 - Layer 3
1 - Layer 4
route/max_size - INTEGER
Maximum number of routes allowed in the kernel. Increase
this when using large numbers of interfaces and/or routes.
@ -594,6 +602,14 @@ tcp_fastopen - INTEGER
Note that that additional client or server features are only
effective if the basic support (0x1 and 0x2) are enabled respectively.
tcp_fastopen_blackhole_timeout_sec - INTEGER
Initial time period in second to disable Fastopen on active TCP sockets
when a TFO firewall blackhole issue happens.
This time period will grow exponentially when more blackhole issues
get detected right after Fastopen is re-enabled and will reset to
initial value when the blackhole issue goes away.
By default, it is set to 1hr.
tcp_syn_retries - INTEGER
Number of times initial SYNs for an active TCP connection attempt
will be retransmitted. Should not be higher than 127. Default value
@ -640,11 +656,6 @@ tcp_tso_win_divisor - INTEGER
building larger TSO frames.
Default: 3
tcp_tw_recycle - BOOLEAN
Enable fast recycling TIME-WAIT sockets. Default value is 0.
It should not be changed without advice/request of technical
experts.
tcp_tw_reuse - BOOLEAN
Allow to reuse TIME-WAIT sockets for new connections when it is
safe from protocol viewpoint. Default value is 0.
@ -853,12 +864,21 @@ ip_dynaddr - BOOLEAN
ip_early_demux - BOOLEAN
Optimize input packet processing down to one demux for
certain kinds of local sockets. Currently we only do this
for established TCP sockets.
for established TCP and connected UDP sockets.
It may add an additional cost for pure routing workloads that
reduces overall throughput, in such case you should disable it.
Default: 1
tcp_early_demux - BOOLEAN
Enable early demux for established TCP sockets.
Default: 1
udp_early_demux - BOOLEAN
Enable early demux for connected UDP sockets. Disable this if
your system could experience more unconnected load.
Default: 1
icmp_echo_ignore_all - BOOLEAN
If set non-zero, then the kernel will ignore all ICMP ECHO
requests sent to it.
@ -1458,11 +1478,20 @@ accept_ra_pinfo - BOOLEAN
Functional default: enabled if accept_ra is enabled.
disabled if accept_ra is disabled.
accept_ra_rt_info_min_plen - INTEGER
Minimum prefix length of Route Information in RA.
Route Information w/ prefix smaller than this variable shall
be ignored.
Functional default: 0 if accept_ra_rtr_pref is enabled.
-1 if accept_ra_rtr_pref is disabled.
accept_ra_rt_info_max_plen - INTEGER
Maximum prefix length of Route Information in RA.
Route Information w/ prefix larger than or equal to this
variable shall be ignored.
Route Information w/ prefix larger than this variable shall
be ignored.
Functional default: 0 if accept_ra_rtr_pref is enabled.
-1 if accept_ra_rtr_pref is disabled.

View File

@ -175,6 +175,14 @@ nat_icmp_send - BOOLEAN
for VS/NAT when the load balancer receives packets from real
servers but the connection entries don't exist.
pmtu_disc - BOOLEAN
0 - disabled
not 0 - enabled (default)
By default, reject with FRAG_NEEDED all DF packets that exceed
the PMTU, irrespective of the forwarding method. For TUN method
the flag can be disabled to fragment such packets.
secure_tcp - INTEGER
0 - disabled (default)
@ -185,15 +193,59 @@ secure_tcp - INTEGER
The value definition is the same as that of drop_entry and
drop_packet.
sync_threshold - INTEGER
default 3
sync_threshold - vector of 2 INTEGERs: sync_threshold, sync_period
default 3 50
It sets synchronization threshold, which is the minimum number
of incoming packets that a connection needs to receive before
the connection will be synchronized. A connection will be
synchronized, every time the number of its incoming packets
modulus 50 equals the threshold. The range of the threshold is
from 0 to 49.
modulus sync_period equals the threshold. The range of the
threshold is from 0 to sync_period.
When sync_period and sync_refresh_period are 0, send sync only
for state changes or only once when pkts matches sync_threshold
sync_refresh_period - UNSIGNED INTEGER
default 0
In seconds, difference in reported connection timer that triggers
new sync message. It can be used to avoid sync messages for the
specified period (or half of the connection timeout if it is lower)
if connection state is not changed since last sync.
This is useful for normal connections with high traffic to reduce
sync rate. Additionally, retry sync_retries times with period of
sync_refresh_period/8.
sync_retries - INTEGER
default 0
Defines sync retries with period of sync_refresh_period/8. Useful
to protect against loss of sync messages. The range of the
sync_retries is from 0 to 3.
sync_qlen_max - UNSIGNED LONG
Hard limit for queued sync messages that are not sent yet. It
defaults to 1/32 of the memory pages but actually represents
number of messages. It will protect us from allocating large
parts of memory when the sending rate is lower than the queuing
rate.
sync_sock_size - INTEGER
default 0
Configuration of SNDBUF (master) or RCVBUF (slave) socket limit.
Default value is 0 (preserve system defaults).
sync_ports - INTEGER
default 1
The number of threads that master and backup servers can use for
sync traffic. Every thread will use single UDP port, thread 0 will
use the default port 8848 while last thread will use port
8848+sync_ports-1.
snat_reroute - BOOLEAN
0 - disabled

View File

@ -19,6 +19,25 @@ platform_labels - INTEGER
Possible values: 0 - 1048575
Default: 0
ip_ttl_propagate - BOOL
Control whether TTL is propagated from the IPv4/IPv6 header to
the MPLS header on imposing labels and propagated from the
MPLS header to the IPv4/IPv6 header on popping the last label.
If disabled, the MPLS transport network will appear as a
single hop to transit traffic.
0 - disabled / RFC 3443 [Short] Pipe Model
1 - enabled / RFC 3443 Uniform Model (default)
default_ttl - BOOL
Default TTL value to use for MPLS packets where it cannot be
propagated from an IP header, either because one isn't present
or ip_ttl_propagate has been disabled.
Possible values: 1 - 255
Default: 255
conf/<interface>/input - BOOL
Control whether packets can be input on this interface.

View File

@ -13,43 +13,43 @@ an example setup using a data-center-class switch ASIC chip. Other setups
with SR-IOV or soft switches, such as OVS, are possible.
User-spacetools
userspace|
+-------------------------------------------------------------------+
kernel|Netlink
|
+--------------+-------------------------------+
|Networkstack|
|(Linux)|
||
+----------------------------------------------+
User-spacetools
userspace|
+-------------------------------------------------------------------+
kernel|Netlink
|
+--------------+-------------------------------+
|Networkstack|
|(Linux)|
||
+----------------------------------------------+
sw1p2 sw1p4 sw1p6
sw1p1 + sw1p3 + sw1p5 + eth1
+|+|+|+
|||||||
+--+----+----+----+-+--+----+---++-----+-----+
|Switchdriver||mgmt|
|(thisdocument)||driver|
||||
+--------------+----------------++-----------+
|
kernel|HWbus(egPCI)
+-------------------------------------------------------------------+
hardware|
+--------------+---+------------+
|Switchdevice (sw1)|
|+----++--------+
||voffloadeddatapath|mgmtport
||||
+--|----|----+----+----+----+---+
||||||
++++++
sw1p1 + sw1p3 + sw1p5 + eth1
+|+|+|+
|||||||
+--+----+----+----+-+--+----+---++-----+-----+
|Switchdriver||mgmt|
|(thisdocument)||driver|
||||
+--------------+----------------++-----------+
|
kernel|HWbus(egPCI)
+-------------------------------------------------------------------+
hardware|
+--------------+---+------------+
|Switchdevice (sw1)|
|+----++--------+
||voffloadeddatapath|mgmtport
||||
+--|----|----+----+----+----+---+
||||||
++++++
p1p2p3p4p5p6
front-panelports
front-panelports
Fig 1.

View File

@ -188,7 +188,16 @@ netdev_budget
Maximum number of packets taken from all interfaces in one polling cycle (NAPI
poll). In one polling cycle interfaces which are registered to polling are
probed in a round-robin manner.
probed in a round-robin manner. Also, a polling cycle may not exceed
netdev_budget_usecs microseconds, even if netdev_budget has not been
exhausted.
netdev_budget_usecs
---------------------
Maximum number of microseconds in one NAPI polling cycle. Polling
will exit when either netdev_budget_usecs have elapsed during the
poll cycle or the number of packets processed reaches netdev_budget.
netdev_max_backlog
------------------

View File

@ -896,12 +896,19 @@ F: arch/arm64/boot/dts/apm/
APPLIED MICRO (APM) X-GENE SOC ETHERNET DRIVER
M: Iyappan Subramanian <isubramanian@apm.com>
M: Keyur Chudgar <kchudgar@apm.com>
M: Quan Nguyen <qnguyen@apm.com>
S: Supported
F: drivers/net/ethernet/apm/xgene/
F: drivers/net/phy/mdio-xgene.c
F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
F: Documentation/devicetree/bindings/net/apm-xgene-mdio.txt
APPLIED MICRO (APM) X-GENE SOC ETHERNET (V2) DRIVER
M: Iyappan Subramanian <isubramanian@apm.com>
M: Keyur Chudgar <kchudgar@apm.com>
S: Supported
F: drivers/net/ethernet/apm/xgene-v2/
APPLIED MICRO (APM) X-GENE SOC PMU
M: Tai Nguyen <ttnguyen@apm.com>
S: Supported
@ -2944,6 +2951,15 @@ W: http://www.linux-c6x.org/wiki/index.php/Main_Page
S: Maintained
F: arch/c6x/
CA8210 IEEE-802.15.4 RADIO DRIVER
M: Harry Morris <h.morris@cascoda.com>
M: linuxdev@cascoda.com
L: linux-wpan@vger.kernel.org
W: https://github.com/Cascoda/ca8210-linux.git
S: Maintained
F: drivers/net/ieee802154/ca8210.c
F: Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS
M: David Howells <dhowells@redhat.com>
L: linux-cachefs@redhat.com (moderated for non-subscribers)
@ -7884,7 +7900,7 @@ S: Maintained
F: drivers/net/ethernet/marvell/mvneta.*
MARVELL MWIFIEX WIRELESS DRIVER
M: Amitkumar Karwar <akarwar@marvell.com>
M: Amitkumar Karwar <amitkarwar@gmail.com>
M: Nishant Sarmukadam <nishants@marvell.com>
M: Ganapathi Bhat <gbhat@marvell.com>
M: Xinming Hu <huxm@marvell.com>
@ -8829,12 +8845,12 @@ F: net/core/flow.c
F: net/xfrm/
F: net/key/
F: net/ipv4/xfrm*
F: net/ipv4/esp4.c
F: net/ipv4/esp4*
F: net/ipv4/ah4.c
F: net/ipv4/ipcomp.c
F: net/ipv4/ip_vti.c
F: net/ipv6/xfrm*
F: net/ipv6/esp6.c
F: net/ipv6/esp6*
F: net/ipv6/ah6.c
F: net/ipv6/ipcomp6.c
F: net/ipv6/ip6_vti.c
@ -8888,8 +8904,6 @@ S: Supported
F: drivers/net/ethernet/qlogic/netxen/
NFC SUBSYSTEM
M: Lauro Ramos Venancio <lauro.venancio@openbossa.org>
M: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
M: Samuel Ortiz <sameo@linux.intel.com>
L: linux-wireless@vger.kernel.org
L: linux-nfc@lists.01.org (subscribers-only)
@ -11125,6 +11139,12 @@ F: include/linux/dma/dw.h
F: include/linux/platform_data/dma-dw.h
F: drivers/dma/dw/
SYNOPSYS DESIGNWARE ENTERPRISE ETHERNET DRIVER
M: Jie Deng <jiedeng@synopsys.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/synopsys/
SYNOPSYS DESIGNWARE I2C DRIVER
M: Jarkko Nikula <jarkko.nikula@linux.intel.com>
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
@ -12229,12 +12249,19 @@ F: Documentation/accounting/taskstats*
F: include/linux/taskstats*
F: kernel/taskstats.c
TC CLASSIFIER
TC subsystem
M: Jamal Hadi Salim <jhs@mojatatu.com>
M: Cong Wang <xiyou.wangcong@gmail.com>
M: Jiri Pirko <jiri@resnulli.us>
L: netdev@vger.kernel.org
S: Maintained
F: include/net/pkt_cls.h
F: include/net/pkt_sched.h
F: include/net/tc_act/
F: include/uapi/linux/pkt_cls.h
F: include/uapi/linux/pkt_sched.h
F: include/uapi/linux/tc_act/
F: include/uapi/linux/tc_ematch/
F: net/sched/
TCP LOW PRIORITY MODULE
@ -13330,8 +13357,11 @@ L: netdev@vger.kernel.org
S: Maintained
F: include/linux/virtio_vsock.h
F: include/uapi/linux/virtio_vsock.h
F: include/uapi/linux/vsockmon.h
F: net/vmw_vsock/af_vsock_tap.c
F: net/vmw_vsock/virtio_transport_common.c
F: net/vmw_vsock/virtio_transport.c
F: drivers/net/vsockmon.c
F: drivers/vhost/vsock.c
F: drivers/vhost/vsock.h

View File

@ -99,4 +99,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _UAPI_ASM_SOCKET_H */

View File

@ -42,18 +42,16 @@ vic: interrupt-controller@1e6c0080 {
};
mac0: ethernet@1e660000 {
compatible = "faraday,ftgmac100";
compatible = "aspeed,ast2400-mac", "faraday,ftgmac100";
reg = <0x1e660000 0x180>;
interrupts = <2>;
no-hw-checksum;
status = "disabled";
};
mac1: ethernet@1e680000 {
compatible = "faraday,ftgmac100";
compatible = "aspeed,ast2400-mac", "faraday,ftgmac100";
reg = <0x1e680000 0x180>;
interrupts = <3>;
no-hw-checksum;
status = "disabled";
};

View File

@ -33,18 +33,16 @@ vic: interrupt-controller@1e6c0080 {
};
mac0: ethernet@1e660000 {
compatible = "faraday,ftgmac100";
compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
reg = <0x1e660000 0x180>;
interrupts = <2>;
no-hw-checksum;
status = "disabled";
};
mac1: ethernet@1e680000 {
compatible = "faraday,ftgmac100";
compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
reg = <0x1e680000 0x180>;
interrupts = <3>;
no-hw-checksum;
status = "disabled";
};

View File

@ -98,6 +98,11 @@ uart1: uart@f7111000 {
assigned-clocks = <&sys_ctrl HI6220_UART1_SRC>;
assigned-clock-rates = <150000000>;
status = "ok";
bluetooth {
compatible = "ti,wl1835-st";
enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
};
uart2: uart@f7112000 {

View File

@ -80,6 +80,7 @@ enum aarch64_insn_register_type {
AARCH64_INSN_REGTYPE_RM,
AARCH64_INSN_REGTYPE_RD,
AARCH64_INSN_REGTYPE_RA,
AARCH64_INSN_REGTYPE_RS,
};
enum aarch64_insn_register {
@ -188,6 +189,8 @@ enum aarch64_insn_ldst_type {
AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX,
AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX,
AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX,
AARCH64_INSN_LDST_LOAD_EX,
AARCH64_INSN_LDST_STORE_EX,
};
enum aarch64_insn_adsb_type {
@ -240,6 +243,23 @@ enum aarch64_insn_logic_type {
AARCH64_INSN_LOGIC_BIC_SETFLAGS
};
enum aarch64_insn_prfm_type {
AARCH64_INSN_PRFM_TYPE_PLD,
AARCH64_INSN_PRFM_TYPE_PLI,
AARCH64_INSN_PRFM_TYPE_PST,
};
enum aarch64_insn_prfm_target {
AARCH64_INSN_PRFM_TARGET_L1,
AARCH64_INSN_PRFM_TARGET_L2,
AARCH64_INSN_PRFM_TARGET_L3,
};
enum aarch64_insn_prfm_policy {
AARCH64_INSN_PRFM_POLICY_KEEP,
AARCH64_INSN_PRFM_POLICY_STRM,
};
#define __AARCH64_INSN_FUNCS(abbr, mask, val) \
static __always_inline bool aarch64_insn_is_##abbr(u32 code) \
{ return (code & (mask)) == (val); } \
@ -248,6 +268,7 @@ static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \
__AARCH64_INSN_FUNCS(adr, 0x9F000000, 0x10000000)
__AARCH64_INSN_FUNCS(adrp, 0x9F000000, 0x90000000)
__AARCH64_INSN_FUNCS(prfm, 0x3FC00000, 0x39800000)
__AARCH64_INSN_FUNCS(prfm_lit, 0xFF000000, 0xD8000000)
__AARCH64_INSN_FUNCS(str_reg, 0x3FE0EC00, 0x38206800)
__AARCH64_INSN_FUNCS(ldr_reg, 0x3FE0EC00, 0x38606800)
@ -357,6 +378,11 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
int offset,
enum aarch64_insn_variant variant,
enum aarch64_insn_ldst_type type);
u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
enum aarch64_insn_register base,
enum aarch64_insn_register state,
enum aarch64_insn_size_type size,
enum aarch64_insn_ldst_type type);
u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
enum aarch64_insn_register src,
int imm, enum aarch64_insn_variant variant,
@ -397,6 +423,10 @@ u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst,
int shift,
enum aarch64_insn_variant variant,
enum aarch64_insn_logic_type type);
u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
enum aarch64_insn_prfm_type type,
enum aarch64_insn_prfm_target target,
enum aarch64_insn_prfm_policy policy);
s32 aarch64_get_branch_offset(u32 insn);
u32 aarch64_set_branch_offset(u32 insn, s32 offset);

View File

@ -474,6 +474,7 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type,
shift = 10;
break;
case AARCH64_INSN_REGTYPE_RM:
case AARCH64_INSN_REGTYPE_RS:
shift = 16;
break;
default:
@ -757,6 +758,111 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
offset >> shift);
}
u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
enum aarch64_insn_register base,
enum aarch64_insn_register state,
enum aarch64_insn_size_type size,
enum aarch64_insn_ldst_type type)
{
u32 insn;
switch (type) {
case AARCH64_INSN_LDST_LOAD_EX:
insn = aarch64_insn_get_load_ex_value();
break;
case AARCH64_INSN_LDST_STORE_EX:
insn = aarch64_insn_get_store_ex_value();
break;
default:
pr_err("%s: unknown load/store exclusive encoding %d\n", __func__, type);
return AARCH64_BREAK_FAULT;
}
insn = aarch64_insn_encode_ldst_size(size, insn);
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
reg);
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
base);
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT2, insn,
AARCH64_INSN_REG_ZR);
return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RS, insn,
state);
}
static u32 aarch64_insn_encode_prfm_imm(enum aarch64_insn_prfm_type type,
enum aarch64_insn_prfm_target target,
enum aarch64_insn_prfm_policy policy,
u32 insn)
{
u32 imm_type = 0, imm_target = 0, imm_policy = 0;
switch (type) {
case AARCH64_INSN_PRFM_TYPE_PLD:
break;
case AARCH64_INSN_PRFM_TYPE_PLI:
imm_type = BIT(0);
break;
case AARCH64_INSN_PRFM_TYPE_PST:
imm_type = BIT(1);
break;
default:
pr_err("%s: unknown prfm type encoding %d\n", __func__, type);
return AARCH64_BREAK_FAULT;
}
switch (target) {
case AARCH64_INSN_PRFM_TARGET_L1:
break;
case AARCH64_INSN_PRFM_TARGET_L2:
imm_target = BIT(0);
break;
case AARCH64_INSN_PRFM_TARGET_L3:
imm_target = BIT(1);
break;
default:
pr_err("%s: unknown prfm target encoding %d\n", __func__, target);
return AARCH64_BREAK_FAULT;
}
switch (policy) {
case AARCH64_INSN_PRFM_POLICY_KEEP:
break;
case AARCH64_INSN_PRFM_POLICY_STRM:
imm_policy = BIT(0);
break;
default:
pr_err("%s: unknown prfm policy encoding %d\n", __func__, policy);
return AARCH64_BREAK_FAULT;
}
/* In this case, imm5 is encoded into Rt field. */
insn &= ~GENMASK(4, 0);
insn |= imm_policy | (imm_target << 1) | (imm_type << 3);
return insn;
}
u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
enum aarch64_insn_prfm_type type,
enum aarch64_insn_prfm_target target,
enum aarch64_insn_prfm_policy policy)
{
u32 insn = aarch64_insn_get_prfm_value();
insn = aarch64_insn_encode_ldst_size(AARCH64_INSN_SIZE_64, insn);
insn = aarch64_insn_encode_prfm_imm(type, target, policy, insn);
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
base);
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, 0);
}
u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
enum aarch64_insn_register src,
int imm, enum aarch64_insn_variant variant,

View File

@ -83,6 +83,25 @@
/* Rt = Rn[0]; Rt2 = Rn[8]; Rn += 16; */
#define A64_POP(Rt, Rt2, Rn) A64_LS_PAIR(Rt, Rt2, Rn, 16, LOAD, POST_INDEX)
/* Load/store exclusive */
#define A64_SIZE(sf) \
((sf) ? AARCH64_INSN_SIZE_64 : AARCH64_INSN_SIZE_32)
#define A64_LSX(sf, Rt, Rn, Rs, type) \
aarch64_insn_gen_load_store_ex(Rt, Rn, Rs, A64_SIZE(sf), \
AARCH64_INSN_LDST_##type)
/* Rt = [Rn]; (atomic) */
#define A64_LDXR(sf, Rt, Rn) \
A64_LSX(sf, Rt, Rn, A64_ZR, LOAD_EX)
/* [Rn] = Rt; (atomic) Rs = [state] */
#define A64_STXR(sf, Rt, Rn, Rs) \
A64_LSX(sf, Rt, Rn, Rs, STORE_EX)
/* Prefetch */
#define A64_PRFM(Rn, type, target, policy) \
aarch64_insn_gen_prefetch(Rn, AARCH64_INSN_PRFM_TYPE_##type, \
AARCH64_INSN_PRFM_TARGET_##target, \
AARCH64_INSN_PRFM_POLICY_##policy)
/* Add/subtract (immediate) */
#define A64_ADDSUB_IMM(sf, Rd, Rn, imm12, type) \
aarch64_insn_gen_add_sub_imm(Rd, Rn, imm12, \

View File

@ -321,6 +321,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
const s32 imm = insn->imm;
const int i = insn - ctx->prog->insnsi;
const bool is64 = BPF_CLASS(code) == BPF_ALU64;
const bool isdw = BPF_SIZE(code) == BPF_DW;
u8 jmp_cond;
s32 jmp_offset;
@ -604,15 +605,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
const struct bpf_insn insn1 = insn[1];
u64 imm64;
if (insn1.code != 0 || insn1.src_reg != 0 ||
insn1.dst_reg != 0 || insn1.off != 0) {
/* Note: verifier in BPF core must catch invalid
* instructions.
*/
pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
return -EINVAL;
}
imm64 = (u64)insn1.imm << 32 | (u32)imm;
emit_a64_mov_i64(dst, imm64, ctx);
@ -690,7 +682,16 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
case BPF_STX | BPF_XADD | BPF_W:
/* STX XADD: lock *(u64 *)(dst + off) += src */
case BPF_STX | BPF_XADD | BPF_DW:
goto notyet;
emit_a64_mov_i(1, tmp, off, ctx);
emit(A64_ADD(1, tmp, tmp, dst), ctx);
emit(A64_PRFM(tmp, PST, L1, STRM), ctx);
emit(A64_LDXR(isdw, tmp2, tmp), ctx);
emit(A64_ADD(isdw, tmp2, tmp2, src), ctx);
emit(A64_STXR(isdw, tmp2, tmp, tmp2), ctx);
jmp_offset = -3;
check_imm19(jmp_offset);
emit(A64_CBNZ(0, tmp2, jmp_offset), ctx);
break;
/* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */
case BPF_LD | BPF_ABS | BPF_W:
@ -757,10 +758,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
}
break;
}
notyet:
pr_info_once("*** NOT YET: opcode %02x ***\n", code);
return -EFAULT;
default:
pr_err_once("unknown opcode %02x\n", code);
return -EINVAL;
@ -779,14 +776,14 @@ static int build_body(struct jit_ctx *ctx)
int ret;
ret = build_insn(insn, ctx);
if (ctx->image == NULL)
ctx->offset[i] = ctx->idx;
if (ret > 0) {
i++;
if (ctx->image == NULL)
ctx->offset[i] = ctx->idx;
continue;
}
if (ctx->image == NULL)
ctx->offset[i] = ctx->idx;
if (ret)
return ret;
}

View File

@ -92,5 +92,11 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _ASM_SOCKET_H */

View File

@ -101,4 +101,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _ASM_IA64_SOCKET_H */

View File

@ -92,4 +92,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _ASM_M32R_SOCKET_H */

View File

@ -110,4 +110,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _UAPI_ASM_SOCKET_H */

View File

@ -92,4 +92,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _ASM_SOCKET_H */

View File

@ -91,4 +91,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 0x402F
#define SO_MEMINFO 0x4030
#define SO_INCOMING_NAPI_ID 0x4031
#define SO_COOKIE 0x4032
#endif /* _UAPI_ASM_SOCKET_H */

View File

@ -99,4 +99,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _ASM_POWERPC_SOCKET_H */

View File

@ -98,4 +98,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _ASM_SOCKET_H */

View File

@ -31,7 +31,8 @@ config SPARC
select ARCH_WANT_IPC_PARSE_VERSION
select GENERIC_PCI_IOMAP
select HAVE_NMI_WATCHDOG if SPARC64
select HAVE_CBPF_JIT
select HAVE_CBPF_JIT if SPARC32
select HAVE_EBPF_JIT if SPARC64
select HAVE_DEBUG_BUGVERBOSE
select GENERIC_SMP_IDLE_THREAD
select GENERIC_CLOCKEVENTS

View File

@ -88,6 +88,12 @@
#define SCM_TIMESTAMPING_OPT_STATS 0x0038
#define SO_MEMINFO 0x0039
#define SO_INCOMING_NAPI_ID 0x003a
#define SO_COOKIE 0x003b
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002

View File

@ -1,4 +1,4 @@
#
# Arch-specific network modules
#
obj-$(CONFIG_BPF_JIT) += bpf_jit_asm.o bpf_jit_comp.o
obj-$(CONFIG_BPF_JIT) += bpf_jit_asm_$(BITS).o bpf_jit_comp_$(BITS).o

View File

@ -39,7 +39,7 @@
#define r_TMP2 G2
#define r_OFF G3
/* assembly code in arch/sparc/net/bpf_jit_asm.S */
/* assembly code in arch/sparc/net/bpf_jit_asm_32.S */
extern u32 bpf_jit_load_word[];
extern u32 bpf_jit_load_half[];
extern u32 bpf_jit_load_byte[];

View File

@ -0,0 +1,66 @@
#ifndef _BPF_JIT_H
#define _BPF_JIT_H
#ifndef __ASSEMBLER__
#define G0 0x00
#define G1 0x01
#define G2 0x02
#define G3 0x03
#define G6 0x06
#define G7 0x07
#define O0 0x08
#define O1 0x09
#define O2 0x0a
#define O3 0x0b
#define O4 0x0c
#define O5 0x0d
#define SP 0x0e
#define O7 0x0f
#define L0 0x10
#define L1 0x11
#define L2 0x12
#define L3 0x13
#define L4 0x14
#define L5 0x15
#define L6 0x16
#define L7 0x17
#define I0 0x18
#define I1 0x19
#define I2 0x1a
#define I3 0x1b
#define I4 0x1c
#define I5 0x1d
#define FP 0x1e
#define I7 0x1f
#define r_SKB L0
#define r_HEADLEN L4
#define r_SKB_DATA L5
#define r_TMP G1
#define r_TMP2 G3
/* assembly code in arch/sparc/net/bpf_jit_asm_64.S */
extern u32 bpf_jit_load_word[];
extern u32 bpf_jit_load_half[];
extern u32 bpf_jit_load_byte[];
extern u32 bpf_jit_load_byte_msh[];
extern u32 bpf_jit_load_word_positive_offset[];
extern u32 bpf_jit_load_half_positive_offset[];
extern u32 bpf_jit_load_byte_positive_offset[];
extern u32 bpf_jit_load_byte_msh_positive_offset[];
extern u32 bpf_jit_load_word_negative_offset[];
extern u32 bpf_jit_load_half_negative_offset[];
extern u32 bpf_jit_load_byte_negative_offset[];
extern u32 bpf_jit_load_byte_msh_negative_offset[];
#else
#define r_RESULT %o0
#define r_SKB %o0
#define r_OFF %o1
#define r_HEADLEN %l4
#define r_SKB_DATA %l5
#define r_TMP %g1
#define r_TMP2 %g3
#endif
#endif /* _BPF_JIT_H */

View File

@ -1,18 +1,11 @@
#include <asm/ptrace.h>
#include "bpf_jit.h"
#include "bpf_jit_32.h"
#ifdef CONFIG_SPARC64
#define SAVE_SZ 176
#define SCRATCH_OFF STACK_BIAS + 128
#define BE_PTR(label) be,pn %xcc, label
#define SIGN_EXTEND(reg) sra reg, 0, reg
#else
#define SAVE_SZ 96
#define SCRATCH_OFF 72
#define BE_PTR(label) be label
#define SIGN_EXTEND(reg)
#endif
#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */

View File

@ -0,0 +1,161 @@
#include <asm/ptrace.h>
#include "bpf_jit_64.h"
#define SAVE_SZ 176
#define SCRATCH_OFF STACK_BIAS + 128
#define BE_PTR(label) be,pn %xcc, label
#define SIGN_EXTEND(reg) sra reg, 0, reg
#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */
.text
.globl bpf_jit_load_word
bpf_jit_load_word:
cmp r_OFF, 0
bl bpf_slow_path_word_neg
nop
.globl bpf_jit_load_word_positive_offset
bpf_jit_load_word_positive_offset:
sub r_HEADLEN, r_OFF, r_TMP
cmp r_TMP, 3
ble bpf_slow_path_word
add r_SKB_DATA, r_OFF, r_TMP
andcc r_TMP, 3, %g0
bne load_word_unaligned
nop
retl
ld [r_TMP], r_RESULT
load_word_unaligned:
ldub [r_TMP + 0x0], r_OFF
ldub [r_TMP + 0x1], r_TMP2
sll r_OFF, 8, r_OFF
or r_OFF, r_TMP2, r_OFF
ldub [r_TMP + 0x2], r_TMP2
sll r_OFF, 8, r_OFF
or r_OFF, r_TMP2, r_OFF
ldub [r_TMP + 0x3], r_TMP2
sll r_OFF, 8, r_OFF
retl
or r_OFF, r_TMP2, r_RESULT
.globl bpf_jit_load_half
bpf_jit_load_half:
cmp r_OFF, 0
bl bpf_slow_path_half_neg
nop
.globl bpf_jit_load_half_positive_offset
bpf_jit_load_half_positive_offset:
sub r_HEADLEN, r_OFF, r_TMP
cmp r_TMP, 1
ble bpf_slow_path_half
add r_SKB_DATA, r_OFF, r_TMP
andcc r_TMP, 1, %g0
bne load_half_unaligned
nop
retl
lduh [r_TMP], r_RESULT
load_half_unaligned:
ldub [r_TMP + 0x0], r_OFF
ldub [r_TMP + 0x1], r_TMP2
sll r_OFF, 8, r_OFF
retl
or r_OFF, r_TMP2, r_RESULT
.globl bpf_jit_load_byte
bpf_jit_load_byte:
cmp r_OFF, 0
bl bpf_slow_path_byte_neg
nop
.globl bpf_jit_load_byte_positive_offset
bpf_jit_load_byte_positive_offset:
cmp r_OFF, r_HEADLEN
bge bpf_slow_path_byte
nop
retl
ldub [r_SKB_DATA + r_OFF], r_RESULT
#define bpf_slow_path_common(LEN) \
save %sp, -SAVE_SZ, %sp; \
mov %i0, %o0; \
mov %i1, %o1; \
add %fp, SCRATCH_OFF, %o2; \
call skb_copy_bits; \
mov (LEN), %o3; \
cmp %o0, 0; \
restore;
bpf_slow_path_word:
bpf_slow_path_common(4)
bl bpf_error
ld [%sp + SCRATCH_OFF], r_RESULT
retl
nop
bpf_slow_path_half:
bpf_slow_path_common(2)
bl bpf_error
lduh [%sp + SCRATCH_OFF], r_RESULT
retl
nop
bpf_slow_path_byte:
bpf_slow_path_common(1)
bl bpf_error
ldub [%sp + SCRATCH_OFF], r_RESULT
retl
nop
#define bpf_negative_common(LEN) \
save %sp, -SAVE_SZ, %sp; \
mov %i0, %o0; \
mov %i1, %o1; \
SIGN_EXTEND(%o1); \
call bpf_internal_load_pointer_neg_helper; \
mov (LEN), %o2; \
mov %o0, r_TMP; \
cmp %o0, 0; \
BE_PTR(bpf_error); \
restore;
bpf_slow_path_word_neg:
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
cmp r_OFF, r_TMP
bl bpf_error
nop
.globl bpf_jit_load_word_negative_offset
bpf_jit_load_word_negative_offset:
bpf_negative_common(4)
andcc r_TMP, 3, %g0
bne load_word_unaligned
nop
retl
ld [r_TMP], r_RESULT
bpf_slow_path_half_neg:
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
cmp r_OFF, r_TMP
bl bpf_error
nop
.globl bpf_jit_load_half_negative_offset
bpf_jit_load_half_negative_offset:
bpf_negative_common(2)
andcc r_TMP, 1, %g0
bne load_half_unaligned
nop
retl
lduh [r_TMP], r_RESULT
bpf_slow_path_byte_neg:
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
cmp r_OFF, r_TMP
bl bpf_error
nop
.globl bpf_jit_load_byte_negative_offset
bpf_jit_load_byte_negative_offset:
bpf_negative_common(1)
retl
ldub [r_TMP], r_RESULT
bpf_error:
/* Make the JIT program itself return zero. */
ret
restore %g0, %g0, %o0

View File

@ -8,7 +8,7 @@
#include <asm/cacheflush.h>
#include <asm/ptrace.h>
#include "bpf_jit.h"
#include "bpf_jit_32.h"
int bpf_jit_enable __read_mostly;
@ -17,24 +17,6 @@ static inline bool is_simm13(unsigned int value)
return value + 0x1000 < 0x2000;
}
static void bpf_flush_icache(void *start_, void *end_)
{
#ifdef CONFIG_SPARC64
/* Cheetah's I-cache is fully coherent. */
if (tlb_type == spitfire) {
unsigned long start = (unsigned long) start_;
unsigned long end = (unsigned long) end_;
start &= ~7UL;
end = (end + 7UL) & ~7UL;
while (start < end) {
flushi(start);
start += 32;
}
}
#endif
}
#define SEEN_DATAREF 1 /* might call external helpers */
#define SEEN_XREG 2 /* ebx is used */
#define SEEN_MEM 4 /* use mem[] for temporary storage */
@ -82,11 +64,7 @@ static void bpf_flush_icache(void *start_, void *end_)
#define BE (F2(0, 2) | CONDE)
#define BNE (F2(0, 2) | CONDNE)
#ifdef CONFIG_SPARC64
#define BE_PTR (F2(0, 1) | CONDE | (2 << 20))
#else
#define BE_PTR BE
#endif
#define SETHI(K, REG) \
(F2(0, 0x4) | RD(REG) | (((K) >> 10) & 0x3fffff))
@ -116,13 +94,8 @@ static void bpf_flush_icache(void *start_, void *end_)
#define LD64 F3(3, 0x0b)
#define ST32 F3(3, 0x04)
#ifdef CONFIG_SPARC64
#define LDPTR LD64
#define BASE_STACKFRAME 176
#else
#define LDPTR LD32
#define BASE_STACKFRAME 96
#endif
#define LD32I (LD32 | IMMED)
#define LD8I (LD8 | IMMED)
@ -234,11 +207,7 @@ do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \
__emit_load8(BASE, STRUCT, FIELD, DEST); \
} while (0)
#ifdef CONFIG_SPARC64
#define BIAS (STACK_BIAS - 4)
#else
#define BIAS (-4)
#endif
#define emit_ldmem(OFF, DEST) \
do { *prog++ = LD32I | RS1(SP) | S13(BIAS - (OFF)) | RD(DEST); \
@ -249,13 +218,8 @@ do { *prog++ = ST32I | RS1(SP) | S13(BIAS - (OFF)) | RD(SRC); \
} while (0)
#ifdef CONFIG_SMP
#ifdef CONFIG_SPARC64
#define emit_load_cpu(REG) \
emit_load16(G6, struct thread_info, cpu, REG)
#else
#define emit_load_cpu(REG) \
emit_load32(G6, struct thread_info, cpu, REG)
#endif
#else
#define emit_load_cpu(REG) emit_clear(REG)
#endif
@ -486,7 +450,6 @@ void bpf_jit_compile(struct bpf_prog *fp)
if (K == 1)
break;
emit_write_y(G0);
#ifdef CONFIG_SPARC32
/* The Sparc v8 architecture requires
* three instructions between a %y
* register write and the first use.
@ -494,31 +457,21 @@ void bpf_jit_compile(struct bpf_prog *fp)
emit_nop();
emit_nop();
emit_nop();
#endif
emit_alu_K(DIV, K);
break;
case BPF_ALU | BPF_DIV | BPF_X: /* A /= X; */
emit_cmpi(r_X, 0);
if (pc_ret0 > 0) {
t_offset = addrs[pc_ret0 - 1];
#ifdef CONFIG_SPARC32
emit_branch(BE, t_offset + 20);
#else
emit_branch(BE, t_offset + 8);
#endif
emit_nop(); /* delay slot */
} else {
emit_branch_off(BNE, 16);
emit_nop();
#ifdef CONFIG_SPARC32
emit_jump(cleanup_addr + 20);
#else
emit_jump(cleanup_addr + 8);
#endif
emit_clear(r_A);
}
emit_write_y(G0);
#ifdef CONFIG_SPARC32
/* The Sparc v8 architecture requires
* three instructions between a %y
* register write and the first use.
@ -526,7 +479,6 @@ void bpf_jit_compile(struct bpf_prog *fp)
emit_nop();
emit_nop();
emit_nop();
#endif
emit_alu_X(DIV);
break;
case BPF_ALU | BPF_NEG:
@ -797,7 +749,6 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
bpf_jit_dump(flen, proglen, pass + 1, image);
if (image) {
bpf_flush_icache(image, image + proglen);
fp->bpf_func = (void *)image;
fp->jited = 1;
}

File diff suppressed because it is too large Load Diff

View File

@ -490,13 +490,6 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
break;
case BPF_LD | BPF_IMM | BPF_DW:
if (insn[1].code != 0 || insn[1].src_reg != 0 ||
insn[1].dst_reg != 0 || insn[1].off != 0) {
/* verifier must catch invalid insns */
pr_err("invalid BPF_LD_IMM64 insn\n");
return -EINVAL;
}
/* optimization: if imm64 is zero, use 'xor <dst>,<dst>'
* to save 7 bytes.
*/

View File

@ -103,4 +103,10 @@
#define SCM_TIMESTAMPING_OPT_STATS 54
#define SO_MEMINFO 55
#define SO_INCOMING_NAPI_ID 56
#define SO_COOKIE 57
#endif /* _XTENSA_SOCKET_H */

View File

@ -483,7 +483,8 @@ static const struct crypto_link {
[CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
};
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{
struct nlattr *attrs[CRYPTOCFGA_MAX+1];
const struct crypto_link *link;
@ -522,7 +523,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
crypto_policy);
crypto_policy, extack);
if (err < 0)
return err;

View File

@ -2267,9 +2267,8 @@ static int amb_probe(struct pci_dev *pci_dev,
dev->atm_dev->ci_range.vpi_bits = NUM_VPI_BITS;
dev->atm_dev->ci_range.vci_bits = NUM_VCI_BITS;
init_timer(&dev->housekeeping);
dev->housekeeping.function = do_housekeeping;
dev->housekeeping.data = (unsigned long) dev;
setup_timer(&dev->housekeeping, do_housekeeping,
(unsigned long)dev);
mod_timer(&dev->housekeeping, jiffies);
// enable host interrupts

View File

@ -185,7 +185,6 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip->owner = THIS_MODULE;
chip->parent = bcma_bus_get_host_dev(bus);
#if IS_BUILTIN(CONFIG_OF)
if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
chip->of_node = cc->core->dev.of_node;
#endif
switch (bus->chipinfo.id) {

View File

@ -201,9 +201,6 @@ static void bcma_of_fill_device(struct device *parent,
{
struct device_node *node;
if (!IS_ENABLED(CONFIG_OF_IRQ))
return;
node = bcma_of_find_child_device(parent, core);
if (node)
core->dev.of_node = node;
@ -242,19 +239,18 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
core->dev.release = bcma_release_core_dev;
core->dev.bus = &bcma_bus_type;
dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
core->dev.parent = bcma_bus_get_host_dev(bus);
if (core->dev.parent)
bcma_of_fill_device(core->dev.parent, core);
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
core->dev.parent = &bus->host_pci->dev;
core->dma_dev = &bus->host_pci->dev;
core->irq = bus->host_pci->irq;
break;
case BCMA_HOSTTYPE_SOC:
if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) {
core->dma_dev = &bus->host_pdev->dev;
core->dev.parent = &bus->host_pdev->dev;
if (core->dev.parent)
bcma_of_fill_device(core->dev.parent, core);
} else {
core->dev.dma_mask = &core->dev.coherent_dma_mask;
core->dma_dev = &core->dev;

View File

@ -34,7 +34,7 @@ int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
err = drbd_nla_check_mandatory(maxtype, nla);
if (!err)
err = nla_parse_nested(tb, maxtype, nla, policy);
err = nla_parse_nested(tb, maxtype, nla, policy, NULL);
return err;
}

View File

@ -1662,7 +1662,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
goto out;
}
ret = nla_parse_nested(socks, NBD_SOCK_MAX, attr,
nbd_sock_policy);
nbd_sock_policy, info->extack);
if (ret != 0) {
printk(KERN_ERR "nbd: error processing sock list\n");
ret = -EINVAL;
@ -1818,7 +1818,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
goto out;
}
ret = nla_parse_nested(socks, NBD_SOCK_MAX, attr,
nbd_sock_policy);
nbd_sock_policy, info->extack);
if (ret != 0) {
printk(KERN_ERR "nbd: error processing sock list\n");
ret = -EINVAL;

View File

@ -76,6 +76,12 @@ config BT_HCIUART
Say Y here to compile support for Bluetooth UART devices into the
kernel or say M to compile it as module (hci_uart).
config BT_HCIUART_SERDEV
bool
depends on SERIAL_DEV_BUS && BT_HCIUART
depends on SERIAL_DEV_BUS=y || SERIAL_DEV_BUS=BT_HCIUART
default y
config BT_HCIUART_H4
bool "UART (H4) protocol support"
depends on BT_HCIUART
@ -86,6 +92,18 @@ config BT_HCIUART_H4
Say Y here to compile support for HCI UART (H4) protocol.
config BT_HCIUART_NOKIA
tristate "UART Nokia H4+ protocol support"
depends on BT_HCIUART
depends on BT_HCIUART_SERDEV
depends on PM
help
Nokia H4+ is serial protocol for communication between Bluetooth
device and host. This protocol is required for Bluetooth devices
with UART interface in Nokia devices.
Say Y here to compile support for Nokia's H4+ protocol.
config BT_HCIUART_BCSP
bool "BCSP protocol support"
depends on BT_HCIUART
@ -344,7 +362,7 @@ config BT_WILINK
config BT_QCOMSMD
tristate "Qualcomm SMD based HCI support"
depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
depends on RPMSG || (COMPILE_TEST && RPMSG=n)
depends on QCOM_WCNSS_CTRL || (COMPILE_TEST && QCOM_WCNSS_CTRL=n)
select BT_QCA
help

View File

@ -25,10 +25,13 @@ obj-$(CONFIG_BT_BCM) += btbcm.o
obj-$(CONFIG_BT_RTL) += btrtl.o
obj-$(CONFIG_BT_QCA) += btqca.o
obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o
btmrvl-y := btmrvl_main.o
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BT_HCIUART_SERDEV) += hci_serdev.o
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o

View File

@ -695,9 +695,8 @@ static int bluecard_open(struct bluecard_info *info)
spin_lock_init(&(info->lock));
init_timer(&(info->timer));
info->timer.function = &bluecard_activity_led_timeout;
info->timer.data = (u_long)info;
setup_timer(&(info->timer), &bluecard_activity_led_timeout,
(u_long)info);
skb_queue_head_init(&(info->txq));

View File

@ -20,6 +20,7 @@
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
@ -60,13 +61,15 @@ static const struct of_device_id btmrvl_sdio_of_match_table[] = {
static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
{
struct btmrvl_plt_wake_cfg *cfg = priv;
struct btmrvl_sdio_card *card = priv;
struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg;
if (cfg->irq_bt >= 0) {
pr_info("%s: wake by bt", __func__);
cfg->wake_by_bt = true;
disable_irq_nosync(irq);
}
pm_wakeup_event(&card->func->dev, 0);
pm_system_wakeup();
return IRQ_HANDLED;
}
@ -101,7 +104,7 @@ static int btmrvl_sdio_probe_of(struct device *dev,
} else {
ret = devm_request_irq(dev, cfg->irq_bt,
btmrvl_wake_irq_bt,
0, "bt_wake", cfg);
0, "bt_wake", card);
if (ret) {
dev_err(dev,
"Failed to request irq_bt %d (%d)\n",
@ -1574,7 +1577,7 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
MODULE_SHUTDOWN_REQ);
btmrvl_sdio_disable_host_int(card);
}
BT_DBG("unregester dev");
BT_DBG("unregister dev");
card->priv->surprise_removed = true;
btmrvl_sdio_unregister_dev(card);
btmrvl_remove_card(card->priv);
@ -1625,6 +1628,13 @@ static int btmrvl_sdio_suspend(struct device *dev)
if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) {
BT_ERR("HS not activated, suspend failed!");
/* Disable platform specific wakeup interrupt */
if (card->plt_wake_cfg &&
card->plt_wake_cfg->irq_bt >= 0) {
disable_irq_wake(card->plt_wake_cfg->irq_bt);
disable_irq(card->plt_wake_cfg->irq_bt);
}
priv->adapter->is_suspending = false;
return -EBUSY;
}
@ -1637,10 +1647,10 @@ static int btmrvl_sdio_suspend(struct device *dev)
if (priv->adapter->hs_state == HS_ACTIVATED) {
BT_DBG("suspend with MMC_PM_KEEP_POWER");
return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
} else {
}
BT_DBG("suspend without MMC_PM_KEEP_POWER");
return 0;
}
}
static int btmrvl_sdio_resume(struct device *dev)

View File

@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smd.h>
#include <linux/rpmsg.h>
#include <linux/soc/qcom/wcnss_ctrl.h>
#include <linux/platform_device.h>
@ -26,8 +26,8 @@
struct btqcomsmd {
struct hci_dev *hdev;
struct qcom_smd_channel *acl_channel;
struct qcom_smd_channel *cmd_channel;
struct rpmsg_endpoint *acl_channel;
struct rpmsg_endpoint *cmd_channel;
};
static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
@ -48,19 +48,19 @@ static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
return hci_recv_frame(hdev, skb);
}
static int btqcomsmd_acl_callback(struct qcom_smd_channel *channel,
const void *data, size_t count)
static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
int count, void *priv, u32 addr)
{
struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
struct btqcomsmd *btq = priv;
btq->hdev->stat.byte_rx += count;
return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
}
static int btqcomsmd_cmd_callback(struct qcom_smd_channel *channel,
const void *data, size_t count)
static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
int count, void *priv, u32 addr)
{
struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
struct btqcomsmd *btq = priv;
return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
}
@ -72,12 +72,12 @@ static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
switch (hci_skb_pkt_type(skb)) {
case HCI_ACLDATA_PKT:
ret = qcom_smd_send(btq->acl_channel, skb->data, skb->len);
ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
hdev->stat.acl_tx++;
hdev->stat.byte_tx += skb->len;
break;
case HCI_COMMAND_PKT:
ret = qcom_smd_send(btq->cmd_channel, skb->data, skb->len);
ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
hdev->stat.cmd_tx++;
break;
default:
@ -114,18 +114,15 @@ static int btqcomsmd_probe(struct platform_device *pdev)
wcnss = dev_get_drvdata(pdev->dev.parent);
btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
btqcomsmd_acl_callback);
btqcomsmd_acl_callback, btq);
if (IS_ERR(btq->acl_channel))
return PTR_ERR(btq->acl_channel);
btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
btqcomsmd_cmd_callback);
btqcomsmd_cmd_callback, btq);
if (IS_ERR(btq->cmd_channel))
return PTR_ERR(btq->cmd_channel);
qcom_smd_set_drvdata(btq->acl_channel, btq);
qcom_smd_set_drvdata(btq->cmd_channel, btq);
hdev = hci_alloc_dev();
if (!hdev)
return -ENOMEM;
@ -158,6 +155,9 @@ static int btqcomsmd_remove(struct platform_device *pdev)
hci_unregister_dev(btq->hdev);
hci_free_dev(btq->hdev);
rpmsg_destroy_ept(btq->cmd_channel);
rpmsg_destroy_ept(btq->acl_channel);
return 0;
}

View File

@ -275,11 +275,8 @@ static int rtl_load_config(struct hci_dev *hdev, const char *name, u8 **buff)
BT_INFO("%s: rtl: loading %s", hdev->name, name);
ret = request_firmware(&fw, name, &hdev->dev);
if (ret < 0) {
BT_ERR("%s: Failed to load %s", hdev->name, name);
if (ret < 0)
return ret;
}
ret = fw->size;
*buff = kmemdup(fw->data, ret, GFP_KERNEL);
@ -331,6 +328,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
u8 *cfg_buff = NULL;
u8 *tbuff;
char *cfg_name = NULL;
bool config_needed = false;
switch (lmp_subver) {
case RTL_ROM_LMP_8723B:
@ -344,6 +342,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
break;
case RTL_ROM_LMP_8822B:
cfg_name = "rtl_bt/rtl8822b_config.bin";
config_needed = true;
break;
default:
BT_ERR("%s: rtl: no config according to lmp_subver %04x",
@ -353,8 +352,12 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
if (cfg_name) {
cfg_sz = rtl_load_config(hdev, cfg_name, &cfg_buff);
if (cfg_sz < 0)
if (cfg_sz < 0) {
cfg_sz = 0;
if (config_needed)
BT_ERR("Necessary config file %s not found\n",
cfg_name);
}
} else
cfg_sz = 0;

View File

@ -26,6 +26,7 @@
#include <linux/firmware.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/suspend.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@ -262,6 +263,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME },
@ -328,6 +330,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
/* Intel Bluetooth devices */
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW },
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
@ -2024,13 +2027,18 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
return -EINVAL;
}
/* At the moment the iBT 3.0 hardware variants 0x0b (LnP/SfP)
* and 0x0c (WsP) are supported by this firmware loading method.
/* Check for supported iBT hardware variants of this firmware
* loading method.
*
* This check has been put in place to ensure correct forward
* compatibility options when newer hardware variants come along.
*/
if (ver.hw_variant != 0x0b && ver.hw_variant != 0x0c) {
switch (ver.hw_variant) {
case 0x0b: /* SfP */
case 0x0c: /* WsP */
case 0x12: /* ThP */
break;
default:
BT_ERR("%s: Unsupported Intel hardware variant (%u)",
hdev->name, ver.hw_variant);
return -EINVAL;
@ -2792,6 +2800,7 @@ static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
struct btusb_data *data = priv;
pm_wakeup_event(&data->udev->dev, 0);
pm_system_wakeup();
/* Disable only if not already disabled (keep it balanced) */
if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {

View File

@ -146,13 +146,13 @@ static bool bcm_device_exists(struct bcm_device *device)
static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
{
if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled)
clk_enable(dev->clk);
clk_prepare_enable(dev->clk);
gpiod_set_value(dev->shutdown, powered);
gpiod_set_value(dev->device_wakeup, powered);
if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled)
clk_disable(dev->clk);
clk_disable_unprepare(dev->clk);
dev->clk_enabled = powered;
@ -287,6 +287,9 @@ static int bcm_open(struct hci_uart *hu)
hu->priv = bcm;
if (!hu->tty->dev)
goto out;
mutex_lock(&bcm_device_lock);
list_for_each(p, &bcm_device_list) {
struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@ -307,7 +310,7 @@ static int bcm_open(struct hci_uart *hu)
}
mutex_unlock(&bcm_device_lock);
out:
return 0;
}
@ -697,28 +700,14 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
/* Always tell the ACPI core to skip this resource */
return 1;
}
#endif /* CONFIG_ACPI */
static int bcm_acpi_probe(struct bcm_device *dev)
static int bcm_platform_probe(struct bcm_device *dev)
{
struct platform_device *pdev = dev->pdev;
LIST_HEAD(resources);
const struct dmi_system_id *dmi_id;
const struct acpi_gpio_mapping *gpio_mapping = acpi_bcm_int_last_gpios;
const struct acpi_device_id *id;
int ret;
dev->name = dev_name(&pdev->dev);
/* Retrieve GPIO data */
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id)
gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
gpio_mapping);
if (ret)
return ret;
dev->clk = devm_clk_get(&pdev->dev, NULL);
dev->device_wakeup = devm_gpiod_get_optional(&pdev->dev,
@ -755,6 +744,33 @@ static int bcm_acpi_probe(struct bcm_device *dev)
return -EINVAL;
}
return 0;
}
#ifdef CONFIG_ACPI
static int bcm_acpi_probe(struct bcm_device *dev)
{
struct platform_device *pdev = dev->pdev;
LIST_HEAD(resources);
const struct dmi_system_id *dmi_id;
const struct acpi_gpio_mapping *gpio_mapping = acpi_bcm_int_last_gpios;
const struct acpi_device_id *id;
int ret;
/* Retrieve GPIO data */
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id)
gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
gpio_mapping);
if (ret)
return ret;
ret = bcm_platform_probe(dev);
if (ret)
return ret;
/* Retrieve UART ACPI info */
ret = acpi_dev_get_resources(ACPI_COMPANION(&dev->pdev->dev),
&resources, bcm_resource, dev);
@ -789,7 +805,10 @@ static int bcm_probe(struct platform_device *pdev)
dev->pdev = pdev;
if (has_acpi_companion(&pdev->dev))
ret = bcm_acpi_probe(dev);
else
ret = bcm_platform_probe(dev);
if (ret)
return ret;

View File

@ -171,9 +171,20 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
const unsigned char *buffer, int count,
const struct h4_recv_pkt *pkts, int pkts_count)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
u8 alignment = hu->alignment;
while (count) {
int i, len;
/* remove padding bytes from buffer */
for (; hu->padding && count > 0; hu->padding--) {
count--;
buffer++;
}
if (!count)
break;
if (!skb) {
for (i = 0; i < pkts_count; i++) {
if (buffer[0] != (&pkts[i])->type)
@ -253,11 +264,17 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
}
if (!dlen) {
hu->padding = (skb->len - 1) % alignment;
hu->padding = (alignment - hu->padding) % alignment;
/* No more data, complete frame */
(&pkts[i])->recv(hdev, skb);
skb = NULL;
}
} else {
hu->padding = (skb->len - 1) % alignment;
hu->padding = (alignment - hu->padding) % alignment;
/* Complete frame */
(&pkts[i])->recv(hdev, skb);
skb = NULL;

View File

@ -307,6 +307,9 @@ static int intel_set_power(struct hci_uart *hu, bool powered)
struct list_head *p;
int err = -ENODEV;
if (!hu->tty->dev)
return err;
mutex_lock(&intel_device_list_lock);
list_for_each(p, &intel_device_list) {
@ -379,6 +382,9 @@ static void intel_busy_work(struct work_struct *work)
struct intel_data *intel = container_of(work, struct intel_data,
busy_work);
if (!intel->hu->tty->dev)
return;
/* Link is busy, delay the suspend */
mutex_lock(&intel_device_list_lock);
list_for_each(p, &intel_device_list) {
@ -601,12 +607,18 @@ static int intel_setup(struct hci_uart *hu)
return -EINVAL;
}
/* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is
* supported by this firmware loading method. This check has been
* put in place to ensure correct forward compatibility options
* when newer hardware variants come along.
/* Check for supported iBT hardware variants of this firmware
* loading method.
*
* This check has been put in place to ensure correct forward
* compatibility options when newer hardware variants come along.
*/
if (ver.hw_variant != 0x0b) {
switch (ver.hw_variant) {
case 0x0b: /* LnP */
case 0x0c: /* WsP */
case 0x12: /* ThP */
break;
default:
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
ver.hw_variant);
return -EINVAL;
@ -699,10 +711,13 @@ static int intel_setup(struct hci_uart *hu)
/* With this Intel bootloader only the hardware variant and device
* revision information are used to select the right firmware.
*
* Currently this bootloader support is limited to hardware variant
* iBT 3.0 (LnP/SfP) which is identified by the value 11 (0x0b).
* The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
*
* Currently the supported hardware variants are:
* 11 (0x0b) for iBT 3.0 (LnP/SfP)
*/
snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.sfi",
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
le16_to_cpu(ver.hw_variant),
le16_to_cpu(params->dev_revid));
err = request_firmware(&fw, fwname, &hdev->dev);
@ -716,7 +731,8 @@ static int intel_setup(struct hci_uart *hu)
bt_dev_info(hdev, "Found device firmware: %s", fwname);
/* Save the DDC file name for later */
snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.ddc",
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
le16_to_cpu(ver.hw_variant),
le16_to_cpu(params->dev_revid));
kfree_skb(skb);
@ -889,6 +905,8 @@ static int intel_setup(struct hci_uart *hu)
list_for_each(p, &intel_device_list) {
struct intel_device *dev = list_entry(p, struct intel_device,
list);
if (!hu->tty->dev)
break;
if (hu->tty->dev->parent == dev->pdev->dev.parent) {
if (device_may_wakeup(&dev->pdev->dev)) {
set_bit(STATE_LPM_ENABLED, &intel->flags);
@ -1056,6 +1074,9 @@ static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb)
BT_DBG("hu %p skb %p", hu, skb);
if (!hu->tty->dev)
goto out_enqueue;
/* Be sure our controller is resumed and potential LPM transaction
* completed before enqueuing any packet.
*/
@ -1072,7 +1093,7 @@ static int intel_enqueue(struct hci_uart *hu, struct sk_buff *skb)
}
}
mutex_unlock(&intel_device_list_lock);
out_enqueue:
skb_queue_tail(&intel->txq, skb);
return 0;

View File

@ -113,16 +113,21 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
{
struct sk_buff *skb = hu->tx_skb;
if (!skb)
if (!skb) {
if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
skb = hu->proto->dequeue(hu);
else
} else {
hu->tx_skb = NULL;
}
return skb;
}
int hci_uart_tx_wakeup(struct hci_uart *hu)
{
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
return 0;
if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
return 0;
@ -134,6 +139,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
return 0;
}
EXPORT_SYMBOL_GPL(hci_uart_tx_wakeup);
static void hci_uart_write_work(struct work_struct *work)
{
@ -176,6 +182,7 @@ static void hci_uart_init_work(struct work_struct *work)
{
struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
int err;
struct hci_dev *hdev;
if (!test_and_clear_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return;
@ -183,9 +190,12 @@ static void hci_uart_init_work(struct work_struct *work)
err = hci_register_dev(hu->hdev);
if (err < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hu->hdev);
hdev = hu->hdev;
hu->hdev = NULL;
hci_free_dev(hdev);
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
hu->proto->close(hu);
return;
}
set_bit(HCI_UART_REGISTERED, &hu->flags);
@ -251,6 +261,9 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb),
skb->len);
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
return -EUNATCH;
hu->proto->enqueue(hu, skb);
hci_uart_tx_wakeup(hu);
@ -318,25 +331,6 @@ void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
hu->oper_speed = oper_speed;
}
void hci_uart_init_tty(struct hci_uart *hu)
{
struct tty_struct *tty = hu->tty;
struct ktermios ktermios;
/* Bring the UART into a known 8 bits no parity hw fc state */
ktermios = tty->termios;
ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
INLCR | IGNCR | ICRNL | IXON);
ktermios.c_oflag &= ~OPOST;
ktermios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
ktermios.c_cflag &= ~(CSIZE | PARENB);
ktermios.c_cflag |= CS8;
ktermios.c_cflag |= CRTSCTS;
/* tty_set_termios() return not checked as it is always 0 */
tty_set_termios(tty, &ktermios);
}
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed)
{
struct tty_struct *tty = hu->tty;
@ -459,6 +453,10 @@ static int hci_uart_tty_open(struct tty_struct *tty)
hu->tty = tty;
tty->receive_room = 65536;
/* disable alignment support by default */
hu->alignment = 1;
hu->padding = 0;
INIT_WORK(&hu->init_ready, hci_uart_init_work);
INIT_WORK(&hu->write_work, hci_uart_write_work);
@ -616,6 +614,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hu->hdev = NULL;
hci_free_dev(hdev);
return -ENODEV;
}

View File

@ -34,20 +34,24 @@
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/firmware.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/signal.h>
#include <linux/ioctl.h>
#include <linux/of.h>
#include <linux/serdev.h>
#include <linux/skbuff.h>
#include <linux/ti_wilink_st.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <linux/gpio/consumer.h>
#include "hci_uart.h"
@ -76,6 +80,12 @@ struct hcill_cmd {
u8 cmd;
} __packed;
struct ll_device {
struct hci_uart hu;
struct serdev_device *serdev;
struct gpio_desc *enable_gpio;
};
struct ll_struct {
unsigned long rx_state;
unsigned long rx_count;
@ -136,6 +146,9 @@ static int ll_open(struct hci_uart *hu)
hu->priv = ll;
if (hu->serdev)
serdev_device_open(hu->serdev);
return 0;
}
@ -164,6 +177,13 @@ static int ll_close(struct hci_uart *hu)
kfree_skb(ll->rx_skb);
if (hu->serdev) {
struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
gpiod_set_value_cansleep(lldev->enable_gpio, 0);
serdev_device_close(hu->serdev);
}
hu->priv = NULL;
kfree(ll);
@ -505,9 +525,244 @@ static struct sk_buff *ll_dequeue(struct hci_uart *hu)
return skb_dequeue(&ll->txq);
}
#if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)
static int read_local_version(struct hci_dev *hdev)
{
int err = 0;
unsigned short version = 0;
struct sk_buff *skb;
struct hci_rp_read_local_version *ver;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading TI version information failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
err = -EILSEQ;
goto out;
}
ver = (struct hci_rp_read_local_version *)skb->data;
if (le16_to_cpu(ver->manufacturer) != 13) {
err = -ENODEV;
goto out;
}
version = le16_to_cpu(ver->lmp_subver);
out:
if (err) bt_dev_err(hdev, "Failed to read TI version info: %d", err);
kfree_skb(skb);
return err ? err : version;
}
/**
* download_firmware -
* internal function which parses through the .bts firmware
* script file intreprets SEND, DELAY actions only as of now
*/
static int download_firmware(struct ll_device *lldev)
{
unsigned short chip, min_ver, maj_ver;
int version, err, len;
unsigned char *ptr, *action_ptr;
unsigned char bts_scr_name[40]; /* 40 char long bts scr name? */
const struct firmware *fw;
struct sk_buff *skb;
struct hci_command *cmd;
version = read_local_version(lldev->hu.hdev);
if (version < 0)
return version;
chip = (version & 0x7C00) >> 10;
min_ver = (version & 0x007F);
maj_ver = (version & 0x0380) >> 7;
if (version & 0x8000)
maj_ver |= 0x0008;
snprintf(bts_scr_name, sizeof(bts_scr_name),
"ti-connectivity/TIInit_%d.%d.%d.bts",
chip, maj_ver, min_ver);
err = request_firmware(&fw, bts_scr_name, &lldev->serdev->dev);
if (err || !fw->data || !fw->size) {
bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s",
err, bts_scr_name);
return -EINVAL;
}
ptr = (void *)fw->data;
len = fw->size;
/* bts_header to remove out magic number and
* version
*/
ptr += sizeof(struct bts_header);
len -= sizeof(struct bts_header);
while (len > 0 && ptr) {
bt_dev_dbg(lldev->hu.hdev, " action size %d, type %d ",
((struct bts_action *)ptr)->size,
((struct bts_action *)ptr)->type);
action_ptr = &(((struct bts_action *)ptr)->data[0]);
switch (((struct bts_action *)ptr)->type) {
case ACTION_SEND_COMMAND: /* action send */
bt_dev_dbg(lldev->hu.hdev, "S");
cmd = (struct hci_command *)action_ptr;
if (cmd->opcode == 0xff36) {
/* ignore remote change
* baud rate HCI VS command */
bt_dev_warn(lldev->hu.hdev, "change remote baud rate command in firmware");
break;
}
if (cmd->prefix != 1)
bt_dev_dbg(lldev->hu.hdev, "command type %d\n", cmd->prefix);
skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen, &cmd->speed, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(lldev->hu.hdev, "send command failed\n");
goto out_rel_fw;
}
kfree_skb(skb);
break;
case ACTION_WAIT_EVENT: /* wait */
/* no need to wait as command was synchronous */
bt_dev_dbg(lldev->hu.hdev, "W");
break;
case ACTION_DELAY: /* sleep */
bt_dev_info(lldev->hu.hdev, "sleep command in scr");
mdelay(((struct bts_action_delay *)action_ptr)->msec);
break;
}
len -= (sizeof(struct bts_action) +
((struct bts_action *)ptr)->size);
ptr += sizeof(struct bts_action) +
((struct bts_action *)ptr)->size;
}
out_rel_fw:
/* fw download complete */
release_firmware(fw);
return err;
}
static int ll_setup(struct hci_uart *hu)
{
int err, retry = 3;
struct ll_device *lldev;
struct serdev_device *serdev = hu->serdev;
u32 speed;
if (!serdev)
return 0;
lldev = serdev_device_get_drvdata(serdev);
serdev_device_set_flow_control(serdev, true);
do {
/* Configure BT_EN to HIGH state */
gpiod_set_value_cansleep(lldev->enable_gpio, 0);
msleep(5);
gpiod_set_value_cansleep(lldev->enable_gpio, 1);
msleep(100);
err = download_firmware(lldev);
if (!err)
break;
/* Toggle BT_EN and retry */
bt_dev_err(hu->hdev, "download firmware failed, retrying...");
} while (retry--);
if (err)
return err;
/* Operational speed if any */
if (hu->oper_speed)
speed = hu->oper_speed;
else if (hu->proto->oper_speed)
speed = hu->proto->oper_speed;
else
speed = 0;
if (speed) {
struct sk_buff *skb = __hci_cmd_sync(hu->hdev, 0xff36, sizeof(speed), &speed, HCI_INIT_TIMEOUT);
if (!IS_ERR(skb)) {
kfree_skb(skb);
serdev_device_set_baudrate(serdev, speed);
}
}
return 0;
}
static const struct hci_uart_proto llp;
static int hci_ti_probe(struct serdev_device *serdev)
{
struct hci_uart *hu;
struct ll_device *lldev;
u32 max_speed = 3000000;
lldev = devm_kzalloc(&serdev->dev, sizeof(struct ll_device), GFP_KERNEL);
if (!lldev)
return -ENOMEM;
hu = &lldev->hu;
serdev_device_set_drvdata(serdev, lldev);
lldev->serdev = hu->serdev = serdev;
lldev->enable_gpio = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(lldev->enable_gpio))
return PTR_ERR(lldev->enable_gpio);
of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed);
hci_uart_set_speeds(hu, 115200, max_speed);
return hci_uart_register_device(hu, &llp);
}
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);
}
static const struct of_device_id hci_ti_of_match[] = {
{ .compatible = "ti,wl1831-st" },
{ .compatible = "ti,wl1835-st" },
{ .compatible = "ti,wl1837-st" },
{},
};
MODULE_DEVICE_TABLE(of, hci_ti_of_match);
static struct serdev_device_driver hci_ti_drv = {
.driver = {
.name = "hci-ti",
.of_match_table = of_match_ptr(hci_ti_of_match),
},
.probe = hci_ti_probe,
.remove = hci_ti_remove,
};
#else
#define ll_setup NULL
#endif
static const struct hci_uart_proto llp = {
.id = HCI_UART_LL,
.name = "LL",
.setup = ll_setup,
.open = ll_open,
.close = ll_close,
.recv = ll_recv,
@ -518,10 +773,14 @@ static const struct hci_uart_proto llp = {
int __init ll_init(void)
{
serdev_device_driver_register(&hci_ti_drv);
return hci_uart_register_proto(&llp);
}
int __exit ll_deinit(void)
{
serdev_device_driver_unregister(&hci_ti_drv);
return hci_uart_unregister_proto(&llp);
}

View File

@ -0,0 +1,827 @@
/*
* Bluetooth HCI UART H4 driver with Nokia Extensions AKA Nokia H4+
*
* Copyright (C) 2015 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2015-2017 Sebastian Reichel <sre@kernel.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/serdev.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/unaligned/le_struct.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "hci_uart.h"
#include "btbcm.h"
#define VERSION "0.1"
#define NOKIA_ID_BCM2048 0x04
#define NOKIA_ID_TI1271 0x31
#define FIRMWARE_BCM2048 "nokia/bcmfw.bin"
#define FIRMWARE_TI1271 "nokia/ti1273.bin"
#define HCI_NOKIA_NEG_PKT 0x06
#define HCI_NOKIA_ALIVE_PKT 0x07
#define HCI_NOKIA_RADIO_PKT 0x08
#define HCI_NOKIA_NEG_HDR_SIZE 1
#define HCI_NOKIA_MAX_NEG_SIZE 255
#define HCI_NOKIA_ALIVE_HDR_SIZE 1
#define HCI_NOKIA_MAX_ALIVE_SIZE 255
#define HCI_NOKIA_RADIO_HDR_SIZE 2
#define HCI_NOKIA_MAX_RADIO_SIZE 255
#define NOKIA_PROTO_PKT 0x44
#define NOKIA_PROTO_BYTE 0x4c
#define NOKIA_NEG_REQ 0x00
#define NOKIA_NEG_ACK 0x20
#define NOKIA_NEG_NAK 0x40
#define H4_TYPE_SIZE 1
#define NOKIA_RECV_ALIVE \
.type = HCI_NOKIA_ALIVE_PKT, \
.hlen = HCI_NOKIA_ALIVE_HDR_SIZE, \
.loff = 0, \
.lsize = 1, \
.maxlen = HCI_NOKIA_MAX_ALIVE_SIZE \
#define NOKIA_RECV_NEG \
.type = HCI_NOKIA_NEG_PKT, \
.hlen = HCI_NOKIA_NEG_HDR_SIZE, \
.loff = 0, \
.lsize = 1, \
.maxlen = HCI_NOKIA_MAX_NEG_SIZE \
#define NOKIA_RECV_RADIO \
.type = HCI_NOKIA_RADIO_PKT, \
.hlen = HCI_NOKIA_RADIO_HDR_SIZE, \
.loff = 1, \
.lsize = 1, \
.maxlen = HCI_NOKIA_MAX_RADIO_SIZE \
struct hci_nokia_neg_hdr {
u8 dlen;
} __packed;
struct hci_nokia_neg_cmd {
u8 ack;
u16 baud;
u16 unused1;
u8 proto;
u16 sys_clk;
u16 unused2;
} __packed;
#define NOKIA_ALIVE_REQ 0x55
#define NOKIA_ALIVE_RESP 0xcc
struct hci_nokia_alive_hdr {
u8 dlen;
} __packed;
struct hci_nokia_alive_pkt {
u8 mid;
u8 unused;
} __packed;
struct hci_nokia_neg_evt {
u8 ack;
u16 baud;
u16 unused1;
u8 proto;
u16 sys_clk;
u16 unused2;
u8 man_id;
u8 ver_id;
} __packed;
#define MAX_BAUD_RATE 3692300
#define SETUP_BAUD_RATE 921600
#define INIT_BAUD_RATE 120000
struct hci_nokia_radio_hdr {
u8 evt;
u8 dlen;
} __packed;
struct nokia_bt_dev {
struct hci_uart hu;
struct serdev_device *serdev;
struct gpio_desc *reset;
struct gpio_desc *wakeup_host;
struct gpio_desc *wakeup_bt;
unsigned long sysclk_speed;
int wake_irq;
struct sk_buff *rx_skb;
struct sk_buff_head txq;
bdaddr_t bdaddr;
int init_error;
struct completion init_completion;
u8 man_id;
u8 ver_id;
bool initialized;
bool tx_enabled;
bool rx_enabled;
};
static int nokia_enqueue(struct hci_uart *hu, struct sk_buff *skb);
static void nokia_flow_control(struct serdev_device *serdev, bool enable)
{
if (enable) {
serdev_device_set_rts(serdev, true);
serdev_device_set_flow_control(serdev, true);
} else {
serdev_device_set_flow_control(serdev, false);
serdev_device_set_rts(serdev, false);
}
}
static irqreturn_t wakeup_handler(int irq, void *data)
{
struct nokia_bt_dev *btdev = data;
struct device *dev = &btdev->serdev->dev;
int wake_state = gpiod_get_value(btdev->wakeup_host);
if (btdev->rx_enabled == wake_state)
return IRQ_HANDLED;
if (wake_state)
pm_runtime_get(dev);
else
pm_runtime_put(dev);
btdev->rx_enabled = wake_state;
return IRQ_HANDLED;
}
static int nokia_reset(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
int err;
/* reset routine */
gpiod_set_value_cansleep(btdev->reset, 1);
gpiod_set_value_cansleep(btdev->wakeup_bt, 1);
msleep(100);
/* safety check */
err = gpiod_get_value_cansleep(btdev->wakeup_host);
if (err == 1) {
dev_err(dev, "reset: host wakeup not low!");
return -EPROTO;
}
/* flush queue */
serdev_device_write_flush(btdev->serdev);
/* init uart */
nokia_flow_control(btdev->serdev, false);
serdev_device_set_baudrate(btdev->serdev, INIT_BAUD_RATE);
gpiod_set_value_cansleep(btdev->reset, 0);
/* wait for cts */
err = serdev_device_wait_for_cts(btdev->serdev, true, 200);
if (err < 0) {
dev_err(dev, "CTS not received: %d", err);
return err;
}
nokia_flow_control(btdev->serdev, true);
return 0;
}
static int nokia_send_alive_packet(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
struct hci_nokia_alive_hdr *hdr;
struct hci_nokia_alive_pkt *pkt;
struct sk_buff *skb;
int len;
init_completion(&btdev->init_completion);
len = H4_TYPE_SIZE + sizeof(*hdr) + sizeof(*pkt);
skb = bt_skb_alloc(len, GFP_KERNEL);
if (!skb)
return -ENOMEM;
hci_skb_pkt_type(skb) = HCI_NOKIA_ALIVE_PKT;
memset(skb->data, 0x00, len);
hdr = (struct hci_nokia_alive_hdr *)skb_put(skb, sizeof(*hdr));
hdr->dlen = sizeof(*pkt);
pkt = (struct hci_nokia_alive_pkt *)skb_put(skb, sizeof(*pkt));
pkt->mid = NOKIA_ALIVE_REQ;
nokia_enqueue(hu, skb);
hci_uart_tx_wakeup(hu);
dev_dbg(dev, "Alive sent");
if (!wait_for_completion_interruptible_timeout(&btdev->init_completion,
msecs_to_jiffies(1000))) {
return -ETIMEDOUT;
}
if (btdev->init_error < 0)
return btdev->init_error;
return 0;
}
static int nokia_send_negotiation(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
struct hci_nokia_neg_cmd *neg_cmd;
struct hci_nokia_neg_hdr *neg_hdr;
struct sk_buff *skb;
int len, err;
u16 baud = DIV_ROUND_CLOSEST(btdev->sysclk_speed * 10, SETUP_BAUD_RATE);
int sysclk = btdev->sysclk_speed / 1000;
len = H4_TYPE_SIZE + sizeof(*neg_hdr) + sizeof(*neg_cmd);
skb = bt_skb_alloc(len, GFP_KERNEL);
if (!skb)
return -ENOMEM;
hci_skb_pkt_type(skb) = HCI_NOKIA_NEG_PKT;
neg_hdr = (struct hci_nokia_neg_hdr *)skb_put(skb, sizeof(*neg_hdr));
neg_hdr->dlen = sizeof(*neg_cmd);
neg_cmd = (struct hci_nokia_neg_cmd *)skb_put(skb, sizeof(*neg_cmd));
neg_cmd->ack = NOKIA_NEG_REQ;
neg_cmd->baud = cpu_to_le16(baud);
neg_cmd->unused1 = 0x0000;
neg_cmd->proto = NOKIA_PROTO_BYTE;
neg_cmd->sys_clk = cpu_to_le16(sysclk);
neg_cmd->unused2 = 0x0000;
btdev->init_error = 0;
init_completion(&btdev->init_completion);
nokia_enqueue(hu, skb);
hci_uart_tx_wakeup(hu);
dev_dbg(dev, "Negotiation sent");
if (!wait_for_completion_interruptible_timeout(&btdev->init_completion,
msecs_to_jiffies(10000))) {
return -ETIMEDOUT;
}
if (btdev->init_error < 0)
return btdev->init_error;
/* Change to previously negotiated speed. Flow Control
* is disabled until bluetooth adapter is ready to avoid
* broken bytes being received.
*/
nokia_flow_control(btdev->serdev, false);
serdev_device_set_baudrate(btdev->serdev, SETUP_BAUD_RATE);
err = serdev_device_wait_for_cts(btdev->serdev, true, 200);
if (err < 0) {
dev_err(dev, "CTS not received: %d", err);
return err;
}
nokia_flow_control(btdev->serdev, true);
dev_dbg(dev, "Negotiation successful");
return 0;
}
static int nokia_setup_fw(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
const char *fwname;
const struct firmware *fw;
const u8 *fw_ptr;
size_t fw_size;
int err;
dev_dbg(dev, "setup firmware");
if (btdev->man_id == NOKIA_ID_BCM2048) {
fwname = FIRMWARE_BCM2048;
} else if (btdev->man_id == NOKIA_ID_TI1271) {
fwname = FIRMWARE_TI1271;
} else {
dev_err(dev, "Unsupported bluetooth device!");
return -ENODEV;
}
err = request_firmware(&fw, fwname, dev);
if (err < 0) {
dev_err(dev, "%s: Failed to load Nokia firmware file (%d)",
hu->hdev->name, err);
return err;
}
fw_ptr = fw->data;
fw_size = fw->size;
while (fw_size >= 4) {
u16 pkt_size = get_unaligned_le16(fw_ptr);
u8 pkt_type = fw_ptr[2];
const struct hci_command_hdr *cmd;
u16 opcode;
struct sk_buff *skb;
switch (pkt_type) {
case HCI_COMMAND_PKT:
cmd = (struct hci_command_hdr *)(fw_ptr + 3);
opcode = le16_to_cpu(cmd->opcode);
skb = __hci_cmd_sync(hu->hdev, opcode, cmd->plen,
fw_ptr + 3 + HCI_COMMAND_HDR_SIZE,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
dev_err(dev, "%s: FW command %04x failed (%d)",
hu->hdev->name, opcode, err);
goto done;
}
kfree_skb(skb);
break;
case HCI_NOKIA_RADIO_PKT:
case HCI_NOKIA_NEG_PKT:
case HCI_NOKIA_ALIVE_PKT:
break;
}
fw_ptr += pkt_size + 2;
fw_size -= pkt_size + 2;
}
done:
release_firmware(fw);
return err;
}
static int nokia_setup(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
int err;
btdev->initialized = false;
nokia_flow_control(btdev->serdev, false);
pm_runtime_get_sync(dev);
if (btdev->tx_enabled) {
gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
pm_runtime_put(&btdev->serdev->dev);
btdev->tx_enabled = false;
}
dev_dbg(dev, "protocol setup");
/* 0. reset connection */
err = nokia_reset(hu);
if (err < 0) {
dev_err(dev, "Reset failed: %d", err);
goto out;
}
/* 1. negotiate speed etc */
err = nokia_send_negotiation(hu);
if (err < 0) {
dev_err(dev, "Negotiation failed: %d", err);
goto out;
}
/* 2. verify correct setup using alive packet */
err = nokia_send_alive_packet(hu);
if (err < 0) {
dev_err(dev, "Alive check failed: %d", err);
goto out;
}
/* 3. send firmware */
err = nokia_setup_fw(hu);
if (err < 0) {
dev_err(dev, "Could not setup FW: %d", err);
goto out;
}
nokia_flow_control(btdev->serdev, false);
serdev_device_set_baudrate(btdev->serdev, MAX_BAUD_RATE);
nokia_flow_control(btdev->serdev, true);
if (btdev->man_id == NOKIA_ID_BCM2048) {
hu->hdev->set_bdaddr = btbcm_set_bdaddr;
set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks);
dev_dbg(dev, "bcm2048 has invalid bluetooth address!");
}
dev_dbg(dev, "protocol setup done!");
gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
pm_runtime_put(dev);
btdev->tx_enabled = false;
btdev->initialized = true;
return 0;
out:
pm_runtime_put(dev);
return err;
}
static int nokia_open(struct hci_uart *hu)
{
struct device *dev = &hu->serdev->dev;
dev_dbg(dev, "protocol open");
serdev_device_open(hu->serdev);
pm_runtime_enable(dev);
return 0;
}
static int nokia_flush(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
dev_dbg(&btdev->serdev->dev, "flush device");
skb_queue_purge(&btdev->txq);
return 0;
}
static int nokia_close(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
dev_dbg(dev, "close device");
btdev->initialized = false;
skb_queue_purge(&btdev->txq);
kfree_skb(btdev->rx_skb);
/* disable module */
gpiod_set_value(btdev->reset, 1);
gpiod_set_value(btdev->wakeup_bt, 0);
pm_runtime_disable(&btdev->serdev->dev);
serdev_device_close(btdev->serdev);
return 0;
}
/* Enqueue frame for transmittion (padding, crc, etc) */
static int nokia_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct nokia_bt_dev *btdev = hu->priv;
int err;
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
/* Packets must be word aligned */
if (skb->len % 2) {
err = skb_pad(skb, 1);
if (err)
return err;
*skb_put(skb, 1) = 0x00;
}
skb_queue_tail(&btdev->txq, skb);
return 0;
}
static int nokia_recv_negotiation_packet(struct hci_dev *hdev,
struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
struct hci_nokia_neg_hdr *hdr;
struct hci_nokia_neg_evt *evt;
int ret = 0;
hdr = (struct hci_nokia_neg_hdr *)skb->data;
if (hdr->dlen != sizeof(*evt)) {
btdev->init_error = -EIO;
ret = -EIO;
goto finish_neg;
}
evt = (struct hci_nokia_neg_evt *)skb_pull(skb, sizeof(*hdr));
if (evt->ack != NOKIA_NEG_ACK) {
dev_err(dev, "Negotiation received: wrong reply");
btdev->init_error = -EINVAL;
ret = -EINVAL;
goto finish_neg;
}
btdev->man_id = evt->man_id;
btdev->ver_id = evt->ver_id;
dev_dbg(dev, "Negotiation received: baud=%u:clk=%u:manu=%u:vers=%u",
evt->baud, evt->sys_clk, evt->man_id, evt->ver_id);
finish_neg:
complete(&btdev->init_completion);
kfree_skb(skb);
return ret;
}
static int nokia_recv_alive_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
struct hci_nokia_alive_hdr *hdr;
struct hci_nokia_alive_pkt *pkt;
int ret = 0;
hdr = (struct hci_nokia_alive_hdr *)skb->data;
if (hdr->dlen != sizeof(*pkt)) {
dev_err(dev, "Corrupted alive message");
btdev->init_error = -EIO;
ret = -EIO;
goto finish_alive;
}
pkt = (struct hci_nokia_alive_pkt *)skb_pull(skb, sizeof(*hdr));
if (pkt->mid != NOKIA_ALIVE_RESP) {
dev_err(dev, "Alive received: invalid response: 0x%02x!",
pkt->mid);
btdev->init_error = -EINVAL;
ret = -EINVAL;
goto finish_alive;
}
dev_dbg(dev, "Alive received");
finish_alive:
complete(&btdev->init_completion);
kfree_skb(skb);
return ret;
}
static int nokia_recv_radio(struct hci_dev *hdev, struct sk_buff *skb)
{
/* Packets received on the dedicated radio channel are
* HCI events and so feed them back into the core.
*/
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
return hci_recv_frame(hdev, skb);
}
/* Recv data */
static const struct h4_recv_pkt nokia_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ NOKIA_RECV_ALIVE, .recv = nokia_recv_alive_packet },
{ NOKIA_RECV_NEG, .recv = nokia_recv_negotiation_packet },
{ NOKIA_RECV_RADIO, .recv = nokia_recv_radio },
};
static int nokia_recv(struct hci_uart *hu, const void *data, int count)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
int err;
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
return -EUNATCH;
btdev->rx_skb = h4_recv_buf(hu->hdev, btdev->rx_skb, data, count,
nokia_recv_pkts, ARRAY_SIZE(nokia_recv_pkts));
if (IS_ERR(btdev->rx_skb)) {
err = PTR_ERR(btdev->rx_skb);
dev_err(dev, "Frame reassembly failed (%d)", err);
btdev->rx_skb = NULL;
return err;
}
return count;
}
static struct sk_buff *nokia_dequeue(struct hci_uart *hu)
{
struct nokia_bt_dev *btdev = hu->priv;
struct device *dev = &btdev->serdev->dev;
struct sk_buff *result = skb_dequeue(&btdev->txq);
if (!btdev->initialized)
return result;
if (btdev->tx_enabled == !!result)
return result;
if (result) {
pm_runtime_get_sync(dev);
gpiod_set_value_cansleep(btdev->wakeup_bt, 1);
} else {
serdev_device_wait_until_sent(btdev->serdev, 0);
gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
pm_runtime_put(dev);
}
btdev->tx_enabled = !!result;
return result;
}
static const struct hci_uart_proto nokia_proto = {
.id = HCI_UART_NOKIA,
.name = "Nokia",
.open = nokia_open,
.close = nokia_close,
.recv = nokia_recv,
.enqueue = nokia_enqueue,
.dequeue = nokia_dequeue,
.flush = nokia_flush,
.setup = nokia_setup,
.manufacturer = 1,
};
static int nokia_bluetooth_serdev_probe(struct serdev_device *serdev)
{
struct device *dev = &serdev->dev;
struct nokia_bt_dev *btdev;
struct clk *sysclk;
int err = 0;
btdev = devm_kzalloc(dev, sizeof(*btdev), GFP_KERNEL);
if (!btdev)
return -ENOMEM;
btdev->hu.serdev = btdev->serdev = serdev;
serdev_device_set_drvdata(serdev, btdev);
btdev->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(btdev->reset)) {
err = PTR_ERR(btdev->reset);
dev_err(dev, "could not get reset gpio: %d", err);
return err;
}
btdev->wakeup_host = devm_gpiod_get(dev, "host-wakeup", GPIOD_IN);
if (IS_ERR(btdev->wakeup_host)) {
err = PTR_ERR(btdev->wakeup_host);
dev_err(dev, "could not get host wakeup gpio: %d", err);
return err;
}
btdev->wake_irq = gpiod_to_irq(btdev->wakeup_host);
err = devm_request_threaded_irq(dev, btdev->wake_irq, NULL,
wakeup_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"wakeup", btdev);
if (err) {
dev_err(dev, "could request wakeup irq: %d", err);
return err;
}
btdev->wakeup_bt = devm_gpiod_get(dev, "bluetooth-wakeup",
GPIOD_OUT_LOW);
if (IS_ERR(btdev->wakeup_bt)) {
err = PTR_ERR(btdev->wakeup_bt);
dev_err(dev, "could not get BT wakeup gpio: %d", err);
return err;
}
sysclk = devm_clk_get(dev, "sysclk");
if (IS_ERR(sysclk)) {
err = PTR_ERR(sysclk);
dev_err(dev, "could not get sysclk: %d", err);
return err;
}
clk_prepare_enable(sysclk);
btdev->sysclk_speed = clk_get_rate(sysclk);
clk_disable_unprepare(sysclk);
skb_queue_head_init(&btdev->txq);
btdev->hu.priv = btdev;
btdev->hu.alignment = 2; /* Nokia H4+ is word aligned */
err = hci_uart_register_device(&btdev->hu, &nokia_proto);
if (err) {
dev_err(dev, "could not register bluetooth uart: %d", err);
return err;
}
return 0;
}
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);
}
static int nokia_bluetooth_runtime_suspend(struct device *dev)
{
struct serdev_device *serdev = to_serdev_device(dev);
nokia_flow_control(serdev, false);
return 0;
}
static int nokia_bluetooth_runtime_resume(struct device *dev)
{
struct serdev_device *serdev = to_serdev_device(dev);
nokia_flow_control(serdev, true);
return 0;
}
static const struct dev_pm_ops nokia_bluetooth_pm_ops = {
SET_RUNTIME_PM_OPS(nokia_bluetooth_runtime_suspend,
nokia_bluetooth_runtime_resume,
NULL)
};
#ifdef CONFIG_OF
static const struct of_device_id nokia_bluetooth_of_match[] = {
{ .compatible = "nokia,h4p-bluetooth", },
{},
};
MODULE_DEVICE_TABLE(of, nokia_bluetooth_of_match);
#endif
static struct serdev_device_driver nokia_bluetooth_serdev_driver = {
.probe = nokia_bluetooth_serdev_probe,
.remove = nokia_bluetooth_serdev_remove,
.driver = {
.name = "nokia-bluetooth",
.pm = &nokia_bluetooth_pm_ops,
.of_match_table = of_match_ptr(nokia_bluetooth_of_match),
},
};
module_serdev_device_driver(nokia_bluetooth_serdev_driver);
MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
MODULE_DESCRIPTION("Bluetooth HCI UART Nokia H4+ driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,356 @@
/*
* Bluetooth HCI serdev driver lib
*
* Copyright (C) 2017 Linaro, Ltd., Rob Herring <robh@kernel.org>
*
* Based on hci_ldisc.c:
*
* Copyright (C) 2000-2001 Qualcomm Incorporated
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/serdev.h>
#include <linux/skbuff.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "hci_uart.h"
struct serdev_device_ops hci_serdev_client_ops;
static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
{
struct hci_dev *hdev = hu->hdev;
/* Update HCI stat counters */
switch (pkt_type) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
case HCI_ACLDATA_PKT:
hdev->stat.acl_tx++;
break;
case HCI_SCODATA_PKT:
hdev->stat.sco_tx++;
break;
}
}
static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
{
struct sk_buff *skb = hu->tx_skb;
if (!skb)
skb = hu->proto->dequeue(hu);
else
hu->tx_skb = NULL;
return skb;
}
static void hci_uart_write_work(struct work_struct *work)
{
struct hci_uart *hu = container_of(work, struct hci_uart, write_work);
struct serdev_device *serdev = hu->serdev;
struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb;
/* REVISIT:
* should we cope with bad skbs or ->write() returning an error value?
*/
do {
clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
while ((skb = hci_uart_dequeue(hu))) {
int len;
len = serdev_device_write_buf(serdev,
skb->data, skb->len);
hdev->stat.byte_tx += len;
skb_pull(skb, len);
if (skb->len) {
hu->tx_skb = skb;
break;
}
hci_uart_tx_complete(hu, hci_skb_pkt_type(skb));
kfree_skb(skb);
}
} while(test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state));
clear_bit(HCI_UART_SENDING, &hu->tx_state);
}
/* ------- Interface to HCI layer ------ */
/* Initialize device */
static int hci_uart_open(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
return 0;
}
/* Reset device */
static int hci_uart_flush(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
BT_DBG("hdev %p serdev %p", hdev, hu->serdev);
if (hu->tx_skb) {
kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
}
/* Flush any pending characters in the driver and discipline. */
serdev_device_write_flush(hu->serdev);
if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
hu->proto->flush(hu);
return 0;
}
/* Close device */
static int hci_uart_close(struct hci_dev *hdev)
{
BT_DBG("hdev %p", hdev);
hci_uart_flush(hdev);
hdev->flush = NULL;
return 0;
}
/* Send frames from HCI layer */
static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb),
skb->len);
hu->proto->enqueue(hu, skb);
hci_uart_tx_wakeup(hu);
return 0;
}
static int hci_uart_setup(struct hci_dev *hdev)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct hci_rp_read_local_version *ver;
struct sk_buff *skb;
unsigned int speed;
int err;
/* Init speed if any */
if (hu->init_speed)
speed = hu->init_speed;
else if (hu->proto->init_speed)
speed = hu->proto->init_speed;
else
speed = 0;
if (speed)
serdev_device_set_baudrate(hu->serdev, speed);
/* Operational speed if any */
if (hu->oper_speed)
speed = hu->oper_speed;
else if (hu->proto->oper_speed)
speed = hu->proto->oper_speed;
else
speed = 0;
if (hu->proto->set_baudrate && speed) {
err = hu->proto->set_baudrate(hu, speed);
if (err)
BT_ERR("%s: failed to set baudrate", hdev->name);
else
serdev_device_set_baudrate(hu->serdev, speed);
}
if (hu->proto->setup)
return hu->proto->setup(hu);
if (!test_bit(HCI_UART_VND_DETECT, &hu->hdev_flags))
return 0;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s: Reading local version information failed (%ld)",
hdev->name, PTR_ERR(skb));
return 0;
}
if (skb->len != sizeof(*ver)) {
BT_ERR("%s: Event length mismatch for version information",
hdev->name);
}
kfree_skb(skb);
return 0;
}
/** hci_uart_write_wakeup - transmit buffer wakeup
* @serdev: serial device
*
* This function is called by the serdev framework when it accepts
* more data being sent.
*/
static void hci_uart_write_wakeup(struct serdev_device *serdev)
{
struct hci_uart *hu = serdev_device_get_drvdata(serdev);
BT_DBG("");
if (!hu || serdev != hu->serdev) {
WARN_ON(1);
return;
}
if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
hci_uart_tx_wakeup(hu);
}
/** hci_uart_receive_buf - receive buffer wakeup
* @serdev: serial device
* @data: pointer to received data
* @count: count of received data in bytes
*
* This function is called by the serdev framework when it received data
* in the RX buffer.
*
* Return: number of processed bytes
*/
static int hci_uart_receive_buf(struct serdev_device *serdev, const u8 *data,
size_t count)
{
struct hci_uart *hu = serdev_device_get_drvdata(serdev);
if (!hu || serdev != hu->serdev) {
WARN_ON(1);
return 0;
}
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
return 0;
/* It does not need a lock here as it is already protected by a mutex in
* tty caller
*/
hu->proto->recv(hu, data, count);
if (hu->hdev)
hu->hdev->stat.byte_rx += count;
return count;
}
struct serdev_device_ops hci_serdev_client_ops = {
.receive_buf = hci_uart_receive_buf,
.write_wakeup = hci_uart_write_wakeup,
};
int hci_uart_register_device(struct hci_uart *hu,
const struct hci_uart_proto *p)
{
int err;
struct hci_dev *hdev;
BT_DBG("");
serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops);
err = p->open(hu);
if (err)
return err;
hu->proto = p;
set_bit(HCI_UART_PROTO_READY, &hu->flags);
/* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
BT_ERR("Can't allocate HCI device");
err = -ENOMEM;
goto err_alloc;
}
hu->hdev = hdev;
hdev->bus = HCI_UART;
hci_set_drvdata(hdev, hu);
INIT_WORK(&hu->write_work, hci_uart_write_work);
/* Only when vendor specific setup callback is provided, consider
* the manufacturer information valid. This avoids filling in the
* value for Ericsson when nothing is specified.
*/
if (hu->proto->setup)
hdev->manufacturer = hu->proto->manufacturer;
hdev->open = hci_uart_open;
hdev->close = hci_uart_close;
hdev->flush = hci_uart_flush;
hdev->send = hci_uart_send_frame;
hdev->setup = hci_uart_setup;
SET_HCIDEV_DEV(hdev, &hu->serdev->dev);
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
hdev->dev_type = HCI_AMP;
else
hdev->dev_type = HCI_PRIMARY;
if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return 0;
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
err = -ENODEV;
goto err_register;
}
set_bit(HCI_UART_REGISTERED, &hu->flags);
return 0;
err_register:
hci_free_dev(hdev);
err_alloc:
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
p->close(hu);
return err;
}
EXPORT_SYMBOL_GPL(hci_uart_register_device);

View File

@ -58,6 +58,7 @@
#define HCI_UART_VND_DETECT 5
struct hci_uart;
struct serdev_device;
struct hci_uart_proto {
unsigned int id;
@ -77,6 +78,7 @@ struct hci_uart_proto {
struct hci_uart {
struct tty_struct *tty;
struct serdev_device *serdev;
struct hci_dev *hdev;
unsigned long flags;
unsigned long hdev_flags;
@ -92,6 +94,9 @@ struct hci_uart {
unsigned int init_speed;
unsigned int oper_speed;
u8 alignment;
u8 padding;
};
/* HCI_UART proto flag bits */
@ -105,9 +110,10 @@ 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);
int hci_uart_tx_wakeup(struct hci_uart *hu);
int hci_uart_init_ready(struct hci_uart *hu);
void hci_uart_init_tty(struct hci_uart *hu);
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,

View File

@ -32,6 +32,8 @@
#include "hyperv_vmbus.h"
#define VMBUS_PKT_TRAILER 8
/*
* When we write to the ring buffer, check if the host needs to
* be signaled. Here is the details of this protocol:
@ -336,6 +338,12 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
return 0;
}
static inline void
init_cached_read_index(struct hv_ring_buffer_info *rbi)
{
rbi->cached_read_index = rbi->ring_buffer->read_index;
}
int hv_ringbuffer_read(struct vmbus_channel *channel,
void *buffer, u32 buflen, u32 *buffer_actual_len,
u64 *requestid, bool raw)
@ -366,7 +374,8 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
return ret;
}
init_cached_read_index(channel);
init_cached_read_index(inring_info);
next_read_location = hv_get_next_read_location(inring_info);
next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc,
sizeof(desc),
@ -410,3 +419,86 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
return ret;
}
/*
* Determine number of bytes available in ring buffer after
* the current iterator (priv_read_index) location.
*
* This is similar to hv_get_bytes_to_read but with private
* read index instead.
*/
static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi)
{
u32 priv_read_loc = rbi->priv_read_index;
u32 write_loc = READ_ONCE(rbi->ring_buffer->write_index);
if (write_loc >= priv_read_loc)
return write_loc - priv_read_loc;
else
return (rbi->ring_datasize - priv_read_loc) + write_loc;
}
/*
* Get first vmbus packet from ring buffer after read_index
*
* If ring buffer is empty, returns NULL and no other action needed.
*/
struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel)
{
struct hv_ring_buffer_info *rbi = &channel->inbound;
/* set state for later hv_signal_on_read() */
init_cached_read_index(rbi);
if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor))
return NULL;
return hv_get_ring_buffer(rbi) + rbi->priv_read_index;
}
EXPORT_SYMBOL_GPL(hv_pkt_iter_first);
/*
* Get next vmbus packet from ring buffer.
*
* Advances the current location (priv_read_index) and checks for more
* data. If the end of the ring buffer is reached, then return NULL.
*/
struct vmpacket_descriptor *
__hv_pkt_iter_next(struct vmbus_channel *channel,
const struct vmpacket_descriptor *desc)
{
struct hv_ring_buffer_info *rbi = &channel->inbound;
u32 packetlen = desc->len8 << 3;
u32 dsize = rbi->ring_datasize;
/* bump offset to next potential packet */
rbi->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
if (rbi->priv_read_index >= dsize)
rbi->priv_read_index -= dsize;
/* more data? */
if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor))
return NULL;
else
return hv_get_ring_buffer(rbi) + rbi->priv_read_index;
}
EXPORT_SYMBOL_GPL(__hv_pkt_iter_next);
/*
* Update host ring buffer after iterating over packets.
*/
void hv_pkt_iter_close(struct vmbus_channel *channel)
{
struct hv_ring_buffer_info *rbi = &channel->inbound;
/*
* Make sure all reads are done before we update the read index since
* the writer may start writing to the read area once the read index
* is updated.
*/
virt_rmb();
rbi->ring_buffer->read_index = rbi->priv_read_index;
hv_signal_on_read(channel);
}
EXPORT_SYMBOL_GPL(hv_pkt_iter_close);

View File

@ -88,7 +88,7 @@ static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
return false;
ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_addr_policy);
nlmsg_len(nlh), ib_nl_addr_policy, NULL);
if (ret)
return false;

View File

@ -472,12 +472,14 @@ int iwpm_parse_nlmsg(struct netlink_callback *cb, int policy_max,
int ret;
const char *err_str = "";
ret = nlmsg_validate(cb->nlh, nlh_len, policy_max-1, nlmsg_policy);
ret = nlmsg_validate(cb->nlh, nlh_len, policy_max - 1, nlmsg_policy,
NULL);
if (ret) {
err_str = "Invalid attribute";
goto parse_nlmsg_error;
}
ret = nlmsg_parse(cb->nlh, nlh_len, nltb, policy_max-1, nlmsg_policy);
ret = nlmsg_parse(cb->nlh, nlh_len, nltb, policy_max - 1,
nlmsg_policy, NULL);
if (ret) {
err_str = "Unable to parse the nlmsg";
goto parse_nlmsg_error;

View File

@ -146,7 +146,8 @@ int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
}
EXPORT_SYMBOL(ibnl_put_attr);
static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{
struct ibnl_client *client;
int type = nlh->nlmsg_type;
@ -209,7 +210,7 @@ static void ibnl_rcv_reply_skb(struct sk_buff *skb)
if (nlh->nlmsg_flags & NLM_F_REQUEST)
return;
ibnl_rcv_msg(skb, nlh);
ibnl_rcv_msg(skb, nlh, NULL);
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
if (msglen > skb->len)

View File

@ -808,7 +808,7 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
return -EPERM;
ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_policy);
nlmsg_len(nlh), ib_nl_policy, NULL);
attr = (const struct nlattr *)tb[LS_NLA_TYPE_TIMEOUT];
if (ret || !attr)
goto settimeout_out;
@ -860,7 +860,7 @@ static inline int ib_nl_is_good_resolve_resp(const struct nlmsghdr *nlh)
return 0;
ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_policy);
nlmsg_len(nlh), ib_nl_policy, NULL);
if (ret)
return 0;

View File

@ -729,16 +729,6 @@ static inline struct mlx5_ib_mw *to_mmw(struct ib_mw *ibmw)
return container_of(ibmw, struct mlx5_ib_mw, ibmw);
}
struct mlx5_ib_ah {
struct ib_ah ibah;
struct mlx5_av av;
};
static inline struct mlx5_ib_ah *to_mah(struct ib_ah *ibah)
{
return container_of(ibah, struct mlx5_ib_ah, ibah);
}
int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt,
struct mlx5_db *db);
void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db);

View File

@ -897,6 +897,7 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
if (init_attr->create_flags & ~(IB_QP_CREATE_SIGNATURE_EN |
IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK |
IB_QP_CREATE_IPOIB_UD_LSO |
IB_QP_CREATE_NETIF_QP |
mlx5_ib_create_qp_sqpn_qp1()))
return -EINVAL;

View File

@ -36,6 +36,7 @@
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/delay.h>

View File

@ -587,9 +587,8 @@ void qedr_affiliated_event(void *context, u8 e_code, void *fw_handle)
#define EVENT_TYPE_CQ 1
#define EVENT_TYPE_QP 2
struct qedr_dev *dev = (struct qedr_dev *)context;
union event_ring_data *data = fw_handle;
u64 roce_handle64 = ((u64)data->roce_handle.hi << 32) +
data->roce_handle.lo;
struct regpair *async_handle = (struct regpair *)fw_handle;
u64 roce_handle64 = ((u64) async_handle->hi << 32) + async_handle->lo;
u8 event_type = EVENT_TYPE_NOT_DEFINED;
struct ib_event event;
struct ib_cq *ibcq;

View File

@ -38,7 +38,8 @@
#include <linux/qed/qed_chain.h>
#include <linux/qed/qed_roce_if.h>
#include <linux/qed/qede_roce.h>
#include "qedr_hsi.h"
#include <linux/qed/roce_common.h>
#include "qedr_hsi_rdma.h"
#define QEDR_MODULE_VERSION "8.10.10.0"
#define QEDR_NODE_DESC "QLogic 579xx RoCE HCA"

View File

@ -43,14 +43,11 @@
#include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
#include "qedr_hsi.h"
#include <linux/qed/qed_if.h>
#include <linux/qed/qed_roce_if.h>
#include "qedr.h"
#include "qedr_hsi.h"
#include "verbs.h"
#include <rdma/qedr-abi.h>
#include "qedr_hsi.h"
#include "qedr_cm.h"
void qedr_inc_sw_gsi_cons(struct qedr_qp_hwq_info *info)

View File

@ -43,7 +43,8 @@
#include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
#include "qedr_hsi.h"
#include <linux/qed/common_hsi.h>
#include "qedr_hsi_rdma.h"
#include <linux/qed/qed_if.h>
#include "qedr.h"
#include "verbs.h"

View File

@ -157,10 +157,8 @@ int cf_command(int drvid, int mode,
/* allocate mem for information struct */
if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
return (-ENOMEM); /* no memory */
init_timer(&cs->timer);
setup_timer(&cs->timer, deflect_timer_expire, (ulong)cs);
cs->info[0] = '\0';
cs->timer.function = deflect_timer_expire;
cs->timer.data = (ulong) cs; /* pointer to own structure */
cs->ics.driver = drvid;
cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */
cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */
@ -452,10 +450,9 @@ static int isdn_divert_icall(isdn_ctrl *ic)
return (0); /* no external deflection needed */
if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
return (0); /* no memory */
init_timer(&cs->timer);
setup_timer(&cs->timer, deflect_timer_expire,
(ulong)cs);
cs->info[0] = '\0';
cs->timer.function = deflect_timer_expire;
cs->timer.data = (ulong) cs; /* pointer to own structure */
cs->ics = *ic; /* copy incoming data */
if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone, "0");

View File

@ -300,9 +300,8 @@ static int um_idi_open_adapter(struct file *file, int adapter_nr)
p_os = (diva_um_idi_os_context_t *) diva_um_id_get_os_context(e);
init_waitqueue_head(&p_os->read_wait);
init_waitqueue_head(&p_os->close_wait);
init_timer(&p_os->diva_timer_id);
p_os->diva_timer_id.function = (void *) diva_um_timer_function;
p_os->diva_timer_id.data = (unsigned long) p_os;
setup_timer(&p_os->diva_timer_id, (void *)diva_um_timer_function,
(unsigned long)p_os);
p_os->aborted = 0;
p_os->adapter_nr = adapter_nr;
return (1);

View File

@ -13,7 +13,7 @@ config MISDN_HFCPCI
config MISDN_HFCMULTI
tristate "Support for HFC multiport cards (HFC-4S/8S/E1)"
depends on PCI || 8xx
depends on PCI || CPM1
depends on MISDN
help
Enable support for cards with Cologne Chip AG's HFC multiport
@ -27,8 +27,8 @@ config MISDN_HFCMULTI_8xx
bool "Support for XHFC embedded board in HFC multiport driver"
depends on MISDN
depends on MISDN_HFCMULTI
depends on 8xx
default 8xx
depends on CPM1
default CPM1
help
Enable support for the XHFC embedded solution from Speech Design.

View File

@ -6,7 +6,7 @@
*
*/
#include <asm/8xx_immap.h>
#include <asm/cpm1.h>
/* Change this to the value used by your board */
#ifndef IMAP_ADDR

View File

@ -3878,9 +3878,8 @@ hfcmulti_initmode(struct dchannel *dch)
if (hc->dnum[pt]) {
mode_hfcmulti(hc, dch->slot, dch->dev.D.protocol,
-1, 0, -1, 0);
dch->timer.function = (void *) hfcmulti_dbusy_timer;
dch->timer.data = (long) dch;
init_timer(&dch->timer);
setup_timer(&dch->timer, (void *)hfcmulti_dbusy_timer,
(long)dch);
}
for (i = 1; i <= 31; i++) {
if (!((1 << i) & hc->bmask[pt])) /* skip unused chan */
@ -3986,9 +3985,8 @@ hfcmulti_initmode(struct dchannel *dch)
hc->chan[i].slot_rx = -1;
hc->chan[i].conf = -1;
mode_hfcmulti(hc, i, dch->dev.D.protocol, -1, 0, -1, 0);
dch->timer.function = (void *) hfcmulti_dbusy_timer;
dch->timer.data = (long) dch;
init_timer(&dch->timer);
setup_timer(&dch->timer, (void *)hfcmulti_dbusy_timer,
(long)dch);
hc->chan[i - 2].slot_tx = -1;
hc->chan[i - 2].slot_rx = -1;
hc->chan[i - 2].conf = -1;

View File

@ -1717,9 +1717,8 @@ static void
inithfcpci(struct hfc_pci *hc)
{
printk(KERN_DEBUG "inithfcpci: entered\n");
hc->dch.timer.function = (void *) hfcpci_dbusy_timer;
hc->dch.timer.data = (long) &hc->dch;
init_timer(&hc->dch.timer);
setup_timer(&hc->dch.timer, (void *)hfcpci_dbusy_timer,
(long)&hc->dch);
hc->chanlimit = 2;
mode_hfcpci(&hc->bch[0], 1, -1);
mode_hfcpci(&hc->bch[1], 2, -1);
@ -2044,9 +2043,7 @@ setup_hw(struct hfc_pci *hc)
Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
/* At this point the needed PCI config is done */
/* fifos are still not enabled */
hc->hw.timer.function = (void *) hfcpci_Timer;
hc->hw.timer.data = (long) hc;
init_timer(&hc->hw.timer);
setup_timer(&hc->hw.timer, (void *)hfcpci_Timer, (long)hc);
/* default PCM master */
test_and_set_bit(HFC_CFG_MASTER, &hc->cfg);
return 0;

View File

@ -796,9 +796,8 @@ isac_init(struct isac_hw *isac)
}
isac->mon_tx = NULL;
isac->mon_rx = NULL;
isac->dch.timer.function = (void *) dbusy_timer_handler;
isac->dch.timer.data = (long)isac;
init_timer(&isac->dch.timer);
setup_timer(&isac->dch.timer, (void *)dbusy_timer_handler,
(long)isac);
isac->mocr = 0xaa;
if (isac->type & IPAC_TYPE_ISACX) {
/* Disable all IRQ */

View File

@ -1635,13 +1635,11 @@ init_isar(struct isar_hw *isar)
}
if (isar->version != 1)
return -EINVAL;
isar->ch[0].ftimer.function = &ftimer_handler;
isar->ch[0].ftimer.data = (long)&isar->ch[0];
init_timer(&isar->ch[0].ftimer);
setup_timer(&isar->ch[0].ftimer, &ftimer_handler,
(long)&isar->ch[0]);
test_and_set_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags);
isar->ch[1].ftimer.function = &ftimer_handler;
isar->ch[1].ftimer.data = (long)&isar->ch[1];
init_timer(&isar->ch[1].ftimer);
setup_timer(&isar->ch[1].ftimer, &ftimer_handler,
(long)&isar->ch[1]);
test_and_set_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags);
return 0;
}

View File

@ -852,9 +852,8 @@ static void initW6692(struct w6692_hw *card)
{
u8 val;
card->dch.timer.function = (void *)dbusy_timer_handler;
card->dch.timer.data = (u_long)&card->dch;
init_timer(&card->dch.timer);
setup_timer(&card->dch.timer, (void *)dbusy_timer_handler,
(u_long)&card->dch);
w6692_mode(&card->bc[0], ISDN_P_NONE);
w6692_mode(&card->bc[1], ISDN_P_NONE);
WriteW6692(card, W_D_CTL, 0x00);

View File

@ -789,7 +789,5 @@ void Amd7930_init(struct IsdnCardState *cs)
void setup_Amd7930(struct IsdnCardState *cs)
{
INIT_WORK(&cs->tqueue, Amd7930_bh);
cs->dbusytimer.function = (void *) dbusy_timer_handler;
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler, (long)cs);
}

View File

@ -125,9 +125,7 @@ clear_arcofi(struct IsdnCardState *cs) {
void
init_arcofi(struct IsdnCardState *cs) {
cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
cs->dc.isac.arcofitimer.data = (long) cs;
init_timer(&cs->dc.isac.arcofitimer);
setup_timer(&cs->dc.isac.arcofitimer, (void *)arcofi_timer, (long)cs);
init_waitqueue_head(&cs->dc.isac.arcofi_wait);
test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
}

View File

@ -976,9 +976,8 @@ static int setup_diva_common(struct IsdnCardState *cs)
printk(KERN_INFO "Diva: IPACX Design Id: %x\n",
MemReadISAC_IPACX(cs, IPACX_ID) & 0x3F);
} else { /* DIVA 2.0 */
cs->hw.diva.tl.function = (void *) diva_led_handler;
cs->hw.diva.tl.data = (long) cs;
init_timer(&cs->hw.diva.tl);
setup_timer(&cs->hw.diva.tl, (void *)diva_led_handler,
(long)cs);
cs->readisac = &ReadISAC;
cs->writeisac = &WriteISAC;
cs->readisacfifo = &ReadISACfifo;

View File

@ -1147,9 +1147,7 @@ static int setup_elsa_common(struct IsdnCard *card)
init_arcofi(cs);
#endif
setup_isac(cs);
cs->hw.elsa.tl.function = (void *) elsa_led_handler;
cs->hw.elsa.tl.data = (long) cs;
init_timer(&cs->hw.elsa.tl);
setup_timer(&cs->hw.elsa.tl, (void *)elsa_led_handler, (long)cs);
/* Teste Timer */
if (cs->hw.elsa.timer) {
byteout(cs->hw.elsa.trig, 0xff);

View File

@ -98,13 +98,11 @@ void
FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
{
ft->fi = fi;
ft->tl.function = (void *) FsmExpireTimer;
ft->tl.data = (long) ft;
#if FSM_TIMER_DEBUG
if (ft->fi->debug)
ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
#endif
init_timer(&ft->tl);
setup_timer(&ft->tl, (void *)FsmExpireTimer, (long)ft);
}
void

Some files were not shown because too many files have changed in this diff Show More