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

Pull networking updates from David Miller:
 "Highlights:

   1) Maintain the TCP retransmit queue using an rbtree, with 1GB
      windows at 100Gb this really has become necessary. From Eric
      Dumazet.

   2) Multi-program support for cgroup+bpf, from Alexei Starovoitov.

   3) Perform broadcast flooding in hardware in mv88e6xxx, from Andrew
      Lunn.

   4) Add meter action support to openvswitch, from Andy Zhou.

   5) Add a data meta pointer for BPF accessible packets, from Daniel
      Borkmann.

   6) Namespace-ify almost all TCP sysctl knobs, from Eric Dumazet.

   7) Turn on Broadcom Tags in b53 driver, from Florian Fainelli.

   8) More work to move the RTNL mutex down, from Florian Westphal.

   9) Add 'bpftool' utility, to help with bpf program introspection.
      From Jakub Kicinski.

  10) Add new 'cpumap' type for XDP_REDIRECT action, from Jesper
      Dangaard Brouer.

  11) Support 'blocks' of transformations in the packet scheduler which
      can span multiple network devices, from Jiri Pirko.

  12) TC flower offload support in cxgb4, from Kumar Sanghvi.

  13) Priority based stream scheduler for SCTP, from Marcelo Ricardo
      Leitner.

  14) Thunderbolt networking driver, from Amir Levy and Mika Westerberg.

  15) Add RED qdisc offloadability, and use it in mlxsw driver. From
      Nogah Frankel.

  16) eBPF based device controller for cgroup v2, from Roman Gushchin.

  17) Add some fundamental tracepoints for TCP, from Song Liu.

  18) Remove garbage collection from ipv6 route layer, this is a
      significant accomplishment. From Wei Wang.

  19) Add multicast route offload support to mlxsw, from Yotam Gigi"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (2177 commits)
  tcp: highest_sack fix
  geneve: fix fill_info when link down
  bpf: fix lockdep splat
  net: cdc_ncm: GetNtbFormat endian fix
  openvswitch: meter: fix NULL pointer dereference in ovs_meter_cmd_reply_start
  netem: remove unnecessary 64 bit modulus
  netem: use 64 bit divide by rate
  tcp: Namespace-ify sysctl_tcp_default_congestion_control
  net: Protect iterations over net::fib_notifier_ops in fib_seq_sum()
  ipv6: set all.accept_dad to 0 by default
  uapi: fix linux/tls.h userspace compilation error
  usbnet: ipheth: prevent TX queue timeouts when device not ready
  vhost_net: conditionally enable tx polling
  uapi: fix linux/rxrpc.h userspace compilation errors
  net: stmmac: fix LPI transitioning for dwmac4
  atm: horizon: Fix irq release error
  net-sysfs: trigger netlink notification on ifalias change via sysfs
  openvswitch: Using kfree_rcu() to simplify the code
  openvswitch: Make local function ovs_nsh_key_attr_size() static
  openvswitch: Fix return value check in ovs_meter_cmd_features()
  ...
This commit is contained in:
Linus Torvalds 2017-11-15 11:56:19 -08:00
commit 5bbcc0f595
1617 changed files with 91499 additions and 27219 deletions

View File

@ -110,3 +110,51 @@ Description: When new NVM image is written to the non-active NVM
is directly the status value from the DMA configuration is directly the status value from the DMA configuration
based mailbox before the device is power cycled. Writing based mailbox before the device is power cycled. Writing
0 here clears the status. 0 here clears the status.
What: /sys/bus/thunderbolt/devices/<xdomain>.<service>/key
Date: Jan 2018
KernelVersion: 4.15
Contact: thunderbolt-software@lists.01.org
Description: This contains name of the property directory the XDomain
service exposes. This entry describes the protocol in
question. Following directories are already reserved by
the Apple XDomain specification:
network: IP/ethernet over Thunderbolt
targetdm: Target disk mode protocol over Thunderbolt
extdisp: External display mode protocol over Thunderbolt
What: /sys/bus/thunderbolt/devices/<xdomain>.<service>/modalias
Date: Jan 2018
KernelVersion: 4.15
Contact: thunderbolt-software@lists.01.org
Description: Stores the same MODALIAS value emitted by uevent for
the XDomain service. Format: tbtsvc:kSpNvNrN
What: /sys/bus/thunderbolt/devices/<xdomain>.<service>/prtcid
Date: Jan 2018
KernelVersion: 4.15
Contact: thunderbolt-software@lists.01.org
Description: This contains XDomain protocol identifier the XDomain
service supports.
What: /sys/bus/thunderbolt/devices/<xdomain>.<service>/prtcvers
Date: Jan 2018
KernelVersion: 4.15
Contact: thunderbolt-software@lists.01.org
Description: This contains XDomain protocol version the XDomain
service supports.
What: /sys/bus/thunderbolt/devices/<xdomain>.<service>/prtcrevs
Date: Jan 2018
KernelVersion: 4.15
Contact: thunderbolt-software@lists.01.org
Description: This contains XDomain software version the XDomain
service supports.
What: /sys/bus/thunderbolt/devices/<xdomain>.<service>/prtcstns
Date: Jan 2018
KernelVersion: 4.15
Contact: thunderbolt-software@lists.01.org
Description: This contains XDomain service specific settings as
bitmask. Format: %x

View File

@ -197,3 +197,27 @@ information is missing.
To recover from this mode, one needs to flash a valid NVM image to the To recover from this mode, one needs to flash a valid NVM image to the
host host controller in the same way it is done in the previous chapter. host host controller in the same way it is done in the previous chapter.
Networking over Thunderbolt cable
---------------------------------
Thunderbolt technology allows software communication across two hosts
connected by a Thunderbolt cable.
It is possible to tunnel any kind of traffic over Thunderbolt link but
currently we only support Apple ThunderboltIP protocol.
If the other host is running Windows or macOS only thing you need to
do is to connect Thunderbolt cable between the two hosts, the
``thunderbolt-net`` is loaded automatically. If the other host is also
Linux you should load ``thunderbolt-net`` manually on one host (it does
not matter which one)::
# modprobe thunderbolt-net
This triggers module load on the other host automatically. If the driver
is built-in to the kernel image, there is no need to do anything.
The driver will create one virtual ethernet interface per Thunderbolt
port which are named like ``thunderbolt0`` and so on. From this point
you can either use standard userspace tools like ``ifconfig`` to
configure the interface or let your GUI to handle it automatically.

View File

@ -0,0 +1,156 @@
BPF extensibility and applicability to networking, tracing, security
in the linux kernel and several user space implementations of BPF
virtual machine led to a number of misunderstanding on what BPF actually is.
This short QA is an attempt to address that and outline a direction
of where BPF is heading long term.
Q: Is BPF a generic instruction set similar to x64 and arm64?
A: NO.
Q: Is BPF a generic virtual machine ?
A: NO.
BPF is generic instruction set _with_ C calling convention.
Q: Why C calling convention was chosen?
A: Because BPF programs are designed to run in the linux kernel
which is written in C, hence BPF defines instruction set compatible
with two most used architectures x64 and arm64 (and takes into
consideration important quirks of other architectures) and
defines calling convention that is compatible with C calling
convention of the linux kernel on those architectures.
Q: can multiple return values be supported in the future?
A: NO. BPF allows only register R0 to be used as return value.
Q: can more than 5 function arguments be supported in the future?
A: NO. BPF calling convention only allows registers R1-R5 to be used
as arguments. BPF is not a standalone instruction set.
(unlike x64 ISA that allows msft, cdecl and other conventions)
Q: can BPF programs access instruction pointer or return address?
A: NO.
Q: can BPF programs access stack pointer ?
A: NO. Only frame pointer (register R10) is accessible.
From compiler point of view it's necessary to have stack pointer.
For example LLVM defines register R11 as stack pointer in its
BPF backend, but it makes sure that generated code never uses it.
Q: Does C-calling convention diminishes possible use cases?
A: YES. BPF design forces addition of major functionality in the form
of kernel helper functions and kernel objects like BPF maps with
seamless interoperability between them. It lets kernel call into
BPF programs and programs call kernel helpers with zero overhead.
As all of them were native C code. That is particularly the case
for JITed BPF programs that are indistinguishable from
native kernel C code.
Q: Does it mean that 'innovative' extensions to BPF code are disallowed?
A: Soft yes. At least for now until BPF core has support for
bpf-to-bpf calls, indirect calls, loops, global variables,
jump tables, read only sections and all other normal constructs
that C code can produce.
Q: Can loops be supported in a safe way?
A: It's not clear yet. BPF developers are trying to find a way to
support bounded loops where the verifier can guarantee that
the program terminates in less than 4096 instructions.
Q: How come LD_ABS and LD_IND instruction are present in BPF whereas
C code cannot express them and has to use builtin intrinsics?
A: This is artifact of compatibility with classic BPF. Modern
networking code in BPF performs better without them.
See 'direct packet access'.
Q: It seems not all BPF instructions are one-to-one to native CPU.
For example why BPF_JNE and other compare and jumps are not cpu-like?
A: This was necessary to avoid introducing flags into ISA which are
impossible to make generic and efficient across CPU architectures.
Q: why BPF_DIV instruction doesn't map to x64 div?
A: Because if we picked one-to-one relationship to x64 it would have made
it more complicated to support on arm64 and other archs. Also it
needs div-by-zero runtime check.
Q: why there is no BPF_SDIV for signed divide operation?
A: Because it would be rarely used. llvm errors in such case and
prints a suggestion to use unsigned divide instead
Q: Why BPF has implicit prologue and epilogue?
A: Because architectures like sparc have register windows and in general
there are enough subtle differences between architectures, so naive
store return address into stack won't work. Another reason is BPF has
to be safe from division by zero (and legacy exception path
of LD_ABS insn). Those instructions need to invoke epilogue and
return implicitly.
Q: Why BPF_JLT and BPF_JLE instructions were not introduced in the beginning?
A: Because classic BPF didn't have them and BPF authors felt that compiler
workaround would be acceptable. Turned out that programs lose performance
due to lack of these compare instructions and they were added.
These two instructions is a perfect example what kind of new BPF
instructions are acceptable and can be added in the future.
These two already had equivalent instructions in native CPUs.
New instructions that don't have one-to-one mapping to HW instructions
will not be accepted.
Q: BPF 32-bit subregisters have a requirement to zero upper 32-bits of BPF
registers which makes BPF inefficient virtual machine for 32-bit
CPU architectures and 32-bit HW accelerators. Can true 32-bit registers
be added to BPF in the future?
A: NO. The first thing to improve performance on 32-bit archs is to teach
LLVM to generate code that uses 32-bit subregisters. Then second step
is to teach verifier to mark operations where zero-ing upper bits
is unnecessary. Then JITs can take advantage of those markings and
drastically reduce size of generated code and improve performance.
Q: Does BPF have a stable ABI?
A: YES. BPF instructions, arguments to BPF programs, set of helper
functions and their arguments, recognized return codes are all part
of ABI. However when tracing programs are using bpf_probe_read() helper
to walk kernel internal datastructures and compile with kernel
internal headers these accesses can and will break with newer
kernels. The union bpf_attr -> kern_version is checked at load time
to prevent accidentally loading kprobe-based bpf programs written
for a different kernel. Networking programs don't do kern_version check.
Q: How much stack space a BPF program uses?
A: Currently all program types are limited to 512 bytes of stack
space, but the verifier computes the actual amount of stack used
and both interpreter and most JITed code consume necessary amount.
Q: Can BPF be offloaded to HW?
A: YES. BPF HW offload is supported by NFP driver.
Q: Does classic BPF interpreter still exist?
A: NO. Classic BPF programs are converted into extend BPF instructions.
Q: Can BPF call arbitrary kernel functions?
A: NO. BPF programs can only call a set of helper functions which
is defined for every program type.
Q: Can BPF overwrite arbitrary kernel memory?
A: NO. Tracing bpf programs can _read_ arbitrary memory with bpf_probe_read()
and bpf_probe_read_str() helpers. Networking programs cannot read
arbitrary memory, since they don't have access to these helpers.
Programs can never read or write arbitrary memory directly.
Q: Can BPF overwrite arbitrary user memory?
A: Sort-of. Tracing BPF programs can overwrite the user memory
of the current task with bpf_probe_write_user(). Every time such
program is loaded the kernel will print warning message, so
this helper is only useful for experiments and prototypes.
Tracing BPF programs are root only.
Q: When bpf_trace_printk() helper is used the kernel prints nasty
warning message. Why is that?
A: This is done to nudge program authors into better interfaces when
programs need to pass data to user space. Like bpf_perf_event_output()
can be used to efficiently stream data via perf ring buffer.
BPF maps can be used for asynchronous data sharing between kernel
and user space. bpf_trace_printk() should only be used for debugging.
Q: Can BPF functionality such as new program or map types, new
helpers, etc be added out of kernel module code?
A: NO.

View File

@ -0,0 +1,5 @@
The following properties are common to the Bluetooth controllers:
- local-bd-address: array of 6 bytes, specifies the BD address that was
uniquely assigned to the Bluetooth device, formatted with least significant
byte first (little-endian).

View File

@ -52,7 +52,7 @@ I2C managed mode:
port@1 { /* external port 1 */ port@1 { /* external port 1 */
reg = <1>; reg = <1>;
label = "lan1; label = "lan1";
}; };
port@2 { /* external port 2 */ port@2 { /* external port 2 */
@ -89,7 +89,7 @@ MDIO managed mode:
port@1 { /* external port 1 */ port@1 { /* external port 1 */
reg = <1>; reg = <1>;
label = "lan1; label = "lan1";
}; };
port@2 { /* external port 2 */ port@2 { /* external port 2 */

View File

@ -34,6 +34,19 @@ Optional properties:
- fsl,err006687-workaround-present: If present indicates that the system has - fsl,err006687-workaround-present: If present indicates that the system has
the hardware workaround for ERR006687 applied and does not need a software the hardware workaround for ERR006687 applied and does not need a software
workaround. workaround.
-interrupt-names: names of the interrupts listed in interrupts property in
the same order. The defaults if not specified are
__Number of interrupts__ __Default__
1 "int0"
2 "int0", "pps"
3 "int0", "int1", "int2"
4 "int0", "int1", "int2", "pps"
The order may be changed as long as they correspond to the interrupts
property. Currently, only i.mx7 uses "int1" and "int2". They correspond to
tx/rx queues 1 and 2. "int0" will be used for queue 0 and ENET_MII interrupts.
For imx6sx, "int0" handles all 3 queues and ENET_MII. "pps" is for the pulse
per second interrupt associated with 1588 precision time protocol(PTP).
Optional subnodes: Optional subnodes:
- mdio : specifies the mdio bus in the FEC, used as a container for phy nodes - mdio : specifies the mdio bus in the FEC, used as a container for phy nodes

View File

@ -17,6 +17,8 @@ Required properties:
- "renesas,etheravb-r8a7795" for the R8A7795 SoC. - "renesas,etheravb-r8a7795" for the R8A7795 SoC.
- "renesas,etheravb-r8a7796" for the R8A7796 SoC. - "renesas,etheravb-r8a7796" for the R8A7796 SoC.
- "renesas,etheravb-r8a77970" for the R8A77970 SoC.
- "renesas,etheravb-r8a77995" for the R8A77995 SoC.
- "renesas,etheravb-rcar-gen3" as a fallback for the above - "renesas,etheravb-rcar-gen3" as a fallback for the above
R-Car Gen3 devices. R-Car Gen3 devices.
@ -40,7 +42,7 @@ Optional properties:
- interrupt-parent: the phandle for the interrupt controller that services - interrupt-parent: the phandle for the interrupt controller that services
interrupts for this device. interrupts for this device.
- interrupt-names: A list of interrupt names. - interrupt-names: A list of interrupt names.
For the R8A779[56] SoCs this property is mandatory; For the R-Car Gen 3 SoCs this property is mandatory;
it should include one entry per channel, named "ch%u", it should include one entry per channel, named "ch%u",
where %u is the channel number ranging from 0 to 24. where %u is the channel number ranging from 0 to 24.
For other SoCs this property is optional; if present For other SoCs this property is optional; if present

View File

@ -4,7 +4,8 @@ This file provides information on what the device node for the SH EtherMAC
interface contains. interface contains.
Required properties: Required properties:
- compatible: "renesas,gether-r8a7740" if the device is a part of R8A7740 SoC. - compatible: Must contain one or more of the following:
"renesas,gether-r8a7740" if the device is a part of R8A7740 SoC.
"renesas,ether-r8a7743" if the device is a part of R8A7743 SoC. "renesas,ether-r8a7743" if the device is a part of R8A7743 SoC.
"renesas,ether-r8a7745" if the device is a part of R8A7745 SoC. "renesas,ether-r8a7745" if the device is a part of R8A7745 SoC.
"renesas,ether-r8a7778" if the device is a part of R8A7778 SoC. "renesas,ether-r8a7778" if the device is a part of R8A7778 SoC.
@ -14,6 +15,14 @@ Required properties:
"renesas,ether-r8a7793" if the device is a part of R8A7793 SoC. "renesas,ether-r8a7793" if the device is a part of R8A7793 SoC.
"renesas,ether-r8a7794" if the device is a part of R8A7794 SoC. "renesas,ether-r8a7794" if the device is a part of R8A7794 SoC.
"renesas,ether-r7s72100" if the device is a part of R7S72100 SoC. "renesas,ether-r7s72100" if the device is a part of R7S72100 SoC.
"renesas,rcar-gen1-ether" for a generic R-Car Gen1 device.
"renesas,rcar-gen2-ether" for a generic R-Car Gen2 or RZ/G1
device.
When compatible with the generic version, nodes must list
the SoC-specific version corresponding to the platform
first followed by the generic version.
- reg: offset and length of (1) the E-DMAC/feLic register block (required), - reg: offset and length of (1) the E-DMAC/feLic register block (required),
(2) the TSU register block (optional). (2) the TSU register block (optional).
- interrupts: interrupt specifier for the sole interrupt. - interrupts: interrupt specifier for the sole interrupt.
@ -36,7 +45,8 @@ Optional properties:
Example (Lager board): Example (Lager board):
ethernet@ee700000 { ethernet@ee700000 {
compatible = "renesas,ether-r8a7790"; compatible = "renesas,ether-r8a7790",
"renesas,rcar-gen2-ether";
reg = <0 0xee700000 0 0x400>; reg = <0 0xee700000 0 0x400>;
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;

View File

@ -12,7 +12,7 @@ Required properties:
Valid interrupt names are: Valid interrupt names are:
- "macirq" (combined signal for various interrupt events) - "macirq" (combined signal for various interrupt events)
- "eth_wake_irq" (the interrupt to manage the remote wake-up packet detection) - "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) - "eth_lpi" (the interrupt that occurs when Rx exits the LPI state)
- phy-mode: See ethernet.txt file in the same directory. - phy-mode: See ethernet.txt file in the same directory.
- snps,reset-gpio gpio number for phy reset. - snps,reset-gpio gpio number for phy reset.
- snps,reset-active-low boolean flag to indicate if phy reset is active low. - snps,reset-active-low boolean flag to indicate if phy reset is active low.

View File

@ -37,6 +37,11 @@ The following properties are defined to the bluetooth node:
Definition: must be: Definition: must be:
"qcom,wcnss-bt" "qcom,wcnss-bt"
- local-bd-address:
Usage: optional
Value type: <u8 array>
Definition: see Documentation/devicetree/bindings/net/bluetooth.txt
== WiFi == WiFi
The following properties are defined to the WiFi node: The following properties are defined to the WiFi node:
@ -91,6 +96,9 @@ smd {
bt { bt {
compatible = "qcom,wcnss-bt"; compatible = "qcom,wcnss-bt";
/* BD address 00:11:22:33:44:55 */
local-bd-address = [ 55 44 33 22 11 00 ];
}; };
wlan { wlan {

View File

@ -299,9 +299,6 @@ Data path helpers
.. kernel-doc:: include/net/cfg80211.h .. kernel-doc:: include/net/cfg80211.h
:functions: ieee80211_data_to_8023 :functions: ieee80211_data_to_8023
.. kernel-doc:: include/net/cfg80211.h
:functions: ieee80211_data_from_8023
.. kernel-doc:: include/net/cfg80211.h .. kernel-doc:: include/net/cfg80211.h
:functions: ieee80211_amsdu_to_8023s :functions: ieee80211_amsdu_to_8023s

View File

@ -0,0 +1,37 @@
LAN9303 Ethernet switch driver
==============================
The LAN9303 is a three port 10/100 Mbps ethernet switch with integrated phys for
the two external ethernet ports. The third port is an RMII/MII interface to a
host master network interface (e.g. fixed link).
Driver details
==============
The driver is implemented as a DSA driver, see
Documentation/networking/dsa/dsa.txt.
See Documentation/devicetree/bindings/net/dsa/lan9303.txt for device tree
binding.
The LAN9303 can be managed both via MDIO and I2C, both supported by this driver.
At startup the driver configures the device to provide two separate network
interfaces (which is the default state of a DSA device). Due to HW limitations,
no HW MAC learning takes place in this mode.
When both user ports are joined to the same bridge, the normal HW MAC learning
is enabled. This means that unicast traffic is forwarded in HW. Broadcast and
multicast is flooded in HW. STP is also supported in this mode. The driver
support fdb/mdb operations as well, meaning IGMP snooping is supported.
If one of the user ports leave the bridge, the ports goes back to the initial
separated operation.
Driver limitations
==================
- Support for VLAN filtering is not implemented
- The HW does not support VLAN-specific fdb entries

View File

@ -1,6 +1,7 @@
The Linux kernel GTP tunneling module The Linux kernel GTP tunneling module
====================================================================== ======================================================================
Documentation by Harald Welte <laforge@gnumonks.org> Documentation by Harald Welte <laforge@gnumonks.org> and
Andreas Schultz <aschultz@tpip.net>
In 'drivers/net/gtp.c' you are finding a kernel-level implementation In 'drivers/net/gtp.c' you are finding a kernel-level implementation
of a GTP tunnel endpoint. of a GTP tunnel endpoint.
@ -91,9 +92,13 @@ http://git.osmocom.org/libgtpnl/
== Protocol Versions == == Protocol Versions ==
There are two different versions of GTP-U: v0 and v1. Both are There are two different versions of GTP-U: v0 [GSM TS 09.60] and v1
implemented in the Kernel GTP module. Version 0 is a legacy version, [3GPP TS 29.281]. Both are implemented in the Kernel GTP module.
and deprecated from recent 3GPP specifications. Version 0 is a legacy version, and deprecated from recent 3GPP
specifications.
GTP-U uses UDP for transporting PDUs. The receiving UDP port is 2151
for GTPv1-U and 3386 for GTPv0-U.
There are three versions of GTP-C: v0, v1, and v2. As the kernel There are three versions of GTP-C: v0, v1, and v2. As the kernel
doesn't implement GTP-C, we don't have to worry about this. It's the doesn't implement GTP-C, we don't have to worry about this. It's the
@ -133,3 +138,93 @@ doe to a lack of user interest, it never got merged.
In 2015, Andreas Schultz came to the rescue and fixed lots more bugs, In 2015, Andreas Schultz came to the rescue and fixed lots more bugs,
extended it with new features and finally pushed all of us to get it extended it with new features and finally pushed all of us to get it
mainline, where it was merged in 4.7.0. mainline, where it was merged in 4.7.0.
== Architectural Details ==
=== Local GTP-U entity and tunnel identification ===
GTP-U uses UDP for transporting PDU's. The receiving UDP port is 2152
for GTPv1-U and 3386 for GTPv0-U.
There is only one GTP-U entity (and therefor SGSN/GGSN/S-GW/PDN-GW
instance) per IP address. Tunnel Endpoint Identifier (TEID) are unique
per GTP-U entity.
A specific tunnel is only defined by the destination entity. Since the
destination port is constant, only the destination IP and TEID define
a tunnel. The source IP and Port have no meaning for the tunnel.
Therefore:
* when sending, the remote entity is defined by the remote IP and
the tunnel endpoint id. The source IP and port have no meaning and
can be changed at any time.
* when receiving the local entity is defined by the local
destination IP and the tunnel endpoint id. The source IP and port
have no meaning and can change at any time.
[3GPP TS 29.281] Section 4.3.0 defines this so:
> The TEID in the GTP-U header is used to de-multiplex traffic
> incoming from remote tunnel endpoints so that it is delivered to the
> User plane entities in a way that allows multiplexing of different
> users, different packet protocols and different QoS levels.
> Therefore no two remote GTP-U endpoints shall send traffic to a
> GTP-U protocol entity using the same TEID value except
> for data forwarding as part of mobility procedures.
The definition above only defines that two remote GTP-U endpoints
*should not* send to the same TEID, it *does not* forbid or exclude
such a scenario. In fact, the mentioned mobility procedures make it
necessary that the GTP-U entity accepts traffic for TEIDs from
multiple or unknown peers.
Therefore, the receiving side identifies tunnels exclusively based on
TEIDs, not based on the source IP!
== APN vs. Network Device ==
The GTP-U driver creates a Linux network device for each Gi/SGi
interface.
[3GPP TS 29.281] calls the Gi/SGi reference point an interface. This
may lead to the impression that the GGSN/P-GW can have only one such
interface.
Correct is that the Gi/SGi reference point defines the interworking
between +the 3GPP packet domain (PDN) based on GTP-U tunnel and IP
based networks.
There is no provision in any of the 3GPP documents that limits the
number of Gi/SGi interfaces implemented by a GGSN/P-GW.
[3GPP TS 29.061] Section 11.3 makes it clear that the selection of a
specific Gi/SGi interfaces is made through the Access Point Name
(APN):
> 2. each private network manages its own addressing. In general this
> will result in different private networks having overlapping
> address ranges. A logically separate connection (e.g. an IP in IP
> tunnel or layer 2 virtual circuit) is used between the GGSN/P-GW
> and each private network.
>
> In this case the IP address alone is not necessarily unique. The
> pair of values, Access Point Name (APN) and IPv4 address and/or
> IPv6 prefixes, is unique.
In order to support the overlapping address range use case, each APN
is mapped to a separate Gi/SGi interface (network device).
NOTE: The Access Point Name is purely a control plane (GTP-C) concept.
At the GTP-U level, only Tunnel Endpoint Identifiers are present in
GTP-U packets and network devices are known
Therefore for a given UE the mapping in IP to PDN network is:
* network device + MS IP -> Peer IP + Peer TEID,
and from PDN to IP network:
* local GTP-U IP + TEID -> network device
Furthermore, before a received T-PDU is injected into the network
device the MS IP is checked against the IP recorded in PDP context.

View File

@ -0,0 +1,285 @@
Identifier Locator Addressing (ILA)
Introduction
============
Identifier-locator addressing (ILA) is a technique used with IPv6 that
differentiates between location and identity of a network node. Part of an
address expresses the immutable identity of the node, and another part
indicates the location of the node which can be dynamic. Identifier-locator
addressing can be used to efficiently implement overlay networks for
network virtualization as well as solutions for use cases in mobility.
ILA can be thought of as means to implement an overlay network without
encapsulation. This is accomplished by performing network address
translation on destination addresses as a packet traverses a network. To
the network, an ILA translated packet appears to be no different than any
other IPv6 packet. For instance, if the transport protocol is TCP then an
ILA translated packet looks like just another TCP/IPv6 packet. The
advantage of this is that ILA is transparent to the network so that
optimizations in the network, such as ECMP, RSS, GRO, GSO, etc., just work.
The ILA protocol is described in Internet-Draft draft-herbert-intarea-ila.
ILA terminology
===============
- Identifier A number that identifies an addressable node in the network
independent of its location. ILA identifiers are sixty-four
bit values.
- Locator A network prefix that routes to a physical host. Locators
provide the topological location of an addressed node. ILA
locators are sixty-four bit prefixes.
- ILA mapping
A mapping of an ILA identifier to a locator (or to a
locator and meta data). An ILA domain maintains a database
that contains mappings for all destinations in the domain.
- SIR address
An IPv6 address composed of a SIR prefix (upper sixty-
four bits) and an identifier (lower sixty-four bits).
SIR addresses are visible to applications and provide a
means for them to address nodes independent of their
location.
- ILA address
An IPv6 address composed of a locator (upper sixty-four
bits) and an identifier (low order sixty-four bits). ILA
addresses are never visible to an application.
- ILA host An end host that is capable of performing ILA translations
on transmit or receive.
- ILA router A network node that performs ILA translation and forwarding
of translated packets.
- ILA forwarding cache
A type of ILA router that only maintains a working set
cache of mappings.
- ILA node A network node capable of performing ILA translations. This
can be an ILA router, ILA forwarding cache, or ILA host.
Operation
=========
There are two fundamental operations with ILA:
- Translate a SIR address to an ILA address. This is performed on ingress
to an ILA overlay.
- Translate an ILA address to a SIR address. This is performed on egress
from the ILA overlay.
ILA can be deployed either on end hosts or intermediate devices in the
network; these are provided by "ILA hosts" and "ILA routers" respectively.
Configuration and datapath for these two points of deployment is somewhat
different.
The diagram below illustrates the flow of packets through ILA as well
as showing ILA hosts and routers.
+--------+ +--------+
| Host A +-+ +--->| Host B |
| | | (2) ILA (') | |
+--------+ | ...addressed.... ( ) +--------+
V +---+--+ . packet . +---+--+ (_)
(1) SIR | | ILA |----->-------->---->| ILA | | (3) SIR
addressed +->|router| . . |router|->-+ addressed
packet +---+--+ . IPv6 . +---+--+ packet
/ . Network .
/ . . +--+-++--------+
+--------+ / . . |ILA || Host |
| Host +--+ . .- -|host|| |
| | . . +--+-++--------+
+--------+ ................
Transport checksum handling
===========================
When an address is translated by ILA, an encapsulated transport checksum
that includes the translated address in a pseudo header may be rendered
incorrect on the wire. This is a problem for intermediate devices,
including checksum offload in NICs, that process the checksum. There are
three options to deal with this:
- no action Allow the checksum to be incorrect on the wire. Before
a receiver verifies a checksum the ILA to SIR address
translation must be done.
- adjust transport checksum
When ILA translation is performed the packet is parsed
and if a transport layer checksum is found then it is
adjusted to reflect the correct checksum per the
translated address.
- checksum neutral mapping
When an address is translated the difference can be offset
elsewhere in a part of the packet that is covered by the
the checksum. The low order sixteen bits of the identifier
are used. This method is preferred since it doesn't require
parsing a packet beyond the IP header and in most cases the
adjustment can be precomputed and saved with the mapping.
Note that the checksum neutral adjustment affects the low order sixteen
bits of the identifier. When ILA to SIR address translation is done on
egress the low order bits are restored to the original value which
restores the identifier as it was originally sent.
Identifier types
================
ILA defines different types of identifiers for different use cases.
The defined types are:
0: interface identifier
1: locally unique identifier
2: virtual networking identifier for IPv4 address
3: virtual networking identifier for IPv6 unicast address
4: virtual networking identifier for IPv6 multicast address
5: non-local address identifier
In the current implementation of kernel ILA only locally unique identifiers
(LUID) are supported. LUID allows for a generic, unformatted 64 bit
identifier.
Identifier formats
==================
Kernel ILA supports two optional fields in an identifier for formatting:
"C-bit" and "identifier type". The presence of these fields is determined
by configuration as demonstrated below.
If the identifier type is present it occupies the three highest order
bits of an identifier. The possible values are given in the above list.
If the C-bit is present, this is used as an indication that checksum
neutral mapping has been done. The C-bit can only be set in an
ILA address, never a SIR address.
In the simplest format the identifier types, C-bit, and checksum
adjustment value are not present so an identifier is considered an
unstructured sixty-four bit value.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The checksum neutral adjustment may be configured to always be
present using neutral-map-auto. In this case there is no C-bit, but the
checksum adjustment is in the low order 16 bits. The identifier is
still sixty-four bits.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Checksum-neutral adjustment |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The C-bit may used to explicitly indicate that checksum neutral
mapping has been applied to an ILA address. The format is:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |C| Identifier |
| +-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Checksum-neutral adjustment |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The identifier type field may be present to indicate the identifier
type. If it is not present then the type is inferred based on mapping
configuration. The checksum neutral adjustment may automatically
used with the identifier type as illustrated below.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type| Identifier |
+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Checksum-neutral adjustment |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
If the identifier type and the C-bit can be present simultaneously so
the identifier format would be:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type|C| Identifier |
+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Checksum-neutral adjustment |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Configuration
=============
There are two methods to configure ILA mappings. One is by using LWT routes
and the other is ila_xlat (called from NFHOOK PREROUTING hook). ila_xlat
is intended to be used in the receive path for ILA hosts .
An ILA router has also been implemented in XDP. Description of that is
outside the scope of this document.
The usage of for ILA LWT routes is:
ip route add DEST/128 encap ila LOC csum-mode MODE ident-type TYPE via ADDR
Destination (DEST) can either be a SIR address (for an ILA host or ingress
ILA router) or an ILA address (egress ILA router). LOC is the sixty-four
bit locator (with format W:X:Y:Z) that overwrites the upper sixty-four
bits of the destination address. Checksum MODE is one of "no-action",
"adj-transport", "neutral-map", and "neutral-map-auto". If neutral-map is
set then the C-bit will be present. Identifier TYPE one of "luid" or
"use-format." In the case of use-format, the identifier type field is
present and the effective type is taken from that.
The usage of ila_xlat is:
ip ila add loc_match MATCH loc LOC csum-mode MODE ident-type TYPE
MATCH indicates the incoming locator that must be matched to apply
a the translaiton. LOC is the locator that overwrites the upper
sixty-four bits of the destination address. MODE and TYPE have the
same meanings as described above.
Some examples
=============
# Configure an ILA route that uses checksum neutral mapping as well
# as type field. Note that the type field is set in the SIR address
# (the 2000 implies type is 1 which is LUID).
ip route add 3333:0:0:1:2000:0:1:87/128 encap ila 2001:0:87:0 \
csum-mode neutral-map ident-type use-format
# Configure an ILA LWT route that uses auto checksum neutral mapping
# (no C-bit) and configure identifier type to be LUID so that the
# identifier type field will not be present.
ip route add 3333:0:0:1:2000:0:2:87/128 encap ila 2001:0:87:1 \
csum-mode neutral-map-auto ident-type luid
ila_xlat configuration
# Configure an ILA to SIR mapping that matches a locator and overwrites
# it with a SIR address (3333:0:0:1 in this example). The C-bit and
# identifier field are used.
ip ila add loc_match 2001:0:119:0 loc 3333:0:0:1 \
csum-mode neutral-map-auto ident-type use-format
# Configure an ILA to SIR mapping where checksum neutral is automatically
# set without the C-bit and the identifier type is configured to be LUID
# so that the identifier type field is not present.
ip ila add loc_match 2001:0:119:0 loc 3333:0:0:1 \
csum-mode neutral-map-auto ident-type use-format

View File

@ -289,8 +289,7 @@ tcp_ecn_fallback - BOOLEAN
Default: 1 (fallback enabled) Default: 1 (fallback enabled)
tcp_fack - BOOLEAN tcp_fack - BOOLEAN
Enable FACK congestion avoidance and fast retransmission. This is a legacy option, it has no effect anymore.
The value is not used, if tcp_sack is not enabled.
tcp_fin_timeout - INTEGER tcp_fin_timeout - INTEGER
The length of time an orphaned (no longer referenced by any The length of time an orphaned (no longer referenced by any
@ -454,6 +453,7 @@ tcp_recovery - INTEGER
RACK: 0x1 enables the RACK loss detection for fast detection of lost RACK: 0x1 enables the RACK loss detection for fast detection of lost
retransmissions and tail drops. retransmissions and tail drops.
RACK: 0x2 makes RACK's reordering window static (min_rtt/4).
Default: 0x1 Default: 0x1
@ -1385,6 +1385,30 @@ mld_qrv - INTEGER
Default: 2 (as specified by RFC3810 9.1) Default: 2 (as specified by RFC3810 9.1)
Minimum: 1 (as specified by RFC6636 4.5) Minimum: 1 (as specified by RFC6636 4.5)
max_dst_opts_cnt - INTEGER
Maximum number of non-padding TLVs allowed in a Destination
options extension header. If this value is less than zero
then unknown options are disallowed and the number of known
TLVs allowed is the absolute value of this number.
Default: 8
max_hbh_opts_cnt - INTEGER
Maximum number of non-padding TLVs allowed in a Hop-by-Hop
options extension header. If this value is less than zero
then unknown options are disallowed and the number of known
TLVs allowed is the absolute value of this number.
Default: 8
max dst_opts_len - INTEGER
Maximum length allowed for a Destination options extension
header.
Default: INT_MAX (unlimited)
max hbh_opts_len - INTEGER
Maximum length allowed for a Hop-by-Hop options extension
header.
Default: INT_MAX (unlimited)
IPv6 Fragmentation: IPv6 Fragmentation:
ip6frag_high_thresh - INTEGER ip6frag_high_thresh - INTEGER
@ -1707,6 +1731,15 @@ ndisc_notify - BOOLEAN
1 - Generate unsolicited neighbour advertisements when device is brought 1 - Generate unsolicited neighbour advertisements when device is brought
up or hardware address changes. up or hardware address changes.
ndisc_tclass - INTEGER
The IPv6 Traffic Class to use by default when sending IPv6 Neighbor
Discovery (Router Solicitation, Router Advertisement, Neighbor
Solicitation, Neighbor Advertisement, Redirect) messages.
These 8 bits can be interpreted as 6 high order bits holding the DSCP
value and 2 low order bits representing ECN (which you probably want
to leave cleared).
0 - (default)
mldv1_unsolicited_report_interval - INTEGER mldv1_unsolicited_report_interval - INTEGER
The interval in milliseconds in which the next unsolicited The interval in milliseconds in which the next unsolicited
MLDv1 report retransmit will take place. MLDv1 report retransmit will take place.

View File

@ -22,9 +22,21 @@ The driver can be built into the kernel (CONFIG_IPVLAN=y) or as a module
There are no module parameters for this driver and it can be configured There are no module parameters for this driver and it can be configured
using IProute2/ip utility. using IProute2/ip utility.
ip link add link <master-dev> name <slave-dev> type ipvlan mode { l2 | l3 | l3s } ip link add link <master> name <slave> type ipvlan [ mode MODE ] [ FLAGS ]
where
MODE: l3 (default) | l3s | l2
FLAGS: bridge (default) | private | vepa
e.g. ip link add link eth0 name ipvl0 type ipvlan mode l2 e.g.
(a) Following will create IPvlan link with eth0 as master in
L3 bridge mode
bash# ip link add link eth0 name ipvl0 type ipvlan
(b) This command will create IPvlan link in L2 bridge mode.
bash# ip link add link eth0 name ipvl0 type ipvlan mode l2 bridge
(c) This command will create an IPvlan device in L2 private mode.
bash# ip link add link eth0 name ipvlan type ipvlan mode l2 private
(d) This command will create an IPvlan device in L2 vepa mode.
bash# ip link add link eth0 name ipvlan type ipvlan mode l2 vepa
4. Operating modes: 4. Operating modes:
@ -54,7 +66,29 @@ works in this mode and hence it is L3-symmetric (L3s). This will have slightly l
performance but that shouldn't matter since you are choosing this mode over plain-L3 performance but that shouldn't matter since you are choosing this mode over plain-L3
mode to make conn-tracking work. mode to make conn-tracking work.
5. What to choose (macvlan vs. ipvlan)? 5. Mode flags:
At this time following mode flags are available
5.1 bridge:
This is the default option. To configure the IPvlan port in this mode,
user can choose to either add this option on the command-line or don't specify
anything. This is the traditional mode where slaves can cross-talk among
themseleves apart from talking through the master device.
5.2 private:
If this option is added to the command-line, the port is set in private
mode. i.e. port wont allow cross communication between slaves.
5.3 vepa:
If this is added to the command-line, the port is set in VEPA mode.
i.e. port will offload switching functionality to the external entity as
described in 802.1Qbg
Note: VEPA mode in IPvlan has limitations. IPvlan uses the mac-address of the
master-device, so the packets which are emitted in this mode for the adjacent
neighbor will have source and destination mac same. This will make the switch /
router send the redirect message.
6. What to choose (macvlan vs. ipvlan)?
These two devices are very similar in many regards and the specific use These two devices are very similar in many regards and the specific use
case could very well define which device to choose. if one of the following case could very well define which device to choose. if one of the following
situations defines your use case then you can choose to use ipvlan - situations defines your use case then you can choose to use ipvlan -

View File

@ -64,7 +64,10 @@ A: To understand this, you need to know a bit of background information
If you aren't subscribed to netdev and/or are simply unsure if net-next If you aren't subscribed to netdev and/or are simply unsure if net-next
has re-opened yet, simply check the net-next git repository link above for has re-opened yet, simply check the net-next git repository link above for
any new networking-related commits. any new networking-related commits. You may also check the following
website for the current status:
http://vger.kernel.org/~davem/net-next.html
The "net" tree continues to collect fixes for the vX.Y content, and The "net" tree continues to collect fixes for the vX.Y content, and
is fed back to Linus at regular (~weekly) intervals. Meaning that the is fed back to Linus at regular (~weekly) intervals. Meaning that the

View File

@ -19,12 +19,12 @@ Features
Receive Side Scaling Receive Side Scaling
-------------------- --------------------
Hyper-V supports receive side scaling. For TCP, packets are Hyper-V supports receive side scaling. For TCP & UDP, packets can
distributed among available queues based on IP address and port be distributed among available queues based on IP address and port
number. number.
For UDP, we can switch UDP hash level between L3 and L4 by ethtool For TCP & UDP, we can switch hash level between L3 and L4 by ethtool
command. UDP over IPv4 and v6 can be set differently. The default command. TCP/UDP over IPv4 and v6 can be set differently. The default
hash level is L4. We currently only allow switching TX hash level hash level is L4. We currently only allow switching TX hash level
from within the guests. from within the guests.

View File

@ -19,6 +19,14 @@ core regulatory domain all wireless devices should adhere to.
How to get regulatory domains to the kernel How to get regulatory domains to the kernel
------------------------------------------- -------------------------------------------
When the regulatory domain is first set up, the kernel will request a
database file (regulatory.db) containing all the regulatory rules. It
will then use that database when it needs to look up the rules for a
given country.
How to get regulatory domains to the kernel (old CRDA solution)
---------------------------------------------------------------
Userspace gets a regulatory domain in the kernel by having Userspace gets a regulatory domain in the kernel by having
a userspace agent build it and send it via nl80211. Only a userspace agent build it and send it via nl80211. Only
expected regulatory domains will be respected by the kernel. expected regulatory domains will be respected by the kernel.
@ -192,23 +200,5 @@ Then in some part of your code after your wiphy has been registered:
Statically compiled regulatory database Statically compiled regulatory database
--------------------------------------- ---------------------------------------
In most situations the userland solution using CRDA as described When a database should be fixed into the kernel, it can be provided as a
above is the preferred solution. However in some cases a set of firmware file at build time that is then linked into the kernel.
rules built into the kernel itself may be desirable. To account
for this situation, a configuration option has been provided
(i.e. CONFIG_CFG80211_INTERNAL_REGDB). With this option enabled,
the wireless database information contained in net/wireless/db.txt is
used to generate a data structure encoded in net/wireless/regdb.c.
That option also enables code in net/wireless/reg.c which queries
the data in regdb.c as an alternative to using CRDA.
The file net/wireless/db.txt should be kept up-to-date with the db.txt
file available in the git repository here:
git://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git
Again, most users in most situations should be using the CRDA package
provided with their distribution, and in most other situations users
should be building and using CRDA on their own rather than using
this option. If you are not absolutely sure that you should be using
CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_.

View File

@ -280,6 +280,18 @@ Interaction with the user of the RxRPC socket:
nominated by a socket option. nominated by a socket option.
Notes on sendmsg:
(*) MSG_WAITALL can be set to tell sendmsg to ignore signals if the peer is
making progress at accepting packets within a reasonable time such that we
manage to queue up all the data for transmission. This requires the
client to accept at least one packet per 2*RTT time period.
If this isn't set, sendmsg() will return immediately, either returning
EINTR/ERESTARTSYS if nothing was consumed or returning the amount of data
consumed.
Notes on recvmsg: Notes on recvmsg:
(*) If there's a sequence of data messages belonging to a particular call on (*) If there's a sequence of data messages belonging to a particular call on
@ -782,7 +794,9 @@ The kernel interface functions are as follows:
struct key *key, struct key *key,
unsigned long user_call_ID, unsigned long user_call_ID,
s64 tx_total_len, s64 tx_total_len,
gfp_t gfp); gfp_t gfp,
rxrpc_notify_rx_t notify_rx,
bool upgrade);
This allocates the infrastructure to make a new RxRPC call and assigns This allocates the infrastructure to make a new RxRPC call and assigns
call and connection numbers. The call will be made on the UDP port that call and connection numbers. The call will be made on the UDP port that
@ -803,6 +817,13 @@ The kernel interface functions are as follows:
allows the kernel to encrypt directly to the packet buffers, thereby allows the kernel to encrypt directly to the packet buffers, thereby
saving a copy. The value may not be less than -1. saving a copy. The value may not be less than -1.
notify_rx is a pointer to a function to be called when events such as
incoming data packets or remote aborts happen.
upgrade should be set to true if a client operation should request that
the server upgrade the service to a better one. The resultant service ID
is returned by rxrpc_kernel_recv_data().
If this function is successful, an opaque reference to the RxRPC call is If this function is successful, an opaque reference to the RxRPC call is
returned. The caller now holds a reference on this and it must be returned. The caller now holds a reference on this and it must be
properly ended. properly ended.
@ -850,7 +871,8 @@ The kernel interface functions are as follows:
size_t size, size_t size,
size_t *_offset, size_t *_offset,
bool want_more, bool want_more,
u32 *_abort) u32 *_abort,
u16 *_service)
This is used to receive data from either the reply part of a client call This is used to receive data from either the reply part of a client call
or the request part of a service call. buf and size specify how much or the request part of a service call. buf and size specify how much
@ -873,6 +895,9 @@ The kernel interface functions are as follows:
If a remote ABORT is detected, the abort code received will be stored in If a remote ABORT is detected, the abort code received will be stored in
*_abort and ECONNABORTED will be returned. *_abort and ECONNABORTED will be returned.
The service ID that the call ended up with is returned into *_service.
This can be used to see if a call got a service upgrade.
(*) Abort a call. (*) Abort a call.
void rxrpc_kernel_abort_call(struct socket *sock, void rxrpc_kernel_abort_call(struct socket *sock,
@ -1020,6 +1045,30 @@ The kernel interface functions are as follows:
It returns 0 if the call was requeued and an error otherwise. It returns 0 if the call was requeued and an error otherwise.
(*) Get call RTT.
u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call);
Get the RTT time to the peer in use by a call. The value returned is in
nanoseconds.
(*) Check call still alive.
u32 rxrpc_kernel_check_life(struct socket *sock,
struct rxrpc_call *call);
This returns a number that is updated when ACKs are received from the peer
(notably including PING RESPONSE ACKs which we can elicit by sending PING
ACKs to see if the call still exists on the server). The caller should
compare the numbers of two calls to see if the call is still alive after
waiting for a suitable interval.
This allows the caller to work out if the server is still contactable and
if the call is still alive on the server whilst waiting for the server to
process a client operation.
This function may transmit a PING ACK.
======================= =======================
CONFIGURABLE PARAMETERS CONFIGURABLE PARAMETERS

View File

@ -71,7 +71,12 @@ Setup
ip ru add iif vrf-blue table 10 ip ru add iif vrf-blue table 10
3. Set the default route for the table (and hence default route for the VRF). 3. Set the default route for the table (and hence default route for the VRF).
ip route add table 10 unreachable default ip route add table 10 unreachable default metric 4278198272
This high metric value ensures that the default unreachable route can
be overridden by a routing protocol suite. FRRouting interprets
kernel metrics as a combined admin distance (upper byte) and priority
(lower 3 bytes). Thus the above metric translates to [255/8192].
4. Enslave L3 interfaces to a VRF device. 4. Enslave L3 interfaces to a VRF device.
ip link set dev eth1 master vrf-blue ip link set dev eth1 master vrf-blue
@ -256,7 +261,7 @@ older form without it.
For example: For example:
$ ip route show vrf red $ ip route show vrf red
prohibit default unreachable default metric 4278198272
broadcast 10.2.1.0 dev eth1 proto kernel scope link src 10.2.1.2 broadcast 10.2.1.0 dev eth1 proto kernel scope link src 10.2.1.2
10.2.1.0/24 dev eth1 proto kernel scope link src 10.2.1.2 10.2.1.0/24 dev eth1 proto kernel scope link src 10.2.1.2
local 10.2.1.2 dev eth1 proto kernel scope host src 10.2.1.2 local 10.2.1.2 dev eth1 proto kernel scope host src 10.2.1.2
@ -282,7 +287,7 @@ older form without it.
ff00::/8 dev red metric 256 pref medium ff00::/8 dev red metric 256 pref medium
ff00::/8 dev eth1 metric 256 pref medium ff00::/8 dev eth1 metric 256 pref medium
ff00::/8 dev eth2 metric 256 pref medium ff00::/8 dev eth2 metric 256 pref medium
unreachable default dev lo metric 4278198272 error -101 pref medium
8. Route Lookup for a VRF 8. Route Lookup for a VRF
@ -331,7 +336,7 @@ function vrf_create
ip link add ${VRF} type vrf table ${TBID} ip link add ${VRF} type vrf table ${TBID}
if [ "${VRF}" != "mgmt" ]; then if [ "${VRF}" != "mgmt" ]; then
ip route add table ${TBID} unreachable default ip route add table ${TBID} unreachable default metric 4278198272
fi fi
ip link set dev ${VRF} up ip link set dev ${VRF} up
} }

View File

@ -695,9 +695,9 @@ F: include/linux/altera_uart.h
F: include/linux/altera_jtaguart.h F: include/linux/altera_jtaguart.h
AMAZON ETHERNET DRIVERS AMAZON ETHERNET DRIVERS
M: Netanel Belgazal <netanel@annapurnalabs.com> M: Netanel Belgazal <netanel@amazon.com>
R: Saeed Bishara <saeed@annapurnalabs.com> R: Saeed Bishara <saeedb@amazon.com>
R: Zorik Machulsky <zorik@annapurnalabs.com> R: Zorik Machulsky <zorik@amazon.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Supported S: Supported
F: Documentation/networking/ena.txt F: Documentation/networking/ena.txt
@ -2712,6 +2712,7 @@ L: linux-kernel@vger.kernel.org
S: Supported S: Supported
F: arch/x86/net/bpf_jit* F: arch/x86/net/bpf_jit*
F: Documentation/networking/filter.txt F: Documentation/networking/filter.txt
F: Documentation/bpf/
F: include/linux/bpf* F: include/linux/bpf*
F: include/linux/filter.h F: include/linux/filter.h
F: include/uapi/linux/bpf* F: include/uapi/linux/bpf*
@ -2724,7 +2725,7 @@ F: net/core/filter.c
F: net/sched/act_bpf.c F: net/sched/act_bpf.c
F: net/sched/cls_bpf.c F: net/sched/cls_bpf.c
F: samples/bpf/ F: samples/bpf/
F: tools/net/bpf* F: tools/bpf/
F: tools/testing/selftests/bpf/ F: tools/testing/selftests/bpf/
BROADCOM B44 10/100 ETHERNET DRIVER BROADCOM B44 10/100 ETHERNET DRIVER
@ -2903,6 +2904,7 @@ S: Maintained
F: drivers/phy/broadcom/phy-brcm-usb* F: drivers/phy/broadcom/phy-brcm-usb*
BROADCOM GENET ETHERNET DRIVER BROADCOM GENET ETHERNET DRIVER
M: Doug Berger <opendmb@gmail.com>
M: Florian Fainelli <f.fainelli@gmail.com> M: Florian Fainelli <f.fainelli@gmail.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Supported S: Supported
@ -3088,7 +3090,6 @@ F: arch/c6x/
CA8210 IEEE-802.15.4 RADIO DRIVER CA8210 IEEE-802.15.4 RADIO DRIVER
M: Harry Morris <h.morris@cascoda.com> M: Harry Morris <h.morris@cascoda.com>
M: linuxdev@cascoda.com
L: linux-wpan@vger.kernel.org L: linux-wpan@vger.kernel.org
W: https://github.com/Cascoda/ca8210-linux.git W: https://github.com/Cascoda/ca8210-linux.git
S: Maintained S: Maintained
@ -3335,17 +3336,22 @@ S: Maintained
F: drivers/auxdisplay/cfag12864bfb.c F: drivers/auxdisplay/cfag12864bfb.c
F: include/linux/cfag12864b.h F: include/linux/cfag12864b.h
CFG80211 and NL80211 802.11 (including CFG80211/NL80211)
M: Johannes Berg <johannes@sipsolutions.net> M: Johannes Berg <johannes@sipsolutions.net>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/ W: http://wireless.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
S: Maintained S: Maintained
F: net/wireless/
F: include/uapi/linux/nl80211.h F: include/uapi/linux/nl80211.h
F: include/linux/ieee80211.h
F: include/net/wext.h
F: include/net/cfg80211.h F: include/net/cfg80211.h
F: net/wireless/* F: include/net/iw_handler.h
X: net/wireless/wext* F: include/net/ieee80211_radiotap.h
F: Documentation/driver-api/80211/cfg80211.rst
F: Documentation/networking/regulatory.txt
CHAR and MISC DRIVERS CHAR and MISC DRIVERS
M: Arnd Bergmann <arnd@arndb.de> M: Arnd Bergmann <arnd@arndb.de>
@ -3421,7 +3427,7 @@ F: drivers/scsi/snic/
CISCO VIC ETHERNET NIC DRIVER CISCO VIC ETHERNET NIC DRIVER
M: Christian Benvenuti <benve@cisco.com> M: Christian Benvenuti <benve@cisco.com>
M: Govindarajulu Varadarajan <_govind@gmx.com> M: Govindarajulu Varadarajan <_govind@gmx.com>
M: Neel Patel <neepatel@cisco.com> M: Parvi Kaustubhi <pkaustub@cisco.com>
S: Supported S: Supported
F: drivers/net/ethernet/cisco/enic/ F: drivers/net/ethernet/cisco/enic/
@ -8231,6 +8237,7 @@ F: Documentation/networking/mac80211-injection.txt
F: include/net/mac80211.h F: include/net/mac80211.h
F: net/mac80211/ F: net/mac80211/
F: drivers/net/wireless/mac80211_hwsim.[ch] F: drivers/net/wireless/mac80211_hwsim.[ch]
F: Documentation/networking/mac80211_hwsim/README
MAILBOX API MAILBOX API
M: Jassi Brar <jassisinghbrar@gmail.com> M: Jassi Brar <jassisinghbrar@gmail.com>
@ -9425,6 +9432,7 @@ M: Florian Fainelli <f.fainelli@gmail.com>
S: Maintained S: Maintained
F: net/dsa/ F: net/dsa/
F: include/net/dsa.h F: include/net/dsa.h
F: include/linux/dsa/
F: drivers/net/dsa/ F: drivers/net/dsa/
NETWORKING [GENERAL] NETWORKING [GENERAL]
@ -9445,8 +9453,8 @@ F: include/uapi/linux/in.h
F: include/uapi/linux/net.h F: include/uapi/linux/net.h
F: include/uapi/linux/netdevice.h F: include/uapi/linux/netdevice.h
F: include/uapi/linux/net_namespace.h F: include/uapi/linux/net_namespace.h
F: tools/net/
F: tools/testing/selftests/net/ F: tools/testing/selftests/net/
F: lib/net_utils.c
F: lib/random32.c F: lib/random32.c
NETWORKING [IPSEC] NETWORKING [IPSEC]
@ -11520,6 +11528,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
S: Maintained S: Maintained
F: Documentation/rfkill.txt F: Documentation/rfkill.txt
F: Documentation/ABI/stable/sysfs-class-rfkill
F: net/rfkill/ F: net/rfkill/
RHASHTABLE RHASHTABLE
@ -13343,6 +13352,15 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com>
M: Yehezkel Bernat <yehezkel.bernat@intel.com> M: Yehezkel Bernat <yehezkel.bernat@intel.com>
S: Maintained S: Maintained
F: drivers/thunderbolt/ F: drivers/thunderbolt/
F: include/linux/thunderbolt.h
THUNDERBOLT NETWORK DRIVER
M: Michael Jamet <michael.jamet@intel.com>
M: Mika Westerberg <mika.westerberg@linux.intel.com>
M: Yehezkel Bernat <yehezkel.bernat@intel.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/thunderbolt.c
THUNDERX GPIO DRIVER THUNDERX GPIO DRIVER
M: David Daney <david.daney@cavium.com> M: David Daney <david.daney@cavium.com>
@ -14322,12 +14340,15 @@ S: Maintained
F: include/linux/virtio_vsock.h F: include/linux/virtio_vsock.h
F: include/uapi/linux/virtio_vsock.h F: include/uapi/linux/virtio_vsock.h
F: include/uapi/linux/vsockmon.h F: include/uapi/linux/vsockmon.h
F: include/uapi/linux/vm_sockets_diag.h
F: net/vmw_vsock/diag.c
F: net/vmw_vsock/af_vsock_tap.c F: net/vmw_vsock/af_vsock_tap.c
F: net/vmw_vsock/virtio_transport_common.c F: net/vmw_vsock/virtio_transport_common.c
F: net/vmw_vsock/virtio_transport.c F: net/vmw_vsock/virtio_transport.c
F: drivers/net/vsockmon.c F: drivers/net/vsockmon.c
F: drivers/vhost/vsock.c F: drivers/vhost/vsock.c
F: drivers/vhost/vsock.h F: drivers/vhost/vsock.h
F: tools/testing/vsock/
VIRTIO CONSOLE DRIVER VIRTIO CONSOLE DRIVER
M: Amit Shah <amit@kernel.org> M: Amit Shah <amit@kernel.org>
@ -14591,7 +14612,6 @@ L: wil6210@qca.qualcomm.com
S: Supported S: Supported
W: http://wireless.kernel.org/en/users/Drivers/wil6210 W: http://wireless.kernel.org/en/users/Drivers/wil6210
F: drivers/net/wireless/ath/wil6210/ F: drivers/net/wireless/ath/wil6210/
F: include/uapi/linux/wil6210_uapi.h
WIMAX STACK WIMAX STACK
M: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> M: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>

View File

@ -25,7 +25,6 @@
#include <asm/dpmc.h> #include <asm/dpmc.h>
#include <asm/bfin_sdh.h> #include <asm/bfin_sdh.h>
#include <linux/spi/ad7877.h> #include <linux/spi/ad7877.h>
#include <net/dsa.h>
/* /*
* Name the Board for the /proc/cpuinfo * Name the Board for the /proc/cpuinfo
@ -105,11 +104,7 @@ static const unsigned short bfin_mac_peripherals[] = {
static struct bfin_phydev_platform_data bfin_phydev_data[] = { static struct bfin_phydev_platform_data bfin_phydev_data[] = {
{ {
#if IS_ENABLED(CONFIG_NET_DSA_KSZ8893M)
.addr = 3,
#else
.addr = 1, .addr = 1,
#endif
.irq = IRQ_MAC_PHYINT, .irq = IRQ_MAC_PHYINT,
}, },
}; };
@ -119,9 +114,6 @@ static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
.phydev_data = bfin_phydev_data, .phydev_data = bfin_phydev_data,
.phy_mode = PHY_INTERFACE_MODE_MII, .phy_mode = PHY_INTERFACE_MODE_MII,
.mac_peripherals = bfin_mac_peripherals, .mac_peripherals = bfin_mac_peripherals,
#if IS_ENABLED(CONFIG_NET_DSA_KSZ8893M)
.phy_mask = 0xfff7, /* Only probe the port phy connect to the on chip MAC */
#endif
.vlan1_mask = 1, .vlan1_mask = 1,
.vlan2_mask = 2, .vlan2_mask = 2,
}; };
@ -140,29 +132,6 @@ static struct platform_device bfin_mac_device = {
} }
}; };
#if IS_ENABLED(CONFIG_NET_DSA_KSZ8893M)
static struct dsa_chip_data ksz8893m_switch_chip_data = {
.mii_bus = &bfin_mii_bus.dev,
.port_names = {
NULL,
"eth%d",
"eth%d",
"cpu",
},
};
static struct dsa_platform_data ksz8893m_switch_data = {
.nr_chips = 1,
.netdev = &bfin_mac_device.dev,
.chip = &ksz8893m_switch_chip_data,
};
static struct platform_device ksz8893m_switch_device = {
.name = "dsa",
.id = 0,
.num_resources = 0,
.dev.platform_data = &ksz8893m_switch_data,
};
#endif
#endif #endif
#if IS_ENABLED(CONFIG_MTD_M25P80) #if IS_ENABLED(CONFIG_MTD_M25P80)
@ -228,19 +197,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
}, },
#endif #endif
#if IS_ENABLED(CONFIG_BFIN_MAC)
#if IS_ENABLED(CONFIG_NET_DSA_KSZ8893M)
{
.modalias = "ksz8893m",
.max_speed_hz = 5000000,
.bus_num = 0,
.chip_select = 1,
.platform_data = NULL,
.mode = SPI_MODE_3,
},
#endif
#endif
#if IS_ENABLED(CONFIG_MMC_SPI) #if IS_ENABLED(CONFIG_MMC_SPI)
{ {
.modalias = "mmc_spi", .modalias = "mmc_spi",
@ -714,9 +670,6 @@ static struct platform_device *stamp_devices[] __initdata = {
#if IS_ENABLED(CONFIG_BFIN_MAC) #if IS_ENABLED(CONFIG_BFIN_MAC)
&bfin_mii_bus, &bfin_mii_bus,
&bfin_mac_device, &bfin_mac_device,
#if IS_ENABLED(CONFIG_NET_DSA_KSZ8893M)
&ksz8893m_switch_device,
#endif
#endif #endif
#if IS_ENABLED(CONFIG_SPI_BFIN5XX) #if IS_ENABLED(CONFIG_SPI_BFIN5XX)

View File

@ -25,7 +25,6 @@
#include <asm/dpmc.h> #include <asm/dpmc.h>
#include <asm/bfin_sdh.h> #include <asm/bfin_sdh.h>
#include <linux/spi/ad7877.h> #include <linux/spi/ad7877.h>
#include <net/dsa.h>
/* /*
* Name the Board for the /proc/cpuinfo * Name the Board for the /proc/cpuinfo

View File

@ -168,7 +168,6 @@ static int uml_net_open(struct net_device *dev)
goto out_close; goto out_close;
} }
lp->tl.data = (unsigned long) &lp->user;
netif_start_queue(dev); netif_start_queue(dev);
/* clear buffer - it can happen that the host side of the interface /* clear buffer - it can happen that the host side of the interface
@ -278,10 +277,11 @@ static const struct ethtool_ops uml_net_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info, .get_ts_info = ethtool_op_get_ts_info,
}; };
static void uml_net_user_timer_expire(unsigned long _conn) static void uml_net_user_timer_expire(struct timer_list *t)
{ {
#ifdef undef #ifdef undef
struct connection *conn = (struct connection *)_conn; struct uml_net_private *lp = from_timer(lp, t, tl);
struct connection *conn = &lp->user;
dprintk(KERN_INFO "uml_net_user_timer_expire [%p]\n", conn); dprintk(KERN_INFO "uml_net_user_timer_expire [%p]\n", conn);
do_connect(conn); do_connect(conn);
@ -458,9 +458,8 @@ static void eth_configure(int n, void *init, char *mac,
.add_address = transport->user->add_address, .add_address = transport->user->add_address,
.delete_address = transport->user->delete_address }); .delete_address = transport->user->delete_address });
init_timer(&lp->tl); timer_setup(&lp->tl, uml_net_user_timer_expire, 0);
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
lp->tl.function = uml_net_user_timer_expire;
memcpy(lp->mac, dev->dev_addr, sizeof(lp->mac)); memcpy(lp->mac, dev->dev_addr, sizeof(lp->mac));
if ((transport->user->init != NULL) && if ((transport->user->init != NULL) &&

View File

@ -358,26 +358,33 @@ fore200e_shutdown(struct fore200e* fore200e)
case FORE200E_STATE_COMPLETE: case FORE200E_STATE_COMPLETE:
kfree(fore200e->stats); kfree(fore200e->stats);
/* fall through */
case FORE200E_STATE_IRQ: case FORE200E_STATE_IRQ:
free_irq(fore200e->irq, fore200e->atm_dev); free_irq(fore200e->irq, fore200e->atm_dev);
/* fall through */
case FORE200E_STATE_ALLOC_BUF: case FORE200E_STATE_ALLOC_BUF:
fore200e_free_rx_buf(fore200e); fore200e_free_rx_buf(fore200e);
/* fall through */
case FORE200E_STATE_INIT_BSQ: case FORE200E_STATE_INIT_BSQ:
fore200e_uninit_bs_queue(fore200e); fore200e_uninit_bs_queue(fore200e);
/* fall through */
case FORE200E_STATE_INIT_RXQ: case FORE200E_STATE_INIT_RXQ:
fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.status); fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.status);
fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.rpd); fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.rpd);
/* fall through */
case FORE200E_STATE_INIT_TXQ: case FORE200E_STATE_INIT_TXQ:
fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.status); fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.status);
fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.tpd); fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.tpd);
/* fall through */
case FORE200E_STATE_INIT_CMDQ: case FORE200E_STATE_INIT_CMDQ:
fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_cmdq.status); fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_cmdq.status);
/* fall through */
case FORE200E_STATE_INITIALIZE: case FORE200E_STATE_INITIALIZE:
/* nothing to do for that state */ /* nothing to do for that state */
@ -390,6 +397,7 @@ fore200e_shutdown(struct fore200e* fore200e)
case FORE200E_STATE_MAP: case FORE200E_STATE_MAP:
fore200e->bus->unmap(fore200e); fore200e->bus->unmap(fore200e);
/* fall through */
case FORE200E_STATE_CONFIGURE: case FORE200E_STATE_CONFIGURE:
/* nothing to do for that state */ /* nothing to do for that state */

View File

@ -2803,7 +2803,7 @@ out:
return err; return err;
out_free_irq: out_free_irq:
free_irq(dev->irq, dev); free_irq(irq, dev);
out_free: out_free:
kfree(dev); kfree(dev);
out_release: out_release:

View File

@ -306,11 +306,9 @@ static int idt77105_start(struct atm_dev *dev)
if (start_timer) { if (start_timer) {
start_timer = 0; start_timer = 0;
setup_timer(&stats_timer, idt77105_stats_timer_func, 0UL);
stats_timer.expires = jiffies+IDT77105_STATS_TIMER_PERIOD; stats_timer.expires = jiffies+IDT77105_STATS_TIMER_PERIOD;
add_timer(&stats_timer); add_timer(&stats_timer);
setup_timer(&restart_timer, idt77105_restart_timer_func, 0UL);
restart_timer.expires = jiffies+IDT77105_RESTART_TIMER_PERIOD; restart_timer.expires = jiffies+IDT77105_RESTART_TIMER_PERIOD;
add_timer(&restart_timer); add_timer(&restart_timer);
} }

View File

@ -2073,21 +2073,19 @@ idt77252_rate_logindex(struct idt77252_dev *card, int pcr)
} }
static void static void
idt77252_est_timer(unsigned long data) idt77252_est_timer(struct timer_list *t)
{ {
struct vc_map *vc = (struct vc_map *)data; struct rate_estimator *est = from_timer(est, t, timer);
struct vc_map *vc = est->vc;
struct idt77252_dev *card = vc->card; struct idt77252_dev *card = vc->card;
struct rate_estimator *est;
unsigned long flags; unsigned long flags;
u32 rate, cps; u32 rate, cps;
u64 ncells; u64 ncells;
u8 lacr; u8 lacr;
spin_lock_irqsave(&vc->lock, flags); spin_lock_irqsave(&vc->lock, flags);
est = vc->estimator; if (!vc->estimator)
if (!est)
goto out; goto out;
ncells = est->cells; ncells = est->cells;
rate = ((u32)(ncells - est->last_cells)) << (7 - est->interval); rate = ((u32)(ncells - est->last_cells)) << (7 - est->interval);
@ -2126,10 +2124,11 @@ idt77252_init_est(struct vc_map *vc, int pcr)
est->maxcps = pcr < 0 ? -pcr : pcr; est->maxcps = pcr < 0 ? -pcr : pcr;
est->cps = est->maxcps; est->cps = est->maxcps;
est->avcps = est->cps << 5; est->avcps = est->cps << 5;
est->vc = vc;
est->interval = 2; /* XXX: make this configurable */ est->interval = 2; /* XXX: make this configurable */
est->ewma_log = 2; /* XXX: make this configurable */ est->ewma_log = 2; /* XXX: make this configurable */
setup_timer(&est->timer, idt77252_est_timer, (unsigned long)vc); timer_setup(&est->timer, idt77252_est_timer, 0);
mod_timer(&est->timer, jiffies + ((HZ / 4) << est->interval)); mod_timer(&est->timer, jiffies + ((HZ / 4) << est->interval));
return est; return est;
@ -2209,16 +2208,20 @@ static int
idt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc, idt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc,
struct atm_vcc *vcc, struct atm_qos *qos) struct atm_vcc *vcc, struct atm_qos *qos)
{ {
struct rate_estimator *est = NULL;
unsigned long flags; unsigned long flags;
int tcr; int tcr;
spin_lock_irqsave(&vc->lock, flags); spin_lock_irqsave(&vc->lock, flags);
if (vc->estimator) { if (vc->estimator) {
del_timer(&vc->estimator->timer); est = vc->estimator;
kfree(vc->estimator);
vc->estimator = NULL; vc->estimator = NULL;
} }
spin_unlock_irqrestore(&vc->lock, flags); spin_unlock_irqrestore(&vc->lock, flags);
if (est) {
del_timer_sync(&est->timer);
kfree(est);
}
tcr = atm_pcr_goal(&qos->txtp); tcr = atm_pcr_goal(&qos->txtp);
if (tcr == 0) if (tcr == 0)

View File

@ -184,6 +184,8 @@ struct aal1 {
unsigned char sequence; unsigned char sequence;
}; };
struct vc_map;
struct rate_estimator { struct rate_estimator {
struct timer_list timer; struct timer_list timer;
unsigned int interval; unsigned int interval;
@ -193,6 +195,7 @@ struct rate_estimator {
long avcps; long avcps;
u32 cps; u32 cps;
u32 maxcps; u32 maxcps;
struct vc_map *vc;
}; };
struct vc_map { struct vc_map {

View File

@ -880,7 +880,7 @@ static void ia_phy_write(struct iadev_priv *iadev,
static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev) static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
{ {
static const struct ia_reg suni_ds3_init [] = { static const struct ia_reg suni_ds3_init[] = {
{ SUNI_DS3_FRM_INTR_ENBL, 0x17 }, { SUNI_DS3_FRM_INTR_ENBL, 0x17 },
{ SUNI_DS3_FRM_CFG, 0x01 }, { SUNI_DS3_FRM_CFG, 0x01 },
{ SUNI_DS3_TRAN_CFG, 0x01 }, { SUNI_DS3_TRAN_CFG, 0x01 },
@ -898,7 +898,7 @@ static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev) static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
{ {
static const struct ia_reg suni_e3_init [] = { static const struct ia_reg suni_e3_init[] = {
{ SUNI_E3_FRM_FRAM_OPTIONS, 0x04 }, { SUNI_E3_FRM_FRAM_OPTIONS, 0x04 },
{ SUNI_E3_FRM_MAINT_OPTIONS, 0x20 }, { SUNI_E3_FRM_MAINT_OPTIONS, 0x20 },
{ SUNI_E3_FRM_FRAM_INTR_ENBL, 0x1d }, { SUNI_E3_FRM_FRAM_INTR_ENBL, 0x1d },
@ -918,7 +918,7 @@ static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
static void ia_suni_pm7345_init(struct iadev_priv *iadev) static void ia_suni_pm7345_init(struct iadev_priv *iadev)
{ {
static const struct ia_reg suni_init [] = { static const struct ia_reg suni_init[] = {
/* Enable RSOP loss of signal interrupt. */ /* Enable RSOP loss of signal interrupt. */
{ SUNI_INTR_ENBL, 0x28 }, { SUNI_INTR_ENBL, 0x28 },
/* Clear error counters. */ /* Clear error counters. */

View File

@ -53,7 +53,7 @@ static DEFINE_SPINLOCK(sunis_lock);
if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX); if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX);
static void suni_hz(unsigned long from_timer) static void suni_hz(struct timer_list *timer)
{ {
struct suni_priv *walk; struct suni_priv *walk;
struct atm_dev *dev; struct atm_dev *dev;
@ -85,7 +85,7 @@ static void suni_hz(unsigned long from_timer)
((GET(TACP_TCC) & 0xff) << 8) | ((GET(TACP_TCC) & 0xff) << 8) |
((GET(TACP_TCCM) & 7) << 16)); ((GET(TACP_TCCM) & 7) << 16));
} }
if (from_timer) mod_timer(&poll_timer,jiffies+HZ); if (timer) mod_timer(&poll_timer,jiffies+HZ);
} }
@ -322,13 +322,11 @@ static int suni_start(struct atm_dev *dev)
printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type, printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type,
dev->number); dev->number);
PRIV(dev)->loop_mode = ATM_LM_NONE; PRIV(dev)->loop_mode = ATM_LM_NONE;
suni_hz(0); /* clear SUNI counters */ suni_hz(NULL); /* clear SUNI counters */
(void) fetch_stats(dev,NULL,1); /* clear kernel counters */ (void) fetch_stats(dev,NULL,1); /* clear kernel counters */
if (first) { if (first) {
init_timer(&poll_timer); timer_setup(&poll_timer, suni_hz, 0);
poll_timer.expires = jiffies+HZ; poll_timer.expires = jiffies+HZ;
poll_timer.function = suni_hz;
poll_timer.data = 1;
#if 0 #if 0
printk(KERN_DEBUG "[u] p=0x%lx,n=0x%lx\n",(unsigned long) poll_timer.list.prev, printk(KERN_DEBUG "[u] p=0x%lx,n=0x%lx\n",(unsigned long) poll_timer.list.prev,
(unsigned long) poll_timer.list.next); (unsigned long) poll_timer.list.next);

View File

@ -11,14 +11,15 @@ menuconfig BCMA
Bus driver for Broadcom specific Advanced Microcontroller Bus Bus driver for Broadcom specific Advanced Microcontroller Bus
Architecture. Architecture.
if BCMA
# Support for Block-I/O. SELECT this from the driver that needs it. # Support for Block-I/O. SELECT this from the driver that needs it.
config BCMA_BLOCKIO config BCMA_BLOCKIO
bool bool
depends on BCMA
config BCMA_HOST_PCI_POSSIBLE config BCMA_HOST_PCI_POSSIBLE
bool bool
depends on BCMA && PCI = y depends on PCI = y
default y default y
config BCMA_HOST_PCI config BCMA_HOST_PCI
@ -29,7 +30,6 @@ config BCMA_HOST_PCI
config BCMA_HOST_SOC config BCMA_HOST_SOC
bool "Support for BCMA in a SoC" bool "Support for BCMA in a SoC"
depends on BCMA
help help
Host interface for a Broadcom AIX bus directly mapped into Host interface for a Broadcom AIX bus directly mapped into
the memory. This only works with the Broadcom SoCs from the the memory. This only works with the Broadcom SoCs from the
@ -39,7 +39,7 @@ config BCMA_HOST_SOC
config BCMA_DRIVER_PCI config BCMA_DRIVER_PCI
bool "BCMA Broadcom PCI core driver" bool "BCMA Broadcom PCI core driver"
depends on BCMA && PCI depends on PCI
default y default y
help help
BCMA bus may have many versions of PCIe core. This driver BCMA bus may have many versions of PCIe core. This driver
@ -55,13 +55,13 @@ config BCMA_DRIVER_PCI
config BCMA_DRIVER_PCI_HOSTMODE config BCMA_DRIVER_PCI_HOSTMODE
bool "Driver for PCI core working in hostmode" bool "Driver for PCI core working in hostmode"
depends on BCMA && MIPS && BCMA_DRIVER_PCI depends on MIPS && BCMA_DRIVER_PCI
help help
PCI core hostmode operation (external PCI bus). PCI core hostmode operation (external PCI bus).
config BCMA_DRIVER_MIPS config BCMA_DRIVER_MIPS
bool "BCMA Broadcom MIPS core driver" bool "BCMA Broadcom MIPS core driver"
depends on BCMA && MIPS depends on MIPS
help help
Driver for the Broadcom MIPS core attached to Broadcom specific Driver for the Broadcom MIPS core attached to Broadcom specific
Advanced Microcontroller Bus. Advanced Microcontroller Bus.
@ -92,7 +92,6 @@ config BCMA_NFLASH
config BCMA_DRIVER_GMAC_CMN config BCMA_DRIVER_GMAC_CMN
bool "BCMA Broadcom GBIT MAC COMMON core driver" bool "BCMA Broadcom GBIT MAC COMMON core driver"
depends on BCMA
help help
Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom
specific Advanced Microcontroller Bus. specific Advanced Microcontroller Bus.
@ -101,7 +100,7 @@ config BCMA_DRIVER_GMAC_CMN
config BCMA_DRIVER_GPIO config BCMA_DRIVER_GPIO
bool "BCMA GPIO driver" bool "BCMA GPIO driver"
depends on BCMA && GPIOLIB depends on GPIOLIB
select GPIOLIB_IRQCHIP if BCMA_HOST_SOC select GPIOLIB_IRQCHIP if BCMA_HOST_SOC
help help
Driver to provide access to the GPIO pins of the bcma bus. Driver to provide access to the GPIO pins of the bcma bus.
@ -110,8 +109,9 @@ config BCMA_DRIVER_GPIO
config BCMA_DEBUG config BCMA_DEBUG
bool "BCMA debugging" bool "BCMA debugging"
depends on BCMA
help help
This turns on additional debugging messages. This turns on additional debugging messages.
If unsure, say N If unsure, say N
endif # BCMA

View File

@ -184,10 +184,14 @@ static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
{ {
int i; int i;
static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id); char interrupts[20];
for (i = 0; i <= 6; i++) char *ints = interrupts;
printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
printk("\n"); for (i = 0; i < ARRAY_SIZE(irq_name); i++)
ints += sprintf(ints, " %s%c",
irq_name[i], i == irq ? '*' : ' ');
bcma_debug(dev->bus, "core 0x%04x, irq:%s\n", dev->id.id, interrupts);
} }
static void bcma_core_mips_dump_irq(struct bcma_bus *bus) static void bcma_core_mips_dump_irq(struct bcma_bus *bus)

View File

@ -66,6 +66,7 @@ config BT_HCIBTSDIO
config BT_HCIUART config BT_HCIUART
tristate "HCI UART driver" tristate "HCI UART driver"
depends on SERIAL_DEV_BUS || !SERIAL_DEV_BUS
depends on TTY depends on TTY
help help
Bluetooth HCI UART driver. Bluetooth HCI UART driver.
@ -80,7 +81,6 @@ config BT_HCIUART
config BT_HCIUART_SERDEV config BT_HCIUART_SERDEV
bool bool
depends on SERIAL_DEV_BUS && BT_HCIUART depends on SERIAL_DEV_BUS && BT_HCIUART
depends on SERIAL_DEV_BUS=y || SERIAL_DEV_BUS=BT_HCIUART
default y default y
config BT_HCIUART_H4 config BT_HCIUART_H4
@ -170,6 +170,7 @@ config BT_HCIUART_BCM
bool "Broadcom protocol support" bool "Broadcom protocol support"
depends on BT_HCIUART depends on BT_HCIUART
depends on BT_HCIUART_SERDEV depends on BT_HCIUART_SERDEV
depends on (!ACPI || SERIAL_DEV_CTRL_TTYPORT)
select BT_HCIUART_H4 select BT_HCIUART_H4
select BT_BCM select BT_BCM
help help

View File

@ -121,7 +121,7 @@ static void bcm203x_complete(struct urb *urb)
} }
data->state = BCM203X_LOAD_FIRMWARE; data->state = BCM203X_LOAD_FIRMWARE;
/* fall through */
case BCM203X_LOAD_FIRMWARE: case BCM203X_LOAD_FIRMWARE:
if (data->fw_sent == data->fw_size) { if (data->fw_sent == data->fw_size) {
usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),

View File

@ -156,9 +156,9 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
/* ======================== LED handling routines ======================== */ /* ======================== LED handling routines ======================== */
static void bluecard_activity_led_timeout(u_long arg) static void bluecard_activity_led_timeout(struct timer_list *t)
{ {
struct bluecard_info *info = (struct bluecard_info *)arg; struct bluecard_info *info = from_timer(info, t, timer);
unsigned int iobase = info->p_dev->resource[0]->start; unsigned int iobase = info->p_dev->resource[0]->start;
if (test_bit(CARD_ACTIVITY, &(info->hw_state))) { if (test_bit(CARD_ACTIVITY, &(info->hw_state))) {
@ -691,8 +691,7 @@ static int bluecard_open(struct bluecard_info *info)
spin_lock_init(&(info->lock)); spin_lock_init(&(info->lock));
setup_timer(&(info->timer), &bluecard_activity_led_timeout, timer_setup(&info->timer, bluecard_activity_led_timeout, 0);
(u_long)info);
skb_queue_head_init(&(info->txq)); skb_queue_head_init(&(info->txq));

View File

@ -117,7 +117,7 @@ static void bpa10x_rx_complete(struct urb *urb)
bpa10x_recv_pkts, bpa10x_recv_pkts,
ARRAY_SIZE(bpa10x_recv_pkts)); ARRAY_SIZE(bpa10x_recv_pkts));
if (IS_ERR(data->rx_skb[idx])) { if (IS_ERR(data->rx_skb[idx])) {
BT_ERR("%s corrupted event packet", hdev->name); bt_dev_err(hdev, "corrupted event packet");
hdev->stat.err_rx++; hdev->stat.err_rx++;
data->rx_skb[idx] = NULL; data->rx_skb[idx] = NULL;
} }
@ -127,8 +127,7 @@ static void bpa10x_rx_complete(struct urb *urb)
err = usb_submit_urb(urb, GFP_ATOMIC); err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p failed to resubmit (%d)", bt_dev_err(hdev, "urb %p failed to resubmit (%d)", urb, -err);
hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
} }
@ -164,8 +163,7 @@ static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
err = usb_submit_urb(urb, GFP_KERNEL); err = usb_submit_urb(urb, GFP_KERNEL);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)", bt_dev_err(hdev, "urb %p submission failed (%d)", urb, -err);
hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -205,8 +203,7 @@ static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
err = usb_submit_urb(urb, GFP_KERNEL); err = usb_submit_urb(urb, GFP_KERNEL);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)", bt_dev_err(hdev, "urb %p submission failed (%d)", urb, -err);
hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -272,7 +269,7 @@ static int bpa10x_setup(struct hci_dev *hdev)
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
hci_set_fw_info(hdev, "%s", skb->data + 1); hci_set_fw_info(hdev, "%s", skb->data + 1);
@ -348,7 +345,7 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
err = usb_submit_urb(urb, GFP_ATOMIC); err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p submission failed", hdev->name, urb); bt_dev_err(hdev, "urb %p submission failed", urb);
kfree(urb->setup_packet); kfree(urb->setup_packet);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }

View File

@ -355,7 +355,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
} else if ((stat & 0xff) != 0xff) { } else if ((stat & 0xff) != 0xff) {
if (stat & 0x0020) { if (stat & 0x0020) {
int status = bt3c_read(iobase, 0x7002) & 0x10; int status = bt3c_read(iobase, 0x7002) & 0x10;
BT_INFO("%s: Antenna %s", info->hdev->name, bt_dev_info(info->hdev, "Antenna %s",
status ? "out" : "in"); status ? "out" : "in");
} }
if (stat & 0x0001) if (stat & 0x0001)

View File

@ -45,13 +45,12 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
HCI_INIT_TIMEOUT); HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
int err = PTR_ERR(skb); int err = PTR_ERR(skb);
BT_ERR("%s: BCM: Reading device address failed (%d)", bt_dev_err(hdev, "BCM: Reading device address failed (%d)", err);
hdev->name, err);
return err; return err;
} }
if (skb->len != sizeof(*bda)) { if (skb->len != sizeof(*bda)) {
BT_ERR("%s: BCM: Device address length mismatch", hdev->name); bt_dev_err(hdev, "BCM: Device address length mismatch");
kfree_skb(skb); kfree_skb(skb);
return -EIO; return -EIO;
} }
@ -74,8 +73,8 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) || if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4324B3) || !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4330B1)) { !bacmp(&bda->bdaddr, BDADDR_BCM4330B1)) {
BT_INFO("%s: BCM: Using default device address (%pMR)", bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
hdev->name, &bda->bdaddr); &bda->bdaddr);
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
} }
@ -93,8 +92,7 @@ int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
err = PTR_ERR(skb); err = PTR_ERR(skb);
BT_ERR("%s: BCM: Change address command failed (%d)", bt_dev_err(hdev, "BCM: Change address command failed (%d)", err);
hdev->name, err);
return err; return err;
} }
kfree_skb(skb); kfree_skb(skb);
@ -116,8 +114,8 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
err = PTR_ERR(skb); err = PTR_ERR(skb);
BT_ERR("%s: BCM: Download Minidrv command failed (%d)", bt_dev_err(hdev, "BCM: Download Minidrv command failed (%d)",
hdev->name, err); err);
goto done; goto done;
} }
kfree_skb(skb); kfree_skb(skb);
@ -136,7 +134,7 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
fw_size -= sizeof(*cmd); fw_size -= sizeof(*cmd);
if (fw_size < cmd->plen) { if (fw_size < cmd->plen) {
BT_ERR("%s: BCM: Patch is corrupted", hdev->name); bt_dev_err(hdev, "BCM: Patch is corrupted");
err = -EINVAL; err = -EINVAL;
goto done; goto done;
} }
@ -151,8 +149,8 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
HCI_INIT_TIMEOUT); HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
err = PTR_ERR(skb); err = PTR_ERR(skb);
BT_ERR("%s: BCM: Patch command %04x failed (%d)", bt_dev_err(hdev, "BCM: Patch command %04x failed (%d)",
hdev->name, opcode, err); opcode, err);
goto done; goto done;
} }
kfree_skb(skb); kfree_skb(skb);
@ -173,7 +171,7 @@ static int btbcm_reset(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
int err = PTR_ERR(skb); int err = PTR_ERR(skb);
BT_ERR("%s: BCM: Reset failed (%d)", hdev->name, err); bt_dev_err(hdev, "BCM: Reset failed (%d)", err);
return err; return err;
} }
kfree_skb(skb); kfree_skb(skb);
@ -191,13 +189,13 @@ static struct sk_buff *btbcm_read_local_name(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL, skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL,
HCI_INIT_TIMEOUT); HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: BCM: Reading local name failed (%ld)", bt_dev_err(hdev, "BCM: Reading local name failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return skb; return skb;
} }
if (skb->len != sizeof(struct hci_rp_read_local_name)) { if (skb->len != sizeof(struct hci_rp_read_local_name)) {
BT_ERR("%s: BCM: Local name length mismatch", hdev->name); bt_dev_err(hdev, "BCM: Local name length mismatch");
kfree_skb(skb); kfree_skb(skb);
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
@ -212,13 +210,13 @@ static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
HCI_INIT_TIMEOUT); HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: BCM: Reading local version info failed (%ld)", bt_dev_err(hdev, "BCM: Reading local version info failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return skb; return skb;
} }
if (skb->len != sizeof(struct hci_rp_read_local_version)) { if (skb->len != sizeof(struct hci_rp_read_local_version)) {
BT_ERR("%s: BCM: Local version length mismatch", hdev->name); bt_dev_err(hdev, "BCM: Local version length mismatch");
kfree_skb(skb); kfree_skb(skb);
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
@ -232,13 +230,13 @@ static struct sk_buff *btbcm_read_verbose_config(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, 0xfc79, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc79, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: BCM: Read verbose config info failed (%ld)", bt_dev_err(hdev, "BCM: Read verbose config info failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return skb; return skb;
} }
if (skb->len != 7) { if (skb->len != 7) {
BT_ERR("%s: BCM: Verbose config length mismatch", hdev->name); bt_dev_err(hdev, "BCM: Verbose config length mismatch");
kfree_skb(skb); kfree_skb(skb);
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
@ -252,14 +250,13 @@ static struct sk_buff *btbcm_read_controller_features(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, 0xfc6e, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc6e, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: BCM: Read controller features failed (%ld)", bt_dev_err(hdev, "BCM: Read controller features failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return skb; return skb;
} }
if (skb->len != 9) { if (skb->len != 9) {
BT_ERR("%s: BCM: Controller features length mismatch", bt_dev_err(hdev, "BCM: Controller features length mismatch");
hdev->name);
kfree_skb(skb); kfree_skb(skb);
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
@ -273,13 +270,13 @@ static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, 0xfc5a, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc5a, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: BCM: Read USB product info failed (%ld)", bt_dev_err(hdev, "BCM: Read USB product info failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return skb; return skb;
} }
if (skb->len != 5) { if (skb->len != 5) {
BT_ERR("%s: BCM: USB product length mismatch", hdev->name); bt_dev_err(hdev, "BCM: USB product length mismatch");
kfree_skb(skb); kfree_skb(skb);
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
@ -296,7 +293,7 @@ static int btbcm_read_info(struct hci_dev *hdev)
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); bt_dev_info(hdev, "BCM: chip id %u", skb->data[1]);
kfree_skb(skb); kfree_skb(skb);
/* Read Controller Features */ /* Read Controller Features */
@ -304,7 +301,7 @@ static int btbcm_read_info(struct hci_dev *hdev)
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]);
kfree_skb(skb); kfree_skb(skb);
/* Read Local Name */ /* Read Local Name */
@ -312,7 +309,7 @@ static int btbcm_read_info(struct hci_dev *hdev)
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
@ -327,6 +324,8 @@ static const struct {
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */ { 0x4406, "BCM4324B3" }, /* 002.004.006 */
{ 0x610c, "BCM4354" }, /* 003.001.012 */ { 0x610c, "BCM4354" }, /* 003.001.012 */
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */ { 0x2209, "BCM43430A1" }, /* 001.002.009 */
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
{ } { }
}; };
@ -361,6 +360,7 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len)
switch ((rev & 0xf000) >> 12) { switch ((rev & 0xf000) >> 12) {
case 0: case 0:
case 1: case 1:
case 2:
case 3: case 3:
for (i = 0; bcm_uart_subver_table[i].name; i++) { for (i = 0; bcm_uart_subver_table[i].name; i++) {
if (subver == bcm_uart_subver_table[i].subver) { if (subver == bcm_uart_subver_table[i].subver) {
@ -375,9 +375,9 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len)
return 0; return 0;
} }
BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u",
hw_name ? : "BCM", (subver & 0xe000) >> 13, hw_name ? : "BCM", (subver & 0xe000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
return 0; return 0;
} }
@ -405,9 +405,9 @@ int btbcm_finalize(struct hci_dev *hdev)
subver = le16_to_cpu(ver->lmp_subver); subver = le16_to_cpu(ver->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
BT_INFO("%s: BCM (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, bt_dev_info(hdev, "BCM (%3.3u.%3.3u.%3.3u) build %4.4u",
(subver & 0xe000) >> 13, (subver & 0x1f00) >> 8, (subver & 0xe000) >> 13, (subver & 0x1f00) >> 8,
(subver & 0x00ff), rev & 0x0fff); (subver & 0x00ff), rev & 0x0fff);
btbcm_check_bdaddr(hdev); btbcm_check_bdaddr(hdev);
@ -502,13 +502,13 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
return 0; return 0;
} }
BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u",
hw_name ? : "BCM", (subver & 0xe000) >> 13, hw_name ? : "BCM", (subver & 0xe000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
err = request_firmware(&fw, fw_name, &hdev->dev); err = request_firmware(&fw, fw_name, &hdev->dev);
if (err < 0) { if (err < 0) {
BT_INFO("%s: BCM: Patch %s not found", hdev->name, fw_name); bt_dev_info(hdev, "BCM: Patch %s not found", fw_name);
goto done; goto done;
} }
@ -531,16 +531,16 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
subver = le16_to_cpu(ver->lmp_subver); subver = le16_to_cpu(ver->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u",
hw_name ? : "BCM", (subver & 0xe000) >> 13, hw_name ? : "BCM", (subver & 0xe000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
/* Read Local Name */ /* Read Local Name */
skb = btbcm_read_local_name(hdev); skb = btbcm_read_local_name(hdev);
if (IS_ERR(skb)) if (IS_ERR(skb))
return PTR_ERR(skb); return PTR_ERR(skb);
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
kfree_skb(skb); kfree_skb(skb);
done: done:
@ -565,31 +565,31 @@ int btbcm_setup_apple(struct hci_dev *hdev)
/* Read Verbose Config Version Info */ /* Read Verbose Config Version Info */
skb = btbcm_read_verbose_config(hdev); skb = btbcm_read_verbose_config(hdev);
if (!IS_ERR(skb)) { if (!IS_ERR(skb)) {
BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, bt_dev_info(hdev, "BCM: chip id %u build %4.4u",
skb->data[1], get_unaligned_le16(skb->data + 5)); skb->data[1], get_unaligned_le16(skb->data + 5));
kfree_skb(skb); kfree_skb(skb);
} }
/* Read USB Product Info */ /* Read USB Product Info */
skb = btbcm_read_usb_product(hdev); skb = btbcm_read_usb_product(hdev);
if (!IS_ERR(skb)) { if (!IS_ERR(skb)) {
BT_INFO("%s: BCM: product %4.4x:%4.4x", hdev->name, bt_dev_info(hdev, "BCM: product %4.4x:%4.4x",
get_unaligned_le16(skb->data + 1), get_unaligned_le16(skb->data + 1),
get_unaligned_le16(skb->data + 3)); get_unaligned_le16(skb->data + 3));
kfree_skb(skb); kfree_skb(skb);
} }
/* Read Controller Features */ /* Read Controller Features */
skb = btbcm_read_controller_features(hdev); skb = btbcm_read_controller_features(hdev);
if (!IS_ERR(skb)) { if (!IS_ERR(skb)) {
BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]);
kfree_skb(skb); kfree_skb(skb);
} }
/* Read Local Name */ /* Read Local Name */
skb = btbcm_read_local_name(hdev); skb = btbcm_read_local_name(hdev);
if (!IS_ERR(skb)) { if (!IS_ERR(skb)) {
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
kfree_skb(skb); kfree_skb(skb);
} }

View File

@ -43,13 +43,13 @@ int btintel_check_bdaddr(struct hci_dev *hdev)
HCI_INIT_TIMEOUT); HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
int err = PTR_ERR(skb); int err = PTR_ERR(skb);
BT_ERR("%s: Reading Intel device address failed (%d)", bt_dev_err(hdev, "Reading Intel device address failed (%d)",
hdev->name, err); err);
return err; return err;
} }
if (skb->len != sizeof(*bda)) { if (skb->len != sizeof(*bda)) {
BT_ERR("%s: Intel device address length mismatch", hdev->name); bt_dev_err(hdev, "Intel device address length mismatch");
kfree_skb(skb); kfree_skb(skb);
return -EIO; return -EIO;
} }
@ -62,8 +62,8 @@ int btintel_check_bdaddr(struct hci_dev *hdev)
* and that in turn can cause problems with Bluetooth operation. * and that in turn can cause problems with Bluetooth operation.
*/ */
if (!bacmp(&bda->bdaddr, BDADDR_INTEL)) { if (!bacmp(&bda->bdaddr, BDADDR_INTEL)) {
BT_ERR("%s: Found Intel default device address (%pMR)", bt_dev_err(hdev, "Found Intel default device address (%pMR)",
hdev->name, &bda->bdaddr); &bda->bdaddr);
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
} }
@ -123,8 +123,8 @@ int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
err = PTR_ERR(skb); err = PTR_ERR(skb);
BT_ERR("%s: Changing Intel device address failed (%d)", bt_dev_err(hdev, "Changing Intel device address failed (%d)",
hdev->name, err); err);
return err; return err;
} }
kfree_skb(skb); kfree_skb(skb);
@ -154,8 +154,8 @@ int btintel_set_diag(struct hci_dev *hdev, bool enable)
err = PTR_ERR(skb); err = PTR_ERR(skb);
if (err == -ENODATA) if (err == -ENODATA)
goto done; goto done;
BT_ERR("%s: Changing Intel diagnostic mode failed (%d)", bt_dev_err(hdev, "Changing Intel diagnostic mode failed (%d)",
hdev->name, err); err);
return err; return err;
} }
kfree_skb(skb); kfree_skb(skb);
@ -189,30 +189,30 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
struct sk_buff *skb; struct sk_buff *skb;
u8 type = 0x00; u8 type = 0x00;
BT_ERR("%s: Hardware error 0x%2.2x", hdev->name, code); bt_dev_err(hdev, "Hardware error 0x%2.2x", code);
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: Reset after hardware error failed (%ld)", bt_dev_err(hdev, "Reset after hardware error failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return; return;
} }
kfree_skb(skb); kfree_skb(skb);
skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: Retrieving Intel exception info failed (%ld)", bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return; return;
} }
if (skb->len != 13) { if (skb->len != 13) {
BT_ERR("%s: Exception info size mismatch", hdev->name); bt_dev_err(hdev, "Exception info size mismatch");
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
BT_ERR("%s: Exception info %s", hdev->name, (char *)(skb->data + 1)); bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1));
kfree_skb(skb); kfree_skb(skb);
} }
@ -233,9 +233,10 @@ void btintel_version_info(struct hci_dev *hdev, struct intel_version *ver)
return; return;
} }
BT_INFO("%s: %s revision %u.%u build %u week %u %u", hdev->name, bt_dev_info(hdev, "%s revision %u.%u build %u week %u %u",
variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f, variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f,
ver->fw_build_num, ver->fw_build_ww, 2000 + ver->fw_build_yy); ver->fw_build_num, ver->fw_build_ww,
2000 + ver->fw_build_yy);
} }
EXPORT_SYMBOL_GPL(btintel_version_info); EXPORT_SYMBOL_GPL(btintel_version_info);
@ -321,8 +322,7 @@ int btintel_set_event_mask(struct hci_dev *hdev, bool debug)
skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
err = PTR_ERR(skb); err = PTR_ERR(skb);
BT_ERR("%s: Setting Intel event mask failed (%d)", bt_dev_err(hdev, "Setting Intel event mask failed (%d)", err);
hdev->name, err);
return err; return err;
} }
kfree_skb(skb); kfree_skb(skb);

View File

@ -64,7 +64,7 @@ static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
struct btmrvl_sdio_card *card = priv; struct btmrvl_sdio_card *card = priv;
struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg; struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg;
pr_info("%s: wake by bt", __func__); pr_info("%s: wake by bt\n", __func__);
cfg->wake_by_bt = true; cfg->wake_by_bt = true;
disable_irq_nosync(irq); disable_irq_nosync(irq);
@ -87,7 +87,7 @@ static int btmrvl_sdio_probe_of(struct device *dev,
if (!dev->of_node || if (!dev->of_node ||
!of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) { !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) {
pr_err("sdio platform data not available"); pr_err("sdio platform data not available\n");
return -1; return -1;
} }
@ -99,7 +99,7 @@ static int btmrvl_sdio_probe_of(struct device *dev,
if (cfg && card->plt_of_node) { if (cfg && card->plt_of_node) {
cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0); cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0);
if (!cfg->irq_bt) { if (!cfg->irq_bt) {
dev_err(dev, "fail to parse irq_bt from device tree"); dev_err(dev, "fail to parse irq_bt from device tree\n");
cfg->irq_bt = -1; cfg->irq_bt = -1;
} else { } else {
ret = devm_request_irq(dev, cfg->irq_bt, ret = devm_request_irq(dev, cfg->irq_bt,

View File

@ -287,7 +287,7 @@ static int rome_download_firmware(struct hci_dev *hdev,
const struct firmware *fw; const struct firmware *fw;
int ret; int ret;
BT_INFO("%s: ROME Downloading %s", hdev->name, config->fwname); bt_dev_info(hdev, "ROME Downloading %s", config->fwname);
ret = request_firmware(&fw, config->fwname, &hdev->dev); ret = request_firmware(&fw, config->fwname, &hdev->dev);
if (ret) { if (ret) {
@ -351,7 +351,7 @@ int qca_uart_setup_rome(struct hci_dev *hdev, uint8_t baudrate)
return err; return err;
} }
BT_INFO("%s: ROME controller version 0x%08x", hdev->name, rome_ver); bt_dev_info(hdev, "ROME controller version 0x%08x", rome_ver);
/* Download rampatch file */ /* Download rampatch file */
config.type = TLV_TYPE_PATCH; config.type = TLV_TYPE_PATCH;
@ -380,7 +380,7 @@ int qca_uart_setup_rome(struct hci_dev *hdev, uint8_t baudrate)
return err; return err;
} }
BT_INFO("%s: ROME setup on UART is completed", hdev->name); bt_dev_info(hdev, "ROME setup on UART is completed");
return 0; return 0;
} }

View File

@ -15,6 +15,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/rpmsg.h> #include <linux/rpmsg.h>
#include <linux/of.h>
#include <linux/soc/qcom/wcnss_ctrl.h> #include <linux/soc/qcom/wcnss_ctrl.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -26,6 +28,7 @@
struct btqcomsmd { struct btqcomsmd {
struct hci_dev *hdev; struct hci_dev *hdev;
bdaddr_t bdaddr;
struct rpmsg_endpoint *acl_channel; struct rpmsg_endpoint *acl_channel;
struct rpmsg_endpoint *cmd_channel; struct rpmsg_endpoint *cmd_channel;
}; };
@ -100,6 +103,38 @@ static int btqcomsmd_close(struct hci_dev *hdev)
return 0; return 0;
} }
static int btqcomsmd_setup(struct hci_dev *hdev)
{
struct btqcomsmd *btq = hci_get_drvdata(hdev);
struct sk_buff *skb;
int err;
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
kfree_skb(skb);
/* Devices do not have persistent storage for BD address. If no
* BD address has been retrieved during probe, mark the device
* as having an invalid BD address.
*/
if (!bacmp(&btq->bdaddr, BDADDR_ANY)) {
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
return 0;
}
/* When setting a configured BD address fails, mark the device
* as having an invalid BD address.
*/
err = qca_set_bdaddr_rome(hdev, &btq->bdaddr);
if (err) {
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
return 0;
}
return 0;
}
static int btqcomsmd_probe(struct platform_device *pdev) static int btqcomsmd_probe(struct platform_device *pdev)
{ {
struct btqcomsmd *btq; struct btqcomsmd *btq;
@ -123,6 +158,15 @@ static int btqcomsmd_probe(struct platform_device *pdev)
if (IS_ERR(btq->cmd_channel)) if (IS_ERR(btq->cmd_channel))
return PTR_ERR(btq->cmd_channel); return PTR_ERR(btq->cmd_channel);
/* The local-bd-address property is usually injected by the
* bootloader which has access to the allocated BD address.
*/
if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address",
(u8 *)&btq->bdaddr, sizeof(bdaddr_t))) {
dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree",
&btq->bdaddr);
}
hdev = hci_alloc_dev(); hdev = hci_alloc_dev();
if (!hdev) if (!hdev)
return -ENOMEM; return -ENOMEM;
@ -135,6 +179,7 @@ static int btqcomsmd_probe(struct platform_device *pdev)
hdev->open = btqcomsmd_open; hdev->open = btqcomsmd_open;
hdev->close = btqcomsmd_close; hdev->close = btqcomsmd_close;
hdev->send = btqcomsmd_send; hdev->send = btqcomsmd_send;
hdev->setup = btqcomsmd_setup;
hdev->set_bdaddr = qca_set_bdaddr_rome; hdev->set_bdaddr = qca_set_bdaddr_rome;
ret = hci_register_dev(hdev); ret = hci_register_dev(hdev);

View File

@ -55,8 +55,8 @@ static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
} }
rom_version = (struct rtl_rom_version_evt *)skb->data; rom_version = (struct rtl_rom_version_evt *)skb->data;
BT_INFO("%s: rom_version status=%x version=%x", bt_dev_info(hdev, "rom_version status=%x version=%x",
hdev->name, rom_version->status, rom_version->version); rom_version->status, rom_version->version);
*version = rom_version->version; *version = rom_version->version;
@ -273,7 +273,7 @@ static int rtl_load_config(struct hci_dev *hdev, const char *name, u8 **buff)
const struct firmware *fw; const struct firmware *fw;
int ret; int ret;
BT_INFO("%s: rtl: loading %s", hdev->name, name); bt_dev_info(hdev, "rtl: loading %s", name);
ret = request_firmware(&fw, name, &hdev->dev); ret = request_firmware(&fw, name, &hdev->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -292,7 +292,7 @@ static int btrtl_setup_rtl8723a(struct hci_dev *hdev)
const struct firmware *fw; const struct firmware *fw;
int ret; int ret;
BT_INFO("%s: rtl: loading rtl_bt/rtl8723a_fw.bin", hdev->name); bt_dev_info(hdev, "rtl: loading rtl_bt/rtl8723a_fw.bin");
ret = request_firmware(&fw, "rtl_bt/rtl8723a_fw.bin", &hdev->dev); ret = request_firmware(&fw, "rtl_bt/rtl8723a_fw.bin", &hdev->dev);
if (ret < 0) { if (ret < 0) {
BT_ERR("%s: Failed to load rtl_bt/rtl8723a_fw.bin", hdev->name); BT_ERR("%s: Failed to load rtl_bt/rtl8723a_fw.bin", hdev->name);
@ -363,7 +363,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
} else } else
cfg_sz = 0; cfg_sz = 0;
BT_INFO("%s: rtl: loading %s", hdev->name, fw_name); bt_dev_info(hdev, "rtl: loading %s", fw_name);
ret = request_firmware(&fw, fw_name, &hdev->dev); ret = request_firmware(&fw, fw_name, &hdev->dev);
if (ret < 0) { if (ret < 0) {
BT_ERR("%s: Failed to load %s", hdev->name, fw_name); BT_ERR("%s: Failed to load %s", hdev->name, fw_name);
@ -390,7 +390,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
fw_data = tbuff; fw_data = tbuff;
} }
BT_INFO("cfg_sz %d, total size %d", cfg_sz, ret); bt_dev_info(hdev, "cfg_sz %d, total size %d", cfg_sz, ret);
ret = rtl_download_firmware(hdev, fw_data, ret); ret = rtl_download_firmware(hdev, fw_data, ret);
@ -436,9 +436,10 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
return -PTR_ERR(skb); return -PTR_ERR(skb);
resp = (struct hci_rp_read_local_version *)skb->data; resp = (struct hci_rp_read_local_version *)skb->data;
BT_INFO("%s: rtl: examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x " bt_dev_info(hdev, "rtl: examining hci_ver=%02x hci_rev=%04x "
"lmp_subver=%04x", hdev->name, resp->hci_ver, resp->hci_rev, "lmp_ver=%02x lmp_subver=%04x",
resp->lmp_ver, resp->lmp_subver); resp->hci_ver, resp->hci_rev,
resp->lmp_ver, resp->lmp_subver);
lmp_subver = le16_to_cpu(resp->lmp_subver); lmp_subver = le16_to_cpu(resp->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
@ -466,7 +467,7 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
return btrtl_setup_rtl8723b(hdev, lmp_subver, return btrtl_setup_rtl8723b(hdev, lmp_subver,
"rtl_bt/rtl8822b_fw.bin"); "rtl_bt/rtl8822b_fw.bin");
default: default:
BT_INFO("rtl: assuming no firmware upload needed."); bt_dev_info(hdev, "rtl: assuming no firmware upload needed");
return 0; return 0;
} }
} }

View File

@ -66,7 +66,6 @@ static struct usb_driver btusb_driver;
#define BTUSB_BCM2045 0x40000 #define BTUSB_BCM2045 0x40000
#define BTUSB_IFNUM_2 0x80000 #define BTUSB_IFNUM_2 0x80000
#define BTUSB_CW6622 0x100000 #define BTUSB_CW6622 0x100000
#define BTUSB_BCM_NO_PRODID 0x200000
static const struct usb_device_id btusb_table[] = { static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
@ -171,10 +170,6 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM }, .driver_info = BTUSB_BCM_PATCHRAM },
/* Broadcom devices with missing product id */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0000, 0x0000, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM | BTUSB_BCM_NO_PRODID },
/* Intel Bluetooth USB Bootloader (RAM module) */ /* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a), { USB_DEVICE(0x8087, 0x0a5a),
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
@ -272,6 +267,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0xe301), .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(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME },
@ -401,6 +397,7 @@ struct btusb_data {
struct usb_interface *intf; struct usb_interface *intf;
struct usb_interface *isoc; struct usb_interface *isoc;
struct usb_interface *diag; struct usb_interface *diag;
unsigned isoc_ifnum;
unsigned long flags; unsigned long flags;
@ -647,7 +644,7 @@ static void btusb_intr_complete(struct urb *urb)
if (btusb_recv_intr(data, urb->transfer_buffer, if (btusb_recv_intr(data, urb->transfer_buffer,
urb->actual_length) < 0) { urb->actual_length) < 0) {
BT_ERR("%s corrupted event packet", hdev->name); bt_dev_err(hdev, "corrupted event packet");
hdev->stat.err_rx++; hdev->stat.err_rx++;
} }
} else if (urb->status == -ENOENT) { } else if (urb->status == -ENOENT) {
@ -667,8 +664,8 @@ static void btusb_intr_complete(struct urb *urb)
* -ENODEV: device got disconnected * -ENODEV: device got disconnected
*/ */
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p failed to resubmit (%d)", bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
} }
@ -710,8 +707,8 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
err = usb_submit_urb(urb, mem_flags); err = usb_submit_urb(urb, mem_flags);
if (err < 0) { if (err < 0) {
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)", bt_dev_err(hdev, "urb %p submission failed (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -737,7 +734,7 @@ static void btusb_bulk_complete(struct urb *urb)
if (data->recv_bulk(data, urb->transfer_buffer, if (data->recv_bulk(data, urb->transfer_buffer,
urb->actual_length) < 0) { urb->actual_length) < 0) {
BT_ERR("%s corrupted ACL packet", hdev->name); bt_dev_err(hdev, "corrupted ACL packet");
hdev->stat.err_rx++; hdev->stat.err_rx++;
} }
} else if (urb->status == -ENOENT) { } else if (urb->status == -ENOENT) {
@ -757,8 +754,8 @@ static void btusb_bulk_complete(struct urb *urb)
* -ENODEV: device got disconnected * -ENODEV: device got disconnected
*/ */
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p failed to resubmit (%d)", bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
} }
@ -799,8 +796,8 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
err = usb_submit_urb(urb, mem_flags); err = usb_submit_urb(urb, mem_flags);
if (err < 0) { if (err < 0) {
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)", bt_dev_err(hdev, "urb %p submission failed (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -833,7 +830,7 @@ static void btusb_isoc_complete(struct urb *urb)
if (btusb_recv_isoc(data, urb->transfer_buffer + offset, if (btusb_recv_isoc(data, urb->transfer_buffer + offset,
length) < 0) { length) < 0) {
BT_ERR("%s corrupted SCO packet", hdev->name); bt_dev_err(hdev, "corrupted SCO packet");
hdev->stat.err_rx++; hdev->stat.err_rx++;
} }
} }
@ -853,8 +850,8 @@ static void btusb_isoc_complete(struct urb *urb)
* -ENODEV: device got disconnected * -ENODEV: device got disconnected
*/ */
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p failed to resubmit (%d)", bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
} }
@ -921,8 +918,8 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
err = usb_submit_urb(urb, mem_flags); err = usb_submit_urb(urb, mem_flags);
if (err < 0) { if (err < 0) {
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)", bt_dev_err(hdev, "urb %p submission failed (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -966,8 +963,8 @@ static void btusb_diag_complete(struct urb *urb)
* -ENODEV: device got disconnected * -ENODEV: device got disconnected
*/ */
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p failed to resubmit (%d)", bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
} }
@ -1008,8 +1005,8 @@ static int btusb_submit_diag_urb(struct hci_dev *hdev, gfp_t mem_flags)
err = usb_submit_urb(urb, mem_flags); err = usb_submit_urb(urb, mem_flags);
if (err < 0) { if (err < 0) {
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)", bt_dev_err(hdev, "urb %p submission failed (%d)",
hdev->name, urb, -err); urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -1270,8 +1267,8 @@ static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
err = usb_submit_urb(urb, GFP_KERNEL); err = usb_submit_urb(urb, GFP_KERNEL);
if (err < 0) { if (err < 0) {
if (err != -EPERM && err != -ENODEV) if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)", bt_dev_err(hdev, "urb %p submission failed (%d)",
hdev->name, urb, -err); urb, -err);
kfree(urb->setup_packet); kfree(urb->setup_packet);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} else { } else {
@ -1364,9 +1361,9 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
if (!data->isoc) if (!data->isoc)
return -ENODEV; return -ENODEV;
err = usb_set_interface(data->udev, 1, altsetting); err = usb_set_interface(data->udev, data->isoc_ifnum, altsetting);
if (err < 0) { if (err < 0) {
BT_ERR("%s setting interface failed (%d)", hdev->name, -err); bt_dev_err(hdev, "setting interface failed (%d)", -err);
return err; return err;
} }
@ -1390,7 +1387,7 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
} }
if (!data->isoc_tx_ep || !data->isoc_rx_ep) { if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
BT_ERR("%s invalid SCO descriptors", hdev->name); bt_dev_err(hdev, "invalid SCO descriptors");
return -ENODEV; return -ENODEV;
} }
@ -1485,7 +1482,7 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) if (IS_ERR(skb))
BT_ERR("BCM92035 command failed (%ld)", -PTR_ERR(skb)); bt_dev_err(hdev, "BCM92035 command failed (%ld)", PTR_ERR(skb));
else else
kfree_skb(skb); kfree_skb(skb);
@ -1503,12 +1500,12 @@ static int btusb_setup_csr(struct hci_dev *hdev)
HCI_INIT_TIMEOUT); HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
int err = PTR_ERR(skb); int err = PTR_ERR(skb);
BT_ERR("%s: CSR: Local version failed (%d)", hdev->name, err); bt_dev_err(hdev, "CSR: Local version failed (%d)", err);
return err; return err;
} }
if (skb->len != sizeof(struct hci_rp_read_local_version)) { if (skb->len != sizeof(struct hci_rp_read_local_version)) {
BT_ERR("%s: CSR: Local version length mismatch", hdev->name); bt_dev_err(hdev, "CSR: Local version length mismatch");
kfree_skb(skb); kfree_skb(skb);
return -EIO; return -EIO;
} }
@ -1570,7 +1567,7 @@ static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
} }
} }
BT_INFO("%s: Intel Bluetooth firmware file: %s", hdev->name, fwname); bt_dev_info(hdev, "Intel Bluetooth firmware file: %s", fwname);
return fw; return fw;
} }
@ -1726,18 +1723,18 @@ static int btusb_setup_intel(struct hci_dev *hdev)
if (err) if (err)
return err; return err;
BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x", bt_dev_info(hdev, "read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x",
hdev->name, ver.hw_platform, ver.hw_variant, ver.hw_revision, ver.hw_platform, ver.hw_variant, ver.hw_revision,
ver.fw_variant, ver.fw_revision, ver.fw_build_num, ver.fw_variant, ver.fw_revision, ver.fw_build_num,
ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num); ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num);
/* fw_patch_num indicates the version of patch the device currently /* fw_patch_num indicates the version of patch the device currently
* have. If there is no patch data in the device, it is always 0x00. * have. If there is no patch data in the device, it is always 0x00.
* So, if it is other than 0x00, no need to patch the device again. * So, if it is other than 0x00, no need to patch the device again.
*/ */
if (ver.fw_patch_num) { if (ver.fw_patch_num) {
BT_INFO("%s: Intel device is already patched. patch num: %02x", bt_dev_info(hdev, "Intel device is already patched. "
hdev->name, ver.fw_patch_num); "patch num: %02x", ver.fw_patch_num);
goto complete; goto complete;
} }
@ -1805,8 +1802,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
if (err) if (err)
return err; return err;
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated", bt_dev_info(hdev, "Intel firmware patch completed and activated");
hdev->name);
goto complete; goto complete;
@ -1816,7 +1812,7 @@ exit_mfg_disable:
if (err) if (err)
return err; return err;
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); bt_dev_info(hdev, "Intel firmware patch completed");
goto complete; goto complete;
@ -1830,8 +1826,7 @@ exit_mfg_deactivate:
if (err) if (err)
return err; return err;
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated", bt_dev_info(hdev, "Intel firmware patch completed and deactivated");
hdev->name);
complete: complete:
/* Set the event mask for Intel specific vendor events. This enables /* Set the event mask for Intel specific vendor events. This enables
@ -2112,24 +2107,24 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
params = (struct intel_boot_params *)skb->data; params = (struct intel_boot_params *)skb->data;
BT_INFO("%s: Device revision is %u", hdev->name, bt_dev_info(hdev, "Device revision is %u",
le16_to_cpu(params->dev_revid)); le16_to_cpu(params->dev_revid));
BT_INFO("%s: Secure boot is %s", hdev->name, bt_dev_info(hdev, "Secure boot is %s",
params->secure_boot ? "enabled" : "disabled"); params->secure_boot ? "enabled" : "disabled");
BT_INFO("%s: OTP lock is %s", hdev->name, bt_dev_info(hdev, "OTP lock is %s",
params->otp_lock ? "enabled" : "disabled"); params->otp_lock ? "enabled" : "disabled");
BT_INFO("%s: API lock is %s", hdev->name, bt_dev_info(hdev, "API lock is %s",
params->api_lock ? "enabled" : "disabled"); params->api_lock ? "enabled" : "disabled");
BT_INFO("%s: Debug lock is %s", hdev->name, bt_dev_info(hdev, "Debug lock is %s",
params->debug_lock ? "enabled" : "disabled"); params->debug_lock ? "enabled" : "disabled");
BT_INFO("%s: Minimum firmware build %u week %u %u", hdev->name, bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
params->min_fw_build_nn, params->min_fw_build_cw, params->min_fw_build_nn, params->min_fw_build_cw,
2000 + params->min_fw_build_yy); 2000 + params->min_fw_build_yy);
/* It is required that every single firmware fragment is acknowledged /* It is required that every single firmware fragment is acknowledged
* with a command complete event. If the boot parameters indicate * with a command complete event. If the boot parameters indicate
@ -2146,24 +2141,49 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* also be no valid address for the operational firmware. * also be no valid address for the operational firmware.
*/ */
if (!bacmp(&params->otp_bdaddr, BDADDR_ANY)) { if (!bacmp(&params->otp_bdaddr, BDADDR_ANY)) {
BT_INFO("%s: No device address configured", hdev->name); bt_dev_info(hdev, "No device address configured");
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
} }
/* With this Intel bootloader only the hardware variant and device /* With this Intel bootloader only the hardware variant and device
* revision information are used to select the right firmware. * revision information are used to select the right firmware for SfP
* and WsP.
* *
* The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi. * The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
* *
* Currently the supported hardware variants are: * Currently the supported hardware variants are:
* 11 (0x0b) for iBT3.0 (LnP/SfP) * 11 (0x0b) for iBT3.0 (LnP/SfP)
* 12 (0x0c) for iBT3.5 (WsP) * 12 (0x0c) for iBT3.5 (WsP)
*
* For ThP/JfP and for future SKU's, the FW name varies based on HW
* variant, HW revision and FW revision, as these are dependent on CNVi
* and RF Combination.
*
* 17 (0x11) for iBT3.5 (JfP) * 17 (0x11) for iBT3.5 (JfP)
* 18 (0x12) for iBT3.5 (ThP) * 18 (0x12) for iBT3.5 (ThP)
*
* The firmware file name for these will be
* ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
*
*/ */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi", switch (ver.hw_variant) {
le16_to_cpu(ver.hw_variant), case 0x0b: /* SfP */
le16_to_cpu(params->dev_revid)); case 0x0c: /* WsP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
le16_to_cpu(ver.hw_variant),
le16_to_cpu(params->dev_revid));
break;
case 0x11: /* JfP */
case 0x12: /* ThP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
le16_to_cpu(ver.hw_variant),
le16_to_cpu(ver.hw_revision),
le16_to_cpu(ver.fw_revision));
break;
default:
BT_ERR("%s: Unsupported Intel firmware naming", hdev->name);
return -EINVAL;
}
err = request_firmware(&fw, fwname, &hdev->dev); err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) { if (err < 0) {
@ -2173,14 +2193,29 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
return err; return err;
} }
BT_INFO("%s: Found device firmware: %s", hdev->name, fwname); bt_dev_info(hdev, "Found device firmware: %s", fwname);
/* Save the DDC file name for later use to apply once the firmware /* Save the DDC file name for later use to apply once the firmware
* downloading is done. * downloading is done.
*/ */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc", switch (ver.hw_variant) {
le16_to_cpu(ver.hw_variant), case 0x0b: /* SfP */
le16_to_cpu(params->dev_revid)); case 0x0c: /* WsP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
le16_to_cpu(ver.hw_variant),
le16_to_cpu(params->dev_revid));
break;
case 0x11: /* JfP */
case 0x12: /* ThP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
le16_to_cpu(ver.hw_variant),
le16_to_cpu(ver.hw_revision),
le16_to_cpu(ver.fw_revision));
break;
default:
BT_ERR("%s: Unsupported Intel firmware naming", hdev->name);
return -EINVAL;
}
kfree_skb(skb); kfree_skb(skb);
@ -2254,7 +2289,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
BT_INFO("%s: Waiting for firmware download to complete", hdev->name); bt_dev_info(hdev, "Waiting for firmware download to complete");
/* Before switching the device into operational mode and with that /* Before switching the device into operational mode and with that
* booting the loaded firmware, wait for the bootloader notification * booting the loaded firmware, wait for the bootloader notification
@ -2291,7 +2326,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
delta = ktime_sub(rettime, calltime); delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10; duration = (unsigned long long) ktime_to_ns(delta) >> 10;
BT_INFO("%s: Firmware loaded in %llu usecs", hdev->name, duration); bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
done: done:
release_firmware(fw); release_firmware(fw);
@ -2317,7 +2352,7 @@ done:
* 1 second. However if that happens, then just fail the setup * 1 second. However if that happens, then just fail the setup
* since something went wrong. * since something went wrong.
*/ */
BT_INFO("%s: Waiting for device to boot", hdev->name); bt_dev_info(hdev, "Waiting for device to boot");
err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING, err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING,
TASK_INTERRUPTIBLE, TASK_INTERRUPTIBLE,
@ -2337,7 +2372,7 @@ done:
delta = ktime_sub(rettime, calltime); delta = ktime_sub(rettime, calltime);
duration = (unsigned long long) ktime_to_ns(delta) >> 10; duration = (unsigned long long) ktime_to_ns(delta) >> 10;
BT_INFO("%s: Device booted in %llu usecs", hdev->name, duration); bt_dev_info(hdev, "Device booted in %llu usecs", duration);
clear_bit(BTUSB_BOOTLOADER, &data->flags); clear_bit(BTUSB_BOOTLOADER, &data->flags);
@ -2440,8 +2475,8 @@ static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
ret = PTR_ERR(skb); ret = PTR_ERR(skb);
BT_ERR("%s: changing Marvell device address failed (%ld)", bt_dev_err(hdev, "changing Marvell device address failed (%ld)",
hdev->name, ret); ret);
return ret; return ret;
} }
kfree_skb(skb); kfree_skb(skb);
@ -2465,8 +2500,7 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
ret = PTR_ERR(skb); ret = PTR_ERR(skb);
BT_ERR("%s: Change address command failed (%ld)", bt_dev_err(hdev, "Change address command failed (%ld)", ret);
hdev->name, ret);
return ret; return ret;
} }
kfree_skb(skb); kfree_skb(skb);
@ -2532,7 +2566,7 @@ static int btusb_qca_send_vendor_req(struct hci_dev *hdev, u8 request,
err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN, err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
0, 0, buf, size, USB_CTRL_SET_TIMEOUT); 0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
if (err < 0) { if (err < 0) {
BT_ERR("%s: Failed to access otp area (%d)", hdev->name, err); bt_dev_err(hdev, "Failed to access otp area (%d)", err);
goto done; goto done;
} }
@ -2572,7 +2606,7 @@ static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
err = usb_control_msg(udev, pipe, QCA_DFU_DOWNLOAD, USB_TYPE_VENDOR, err = usb_control_msg(udev, pipe, QCA_DFU_DOWNLOAD, USB_TYPE_VENDOR,
0, 0, buf, size, USB_CTRL_SET_TIMEOUT); 0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
if (err < 0) { if (err < 0) {
BT_ERR("%s: Failed to send headers (%d)", hdev->name, err); bt_dev_err(hdev, "Failed to send headers (%d)", err);
goto done; goto done;
} }
@ -2588,13 +2622,13 @@ static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
err = usb_bulk_msg(udev, pipe, buf, size, &len, err = usb_bulk_msg(udev, pipe, buf, size, &len,
QCA_DFU_TIMEOUT); QCA_DFU_TIMEOUT);
if (err < 0) { if (err < 0) {
BT_ERR("%s: Failed to send body at %zd of %zd (%d)", bt_dev_err(hdev, "Failed to send body at %zd of %zd (%d)",
hdev->name, sent, firmware->size, err); sent, firmware->size, err);
break; break;
} }
if (size != len) { if (size != len) {
BT_ERR("%s: Failed to get bulk buffer", hdev->name); bt_dev_err(hdev, "Failed to get bulk buffer");
err = -EILSEQ; err = -EILSEQ;
break; break;
} }
@ -2626,24 +2660,23 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
err = request_firmware(&fw, fwname, &hdev->dev); err = request_firmware(&fw, fwname, &hdev->dev);
if (err) { if (err) {
BT_ERR("%s: failed to request rampatch file: %s (%d)", bt_dev_err(hdev, "failed to request rampatch file: %s (%d)",
hdev->name, fwname, err); fwname, err);
return err; return err;
} }
BT_INFO("%s: using rampatch file: %s", hdev->name, fwname); bt_dev_info(hdev, "using rampatch file: %s", fwname);
rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset); rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
rver_rom = le16_to_cpu(rver->rom_version); rver_rom = le16_to_cpu(rver->rom_version);
rver_patch = le16_to_cpu(rver->patch_version); rver_patch = le16_to_cpu(rver->patch_version);
BT_INFO("%s: QCA: patch rome 0x%x build 0x%x, firmware rome 0x%x " bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
"build 0x%x", hdev->name, rver_rom, rver_patch, ver_rom, "firmware rome 0x%x build 0x%x",
ver_patch); rver_rom, rver_patch, ver_rom, ver_patch);
if (rver_rom != ver_rom || rver_patch <= ver_patch) { if (rver_rom != ver_rom || rver_patch <= ver_patch) {
BT_ERR("%s: rampatch file version did not match with firmware", bt_dev_err(hdev, "rampatch file version did not match with firmware");
hdev->name);
err = -EINVAL; err = -EINVAL;
goto done; goto done;
} }
@ -2669,12 +2702,12 @@ static int btusb_setup_qca_load_nvm(struct hci_dev *hdev,
err = request_firmware(&fw, fwname, &hdev->dev); err = request_firmware(&fw, fwname, &hdev->dev);
if (err) { if (err) {
BT_ERR("%s: failed to request NVM file: %s (%d)", bt_dev_err(hdev, "failed to request NVM file: %s (%d)",
hdev->name, fwname, err); fwname, err);
return err; return err;
} }
BT_INFO("%s: using NVM file: %s", hdev->name, fwname); bt_dev_info(hdev, "using NVM file: %s", fwname);
err = btusb_setup_qca_download_fw(hdev, fw, info->nvm_hdr); err = btusb_setup_qca_download_fw(hdev, fw, info->nvm_hdr);
@ -2702,8 +2735,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
info = &qca_devices_table[i]; info = &qca_devices_table[i];
} }
if (!info) { if (!info) {
BT_ERR("%s: don't support firmware rome 0x%x", hdev->name, bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
ver_rom);
return -ENODEV; return -ENODEV;
} }
@ -2757,7 +2789,7 @@ static inline int __set_diag_interface(struct hci_dev *hdev)
} }
if (!data->diag_tx_ep || !data->diag_rx_ep) { if (!data->diag_tx_ep || !data->diag_rx_ep) {
BT_ERR("%s invalid diagnostic descriptors", hdev->name); bt_dev_err(hdev, "invalid diagnostic descriptors");
return -ENODEV; return -ENODEV;
} }
@ -2909,19 +2941,6 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info == BTUSB_IGNORE) if (id->driver_info == BTUSB_IGNORE)
return -ENODEV; return -ENODEV;
if (id->driver_info & BTUSB_BCM_NO_PRODID) {
struct usb_device *udev = interface_to_usbdev(intf);
/* For the broken Broadcom devices that show 0000:0000
* as USB vendor and product information, check that the
* manufacturer string identifies them as Broadcom based
* devices.
*/
if (!udev->manufacturer ||
strcmp(udev->manufacturer, "Broadcom Corp"))
return -ENODEV;
}
if (id->driver_info & BTUSB_ATH3012) { if (id->driver_info & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
@ -3124,6 +3143,7 @@ static int btusb_probe(struct usb_interface *intf,
} else { } else {
/* Interface orders are hardcoded in the specification */ /* Interface orders are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1); data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1);
data->isoc_ifnum = ifnum_base + 1;
} }
if (!reset) if (!reset)

View File

@ -50,6 +50,17 @@ struct ath_struct {
struct work_struct ctxtsw; struct work_struct ctxtsw;
}; };
#define OP_WRITE_TAG 0x01
#define INDEX_BDADDR 0x01
struct ath_vendor_cmd {
__u8 opcode;
__le16 index;
__u8 len;
__u8 data[251];
} __packed;
static int ath_wakeup_ar3k(struct tty_struct *tty) static int ath_wakeup_ar3k(struct tty_struct *tty)
{ {
int status = tty->driver->ops->tiocmget(tty); int status = tty->driver->ops->tiocmget(tty);
@ -144,30 +155,34 @@ static int ath_flush(struct hci_uart *hu)
return 0; return 0;
} }
static int ath_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) static int ath_vendor_cmd(struct hci_dev *hdev, uint8_t opcode, uint16_t index,
const void *data, size_t dlen)
{ {
struct sk_buff *skb; struct sk_buff *skb;
u8 buf[10]; struct ath_vendor_cmd cmd;
int err;
buf[0] = 0x01; if (dlen > sizeof(cmd.data))
buf[1] = 0x01; return -EINVAL;
buf[2] = 0x00;
buf[3] = sizeof(bdaddr_t);
memcpy(buf + 4, bdaddr, sizeof(bdaddr_t));
skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT); cmd.opcode = opcode;
if (IS_ERR(skb)) { cmd.index = cpu_to_le16(index);
err = PTR_ERR(skb); cmd.len = dlen;
BT_ERR("%s: Change address command failed (%d)", memcpy(cmd.data, data, dlen);
hdev->name, err);
return err; skb = __hci_cmd_sync(hdev, 0xfc0b, dlen + 4, &cmd, HCI_INIT_TIMEOUT);
} if (IS_ERR(skb))
return PTR_ERR(skb);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
static int ath_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
return ath_vendor_cmd(hdev, OP_WRITE_TAG, INDEX_BDADDR, bdaddr,
sizeof(*bdaddr));
}
static int ath_setup(struct hci_uart *hu) static int ath_setup(struct hci_uart *hu)
{ {
BT_DBG("hu %p", hu); BT_DBG("hu %p", hu);
@ -191,7 +206,7 @@ static int ath_recv(struct hci_uart *hu, const void *data, int count)
ath_recv_pkts, ARRAY_SIZE(ath_recv_pkts)); ath_recv_pkts, ARRAY_SIZE(ath_recv_pkts));
if (IS_ERR(ath->rx_skb)) { if (IS_ERR(ath->rx_skb)) {
int err = PTR_ERR(ath->rx_skb); int err = PTR_ERR(ath->rx_skb);
BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err); bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
ath->rx_skb = NULL; ath->rx_skb = NULL;
return err; return err;
} }

View File

@ -52,11 +52,13 @@
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */ #define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
/* platform device driver resources */ /* device driver resources */
struct bcm_device { struct bcm_device {
/* Must be the first member, hci_serdev.c expects this. */
struct hci_uart serdev_hu;
struct list_head list; struct list_head list;
struct platform_device *pdev; struct device *dev;
const char *name; const char *name;
struct gpio_desc *device_wakeup; struct gpio_desc *device_wakeup;
@ -68,7 +70,7 @@ struct bcm_device {
u32 init_speed; u32 init_speed;
u32 oper_speed; u32 oper_speed;
int irq; int irq;
u8 irq_polarity; bool irq_active_low;
#ifdef CONFIG_PM #ifdef CONFIG_PM
struct hci_uart *hu; struct hci_uart *hu;
@ -76,11 +78,6 @@ struct bcm_device {
#endif #endif
}; };
/* serdev driver resources */
struct bcm_serdev {
struct hci_uart hu;
};
/* generic bcm uart resources */ /* generic bcm uart resources */
struct bcm_data { struct bcm_data {
struct sk_buff *rx_skb; struct sk_buff *rx_skb;
@ -155,6 +152,12 @@ static bool bcm_device_exists(struct bcm_device *device)
{ {
struct list_head *p; struct list_head *p;
#ifdef CONFIG_PM
/* Devices using serdev always exist */
if (device && device->hu && device->hu->serdev)
return true;
#endif
list_for_each(p, &bcm_device_list) { list_for_each(p, &bcm_device_list) {
struct bcm_device *dev = list_entry(p, struct bcm_device, list); struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@ -188,9 +191,9 @@ static irqreturn_t bcm_host_wake(int irq, void *data)
bt_dev_dbg(bdev, "Host wake IRQ"); bt_dev_dbg(bdev, "Host wake IRQ");
pm_runtime_get(&bdev->pdev->dev); pm_runtime_get(bdev->dev);
pm_runtime_mark_last_busy(&bdev->pdev->dev); pm_runtime_mark_last_busy(bdev->dev);
pm_runtime_put_autosuspend(&bdev->pdev->dev); pm_runtime_put_autosuspend(bdev->dev);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -200,7 +203,6 @@ static int bcm_request_irq(struct bcm_data *bcm)
struct bcm_device *bdev = bcm->dev; struct bcm_device *bdev = bcm->dev;
int err; int err;
/* If this is not a platform device, do not enable PM functionalities */
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (!bcm_device_exists(bdev)) { if (!bcm_device_exists(bdev)) {
err = -ENODEV; err = -ENODEV;
@ -212,18 +214,20 @@ static int bcm_request_irq(struct bcm_data *bcm)
goto unlock; goto unlock;
} }
err = devm_request_irq(&bdev->pdev->dev, bdev->irq, bcm_host_wake, err = devm_request_irq(bdev->dev, bdev->irq, bcm_host_wake,
IRQF_TRIGGER_RISING, "host_wake", bdev); bdev->irq_active_low ? IRQF_TRIGGER_FALLING :
IRQF_TRIGGER_RISING,
"host_wake", bdev);
if (err) if (err)
goto unlock; goto unlock;
device_init_wakeup(&bdev->pdev->dev, true); device_init_wakeup(bdev->dev, true);
pm_runtime_set_autosuspend_delay(&bdev->pdev->dev, pm_runtime_set_autosuspend_delay(bdev->dev,
BCM_AUTOSUSPEND_DELAY); BCM_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(&bdev->pdev->dev); pm_runtime_use_autosuspend(bdev->dev);
pm_runtime_set_active(&bdev->pdev->dev); pm_runtime_set_active(bdev->dev);
pm_runtime_enable(&bdev->pdev->dev); pm_runtime_enable(bdev->dev);
unlock: unlock:
mutex_unlock(&bcm_device_lock); mutex_unlock(&bcm_device_lock);
@ -253,7 +257,7 @@ static int bcm_setup_sleep(struct hci_uart *hu)
struct sk_buff *skb; struct sk_buff *skb;
struct bcm_set_sleep_mode sleep_params = default_sleep_params; struct bcm_set_sleep_mode sleep_params = default_sleep_params;
sleep_params.host_wake_active = !bcm->dev->irq_polarity; sleep_params.host_wake_active = !bcm->dev->irq_active_low;
skb = __hci_cmd_sync(hu->hdev, 0xfc27, sizeof(sleep_params), skb = __hci_cmd_sync(hu->hdev, 0xfc27, sizeof(sleep_params),
&sleep_params, HCI_INIT_TIMEOUT); &sleep_params, HCI_INIT_TIMEOUT);
@ -311,18 +315,17 @@ static int bcm_open(struct hci_uart *hu)
hu->priv = bcm; hu->priv = bcm;
/* If this is a serdev defined device, then only use mutex_lock(&bcm_device_lock);
* serdev open primitive and skip the rest.
*/
if (hu->serdev) { if (hu->serdev) {
serdev_device_open(hu->serdev); serdev_device_open(hu->serdev);
bcm->dev = serdev_device_get_drvdata(hu->serdev);
goto out; goto out;
} }
if (!hu->tty->dev) if (!hu->tty->dev)
goto out; goto out;
mutex_lock(&bcm_device_lock);
list_for_each(p, &bcm_device_list) { list_for_each(p, &bcm_device_list) {
struct bcm_device *dev = list_entry(p, struct bcm_device, list); struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@ -330,50 +333,56 @@ static int bcm_open(struct hci_uart *hu)
* platform device (saved during device probe) and * platform device (saved during device probe) and
* parent of tty device used by hci_uart * parent of tty device used by hci_uart
*/ */
if (hu->tty->dev->parent == dev->pdev->dev.parent) { if (hu->tty->dev->parent == dev->dev->parent) {
bcm->dev = dev; bcm->dev = dev;
hu->init_speed = dev->init_speed;
hu->oper_speed = dev->oper_speed;
#ifdef CONFIG_PM #ifdef CONFIG_PM
dev->hu = hu; dev->hu = hu;
#endif #endif
bcm_gpio_set_power(bcm->dev, true);
break; break;
} }
} }
mutex_unlock(&bcm_device_lock);
out: out:
if (bcm->dev) {
hu->init_speed = bcm->dev->init_speed;
hu->oper_speed = bcm->dev->oper_speed;
bcm_gpio_set_power(bcm->dev, true);
}
mutex_unlock(&bcm_device_lock);
return 0; return 0;
} }
static int bcm_close(struct hci_uart *hu) static int bcm_close(struct hci_uart *hu)
{ {
struct bcm_data *bcm = hu->priv; struct bcm_data *bcm = hu->priv;
struct bcm_device *bdev = bcm->dev; struct bcm_device *bdev = NULL;
bt_dev_dbg(hu->hdev, "hu %p", hu); bt_dev_dbg(hu->hdev, "hu %p", hu);
/* If this is a serdev defined device, only use serdev
* close primitive and then continue as usual.
*/
if (hu->serdev)
serdev_device_close(hu->serdev);
/* Protect bcm->dev against removal of the device or driver */ /* Protect bcm->dev against removal of the device or driver */
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (bcm_device_exists(bdev)) {
if (hu->serdev) {
serdev_device_close(hu->serdev);
bdev = serdev_device_get_drvdata(hu->serdev);
} else if (bcm_device_exists(bcm->dev)) {
bdev = bcm->dev;
#ifdef CONFIG_PM
bdev->hu = NULL;
#endif
}
if (bdev) {
bcm_gpio_set_power(bdev, false); bcm_gpio_set_power(bdev, false);
#ifdef CONFIG_PM #ifdef CONFIG_PM
pm_runtime_disable(&bdev->pdev->dev); pm_runtime_disable(bdev->dev);
pm_runtime_set_suspended(&bdev->pdev->dev); pm_runtime_set_suspended(bdev->dev);
if (device_can_wakeup(&bdev->pdev->dev)) { if (device_can_wakeup(bdev->dev)) {
devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev); devm_free_irq(bdev->dev, bdev->irq, bdev);
device_init_wakeup(&bdev->pdev->dev, false); device_init_wakeup(bdev->dev, false);
} }
bdev->hu = NULL;
#endif #endif
} }
mutex_unlock(&bcm_device_lock); mutex_unlock(&bcm_device_lock);
@ -504,9 +513,9 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
/* Delay auto-suspend when receiving completed packet */ /* Delay auto-suspend when receiving completed packet */
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
if (bcm->dev && bcm_device_exists(bcm->dev)) { if (bcm->dev && bcm_device_exists(bcm->dev)) {
pm_runtime_get(&bcm->dev->pdev->dev); pm_runtime_get(bcm->dev->dev);
pm_runtime_mark_last_busy(&bcm->dev->pdev->dev); pm_runtime_mark_last_busy(bcm->dev->dev);
pm_runtime_put_autosuspend(&bcm->dev->pdev->dev); pm_runtime_put_autosuspend(bcm->dev->dev);
} }
mutex_unlock(&bcm_device_lock); mutex_unlock(&bcm_device_lock);
} }
@ -537,15 +546,15 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
if (bcm_device_exists(bcm->dev)) { if (bcm_device_exists(bcm->dev)) {
bdev = bcm->dev; bdev = bcm->dev;
pm_runtime_get_sync(&bdev->pdev->dev); pm_runtime_get_sync(bdev->dev);
/* Shall be resumed here */ /* Shall be resumed here */
} }
skb = skb_dequeue(&bcm->txq); skb = skb_dequeue(&bcm->txq);
if (bdev) { if (bdev) {
pm_runtime_mark_last_busy(&bdev->pdev->dev); pm_runtime_mark_last_busy(bdev->dev);
pm_runtime_put_autosuspend(&bdev->pdev->dev); pm_runtime_put_autosuspend(bdev->dev);
} }
mutex_unlock(&bcm_device_lock); mutex_unlock(&bcm_device_lock);
@ -556,7 +565,7 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int bcm_suspend_device(struct device *dev) static int bcm_suspend_device(struct device *dev)
{ {
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev)); struct bcm_device *bdev = dev_get_drvdata(dev);
bt_dev_dbg(bdev, ""); bt_dev_dbg(bdev, "");
@ -579,7 +588,7 @@ static int bcm_suspend_device(struct device *dev)
static int bcm_resume_device(struct device *dev) static int bcm_resume_device(struct device *dev)
{ {
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev)); struct bcm_device *bdev = dev_get_drvdata(dev);
bt_dev_dbg(bdev, ""); bt_dev_dbg(bdev, "");
@ -601,16 +610,18 @@ static int bcm_resume_device(struct device *dev)
#endif #endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
/* Platform suspend callback */ /* suspend callback */
static int bcm_suspend(struct device *dev) static int bcm_suspend(struct device *dev)
{ {
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev)); struct bcm_device *bdev = dev_get_drvdata(dev);
int error; int error;
bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended); bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
/* bcm_suspend can be called at any time as long as platform device is /*
* bound, so it should use bcm_device_lock to protect access to hci_uart * When used with a device instantiated as platform_device, bcm_suspend
* can be called at any time as long as the platform device is bound,
* so it should use bcm_device_lock to protect access to hci_uart
* and device_wake-up GPIO. * and device_wake-up GPIO.
*/ */
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
@ -621,7 +632,7 @@ static int bcm_suspend(struct device *dev)
if (pm_runtime_active(dev)) if (pm_runtime_active(dev))
bcm_suspend_device(dev); bcm_suspend_device(dev);
if (device_may_wakeup(&bdev->pdev->dev)) { if (device_may_wakeup(dev)) {
error = enable_irq_wake(bdev->irq); error = enable_irq_wake(bdev->irq);
if (!error) if (!error)
bt_dev_dbg(bdev, "BCM irq: enabled"); bt_dev_dbg(bdev, "BCM irq: enabled");
@ -633,15 +644,17 @@ unlock:
return 0; return 0;
} }
/* Platform resume callback */ /* resume callback */
static int bcm_resume(struct device *dev) static int bcm_resume(struct device *dev)
{ {
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev)); struct bcm_device *bdev = dev_get_drvdata(dev);
bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended); bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
/* bcm_resume can be called at any time as long as platform device is /*
* bound, so it should use bcm_device_lock to protect access to hci_uart * When used with a device instantiated as platform_device, bcm_resume
* can be called at any time as long as platform device is bound,
* so it should use bcm_device_lock to protect access to hci_uart
* and device_wake-up GPIO. * and device_wake-up GPIO.
*/ */
mutex_lock(&bcm_device_lock); mutex_lock(&bcm_device_lock);
@ -649,7 +662,7 @@ static int bcm_resume(struct device *dev)
if (!bdev->hu) if (!bdev->hu)
goto unlock; goto unlock;
if (device_may_wakeup(&bdev->pdev->dev)) { if (device_may_wakeup(dev)) {
disable_irq_wake(bdev->irq); disable_irq_wake(bdev->irq);
bt_dev_dbg(bdev, "BCM irq: disabled"); bt_dev_dbg(bdev, "BCM irq: disabled");
} }
@ -690,10 +703,8 @@ static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = {
}; };
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static u8 acpi_active_low = ACPI_ACTIVE_LOW;
/* IRQ polarity of some chipsets are not defined correctly in ACPI table. */ /* IRQ polarity of some chipsets are not defined correctly in ACPI table. */
static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = { static const struct dmi_system_id bcm_active_low_irq_dmi_table[] = {
{ {
.ident = "Asus T100TA", .ident = "Asus T100TA",
.matches = { .matches = {
@ -701,7 +712,6 @@ static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
"ASUSTeK COMPUTER INC."), "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
}, },
.driver_data = &acpi_active_low,
}, },
{ {
.ident = "Asus T100CHI", .ident = "Asus T100CHI",
@ -710,7 +720,6 @@ static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
"ASUSTeK COMPUTER INC."), "ASUSTeK COMPUTER INC."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"),
}, },
.driver_data = &acpi_active_low,
}, },
{ /* Handle ThinkPad 8 tablets with BCM2E55 chipset ACPI ID */ { /* Handle ThinkPad 8 tablets with BCM2E55 chipset ACPI ID */
.ident = "Lenovo ThinkPad 8", .ident = "Lenovo ThinkPad 8",
@ -718,7 +727,13 @@ static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"), DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"),
}, },
.driver_data = &acpi_active_low, },
{
.ident = "MINIX Z83-4",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MINIX"),
DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
},
}, },
{ } { }
}; };
@ -733,13 +748,13 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
switch (ares->type) { switch (ares->type) {
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
irq = &ares->data.extended_irq; irq = &ares->data.extended_irq;
dev->irq_polarity = irq->polarity; dev->irq_active_low = irq->polarity == ACPI_ACTIVE_LOW;
break; break;
case ACPI_RESOURCE_TYPE_GPIO: case ACPI_RESOURCE_TYPE_GPIO:
gpio = &ares->data.gpio; gpio = &ares->data.gpio;
if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT) if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
dev->irq_polarity = gpio->polarity; dev->irq_active_low = gpio->polarity == ACPI_ACTIVE_LOW;
break; break;
case ACPI_RESOURCE_TYPE_SERIAL_BUS: case ACPI_RESOURCE_TYPE_SERIAL_BUS:
@ -754,36 +769,32 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
break; break;
} }
/* Always tell the ACPI core to skip this resource */ return 0;
return 1;
} }
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
static int bcm_platform_probe(struct bcm_device *dev) static int bcm_get_resources(struct bcm_device *dev)
{ {
struct platform_device *pdev = dev->pdev; dev->name = dev_name(dev->dev);
dev->name = dev_name(&pdev->dev); dev->clk = devm_clk_get(dev->dev, NULL);
dev->clk = devm_clk_get(&pdev->dev, NULL); dev->device_wakeup = devm_gpiod_get_optional(dev->dev,
dev->device_wakeup = devm_gpiod_get_optional(&pdev->dev,
"device-wakeup", "device-wakeup",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(dev->device_wakeup)) if (IS_ERR(dev->device_wakeup))
return PTR_ERR(dev->device_wakeup); return PTR_ERR(dev->device_wakeup);
dev->shutdown = devm_gpiod_get_optional(&pdev->dev, "shutdown", dev->shutdown = devm_gpiod_get_optional(dev->dev, "shutdown",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(dev->shutdown)) if (IS_ERR(dev->shutdown))
return PTR_ERR(dev->shutdown); return PTR_ERR(dev->shutdown);
/* IRQ can be declared in ACPI table as Interrupt or GpioInt */ /* IRQ can be declared in ACPI table as Interrupt or GpioInt */
dev->irq = platform_get_irq(pdev, 0);
if (dev->irq <= 0) { if (dev->irq <= 0) {
struct gpio_desc *gpio; struct gpio_desc *gpio;
gpio = devm_gpiod_get_optional(&pdev->dev, "host-wakeup", gpio = devm_gpiod_get_optional(dev->dev, "host-wakeup",
GPIOD_IN); GPIOD_IN);
if (IS_ERR(gpio)) if (IS_ERR(gpio))
return PTR_ERR(gpio); return PTR_ERR(gpio);
@ -791,54 +802,48 @@ static int bcm_platform_probe(struct bcm_device *dev)
dev->irq = gpiod_to_irq(gpio); dev->irq = gpiod_to_irq(gpio);
} }
dev_info(&pdev->dev, "BCM irq: %d\n", dev->irq); dev_info(dev->dev, "BCM irq: %d\n", dev->irq);
/* Make sure at-least one of the GPIO is defined and that
* a name is specified for this instance
*/
if ((!dev->device_wakeup && !dev->shutdown) || !dev->name) {
dev_err(&pdev->dev, "invalid platform data\n");
return -EINVAL;
}
return 0; return 0;
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static int bcm_acpi_probe(struct bcm_device *dev) static int bcm_acpi_probe(struct bcm_device *dev)
{ {
struct platform_device *pdev = dev->pdev;
LIST_HEAD(resources); LIST_HEAD(resources);
const struct dmi_system_id *dmi_id; const struct dmi_system_id *dmi_id;
const struct acpi_gpio_mapping *gpio_mapping = acpi_bcm_int_last_gpios; const struct acpi_gpio_mapping *gpio_mapping = acpi_bcm_int_last_gpios;
const struct acpi_device_id *id; const struct acpi_device_id *id;
struct resource_entry *entry;
int ret; int ret;
/* Retrieve GPIO data */ /* Retrieve GPIO data */
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); id = acpi_match_device(dev->dev->driver->acpi_match_table, dev->dev);
if (id) if (id)
gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data; gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data;
ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, gpio_mapping); ret = devm_acpi_dev_add_driver_gpios(dev->dev, gpio_mapping);
if (ret)
return ret;
ret = bcm_platform_probe(dev);
if (ret) if (ret)
return ret; return ret;
/* Retrieve UART ACPI info */ /* Retrieve UART ACPI info */
ret = acpi_dev_get_resources(ACPI_COMPANION(&dev->pdev->dev), ret = acpi_dev_get_resources(ACPI_COMPANION(dev->dev),
&resources, bcm_resource, dev); &resources, bcm_resource, dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
resource_list_for_each_entry(entry, &resources) {
if (resource_type(entry->res) == IORESOURCE_IRQ) {
dev->irq = entry->res->start;
break;
}
}
acpi_dev_free_resource_list(&resources); acpi_dev_free_resource_list(&resources);
dmi_id = dmi_first_match(bcm_wrong_irq_dmi_table); dmi_id = dmi_first_match(bcm_active_low_irq_dmi_table);
if (dmi_id) { if (dmi_id) {
bt_dev_warn(dev, "%s: Overwriting IRQ polarity to active low", dev_warn(dev->dev, "%s: Overwriting IRQ polarity to active low",
dmi_id->ident); dmi_id->ident);
dev->irq_polarity = *(u8 *)dmi_id->driver_data; dev->irq_active_low = true;
} }
return 0; return 0;
@ -850,6 +855,12 @@ static int bcm_acpi_probe(struct bcm_device *dev)
} }
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
static int bcm_of_probe(struct bcm_device *bdev)
{
device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed);
return 0;
}
static int bcm_probe(struct platform_device *pdev) static int bcm_probe(struct platform_device *pdev)
{ {
struct bcm_device *dev; struct bcm_device *dev;
@ -859,12 +870,16 @@ static int bcm_probe(struct platform_device *pdev)
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
dev->pdev = pdev; dev->dev = &pdev->dev;
dev->irq = platform_get_irq(pdev, 0);
if (has_acpi_companion(&pdev->dev)) if (has_acpi_companion(&pdev->dev)) {
ret = bcm_acpi_probe(dev); ret = bcm_acpi_probe(dev);
else if (ret)
ret = bcm_platform_probe(dev); return ret;
}
ret = bcm_get_resources(dev);
if (ret) if (ret)
return ret; return ret;
@ -926,14 +941,16 @@ static const struct acpi_device_id bcm_acpi_match[] = {
{ "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios },
{ "BCM2E7E", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
{ "BCM2E95", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, { "BCM2E95", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
{ "BCM2E96", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, { "BCM2E96", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
{ "BCM2EA4", (kernel_ulong_t)&acpi_bcm_int_first_gpios },
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, bcm_acpi_match); MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
#endif #endif
/* Platform suspend and resume callbacks */ /* suspend and resume callbacks */
static const struct dev_pm_ops bcm_pm_ops = { static const struct dev_pm_ops bcm_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(bcm_suspend, bcm_resume) SET_SYSTEM_SLEEP_PM_OPS(bcm_suspend, bcm_resume)
SET_RUNTIME_PM_OPS(bcm_suspend_device, bcm_resume_device, NULL) SET_RUNTIME_PM_OPS(bcm_suspend_device, bcm_resume_device, NULL)
@ -951,29 +968,41 @@ static struct platform_driver bcm_driver = {
static int bcm_serdev_probe(struct serdev_device *serdev) static int bcm_serdev_probe(struct serdev_device *serdev)
{ {
struct bcm_serdev *bcmdev; struct bcm_device *bcmdev;
u32 speed;
int err; int err;
bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL); bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL);
if (!bcmdev) if (!bcmdev)
return -ENOMEM; return -ENOMEM;
bcmdev->hu.serdev = serdev; bcmdev->dev = &serdev->dev;
#ifdef CONFIG_PM
bcmdev->hu = &bcmdev->serdev_hu;
#endif
bcmdev->serdev_hu.serdev = serdev;
serdev_device_set_drvdata(serdev, bcmdev); serdev_device_set_drvdata(serdev, bcmdev);
err = device_property_read_u32(&serdev->dev, "max-speed", &speed); if (has_acpi_companion(&serdev->dev))
if (!err) err = bcm_acpi_probe(bcmdev);
bcmdev->hu.oper_speed = speed; else
err = bcm_of_probe(bcmdev);
if (err)
return err;
return hci_uart_register_device(&bcmdev->hu, &bcm_proto); err = bcm_get_resources(bcmdev);
if (err)
return err;
bcm_gpio_set_power(bcmdev, false);
return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
} }
static void bcm_serdev_remove(struct serdev_device *serdev) static void bcm_serdev_remove(struct serdev_device *serdev)
{ {
struct bcm_serdev *bcmdev = serdev_device_get_drvdata(serdev); struct bcm_device *bcmdev = serdev_device_get_drvdata(serdev);
hci_uart_unregister_device(&bcmdev->hu); hci_uart_unregister_device(&bcmdev->serdev_hu);
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
@ -990,6 +1019,8 @@ static struct serdev_device_driver bcm_serdev_driver = {
.driver = { .driver = {
.name = "hci_uart_bcm", .name = "hci_uart_bcm",
.of_match_table = of_match_ptr(bcm_bluetooth_of_match), .of_match_table = of_match_ptr(bcm_bluetooth_of_match),
.acpi_match_table = ACPI_PTR(bcm_acpi_match),
.pm = &bcm_pm_ops,
}, },
}; };

View File

@ -65,6 +65,7 @@ struct bcsp_struct {
u8 rxseq_txack; /* rxseq == txack. */ u8 rxseq_txack; /* rxseq == txack. */
u8 rxack; /* Last packet sent by us that the peer ack'ed */ u8 rxack; /* Last packet sent by us that the peer ack'ed */
struct timer_list tbcsp; struct timer_list tbcsp;
struct hci_uart *hu;
enum { enum {
BCSP_W4_PKT_DELIMITER, BCSP_W4_PKT_DELIMITER,
@ -697,10 +698,10 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count)
} }
/* Arrange to retransmit all messages in the relq. */ /* Arrange to retransmit all messages in the relq. */
static void bcsp_timed_event(unsigned long arg) static void bcsp_timed_event(struct timer_list *t)
{ {
struct hci_uart *hu = (struct hci_uart *)arg; struct bcsp_struct *bcsp = from_timer(bcsp, t, tbcsp);
struct bcsp_struct *bcsp = hu->priv; struct hci_uart *hu = bcsp->hu;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags; unsigned long flags;
@ -729,11 +730,12 @@ static int bcsp_open(struct hci_uart *hu)
return -ENOMEM; return -ENOMEM;
hu->priv = bcsp; hu->priv = bcsp;
bcsp->hu = hu;
skb_queue_head_init(&bcsp->unack); skb_queue_head_init(&bcsp->unack);
skb_queue_head_init(&bcsp->rel); skb_queue_head_init(&bcsp->rel);
skb_queue_head_init(&bcsp->unrel); skb_queue_head_init(&bcsp->unrel);
setup_timer(&bcsp->tbcsp, bcsp_timed_event, (u_long)hu); timer_setup(&bcsp->tbcsp, bcsp_timed_event, 0);
bcsp->rx_state = BCSP_W4_PKT_DELIMITER; bcsp->rx_state = BCSP_W4_PKT_DELIMITER;

View File

@ -132,7 +132,7 @@ static int h4_recv(struct hci_uart *hu, const void *data, int count)
h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts)); h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
if (IS_ERR(h4->rx_skb)) { if (IS_ERR(h4->rx_skb)) {
int err = PTR_ERR(h4->rx_skb); int err = PTR_ERR(h4->rx_skb);
BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err); bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
h4->rx_skb = NULL; h4->rx_skb = NULL;
return err; return err;
} }

View File

@ -78,6 +78,7 @@ struct h5 {
int (*rx_func)(struct hci_uart *hu, u8 c); int (*rx_func)(struct hci_uart *hu, u8 c);
struct timer_list timer; /* Retransmission timer */ struct timer_list timer; /* Retransmission timer */
struct hci_uart *hu; /* Parent HCI UART */
u8 tx_seq; /* Next seq number to send */ u8 tx_seq; /* Next seq number to send */
u8 tx_ack; /* Next ack number to send */ u8 tx_ack; /* Next ack number to send */
@ -120,12 +121,12 @@ static u8 h5_cfg_field(struct h5 *h5)
return h5->tx_win & 0x07; return h5->tx_win & 0x07;
} }
static void h5_timed_event(unsigned long arg) static void h5_timed_event(struct timer_list *t)
{ {
const unsigned char sync_req[] = { 0x01, 0x7e }; const unsigned char sync_req[] = { 0x01, 0x7e };
unsigned char conf_req[3] = { 0x03, 0xfc }; unsigned char conf_req[3] = { 0x03, 0xfc };
struct hci_uart *hu = (struct hci_uart *)arg; struct h5 *h5 = from_timer(h5, t, timer);
struct h5 *h5 = hu->priv; struct hci_uart *hu = h5->hu;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags; unsigned long flags;
@ -197,6 +198,7 @@ static int h5_open(struct hci_uart *hu)
return -ENOMEM; return -ENOMEM;
hu->priv = h5; hu->priv = h5;
h5->hu = hu;
skb_queue_head_init(&h5->unack); skb_queue_head_init(&h5->unack);
skb_queue_head_init(&h5->rel); skb_queue_head_init(&h5->rel);
@ -204,7 +206,7 @@ static int h5_open(struct hci_uart *hu)
h5_reset_rx(h5); h5_reset_rx(h5);
setup_timer(&h5->timer, h5_timed_event, (unsigned long)hu); timer_setup(&h5->timer, h5_timed_event, 0);
h5->tx_win = H5_TX_WIN_MAX; h5->tx_win = H5_TX_WIN_MAX;

View File

@ -41,6 +41,7 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/serdev.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
@ -114,12 +115,12 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
struct sk_buff *skb = hu->tx_skb; struct sk_buff *skb = hu->tx_skb;
if (!skb) { if (!skb) {
read_lock(&hu->proto_lock); percpu_down_read(&hu->proto_lock);
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
skb = hu->proto->dequeue(hu); skb = hu->proto->dequeue(hu);
read_unlock(&hu->proto_lock); percpu_up_read(&hu->proto_lock);
} else { } else {
hu->tx_skb = NULL; hu->tx_skb = NULL;
} }
@ -129,7 +130,14 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
int hci_uart_tx_wakeup(struct hci_uart *hu) int hci_uart_tx_wakeup(struct hci_uart *hu)
{ {
read_lock(&hu->proto_lock); /* This may be called in an IRQ context, so we can't sleep. Therefore
* we try to acquire the lock only, and if that fails we assume the
* tty is being closed because that is the only time the write lock is
* acquired. If, however, at some point in the future the write lock
* is also acquired in other situations, then this must be revisited.
*/
if (!percpu_down_read_trylock(&hu->proto_lock))
return 0;
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
goto no_schedule; goto no_schedule;
@ -144,7 +152,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
schedule_work(&hu->write_work); schedule_work(&hu->write_work);
no_schedule: no_schedule:
read_unlock(&hu->proto_lock); percpu_up_read(&hu->proto_lock);
return 0; return 0;
} }
@ -246,12 +254,12 @@ static int hci_uart_flush(struct hci_dev *hdev)
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
tty_driver_flush_buffer(tty); tty_driver_flush_buffer(tty);
read_lock(&hu->proto_lock); percpu_down_read(&hu->proto_lock);
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
hu->proto->flush(hu); hu->proto->flush(hu);
read_unlock(&hu->proto_lock); percpu_up_read(&hu->proto_lock);
return 0; return 0;
} }
@ -274,15 +282,15 @@ 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), BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb),
skb->len); skb->len);
read_lock(&hu->proto_lock); percpu_down_read(&hu->proto_lock);
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
read_unlock(&hu->proto_lock); percpu_up_read(&hu->proto_lock);
return -EUNATCH; return -EUNATCH;
} }
hu->proto->enqueue(hu, skb); hu->proto->enqueue(hu, skb);
read_unlock(&hu->proto_lock); percpu_up_read(&hu->proto_lock);
hci_uart_tx_wakeup(hu); hci_uart_tx_wakeup(hu);
@ -298,6 +306,12 @@ void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
unsigned int set = 0; unsigned int set = 0;
unsigned int clear = 0; unsigned int clear = 0;
if (hu->serdev) {
serdev_device_set_flow_control(hu->serdev, !enable);
serdev_device_set_rts(hu->serdev, !enable);
return;
}
if (enable) { if (enable) {
/* Disable hardware flow control */ /* Disable hardware flow control */
ktermios = tty->termios; ktermios = tty->termios;
@ -479,7 +493,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->init_ready, hci_uart_init_work);
INIT_WORK(&hu->write_work, hci_uart_write_work); INIT_WORK(&hu->write_work, hci_uart_write_work);
rwlock_init(&hu->proto_lock); percpu_init_rwsem(&hu->proto_lock);
/* Flush any pending characters in the driver */ /* Flush any pending characters in the driver */
tty_driver_flush_buffer(tty); tty_driver_flush_buffer(tty);
@ -496,7 +510,6 @@ static void hci_uart_tty_close(struct tty_struct *tty)
{ {
struct hci_uart *hu = tty->disc_data; struct hci_uart *hu = tty->disc_data;
struct hci_dev *hdev; struct hci_dev *hdev;
unsigned long flags;
BT_DBG("tty %p", tty); BT_DBG("tty %p", tty);
@ -510,12 +523,12 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev) if (hdev)
hci_uart_close(hdev); hci_uart_close(hdev);
cancel_work_sync(&hu->write_work);
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) { if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
write_lock_irqsave(&hu->proto_lock, flags); percpu_down_write(&hu->proto_lock);
clear_bit(HCI_UART_PROTO_READY, &hu->flags); clear_bit(HCI_UART_PROTO_READY, &hu->flags);
write_unlock_irqrestore(&hu->proto_lock, flags); percpu_up_write(&hu->proto_lock);
cancel_work_sync(&hu->write_work);
if (hdev) { if (hdev) {
if (test_bit(HCI_UART_REGISTERED, &hu->flags)) if (test_bit(HCI_UART_REGISTERED, &hu->flags))
@ -575,10 +588,10 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
if (!hu || tty != hu->tty) if (!hu || tty != hu->tty)
return; return;
read_lock(&hu->proto_lock); percpu_down_read(&hu->proto_lock);
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
read_unlock(&hu->proto_lock); percpu_up_read(&hu->proto_lock);
return; return;
} }
@ -586,7 +599,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
* tty caller * tty caller
*/ */
hu->proto->recv(hu, data, count); hu->proto->recv(hu, data, count);
read_unlock(&hu->proto_lock); percpu_up_read(&hu->proto_lock);
if (hu->hdev) if (hu->hdev)
hu->hdev->stat.byte_rx += count; hu->hdev->stat.byte_rx += count;

View File

@ -242,7 +242,7 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu)
* perfectly safe to always send one. * perfectly safe to always send one.
*/ */
BT_DBG("dual wake-up-indication"); BT_DBG("dual wake-up-indication");
/* deliberate fall-through - do not add break */ /* fall through */
case HCILL_ASLEEP: case HCILL_ASLEEP:
/* acknowledge device wake up */ /* acknowledge device wake up */
if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) { if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) {

View File

@ -307,10 +307,10 @@ static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work)
serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu); serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
} }
static void hci_ibs_tx_idle_timeout(unsigned long arg) static void hci_ibs_tx_idle_timeout(struct timer_list *t)
{ {
struct hci_uart *hu = (struct hci_uart *)arg; struct qca_data *qca = from_timer(qca, t, tx_idle_timer);
struct qca_data *qca = hu->priv; struct hci_uart *hu = qca->hu;
unsigned long flags; unsigned long flags;
BT_DBG("hu %p idle timeout in %d state", hu, qca->tx_ibs_state); BT_DBG("hu %p idle timeout in %d state", hu, qca->tx_ibs_state);
@ -342,10 +342,10 @@ static void hci_ibs_tx_idle_timeout(unsigned long arg)
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
} }
static void hci_ibs_wake_retrans_timeout(unsigned long arg) static void hci_ibs_wake_retrans_timeout(struct timer_list *t)
{ {
struct hci_uart *hu = (struct hci_uart *)arg; struct qca_data *qca = from_timer(qca, t, wake_retrans_timer);
struct qca_data *qca = hu->priv; struct hci_uart *hu = qca->hu;
unsigned long flags, retrans_delay; unsigned long flags, retrans_delay;
bool retransmit = false; bool retransmit = false;
@ -438,11 +438,10 @@ static int qca_open(struct hci_uart *hu)
hu->priv = qca; hu->priv = qca;
setup_timer(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, timer_setup(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, 0);
(u_long)hu);
qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS; qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS;
setup_timer(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, (u_long)hu); timer_setup(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, 0);
qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS; qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS;
BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u", BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u",
@ -801,7 +800,7 @@ static int qca_recv(struct hci_uart *hu, const void *data, int count)
qca_recv_pkts, ARRAY_SIZE(qca_recv_pkts)); qca_recv_pkts, ARRAY_SIZE(qca_recv_pkts));
if (IS_ERR(qca->rx_skb)) { if (IS_ERR(qca->rx_skb)) {
int err = PTR_ERR(qca->rx_skb); int err = PTR_ERR(qca->rx_skb);
BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err); bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
qca->rx_skb = NULL; qca->rx_skb = NULL;
return err; return err;
} }
@ -864,7 +863,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
skb = bt_skb_alloc(sizeof(cmd), GFP_ATOMIC); skb = bt_skb_alloc(sizeof(cmd), GFP_ATOMIC);
if (!skb) { if (!skb) {
BT_ERR("Failed to allocate memory for baudrate packet"); bt_dev_err(hdev, "Failed to allocate baudrate packet");
return -ENOMEM; return -ENOMEM;
} }
@ -893,7 +892,7 @@ static int qca_setup(struct hci_uart *hu)
unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200; unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200;
int ret; int ret;
BT_INFO("%s: ROME setup", hdev->name); bt_dev_info(hdev, "ROME setup");
/* Patch downloading has to be done without IBS mode */ /* Patch downloading has to be done without IBS mode */
clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
@ -918,11 +917,11 @@ static int qca_setup(struct hci_uart *hu)
if (speed) { if (speed) {
qca_baudrate = qca_get_baudrate_value(speed); qca_baudrate = qca_get_baudrate_value(speed);
BT_INFO("%s: Set UART speed to %d", hdev->name, speed); bt_dev_info(hdev, "Set UART speed to %d", speed);
ret = qca_set_baudrate(hdev, qca_baudrate); ret = qca_set_baudrate(hdev, qca_baudrate);
if (ret) { if (ret) {
BT_ERR("%s: Failed to change the baud rate (%d)", bt_dev_err(hdev, "Failed to change the baud rate (%d)",
hdev->name, ret); ret);
return ret; return ret;
} }
hci_uart_set_baudrate(hu, speed); hci_uart_set_baudrate(hu, speed);

View File

@ -185,7 +185,7 @@ static int hci_uart_setup(struct hci_dev *hdev)
if (hu->proto->set_baudrate && speed) { if (hu->proto->set_baudrate && speed) {
err = hu->proto->set_baudrate(hu, speed); err = hu->proto->set_baudrate(hu, speed);
if (err) if (err)
BT_ERR("%s: failed to set baudrate", hdev->name); bt_dev_err(hdev, "Failed to set baudrate");
else else
serdev_device_set_baudrate(hu->serdev, speed); serdev_device_set_baudrate(hu->serdev, speed);
} }
@ -199,14 +199,13 @@ static int hci_uart_setup(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
HCI_INIT_TIMEOUT); HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
BT_ERR("%s: Reading local version information failed (%ld)", bt_dev_err(hdev, "Reading local version info failed (%ld)",
hdev->name, PTR_ERR(skb)); PTR_ERR(skb));
return 0; return 0;
} }
if (skb->len != sizeof(*ver)) { if (skb->len != sizeof(*ver)) {
BT_ERR("%s: Event length mismatch for version information", bt_dev_err(hdev, "Event length mismatch for version info");
hdev->name);
} }
kfree_skb(skb); kfree_skb(skb);

View File

@ -87,7 +87,7 @@ struct hci_uart {
struct work_struct write_work; struct work_struct write_work;
const struct hci_uart_proto *proto; const struct hci_uart_proto *proto;
rwlock_t proto_lock; /* Stop work for proto close */ struct percpu_rw_semaphore proto_lock; /* Stop work for proto close */
void *priv; void *priv;
struct sk_buff *tx_skb; struct sk_buff *tx_skb;

View File

@ -45,7 +45,7 @@ cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name,
return NULL; return NULL;
} }
atomic_set(&cbq->refcnt, 1); refcount_set(&cbq->refcnt, 1);
atomic_inc(&dev->refcnt); atomic_inc(&dev->refcnt);
cbq->pdev = dev; cbq->pdev = dev;
@ -58,7 +58,7 @@ cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name,
void cn_queue_release_callback(struct cn_callback_entry *cbq) void cn_queue_release_callback(struct cn_callback_entry *cbq)
{ {
if (!atomic_dec_and_test(&cbq->refcnt)) if (!refcount_dec_and_test(&cbq->refcnt))
return; return;
atomic_dec(&cbq->pdev->refcnt); atomic_dec(&cbq->pdev->refcnt);

View File

@ -157,7 +157,7 @@ static int cn_call_callback(struct sk_buff *skb)
spin_lock_bh(&dev->cbdev->queue_lock); spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) { list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&i->id.id, &msg->id)) { if (cn_cb_equal(&i->id.id, &msg->id)) {
atomic_inc(&i->refcnt); refcount_inc(&i->refcnt);
cbq = i; cbq = i;
break; break;
} }

View File

@ -2,6 +2,7 @@ config INFINIBAND_QEDR
tristate "QLogic RoCE driver" tristate "QLogic RoCE driver"
depends on 64BIT && QEDE depends on 64BIT && QEDE
select QED_LL2 select QED_LL2
select QED_OOO
select QED_RDMA select QED_RDMA
---help--- ---help---
This driver provides low-level InfiniBand over Ethernet This driver provides low-level InfiniBand over Ethernet

View File

@ -893,13 +893,17 @@ dev_stop:
void ipoib_pkey_dev_check_presence(struct net_device *dev) void ipoib_pkey_dev_check_presence(struct net_device *dev)
{ {
struct ipoib_dev_priv *priv = ipoib_priv(dev); struct ipoib_dev_priv *priv = ipoib_priv(dev);
struct rdma_netdev *rn = netdev_priv(dev);
if (!(priv->pkey & 0x7fff) || if (!(priv->pkey & 0x7fff) ||
ib_find_pkey(priv->ca, priv->port, priv->pkey, ib_find_pkey(priv->ca, priv->port, priv->pkey,
&priv->pkey_index)) &priv->pkey_index)) {
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
else } else {
if (rn->set_id)
rn->set_id(dev, priv->pkey_index);
set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
}
} }
void ipoib_ib_dev_up(struct net_device *dev) void ipoib_ib_dev_up(struct net_device *dev)
@ -1203,10 +1207,15 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
ipoib_ib_dev_down(dev); ipoib_ib_dev_down(dev);
if (level == IPOIB_FLUSH_HEAVY) { if (level == IPOIB_FLUSH_HEAVY) {
rtnl_lock();
if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
ipoib_ib_dev_stop(dev); ipoib_ib_dev_stop(dev);
if (ipoib_ib_dev_open(dev) != 0)
result = ipoib_ib_dev_open(dev);
rtnl_unlock();
if (result)
return; return;
if (netif_queue_stopped(dev)) if (netif_queue_stopped(dev))
netif_start_queue(dev); netif_start_queue(dev);
} }

View File

@ -89,6 +89,7 @@ static int start_cbsend(struct cardstate *);
struct bas_cardstate { struct bas_cardstate {
struct usb_device *udev; /* USB device pointer */ struct usb_device *udev; /* USB device pointer */
struct cardstate *cs;
struct usb_interface *interface; /* interface for this device */ struct usb_interface *interface; /* interface for this device */
unsigned char minor; /* starting minor number */ unsigned char minor; /* starting minor number */
@ -433,10 +434,10 @@ static void check_pending(struct bas_cardstate *ucs)
* argument: * argument:
* controller state structure * controller state structure
*/ */
static void cmd_in_timeout(unsigned long data) static void cmd_in_timeout(struct timer_list *t)
{ {
struct cardstate *cs = (struct cardstate *) data; struct bas_cardstate *ucs = from_timer(ucs, t, timer_cmd_in);
struct bas_cardstate *ucs = cs->hw.bas; struct cardstate *cs = ucs->cs;
int rc; int rc;
if (!ucs->rcvbuf_size) { if (!ucs->rcvbuf_size) {
@ -639,10 +640,10 @@ static void int_in_work(struct work_struct *work)
* argument: * argument:
* controller state structure * controller state structure
*/ */
static void int_in_resubmit(unsigned long data) static void int_in_resubmit(struct timer_list *t)
{ {
struct cardstate *cs = (struct cardstate *) data; struct bas_cardstate *ucs = from_timer(ucs, t, timer_int_in);
struct bas_cardstate *ucs = cs->hw.bas; struct cardstate *cs = ucs->cs;
int rc; int rc;
if (ucs->retry_int_in++ >= BAS_RETRY) { if (ucs->retry_int_in++ >= BAS_RETRY) {
@ -1441,10 +1442,10 @@ error:
* argument: * argument:
* controller state structure * controller state structure
*/ */
static void req_timeout(unsigned long data) static void req_timeout(struct timer_list *t)
{ {
struct cardstate *cs = (struct cardstate *) data; struct bas_cardstate *ucs = from_timer(ucs, t, timer_ctrl);
struct bas_cardstate *ucs = cs->hw.bas; struct cardstate *cs = ucs->cs;
int pending; int pending;
unsigned long flags; unsigned long flags;
@ -1837,10 +1838,10 @@ static void write_command_callback(struct urb *urb)
* argument: * argument:
* controller state structure * controller state structure
*/ */
static void atrdy_timeout(unsigned long data) static void atrdy_timeout(struct timer_list *t)
{ {
struct cardstate *cs = (struct cardstate *) data; struct bas_cardstate *ucs = from_timer(ucs, t, timer_atrdy);
struct bas_cardstate *ucs = cs->hw.bas; struct cardstate *cs = ucs->cs;
dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n"); dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n");
@ -2200,7 +2201,7 @@ static int gigaset_initcshw(struct cardstate *cs)
{ {
struct bas_cardstate *ucs; struct bas_cardstate *ucs;
cs->hw.bas = ucs = kmalloc(sizeof *ucs, GFP_KERNEL); cs->hw.bas = ucs = kzalloc(sizeof(*ucs), GFP_KERNEL);
if (!ucs) { if (!ucs) {
pr_err("out of memory\n"); pr_err("out of memory\n");
return -ENOMEM; return -ENOMEM;
@ -2212,19 +2213,12 @@ static int gigaset_initcshw(struct cardstate *cs)
return -ENOMEM; return -ENOMEM;
} }
ucs->urb_cmd_in = NULL;
ucs->urb_cmd_out = NULL;
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
spin_lock_init(&ucs->lock); spin_lock_init(&ucs->lock);
ucs->pending = 0; ucs->cs = cs;
timer_setup(&ucs->timer_ctrl, req_timeout, 0);
ucs->basstate = 0; timer_setup(&ucs->timer_atrdy, atrdy_timeout, 0);
setup_timer(&ucs->timer_ctrl, req_timeout, (unsigned long) cs); timer_setup(&ucs->timer_cmd_in, cmd_in_timeout, 0);
setup_timer(&ucs->timer_atrdy, atrdy_timeout, (unsigned long) cs); timer_setup(&ucs->timer_int_in, int_in_resubmit, 0);
setup_timer(&ucs->timer_cmd_in, cmd_in_timeout, (unsigned long) cs);
setup_timer(&ucs->timer_int_in, int_in_resubmit, (unsigned long) cs);
init_waitqueue_head(&ucs->waitqueue); init_waitqueue_head(&ucs->waitqueue);
INIT_WORK(&ucs->int_in_wq, int_in_work); INIT_WORK(&ucs->int_in_wq, int_in_work);

View File

@ -153,9 +153,9 @@ static int test_timeout(struct at_state_t *at_state)
return 1; return 1;
} }
static void timer_tick(unsigned long data) static void timer_tick(struct timer_list *t)
{ {
struct cardstate *cs = (struct cardstate *) data; struct cardstate *cs = from_timer(cs, t, timer);
unsigned long flags; unsigned long flags;
unsigned channel; unsigned channel;
struct at_state_t *at_state; struct at_state_t *at_state;
@ -687,7 +687,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->ignoreframes = ignoreframes; cs->ignoreframes = ignoreframes;
INIT_LIST_HEAD(&cs->temp_at_states); INIT_LIST_HEAD(&cs->temp_at_states);
cs->running = 0; cs->running = 0;
init_timer(&cs->timer); /* clear next & prev */ timer_setup(&cs->timer, timer_tick, 0);
spin_lock_init(&cs->ev_lock); spin_lock_init(&cs->ev_lock);
cs->ev_tail = 0; cs->ev_tail = 0;
cs->ev_head = 0; cs->ev_head = 0;
@ -768,7 +768,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
spin_lock_irqsave(&cs->lock, flags); spin_lock_irqsave(&cs->lock, flags);
cs->running = 1; cs->running = 1;
spin_unlock_irqrestore(&cs->lock, flags); spin_unlock_irqrestore(&cs->lock, flags);
setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK); cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
add_timer(&cs->timer); add_timer(&cs->timer);

View File

@ -4501,6 +4501,7 @@ static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
plci->channels++; plci->channels++;
a->ncci_state[ncci] = OUTG_CON_PENDING; a->ncci_state[ncci] = OUTG_CON_PENDING;
} }
/* fall through */
default: default:
if (plci->internal_command_queue[0]) if (plci->internal_command_queue[0])
@ -7020,6 +7021,7 @@ static void nl_ind(PLCI *plci)
plci->NL.RNum = 1; plci->NL.RNum = 1;
return; return;
} }
/* fall through */
case N_BDATA: case N_BDATA:
case N_DATA: case N_DATA:
if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */ if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
@ -9626,9 +9628,9 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
{ {
case DTMF_LISTEN_TONE_START: case DTMF_LISTEN_TONE_START:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_LISTEN_MF_START: case DTMF_LISTEN_MF_START:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_LISTEN_START: case DTMF_LISTEN_START:
switch (internal_command) switch (internal_command)
@ -9636,6 +9638,7 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
default: default:
adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities | adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
B1_FACILITY_DTMFR), DTMF_COMMAND_1); B1_FACILITY_DTMFR), DTMF_COMMAND_1);
/* fall through */
case DTMF_COMMAND_1: case DTMF_COMMAND_1:
if (adjust_b_process(Id, plci, Rc) != GOOD) if (adjust_b_process(Id, plci, Rc) != GOOD)
{ {
@ -9646,6 +9649,7 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
} }
if (plci->internal_command) if (plci->internal_command)
return; return;
/* fall through */
case DTMF_COMMAND_2: case DTMF_COMMAND_2:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -9673,9 +9677,9 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
case DTMF_LISTEN_TONE_STOP: case DTMF_LISTEN_TONE_STOP:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_LISTEN_MF_STOP: case DTMF_LISTEN_MF_STOP:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_LISTEN_STOP: case DTMF_LISTEN_STOP:
switch (internal_command) switch (internal_command)
@ -9710,6 +9714,7 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
*/ */
adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities & adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3); ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
/* fall through */
case DTMF_COMMAND_3: case DTMF_COMMAND_3:
if (adjust_b_process(Id, plci, Rc) != GOOD) if (adjust_b_process(Id, plci, Rc) != GOOD)
{ {
@ -9726,9 +9731,9 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
case DTMF_SEND_TONE: case DTMF_SEND_TONE:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_SEND_MF: case DTMF_SEND_MF:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_DIGITS_SEND: case DTMF_DIGITS_SEND:
switch (internal_command) switch (internal_command)
@ -9737,6 +9742,7 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities | adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)), ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
DTMF_COMMAND_1); DTMF_COMMAND_1);
/* fall through */
case DTMF_COMMAND_1: case DTMF_COMMAND_1:
if (adjust_b_process(Id, plci, Rc) != GOOD) if (adjust_b_process(Id, plci, Rc) != GOOD)
{ {
@ -9747,6 +9753,7 @@ static void dtmf_command(dword Id, PLCI *plci, byte Rc)
} }
if (plci->internal_command) if (plci->internal_command)
return; return;
/* fall through */
case DTMF_COMMAND_2: case DTMF_COMMAND_2:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -9863,7 +9870,7 @@ static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci
case DTMF_LISTEN_TONE_START: case DTMF_LISTEN_TONE_START:
case DTMF_LISTEN_TONE_STOP: case DTMF_LISTEN_TONE_STOP:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_LISTEN_MF_START: case DTMF_LISTEN_MF_START:
case DTMF_LISTEN_MF_STOP: case DTMF_LISTEN_MF_STOP:
mask <<= 1; mask <<= 1;
@ -9875,6 +9882,7 @@ static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci
PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST); PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
break; break;
} }
/* fall through */
case DTMF_LISTEN_START: case DTMF_LISTEN_START:
case DTMF_LISTEN_STOP: case DTMF_LISTEN_STOP:
@ -9904,7 +9912,7 @@ static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci
case DTMF_SEND_TONE: case DTMF_SEND_TONE:
mask <<= 1; mask <<= 1; /* fall through */
case DTMF_SEND_MF: case DTMF_SEND_MF:
mask <<= 1; mask <<= 1;
if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1]) if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
@ -9915,6 +9923,7 @@ static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci
PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST); PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
break; break;
} }
/* fall through */
case DTMF_DIGITS_SEND: case DTMF_DIGITS_SEND:
if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms)) if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
@ -11315,6 +11324,7 @@ static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5; plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_MIXER_2: case ADJUST_B_RESTORE_MIXER_2:
case ADJUST_B_RESTORE_MIXER_3: case ADJUST_B_RESTORE_MIXER_3:
case ADJUST_B_RESTORE_MIXER_4: case ADJUST_B_RESTORE_MIXER_4:
@ -11344,10 +11354,12 @@ static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
plci->internal_command = plci->adjust_b_command; plci->internal_command = plci->adjust_b_command;
break; break;
} }
/* fall through */
case ADJUST_B_RESTORE_MIXER_5: case ADJUST_B_RESTORE_MIXER_5:
xconnect_write_coefs(plci, plci->adjust_b_command); xconnect_write_coefs(plci, plci->adjust_b_command);
plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6; plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_MIXER_6: case ADJUST_B_RESTORE_MIXER_6:
if (!xconnect_write_coefs_process(Id, plci, Rc)) if (!xconnect_write_coefs_process(Id, plci, Rc))
{ {
@ -11392,6 +11404,7 @@ static void mixer_command(dword Id, PLCI *plci, byte Rc)
adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities | adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
B1_FACILITY_MIXER), MIXER_COMMAND_1); B1_FACILITY_MIXER), MIXER_COMMAND_1);
} }
/* fall through */
case MIXER_COMMAND_1: case MIXER_COMMAND_1:
if (plci->li_channel_bits & LI_CHANNEL_INVOLVED) if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
{ {
@ -11419,6 +11432,7 @@ static void mixer_command(dword Id, PLCI *plci, byte Rc)
mixer_indication_coefs_set(Id, plci); mixer_indication_coefs_set(Id, plci);
} while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos); } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
} }
/* fall through */
case MIXER_COMMAND_2: case MIXER_COMMAND_2:
if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED) if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
|| ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER) || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
@ -11450,6 +11464,7 @@ static void mixer_command(dword Id, PLCI *plci, byte Rc)
adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities & adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
~B1_FACILITY_MIXER), MIXER_COMMAND_3); ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
} }
/* fall through */
case MIXER_COMMAND_3: case MIXER_COMMAND_3:
if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED)) if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
{ {
@ -12602,6 +12617,7 @@ static void ec_command(dword Id, PLCI *plci, byte Rc)
default: default:
adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities | adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
B1_FACILITY_EC), EC_COMMAND_1); B1_FACILITY_EC), EC_COMMAND_1);
/* fall through */
case EC_COMMAND_1: case EC_COMMAND_1:
if (adjust_b_process(Id, plci, Rc) != GOOD) if (adjust_b_process(Id, plci, Rc) != GOOD)
{ {
@ -12612,6 +12628,7 @@ static void ec_command(dword Id, PLCI *plci, byte Rc)
} }
if (plci->internal_command) if (plci->internal_command)
return; return;
/* fall through */
case EC_COMMAND_2: case EC_COMMAND_2:
if (plci->sig_req) if (plci->sig_req)
{ {
@ -12650,6 +12667,7 @@ static void ec_command(dword Id, PLCI *plci, byte Rc)
return; return;
} }
Rc = OK; Rc = OK;
/* fall through */
case EC_COMMAND_2: case EC_COMMAND_2:
if ((Rc != OK) && (Rc != OK_FC)) if ((Rc != OK) && (Rc != OK_FC))
{ {
@ -12660,6 +12678,7 @@ static void ec_command(dword Id, PLCI *plci, byte Rc)
} }
adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities & adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
~B1_FACILITY_EC), EC_COMMAND_3); ~B1_FACILITY_EC), EC_COMMAND_3);
/* fall through */
case EC_COMMAND_3: case EC_COMMAND_3:
if (adjust_b_process(Id, plci, Rc) != GOOD) if (adjust_b_process(Id, plci, Rc) != GOOD)
{ {
@ -13485,6 +13504,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1; plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_SAVE_MIXER_1: case ADJUST_B_SAVE_MIXER_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
{ {
@ -13496,6 +13516,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1; plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_SAVE_DTMF_1: case ADJUST_B_SAVE_DTMF_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
{ {
@ -13506,6 +13527,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_REMOVE_L23_1; plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
/* fall through */
case ADJUST_B_REMOVE_L23_1: case ADJUST_B_REMOVE_L23_1:
if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23) if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
&& plci->NL.Id && !plci->nl_remove_id) && plci->NL.Id && !plci->nl_remove_id)
@ -13530,6 +13552,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_REMOVE_L23_2; plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_REMOVE_L23_2: case ADJUST_B_REMOVE_L23_2:
if ((Rc != OK) && (Rc != OK_FC)) if ((Rc != OK) && (Rc != OK_FC))
{ {
@ -13548,6 +13571,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_SAVE_EC_1; plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_SAVE_EC_1: case ADJUST_B_SAVE_EC_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
{ {
@ -13559,6 +13583,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1; plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_SAVE_DTMF_PARAMETER_1: case ADJUST_B_SAVE_DTMF_PARAMETER_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
{ {
@ -13570,6 +13595,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1; plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_SAVE_VOICE_1: case ADJUST_B_SAVE_VOICE_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
{ {
@ -13578,6 +13604,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
break; break;
} }
plci->adjust_b_state = ADJUST_B_SWITCH_L1_1; plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
/* fall through */
case ADJUST_B_SWITCH_L1_1: case ADJUST_B_SWITCH_L1_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1) if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
{ {
@ -13608,6 +13635,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_SWITCH_L1_2; plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_SWITCH_L1_2: case ADJUST_B_SWITCH_L1_2:
if ((Rc != OK) && (Rc != OK_FC)) if ((Rc != OK) && (Rc != OK_FC))
{ {
@ -13619,6 +13647,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1; plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_VOICE_1: case ADJUST_B_RESTORE_VOICE_1:
case ADJUST_B_RESTORE_VOICE_2: case ADJUST_B_RESTORE_VOICE_2:
if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
@ -13629,6 +13658,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1; plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_DTMF_PARAMETER_1: case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
case ADJUST_B_RESTORE_DTMF_PARAMETER_2: case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
@ -13641,6 +13671,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_RESTORE_EC_1; plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_EC_1: case ADJUST_B_RESTORE_EC_1:
case ADJUST_B_RESTORE_EC_2: case ADJUST_B_RESTORE_EC_2:
if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
@ -13652,6 +13683,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1; plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
/* fall through */
case ADJUST_B_ASSIGN_L23_1: case ADJUST_B_ASSIGN_L23_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23) if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
{ {
@ -13681,6 +13713,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2; plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
Rc = ASSIGN_OK; Rc = ASSIGN_OK;
/* fall through */
case ADJUST_B_ASSIGN_L23_2: case ADJUST_B_ASSIGN_L23_2:
if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK)) if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
{ {
@ -13703,6 +13736,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
break; break;
} }
plci->adjust_b_state = ADJUST_B_CONNECT_1; plci->adjust_b_state = ADJUST_B_CONNECT_1;
/* fall through */
case ADJUST_B_CONNECT_1: case ADJUST_B_CONNECT_1:
if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
{ {
@ -13716,6 +13750,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_CONNECT_2: case ADJUST_B_CONNECT_2:
case ADJUST_B_CONNECT_3: case ADJUST_B_CONNECT_3:
case ADJUST_B_CONNECT_4: case ADJUST_B_CONNECT_4:
@ -13751,6 +13786,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
break; break;
} }
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_DTMF_1: case ADJUST_B_RESTORE_DTMF_1:
case ADJUST_B_RESTORE_DTMF_2: case ADJUST_B_RESTORE_DTMF_2:
if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
@ -13763,6 +13799,7 @@ static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
} }
plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1; plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_MIXER_1: case ADJUST_B_RESTORE_MIXER_1:
case ADJUST_B_RESTORE_MIXER_2: case ADJUST_B_RESTORE_MIXER_2:
case ADJUST_B_RESTORE_MIXER_3: case ADJUST_B_RESTORE_MIXER_3:
@ -13827,6 +13864,7 @@ static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
break; break;
} }
Rc = OK; Rc = OK;
/* fall through */
case ADJUST_B_RESTORE_1: case ADJUST_B_RESTORE_1:
if ((Rc != OK) && (Rc != OK_FC)) if ((Rc != OK) && (Rc != OK_FC))
{ {
@ -13841,6 +13879,7 @@ static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
plci->adjust_b_state = ADJUST_B_START; plci->adjust_b_state = ADJUST_B_START;
dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...", dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
UnMapId(Id), (char *)(FILE_), __LINE__)); UnMapId(Id), (char *)(FILE_), __LINE__));
/* fall through */
case ADJUST_B_RESTORE_2: case ADJUST_B_RESTORE_2:
if (adjust_b_process(Id, plci, Rc) != GOOD) if (adjust_b_process(Id, plci, Rc) != GOOD)
{ {
@ -13877,6 +13916,7 @@ static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
plci->adjust_b_state = ADJUST_B_START; plci->adjust_b_state = ADJUST_B_START;
dbug(1, dprintf("[%06lx] %s,%d: Reset B3...", dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
UnMapId(Id), (char *)(FILE_), __LINE__)); UnMapId(Id), (char *)(FILE_), __LINE__));
/* fall through */
case RESET_B3_COMMAND_1: case RESET_B3_COMMAND_1:
Info = adjust_b_process(Id, plci, Rc); Info = adjust_b_process(Id, plci, Rc);
if (Info != GOOD) if (Info != GOOD)
@ -13930,6 +13970,7 @@ static void select_b_command(dword Id, PLCI *plci, byte Rc)
plci->adjust_b_state = ADJUST_B_START; plci->adjust_b_state = ADJUST_B_START;
dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...", dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
UnMapId(Id), (char *)(FILE_), __LINE__)); UnMapId(Id), (char *)(FILE_), __LINE__));
/* fall through */
case SELECT_B_COMMAND_1: case SELECT_B_COMMAND_1:
Info = adjust_b_process(Id, plci, Rc); Info = adjust_b_process(Id, plci, Rc);
if (Info != GOOD) if (Info != GOOD)
@ -13965,7 +14006,7 @@ static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
switch (internal_command) switch (internal_command)
{ {
default: default:
plci->command = 0; plci->command = 0; /* fall through */
case FAX_CONNECT_ACK_COMMAND_1: case FAX_CONNECT_ACK_COMMAND_1:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -14013,6 +14054,7 @@ static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
{ {
default: default:
plci->command = 0; plci->command = 0;
/* fall through */
case FAX_EDATA_ACK_COMMAND_1: case FAX_EDATA_ACK_COMMAND_1:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -14052,7 +14094,7 @@ static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
switch (internal_command) switch (internal_command)
{ {
default: default:
plci->command = 0; plci->command = 0; /* fall through */
case FAX_CONNECT_INFO_COMMAND_1: case FAX_CONNECT_INFO_COMMAND_1:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -14112,6 +14154,7 @@ static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
plci->adjust_b_state = ADJUST_B_START; plci->adjust_b_state = ADJUST_B_START;
dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...", dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
UnMapId(Id), (char *)(FILE_), __LINE__)); UnMapId(Id), (char *)(FILE_), __LINE__));
/* fall through */
case FAX_ADJUST_B23_COMMAND_1: case FAX_ADJUST_B23_COMMAND_1:
Info = adjust_b_process(Id, plci, Rc); Info = adjust_b_process(Id, plci, Rc);
if (Info != GOOD) if (Info != GOOD)
@ -14122,6 +14165,7 @@ static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
} }
if (plci->internal_command) if (plci->internal_command)
return; return;
/* fall through */
case FAX_ADJUST_B23_COMMAND_2: case FAX_ADJUST_B23_COMMAND_2:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -14194,7 +14238,7 @@ static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
switch (internal_command) switch (internal_command)
{ {
default: default:
plci->command = 0; plci->command = 0; /* fall through */
case RTP_CONNECT_B3_REQ_COMMAND_1: case RTP_CONNECT_B3_REQ_COMMAND_1:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -14245,7 +14289,7 @@ static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
switch (internal_command) switch (internal_command)
{ {
default: default:
plci->command = 0; plci->command = 0; /* fall through */
case RTP_CONNECT_B3_RES_COMMAND_1: case RTP_CONNECT_B3_RES_COMMAND_1:
if (plci_nl_busy(plci)) if (plci_nl_busy(plci))
{ {
@ -14310,6 +14354,7 @@ static void hold_save_command(dword Id, PLCI *plci, byte Rc)
plci->adjust_b_state = ADJUST_B_START; plci->adjust_b_state = ADJUST_B_START;
dbug(1, dprintf("[%06lx] %s,%d: HOLD save...", dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
UnMapId(Id), (char *)(FILE_), __LINE__)); UnMapId(Id), (char *)(FILE_), __LINE__));
/* fall through */
case HOLD_SAVE_COMMAND_1: case HOLD_SAVE_COMMAND_1:
Info = adjust_b_process(Id, plci, Rc); Info = adjust_b_process(Id, plci, Rc);
if (Info != GOOD) if (Info != GOOD)
@ -14349,6 +14394,7 @@ static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
plci->adjust_b_state = ADJUST_B_START; plci->adjust_b_state = ADJUST_B_START;
dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...", dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
UnMapId(Id), (char *)(FILE_), __LINE__)); UnMapId(Id), (char *)(FILE_), __LINE__));
/* fall through */
case RETRIEVE_RESTORE_COMMAND_1: case RETRIEVE_RESTORE_COMMAND_1:
Info = adjust_b_process(Id, plci, Rc); Info = adjust_b_process(Id, plci, Rc);
if (Info != GOOD) if (Info != GOOD)

View File

@ -2265,7 +2265,7 @@ static struct pci_driver hfc_driver = {
}; };
static int static int
_hfcpci_softirq(struct device *dev, void *arg) _hfcpci_softirq(struct device *dev, void *unused)
{ {
struct hfc_pci *hc = dev_get_drvdata(dev); struct hfc_pci *hc = dev_get_drvdata(dev);
struct bchannel *bch; struct bchannel *bch;
@ -2290,9 +2290,9 @@ _hfcpci_softirq(struct device *dev, void *arg)
} }
static void static void
hfcpci_softirq(void *arg) hfcpci_softirq(struct timer_list *unused)
{ {
WARN_ON_ONCE(driver_for_each_device(&hfc_driver.driver, NULL, arg, WARN_ON_ONCE(driver_for_each_device(&hfc_driver.driver, NULL, NULL,
_hfcpci_softirq) != 0); _hfcpci_softirq) != 0);
/* if next event would be in the past ... */ /* if next event would be in the past ... */
@ -2327,9 +2327,7 @@ HFC_init(void)
if (poll != HFCPCI_BTRANS_THRESHOLD) { if (poll != HFCPCI_BTRANS_THRESHOLD) {
printk(KERN_INFO "%s: Using alternative poll value of %d\n", printk(KERN_INFO "%s: Using alternative poll value of %d\n",
__func__, poll); __func__, poll);
hfc_tl.function = (void *)hfcpci_softirq; timer_setup(&hfc_tl, hfcpci_softirq, 0);
hfc_tl.data = 0;
init_timer(&hfc_tl);
hfc_tl.expires = jiffies + tics; hfc_tl.expires = jiffies + tics;
hfc_jiffies = hfc_tl.expires; hfc_jiffies = hfc_tl.expires;
add_timer(&hfc_tl); add_timer(&hfc_tl);

View File

@ -172,7 +172,6 @@ isac_fill_fifo(struct isac_hw *isac)
pr_debug("%s: %s dbusytimer running\n", isac->name, __func__); pr_debug("%s: %s dbusytimer running\n", isac->name, __func__);
del_timer(&isac->dch.timer); del_timer(&isac->dch.timer);
} }
init_timer(&isac->dch.timer);
isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
add_timer(&isac->dch.timer); add_timer(&isac->dch.timer);
if (isac->dch.debug & DEBUG_HW_DFIFO) { if (isac->dch.debug & DEBUG_HW_DFIFO) {
@ -727,8 +726,9 @@ isac_release(struct isac_hw *isac)
} }
static void static void
dbusy_timer_handler(struct isac_hw *isac) dbusy_timer_handler(struct timer_list *t)
{ {
struct isac_hw *isac = from_timer(isac, t, dch.timer);
int rbch, star; int rbch, star;
u_long flags; u_long flags;
@ -796,8 +796,7 @@ isac_init(struct isac_hw *isac)
} }
isac->mon_tx = NULL; isac->mon_tx = NULL;
isac->mon_rx = NULL; isac->mon_rx = NULL;
setup_timer(&isac->dch.timer, (void *)dbusy_timer_handler, timer_setup(&isac->dch.timer, dbusy_timer_handler, 0);
(long)isac);
isac->mocr = 0xaa; isac->mocr = 0xaa;
if (isac->type & IPAC_TYPE_ISACX) { if (isac->type & IPAC_TYPE_ISACX) {
/* Disable all IRQ */ /* Disable all IRQ */

View File

@ -311,7 +311,6 @@ W6692_fill_Dfifo(struct w6692_hw *card)
pr_debug("%s: fill_Dfifo dbusytimer running\n", card->name); pr_debug("%s: fill_Dfifo dbusytimer running\n", card->name);
del_timer(&dch->timer); del_timer(&dch->timer);
} }
init_timer(&dch->timer);
dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
add_timer(&dch->timer); add_timer(&dch->timer);
if (debug & DEBUG_HW_DFIFO) { if (debug & DEBUG_HW_DFIFO) {
@ -819,8 +818,9 @@ w6692_irq(int intno, void *dev_id)
} }
static void static void
dbusy_timer_handler(struct dchannel *dch) dbusy_timer_handler(struct timer_list *t)
{ {
struct dchannel *dch = from_timer(dch, t, timer);
struct w6692_hw *card = dch->hw; struct w6692_hw *card = dch->hw;
int rbch, star; int rbch, star;
u_long flags; u_long flags;
@ -852,8 +852,7 @@ static void initW6692(struct w6692_hw *card)
{ {
u8 val; u8 val;
setup_timer(&card->dch.timer, (void *)dbusy_timer_handler, timer_setup(&card->dch.timer, dbusy_timer_handler, 0);
(u_long)&card->dch);
w6692_mode(&card->bc[0], ISDN_P_NONE); w6692_mode(&card->bc[0], ISDN_P_NONE);
w6692_mode(&card->bc[1], ISDN_P_NONE); w6692_mode(&card->bc[1], ISDN_P_NONE);
WriteW6692(card, W_D_CTL, 0x00); WriteW6692(card, W_D_CTL, 0x00);

View File

@ -398,7 +398,6 @@ Amd7930_fill_Dfifo(struct IsdnCardState *cs)
debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running"); debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running");
del_timer(&cs->dbusytimer); del_timer(&cs->dbusytimer);
} }
init_timer(&cs->dbusytimer);
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
add_timer(&cs->dbusytimer); add_timer(&cs->dbusytimer);
@ -686,8 +685,9 @@ DC_Close_Amd7930(struct IsdnCardState *cs) {
static void static void
dbusy_timer_handler(struct IsdnCardState *cs) dbusy_timer_handler(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, dbusytimer);
u_long flags; u_long flags;
struct PStack *stptr; struct PStack *stptr;
WORD dtcr, der; WORD dtcr, der;
@ -790,5 +790,5 @@ void Amd7930_init(struct IsdnCardState *cs)
void setup_Amd7930(struct IsdnCardState *cs) void setup_Amd7930(struct IsdnCardState *cs)
{ {
INIT_WORK(&cs->tqueue, Amd7930_bh); INIT_WORK(&cs->tqueue, Amd7930_bh);
setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler, (long)cs); timer_setup(&cs->dbusytimer, dbusy_timer_handler, 0);
} }

View File

@ -23,7 +23,6 @@ add_arcofi_timer(struct IsdnCardState *cs) {
if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
del_timer(&cs->dc.isac.arcofitimer); del_timer(&cs->dc.isac.arcofitimer);
} }
init_timer(&cs->dc.isac.arcofitimer);
cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ) / 1000); cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ) / 1000);
add_timer(&cs->dc.isac.arcofitimer); add_timer(&cs->dc.isac.arcofitimer);
} }
@ -112,7 +111,8 @@ arcofi_fsm(struct IsdnCardState *cs, int event, void *data) {
} }
static void static void
arcofi_timer(struct IsdnCardState *cs) { arcofi_timer(struct timer_list *t) {
struct IsdnCardState *cs = from_timer(cs, t, dc.isac.arcofitimer);
arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL); arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
} }
@ -125,7 +125,7 @@ clear_arcofi(struct IsdnCardState *cs) {
void void
init_arcofi(struct IsdnCardState *cs) { init_arcofi(struct IsdnCardState *cs) {
setup_timer(&cs->dc.isac.arcofitimer, (void *)arcofi_timer, (long)cs); timer_setup(&cs->dc.isac.arcofitimer, arcofi_timer, 0);
init_waitqueue_head(&cs->dc.isac.arcofi_wait); init_waitqueue_head(&cs->dc.isac.arcofi_wait);
test_and_set_bit(HW_ARCOFI, &cs->HW_Flags); test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
} }

View File

@ -798,8 +798,9 @@ reset_diva(struct IsdnCardState *cs)
#define DIVA_ASSIGN 1 #define DIVA_ASSIGN 1
static void static void
diva_led_handler(struct IsdnCardState *cs) diva_led_handler(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, hw.diva.tl);
int blink = 0; int blink = 0;
if ((cs->subtyp == DIVA_IPAC_ISA) || if ((cs->subtyp == DIVA_IPAC_ISA) ||
@ -828,7 +829,6 @@ diva_led_handler(struct IsdnCardState *cs)
byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
if (blink) { if (blink) {
init_timer(&cs->hw.diva.tl);
cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000); cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000);
add_timer(&cs->hw.diva.tl); add_timer(&cs->hw.diva.tl);
} }
@ -900,7 +900,7 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
(cs->subtyp != DIVA_IPAC_PCI) && (cs->subtyp != DIVA_IPAC_PCI) &&
(cs->subtyp != DIVA_IPACX_PCI)) { (cs->subtyp != DIVA_IPACX_PCI)) {
spin_lock_irqsave(&cs->lock, flags); spin_lock_irqsave(&cs->lock, flags);
diva_led_handler(cs); diva_led_handler(&cs->hw.diva.tl);
spin_unlock_irqrestore(&cs->lock, flags); spin_unlock_irqrestore(&cs->lock, flags);
} }
return (0); return (0);
@ -978,8 +978,7 @@ static int setup_diva_common(struct IsdnCardState *cs)
printk(KERN_INFO "Diva: IPACX Design Id: %x\n", printk(KERN_INFO "Diva: IPACX Design Id: %x\n",
MemReadISAC_IPACX(cs, IPACX_ID) & 0x3F); MemReadISAC_IPACX(cs, IPACX_ID) & 0x3F);
} else { /* DIVA 2.0 */ } else { /* DIVA 2.0 */
setup_timer(&cs->hw.diva.tl, (void *)diva_led_handler, timer_setup(&cs->hw.diva.tl, diva_led_handler, 0);
(long)cs);
cs->readisac = &ReadISAC; cs->readisac = &ReadISAC;
cs->writeisac = &WriteISAC; cs->writeisac = &WriteISAC;
cs->readisacfifo = &ReadISACfifo; cs->readisacfifo = &ReadISACfifo;

View File

@ -606,8 +606,9 @@ check_arcofi(struct IsdnCardState *cs)
#endif /* ARCOFI_USE */ #endif /* ARCOFI_USE */
static void static void
elsa_led_handler(struct IsdnCardState *cs) elsa_led_handler(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, hw.elsa.tl);
int blink = 0; int blink = 0;
if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC) if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC)
@ -640,7 +641,6 @@ elsa_led_handler(struct IsdnCardState *cs)
} else } else
byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
if (blink) { if (blink) {
init_timer(&cs->hw.elsa.tl);
cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000); cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000);
add_timer(&cs->hw.elsa.tl); add_timer(&cs->hw.elsa.tl);
} }
@ -715,7 +715,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
init_modem(cs); init_modem(cs);
} }
#endif #endif
elsa_led_handler(cs); elsa_led_handler(&cs->hw.elsa.tl);
return (ret); return (ret);
case (MDL_REMOVE | REQUEST): case (MDL_REMOVE | REQUEST):
cs->hw.elsa.status &= 0; cs->hw.elsa.status &= 0;
@ -767,7 +767,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
else else
cs->hw.elsa.status &= ~ELSA_BAD_PWR; cs->hw.elsa.status &= ~ELSA_BAD_PWR;
} }
elsa_led_handler(cs); elsa_led_handler(&cs->hw.elsa.tl);
return (ret); return (ret);
} }
@ -1147,7 +1147,7 @@ static int setup_elsa_common(struct IsdnCard *card)
init_arcofi(cs); init_arcofi(cs);
#endif #endif
setup_isac(cs); setup_isac(cs);
setup_timer(&cs->hw.elsa.tl, (void *)elsa_led_handler, (long)cs); timer_setup(&cs->hw.elsa.tl, elsa_led_handler, 0);
/* Teste Timer */ /* Teste Timer */
if (cs->hw.elsa.timer) { if (cs->hw.elsa.timer) {
byteout(cs->hw.elsa.trig, 0xff); byteout(cs->hw.elsa.trig, 0xff);

View File

@ -85,8 +85,9 @@ FsmChangeState(struct FsmInst *fi, int newstate)
} }
static void static void
FsmExpireTimer(struct FsmTimer *ft) FsmExpireTimer(struct timer_list *t)
{ {
struct FsmTimer *ft = from_timer(ft, t, tl);
#if FSM_TIMER_DEBUG #if FSM_TIMER_DEBUG
if (ft->fi->debug) if (ft->fi->debug)
ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft); ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
@ -102,7 +103,7 @@ FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
if (ft->fi->debug) if (ft->fi->debug)
ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft); ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
#endif #endif
setup_timer(&ft->tl, (void *)FsmExpireTimer, (long)ft); timer_setup(&ft->tl, FsmExpireTimer, 0);
} }
void void
@ -131,7 +132,6 @@ FsmAddTimer(struct FsmTimer *ft,
ft->fi->printdebug(ft->fi, "FsmAddTimer already active!"); ft->fi->printdebug(ft->fi, "FsmAddTimer already active!");
return -1; return -1;
} }
init_timer(&ft->tl);
ft->event = event; ft->event = event;
ft->arg = arg; ft->arg = arg;
ft->tl.expires = jiffies + (millisec * HZ) / 1000; ft->tl.expires = jiffies + (millisec * HZ) / 1000;
@ -152,7 +152,6 @@ FsmRestartTimer(struct FsmTimer *ft,
if (timer_pending(&ft->tl)) if (timer_pending(&ft->tl))
del_timer(&ft->tl); del_timer(&ft->tl);
init_timer(&ft->tl);
ft->event = event; ft->event = event;
ft->arg = arg; ft->arg = arg;
ft->tl.expires = jiffies + (millisec * HZ) / 1000; ft->tl.expires = jiffies + (millisec * HZ) / 1000;

View File

@ -591,8 +591,9 @@ bch_l2l1(struct hisax_if *ifc, int pr, void *arg)
/* layer 1 timer function */ /* layer 1 timer function */
/**************************/ /**************************/
static void static void
hfc_l1_timer(struct hfc4s8s_l1 *l1) hfc_l1_timer(struct timer_list *t)
{ {
struct hfc4s8s_l1 *l1 = from_timer(l1, t, l1_timer);
u_long flags; u_long flags;
if (!l1->enabled) if (!l1->enabled)
@ -1396,8 +1397,7 @@ setup_instance(hfc4s8s_hw *hw)
l1p = hw->l1 + i; l1p = hw->l1 + i;
spin_lock_init(&l1p->lock); spin_lock_init(&l1p->lock);
l1p->hw = hw; l1p->hw = hw;
setup_timer(&l1p->l1_timer, (void *)hfc_l1_timer, timer_setup(&l1p->l1_timer, hfc_l1_timer, 0);
(long)(l1p));
l1p->st_num = i; l1p->st_num = i;
skb_queue_head_init(&l1p->d_tx_queue); skb_queue_head_init(&l1p->d_tx_queue);
l1p->d_if.ifc.priv = hw->l1 + i; l1p->d_if.ifc.priv = hw->l1 + i;

View File

@ -1014,7 +1014,7 @@ setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
} }
static void static void
hfc_dbusy_timer(struct IsdnCardState *cs) hfc_dbusy_timer(struct timer_list *t)
{ {
} }
@ -1073,6 +1073,6 @@ set_cs_func(struct IsdnCardState *cs)
cs->writeisacfifo = &dummyf; cs->writeisacfifo = &dummyf;
cs->BC_Read_Reg = &ReadReg; cs->BC_Read_Reg = &ReadReg;
cs->BC_Write_Reg = &WriteReg; cs->BC_Write_Reg = &WriteReg;
setup_timer(&cs->dbusytimer, (void *)hfc_dbusy_timer, (long)cs); timer_setup(&cs->dbusytimer, hfc_dbusy_timer, 0);
INIT_WORK(&cs->tqueue, hfcd_bh); INIT_WORK(&cs->tqueue, hfcd_bh);
} }

View File

@ -165,8 +165,9 @@ reset_hfcpci(struct IsdnCardState *cs)
/* Timer function called when kernel timer expires */ /* Timer function called when kernel timer expires */
/***************************************************/ /***************************************************/
static void static void
hfcpci_Timer(struct IsdnCardState *cs) hfcpci_Timer(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, hw.hfcpci.timer);
cs->hw.hfcpci.timer.expires = jiffies + 75; cs->hw.hfcpci.timer.expires = jiffies + 75;
/* WD RESET */ /* WD RESET */
/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcpci.ctmt | 0x80); /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcpci.ctmt | 0x80);
@ -1095,7 +1096,7 @@ hfcpci_interrupt(int intno, void *dev_id)
/* timer callback for D-chan busy resolution. Currently no function */ /* timer callback for D-chan busy resolution. Currently no function */
/********************************************************************/ /********************************************************************/
static void static void
hfcpci_dbusy_timer(struct IsdnCardState *cs) hfcpci_dbusy_timer(struct timer_list *t)
{ {
} }
@ -1582,7 +1583,7 @@ inithfcpci(struct IsdnCardState *cs)
cs->bcs[1].BC_SetStack = setstack_2b; cs->bcs[1].BC_SetStack = setstack_2b;
cs->bcs[0].BC_Close = close_hfcpci; cs->bcs[0].BC_Close = close_hfcpci;
cs->bcs[1].BC_Close = close_hfcpci; cs->bcs[1].BC_Close = close_hfcpci;
setup_timer(&cs->dbusytimer, (void *)hfcpci_dbusy_timer, (long)cs); timer_setup(&cs->dbusytimer, hfcpci_dbusy_timer, 0);
mode_hfcpci(cs->bcs, 0, 0); mode_hfcpci(cs->bcs, 0, 0);
mode_hfcpci(cs->bcs + 1, 0, 1); mode_hfcpci(cs->bcs + 1, 0, 1);
} }
@ -1744,7 +1745,7 @@ setup_hfcpci(struct IsdnCard *card)
cs->BC_Write_Reg = NULL; cs->BC_Write_Reg = NULL;
cs->irq_func = &hfcpci_interrupt; cs->irq_func = &hfcpci_interrupt;
cs->irq_flags |= IRQF_SHARED; cs->irq_flags |= IRQF_SHARED;
setup_timer(&cs->hw.hfcpci.timer, (void *)hfcpci_Timer, (long)cs); timer_setup(&cs->hw.hfcpci.timer, hfcpci_Timer, 0);
cs->cardmsg = &hfcpci_card_msg; cs->cardmsg = &hfcpci_card_msg;
cs->auxcmd = &hfcpci_auxcmd; cs->auxcmd = &hfcpci_auxcmd;

View File

@ -418,8 +418,9 @@ reset_hfcsx(struct IsdnCardState *cs)
/* Timer function called when kernel timer expires */ /* Timer function called when kernel timer expires */
/***************************************************/ /***************************************************/
static void static void
hfcsx_Timer(struct IsdnCardState *cs) hfcsx_Timer(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, hw.hfcsx.timer);
cs->hw.hfcsx.timer.expires = jiffies + 75; cs->hw.hfcsx.timer.expires = jiffies + 75;
/* WD RESET */ /* WD RESET */
/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcsx.ctmt | 0x80); /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcsx.ctmt | 0x80);
@ -860,7 +861,7 @@ hfcsx_interrupt(int intno, void *dev_id)
/* timer callback for D-chan busy resolution. Currently no function */ /* timer callback for D-chan busy resolution. Currently no function */
/********************************************************************/ /********************************************************************/
static void static void
hfcsx_dbusy_timer(struct IsdnCardState *cs) hfcsx_dbusy_timer(struct timer_list *t)
{ {
} }
@ -1495,7 +1496,7 @@ int setup_hfcsx(struct IsdnCard *card)
} else } else
return (0); /* no valid card type */ return (0); /* no valid card type */
setup_timer(&cs->dbusytimer, (void *)hfcsx_dbusy_timer, (long)cs); timer_setup(&cs->dbusytimer, hfcsx_dbusy_timer, 0);
INIT_WORK(&cs->tqueue, hfcsx_bh); INIT_WORK(&cs->tqueue, hfcsx_bh);
cs->readisac = NULL; cs->readisac = NULL;
cs->writeisac = NULL; cs->writeisac = NULL;
@ -1507,7 +1508,7 @@ int setup_hfcsx(struct IsdnCard *card)
cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */ cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
setup_timer(&cs->hw.hfcsx.timer, (void *)hfcsx_Timer, (long)cs); timer_setup(&cs->hw.hfcsx.timer, hfcsx_Timer, 0);
reset_hfcsx(cs); reset_hfcsx(cs);
cs->cardmsg = &hfcsx_card_msg; cs->cardmsg = &hfcsx_card_msg;

View File

@ -343,8 +343,9 @@ handle_led(hfcusb_data *hfc, int event)
/* ISDN l1 timer T3 expires */ /* ISDN l1 timer T3 expires */
static void static void
l1_timer_expire_t3(hfcusb_data *hfc) l1_timer_expire_t3(struct timer_list *t)
{ {
hfcusb_data *hfc = from_timer(hfc, t, t3_timer);
hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION, hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
NULL); NULL);
@ -360,8 +361,9 @@ l1_timer_expire_t3(hfcusb_data *hfc)
/* ISDN l1 timer T4 expires */ /* ISDN l1 timer T4 expires */
static void static void
l1_timer_expire_t4(hfcusb_data *hfc) l1_timer_expire_t4(struct timer_list *t)
{ {
hfcusb_data *hfc = from_timer(hfc, t, t4_timer);
hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION, hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
NULL); NULL);
@ -1165,10 +1167,10 @@ hfc_usb_init(hfcusb_data *hfc)
hfc->old_led_state = 0; hfc->old_led_state = 0;
/* init the t3 timer */ /* init the t3 timer */
setup_timer(&hfc->t3_timer, (void *)l1_timer_expire_t3, (long)hfc); timer_setup(&hfc->t3_timer, l1_timer_expire_t3, 0);
/* init the t4 timer */ /* init the t4 timer */
setup_timer(&hfc->t4_timer, (void *)l1_timer_expire_t4, (long)hfc); timer_setup(&hfc->t4_timer, l1_timer_expire_t4, 0);
/* init the background machinery for control requests */ /* init the background machinery for control requests */
hfc->ctrl_read.bRequestType = 0xc0; hfc->ctrl_read.bRequestType = 0xc0;

View File

@ -41,8 +41,9 @@ hfcs_interrupt(int intno, void *dev_id)
} }
static void static void
hfcs_Timer(struct IsdnCardState *cs) hfcs_Timer(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, hw.hfcD.timer);
cs->hw.hfcD.timer.expires = jiffies + 75; cs->hw.hfcD.timer.expires = jiffies + 75;
/* WD RESET */ /* WD RESET */
/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80); /* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
@ -253,7 +254,7 @@ int setup_hfcs(struct IsdnCard *card)
outb(0x57, cs->hw.hfcD.addr | 1); outb(0x57, cs->hw.hfcD.addr | 1);
} }
set_cs_func(cs); set_cs_func(cs);
setup_timer(&cs->hw.hfcD.timer, (void *)hfcs_Timer, (long)cs); timer_setup(&cs->hw.hfcD.timer, hfcs_Timer, 0);
cs->cardmsg = &hfcs_card_msg; cs->cardmsg = &hfcs_card_msg;
cs->irq_func = &hfcs_interrupt; cs->irq_func = &hfcs_interrupt;
return (1); return (1);

View File

@ -168,7 +168,6 @@ icc_fill_fifo(struct IsdnCardState *cs)
debugl1(cs, "icc_fill_fifo dbusytimer running"); debugl1(cs, "icc_fill_fifo dbusytimer running");
del_timer(&cs->dbusytimer); del_timer(&cs->dbusytimer);
} }
init_timer(&cs->dbusytimer);
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
add_timer(&cs->dbusytimer); add_timer(&cs->dbusytimer);
if (cs->debug & L1_DEB_ISAC_FIFO) { if (cs->debug & L1_DEB_ISAC_FIFO) {
@ -580,8 +579,9 @@ DC_Close_icc(struct IsdnCardState *cs) {
} }
static void static void
dbusy_timer_handler(struct IsdnCardState *cs) dbusy_timer_handler(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, dbusytimer);
struct PStack *stptr; struct PStack *stptr;
int rbch, star; int rbch, star;
@ -676,5 +676,5 @@ clear_pending_icc_ints(struct IsdnCardState *cs)
void setup_icc(struct IsdnCardState *cs) void setup_icc(struct IsdnCardState *cs)
{ {
INIT_WORK(&cs->tqueue, icc_bh); INIT_WORK(&cs->tqueue, icc_bh);
setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler, (long)cs); timer_setup(&cs->dbusytimer, dbusy_timer_handler, 0);
} }

View File

@ -35,7 +35,7 @@
static void ph_command(struct IsdnCardState *cs, unsigned int command); static void ph_command(struct IsdnCardState *cs, unsigned int command);
static inline void cic_int(struct IsdnCardState *cs); static inline void cic_int(struct IsdnCardState *cs);
static void dch_l2l1(struct PStack *st, int pr, void *arg); static void dch_l2l1(struct PStack *st, int pr, void *arg);
static void dbusy_timer_handler(struct IsdnCardState *cs); static void dbusy_timer_handler(struct timer_list *t);
static void dch_empty_fifo(struct IsdnCardState *cs, int count); static void dch_empty_fifo(struct IsdnCardState *cs, int count);
static void dch_fill_fifo(struct IsdnCardState *cs); static void dch_fill_fifo(struct IsdnCardState *cs);
static inline void dch_int(struct IsdnCardState *cs); static inline void dch_int(struct IsdnCardState *cs);
@ -198,8 +198,9 @@ dch_l2l1(struct PStack *st, int pr, void *arg)
//---------------------------------------------------------- //----------------------------------------------------------
//---------------------------------------------------------- //----------------------------------------------------------
static void static void
dbusy_timer_handler(struct IsdnCardState *cs) dbusy_timer_handler(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, dbusytimer);
struct PStack *st; struct PStack *st;
int rbchd, stard; int rbchd, stard;
@ -298,7 +299,6 @@ dch_fill_fifo(struct IsdnCardState *cs)
debugl1(cs, "dch_fill_fifo dbusytimer running"); debugl1(cs, "dch_fill_fifo dbusytimer running");
del_timer(&cs->dbusytimer); del_timer(&cs->dbusytimer);
} }
init_timer(&cs->dbusytimer);
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
add_timer(&cs->dbusytimer); add_timer(&cs->dbusytimer);
@ -424,7 +424,7 @@ dch_init(struct IsdnCardState *cs)
cs->setstack_d = dch_setstack; cs->setstack_d = dch_setstack;
setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler, (long)cs); timer_setup(&cs->dbusytimer, dbusy_timer_handler, 0);
cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD
cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter

View File

@ -171,7 +171,6 @@ isac_fill_fifo(struct IsdnCardState *cs)
debugl1(cs, "isac_fill_fifo dbusytimer running"); debugl1(cs, "isac_fill_fifo dbusytimer running");
del_timer(&cs->dbusytimer); del_timer(&cs->dbusytimer);
} }
init_timer(&cs->dbusytimer);
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
add_timer(&cs->dbusytimer); add_timer(&cs->dbusytimer);
if (cs->debug & L1_DEB_ISAC_FIFO) { if (cs->debug & L1_DEB_ISAC_FIFO) {
@ -584,8 +583,9 @@ DC_Close_isac(struct IsdnCardState *cs)
} }
static void static void
dbusy_timer_handler(struct IsdnCardState *cs) dbusy_timer_handler(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, dbusytimer);
struct PStack *stptr; struct PStack *stptr;
int rbch, star; int rbch, star;
@ -677,5 +677,5 @@ void clear_pending_isac_ints(struct IsdnCardState *cs)
void setup_isac(struct IsdnCardState *cs) void setup_isac(struct IsdnCardState *cs)
{ {
INIT_WORK(&cs->tqueue, isac_bh); INIT_WORK(&cs->tqueue, isac_bh);
setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler, (long)cs); timer_setup(&cs->dbusytimer, dbusy_timer_handler, 0);
} }

View File

@ -1267,7 +1267,8 @@ isar_int_main(struct IsdnCardState *cs)
} }
static void static void
ftimer_handler(struct BCState *bcs) { ftimer_handler(struct timer_list *t) {
struct BCState *bcs = from_timer(bcs, t, hw.isar.ftimer);
if (bcs->cs->debug) if (bcs->cs->debug)
debugl1(bcs->cs, "ftimer flags %04lx", debugl1(bcs->cs, "ftimer flags %04lx",
bcs->Flag); bcs->Flag);
@ -1902,8 +1903,6 @@ void initisar(struct IsdnCardState *cs)
cs->bcs[1].BC_SetStack = setstack_isar; cs->bcs[1].BC_SetStack = setstack_isar;
cs->bcs[0].BC_Close = close_isarstate; cs->bcs[0].BC_Close = close_isarstate;
cs->bcs[1].BC_Close = close_isarstate; cs->bcs[1].BC_Close = close_isarstate;
setup_timer(&cs->bcs[0].hw.isar.ftimer, (void *)ftimer_handler, timer_setup(&cs->bcs[0].hw.isar.ftimer, ftimer_handler, 0);
(long)&cs->bcs[0]); timer_setup(&cs->bcs[1].hw.isar.ftimer, ftimer_handler, 0);
setup_timer(&cs->bcs[1].hw.isar.ftimer, (void *)ftimer_handler,
(long)&cs->bcs[1]);
} }

View File

@ -160,8 +160,9 @@ newl3state(struct l3_process *pc, int state)
} }
static void static void
L3ExpireTimer(struct L3Timer *t) L3ExpireTimer(struct timer_list *timer)
{ {
struct L3Timer *t = from_timer(t, timer, tl);
t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc); t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc);
} }
@ -169,7 +170,7 @@ void
L3InitTimer(struct l3_process *pc, struct L3Timer *t) L3InitTimer(struct l3_process *pc, struct L3Timer *t)
{ {
t->pc = pc; t->pc = pc;
setup_timer(&t->tl, (void *)L3ExpireTimer, (long)t); timer_setup(&t->tl, L3ExpireTimer, 0);
} }
void void
@ -186,7 +187,6 @@ L3AddTimer(struct L3Timer *t,
printk(KERN_WARNING "L3AddTimer: timer already active!\n"); printk(KERN_WARNING "L3AddTimer: timer already active!\n");
return -1; return -1;
} }
init_timer(&t->tl);
t->event = event; t->event = event;
t->tl.expires = jiffies + (millisec * HZ) / 1000; t->tl.expires = jiffies + (millisec * HZ) / 1000;
add_timer(&t->tl); add_timer(&t->tl);

View File

@ -159,8 +159,9 @@ Start_ISAC:
} }
static void static void
SaphirWatchDog(struct IsdnCardState *cs) SaphirWatchDog(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, hw.saphir.timer);
u_long flags; u_long flags;
spin_lock_irqsave(&cs->lock, flags); spin_lock_irqsave(&cs->lock, flags);
@ -268,9 +269,7 @@ int setup_saphir(struct IsdnCard *card)
cs->irq, cs->hw.saphir.cfg_reg); cs->irq, cs->hw.saphir.cfg_reg);
setup_isac(cs); setup_isac(cs);
cs->hw.saphir.timer.function = (void *) SaphirWatchDog; timer_setup(&cs->hw.saphir.timer, SaphirWatchDog, 0);
cs->hw.saphir.timer.data = (long) cs;
init_timer(&cs->hw.saphir.timer);
cs->hw.saphir.timer.expires = jiffies + 4 * HZ; cs->hw.saphir.timer.expires = jiffies + 4 * HZ;
add_timer(&cs->hw.saphir.timer); add_timer(&cs->hw.saphir.timer);
if (saphir_reset(cs)) { if (saphir_reset(cs)) {

View File

@ -179,8 +179,9 @@ Start_ISAC:
} }
static void static void
TeleInt_Timer(struct IsdnCardState *cs) TeleInt_Timer(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, hw.hfc.timer);
int stat = 0; int stat = 0;
u_long flags; u_long flags;
@ -278,7 +279,7 @@ int setup_TeleInt(struct IsdnCard *card)
cs->bcs[0].hw.hfc.send = NULL; cs->bcs[0].hw.hfc.send = NULL;
cs->bcs[1].hw.hfc.send = NULL; cs->bcs[1].hw.hfc.send = NULL;
cs->hw.hfc.fifosize = 7 * 1024 + 512; cs->hw.hfc.fifosize = 7 * 1024 + 512;
setup_timer(&cs->hw.hfc.timer, (void *)TeleInt_Timer, (long)cs); timer_setup(&cs->hw.hfc.timer, TeleInt_Timer, 0);
if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) { if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: TeleInt config port %x-%x already in use\n", "HiSax: TeleInt config port %x-%x already in use\n",

View File

@ -188,7 +188,6 @@ W6692_fill_fifo(struct IsdnCardState *cs)
debugl1(cs, "W6692_fill_fifo dbusytimer running"); debugl1(cs, "W6692_fill_fifo dbusytimer running");
del_timer(&cs->dbusytimer); del_timer(&cs->dbusytimer);
} }
init_timer(&cs->dbusytimer);
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
add_timer(&cs->dbusytimer); add_timer(&cs->dbusytimer);
if (cs->debug & L1_DEB_ISAC_FIFO) { if (cs->debug & L1_DEB_ISAC_FIFO) {
@ -684,8 +683,9 @@ DC_Close_W6692(struct IsdnCardState *cs)
} }
static void static void
dbusy_timer_handler(struct IsdnCardState *cs) dbusy_timer_handler(struct timer_list *t)
{ {
struct IsdnCardState *cs = from_timer(cs, t, dbusytimer);
struct PStack *stptr; struct PStack *stptr;
int rbch, star; int rbch, star;
u_long flags; u_long flags;
@ -904,8 +904,7 @@ static void initW6692(struct IsdnCardState *cs, int part)
if (part & 1) { if (part & 1) {
cs->setstack_d = setstack_W6692; cs->setstack_d = setstack_W6692;
cs->DC_Close = DC_Close_W6692; cs->DC_Close = DC_Close_W6692;
setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler, timer_setup(&cs->dbusytimer, dbusy_timer_handler, 0);
(long)cs);
resetW6692(cs); resetW6692(cs);
ph_command(cs, W_L1CMD_RST); ph_command(cs, W_L1CMD_RST);
cs->dc.w6692.ph_state = W_L1CMD_RST; cs->dc.w6692.ph_state = W_L1CMD_RST;

View File

@ -90,9 +90,9 @@ isdnloop_bchan_send(isdnloop_card *card, int ch)
* data = pointer to card struct, set by kernel timer.data * data = pointer to card struct, set by kernel timer.data
*/ */
static void static void
isdnloop_pollbchan(unsigned long data) isdnloop_pollbchan(struct timer_list *t)
{ {
isdnloop_card *card = (isdnloop_card *) data; isdnloop_card *card = from_timer(card, t, rb_timer);
unsigned long flags; unsigned long flags;
if (card->flags & ISDNLOOP_FLAGS_B1ACTIVE) if (card->flags & ISDNLOOP_FLAGS_B1ACTIVE)
@ -305,9 +305,9 @@ isdnloop_putmsg(isdnloop_card *card, unsigned char c)
* data = pointer to card struct * data = pointer to card struct
*/ */
static void static void
isdnloop_polldchan(unsigned long data) isdnloop_polldchan(struct timer_list *t)
{ {
isdnloop_card *card = (isdnloop_card *) data; isdnloop_card *card = from_timer(card, t, st_timer);
struct sk_buff *skb; struct sk_buff *skb;
int avail; int avail;
int left; int left;
@ -373,8 +373,6 @@ isdnloop_polldchan(unsigned long data)
card->flags |= ISDNLOOP_FLAGS_RBTIMER; card->flags |= ISDNLOOP_FLAGS_RBTIMER;
spin_lock_irqsave(&card->isdnloop_lock, flags); spin_lock_irqsave(&card->isdnloop_lock, flags);
del_timer(&card->rb_timer); del_timer(&card->rb_timer);
card->rb_timer.function = isdnloop_pollbchan;
card->rb_timer.data = (unsigned long) card;
card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
add_timer(&card->rb_timer); add_timer(&card->rb_timer);
spin_unlock_irqrestore(&card->isdnloop_lock, flags); spin_unlock_irqrestore(&card->isdnloop_lock, flags);
@ -588,9 +586,10 @@ isdnloop_atimeout(isdnloop_card *card, int ch)
* Wrapper for isdnloop_atimeout(). * Wrapper for isdnloop_atimeout().
*/ */
static void static void
isdnloop_atimeout0(unsigned long data) isdnloop_atimeout0(struct timer_list *t)
{ {
isdnloop_card *card = (isdnloop_card *) data; isdnloop_card *card = from_timer(card, t, c_timer[0]);
isdnloop_atimeout(card, 0); isdnloop_atimeout(card, 0);
} }
@ -598,9 +597,10 @@ isdnloop_atimeout0(unsigned long data)
* Wrapper for isdnloop_atimeout(). * Wrapper for isdnloop_atimeout().
*/ */
static void static void
isdnloop_atimeout1(unsigned long data) isdnloop_atimeout1(struct timer_list *t)
{ {
isdnloop_card *card = (isdnloop_card *) data; isdnloop_card *card = from_timer(card, t, c_timer[1]);
isdnloop_atimeout(card, 1); isdnloop_atimeout(card, 1);
} }
@ -617,13 +617,9 @@ isdnloop_start_ctimer(isdnloop_card *card, int ch)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&card->isdnloop_lock, flags); spin_lock_irqsave(&card->isdnloop_lock, flags);
init_timer(&card->c_timer[ch]); timer_setup(&card->c_timer[ch], ch ? isdnloop_atimeout1
: isdnloop_atimeout0, 0);
card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT; card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT;
if (ch)
card->c_timer[ch].function = isdnloop_atimeout1;
else
card->c_timer[ch].function = isdnloop_atimeout0;
card->c_timer[ch].data = (unsigned long) card;
add_timer(&card->c_timer[ch]); add_timer(&card->c_timer[ch]);
spin_unlock_irqrestore(&card->isdnloop_lock, flags); spin_unlock_irqrestore(&card->isdnloop_lock, flags);
} }
@ -1113,10 +1109,9 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp)
sdef.ptype); sdef.ptype);
return -EINVAL; return -EINVAL;
} }
init_timer(&card->st_timer); timer_setup(&card->rb_timer, isdnloop_pollbchan, 0);
timer_setup(&card->st_timer, isdnloop_polldchan, 0);
card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
card->st_timer.function = isdnloop_polldchan;
card->st_timer.data = (unsigned long) card;
add_timer(&card->st_timer); add_timer(&card->st_timer);
card->flags |= ISDNLOOP_FLAGS_RUNNING; card->flags |= ISDNLOOP_FLAGS_RUNNING;
spin_unlock_irqrestore(&card->isdnloop_lock, flags); spin_unlock_irqrestore(&card->isdnloop_lock, flags);

View File

@ -259,7 +259,7 @@ extern u8 *dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len,
extern int dsp_tone(struct dsp *dsp, int tone); extern int dsp_tone(struct dsp *dsp, int tone);
extern void dsp_tone_copy(struct dsp *dsp, u8 *data, int len); extern void dsp_tone_copy(struct dsp *dsp, u8 *data, int len);
extern void dsp_tone_timeout(void *arg); extern void dsp_tone_timeout(struct timer_list *t);
extern void dsp_bf_encrypt(struct dsp *dsp, u8 *data, int len); extern void dsp_bf_encrypt(struct dsp *dsp, u8 *data, int len);
extern void dsp_bf_decrypt(struct dsp *dsp, u8 *data, int len); extern void dsp_bf_decrypt(struct dsp *dsp, u8 *data, int len);

View File

@ -1092,7 +1092,7 @@ dspcreate(struct channel_req *crq)
ndsp->pcm_bank_tx = -1; ndsp->pcm_bank_tx = -1;
ndsp->hfc_conf = -1; /* current conference number */ ndsp->hfc_conf = -1; /* current conference number */
/* set tone timer */ /* set tone timer */
setup_timer(&ndsp->tone.tl, (void *)dsp_tone_timeout, (long)ndsp); timer_setup(&ndsp->tone.tl, dsp_tone_timeout, 0);
if (dtmfthreshold < 20 || dtmfthreshold > 500) if (dtmfthreshold < 20 || dtmfthreshold > 500)
dtmfthreshold = 200; dtmfthreshold = 200;
@ -1202,9 +1202,7 @@ static int __init dsp_init(void)
} }
/* set sample timer */ /* set sample timer */
dsp_spl_tl.function = (void *)dsp_cmx_send; timer_setup(&dsp_spl_tl, (void *)dsp_cmx_send, 0);
dsp_spl_tl.data = 0;
init_timer(&dsp_spl_tl);
dsp_spl_tl.expires = jiffies + dsp_tics; dsp_spl_tl.expires = jiffies + dsp_tics;
dsp_spl_jiffies = dsp_spl_tl.expires; dsp_spl_jiffies = dsp_spl_tl.expires;
add_timer(&dsp_spl_tl); add_timer(&dsp_spl_tl);

View File

@ -457,9 +457,9 @@ dsp_tone_hw_message(struct dsp *dsp, u8 *sample, int len)
* timer expires * * timer expires *
*****************/ *****************/
void void
dsp_tone_timeout(void *arg) dsp_tone_timeout(struct timer_list *t)
{ {
struct dsp *dsp = arg; struct dsp *dsp = from_timer(dsp, t, tone.tl);
struct dsp_tone *tone = &dsp->tone; struct dsp_tone *tone = &dsp->tone;
struct pattern *pat = (struct pattern *)tone->pattern; struct pattern *pat = (struct pattern *)tone->pattern;
int index = tone->index; int index = tone->index;
@ -478,7 +478,6 @@ dsp_tone_timeout(void *arg)
else else
dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index])); dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index]));
/* set timer */ /* set timer */
init_timer(&tone->tl);
tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000; tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
add_timer(&tone->tl); add_timer(&tone->tl);
} }
@ -541,7 +540,6 @@ dsp_tone(struct dsp *dsp, int tone)
/* set timer */ /* set timer */
if (timer_pending(&tonet->tl)) if (timer_pending(&tonet->tl))
del_timer(&tonet->tl); del_timer(&tonet->tl);
init_timer(&tonet->tl);
tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000; tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000;
add_timer(&tonet->tl); add_timer(&tonet->tl);
} else { } else {

View File

@ -100,8 +100,9 @@ mISDN_FsmChangeState(struct FsmInst *fi, int newstate)
EXPORT_SYMBOL(mISDN_FsmChangeState); EXPORT_SYMBOL(mISDN_FsmChangeState);
static void static void
FsmExpireTimer(struct FsmTimer *ft) FsmExpireTimer(struct timer_list *t)
{ {
struct FsmTimer *ft = from_timer(ft, t, tl);
#if FSM_TIMER_DEBUG #if FSM_TIMER_DEBUG
if (ft->fi->debug) if (ft->fi->debug)
ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft); ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
@ -117,7 +118,7 @@ mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
if (ft->fi->debug) if (ft->fi->debug)
ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft); ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft);
#endif #endif
setup_timer(&ft->tl, (void *)FsmExpireTimer, (long)ft); timer_setup(&ft->tl, FsmExpireTimer, 0);
} }
EXPORT_SYMBOL(mISDN_FsmInitTimer); EXPORT_SYMBOL(mISDN_FsmInitTimer);
@ -153,7 +154,6 @@ mISDN_FsmAddTimer(struct FsmTimer *ft,
} }
return -1; return -1;
} }
init_timer(&ft->tl);
ft->event = event; ft->event = event;
ft->arg = arg; ft->arg = arg;
ft->tl.expires = jiffies + (millisec * HZ) / 1000; ft->tl.expires = jiffies + (millisec * HZ) / 1000;
@ -175,7 +175,6 @@ mISDN_FsmRestartTimer(struct FsmTimer *ft,
if (timer_pending(&ft->tl)) if (timer_pending(&ft->tl))
del_timer(&ft->tl); del_timer(&ft->tl);
init_timer(&ft->tl);
ft->event = event; ft->event = event;
ft->arg = arg; ft->arg = arg;
ft->tl.expires = jiffies + (millisec * HZ) / 1000; ft->tl.expires = jiffies + (millisec * HZ) / 1000;

View File

@ -440,14 +440,8 @@ l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase,
#ifdef REORDER_DEBUG #ifdef REORDER_DEBUG
if (hc->chan[channel].disorder_flag) { if (hc->chan[channel].disorder_flag) {
struct sk_buff *skb; swap(hc->chan[channel].disorder_skb, nskb);
int cnt; swap(hc->chan[channel].disorder_cnt, rx_counter);
skb = hc->chan[channel].disorder_skb;
hc->chan[channel].disorder_skb = nskb;
nskb = skb;
cnt = hc->chan[channel].disorder_cnt;
hc->chan[channel].disorder_cnt = rx_counter;
rx_counter = cnt;
} }
hc->chan[channel].disorder_flag ^= 1; hc->chan[channel].disorder_flag ^= 1;
if (nskb) if (nskb)
@ -842,17 +836,18 @@ l1oip_send_bh(struct work_struct *work)
* timer stuff * timer stuff
*/ */
static void static void
l1oip_keepalive(void *data) l1oip_keepalive(struct timer_list *t)
{ {
struct l1oip *hc = (struct l1oip *)data; struct l1oip *hc = from_timer(hc, t, keep_tl);
schedule_work(&hc->workq); schedule_work(&hc->workq);
} }
static void static void
l1oip_timeout(void *data) l1oip_timeout(struct timer_list *t)
{ {
struct l1oip *hc = (struct l1oip *)data; struct l1oip *hc = from_timer(hc, t,
timeout_tl);
struct dchannel *dch = hc->chan[hc->d_idx].dch; struct dchannel *dch = hc->chan[hc->d_idx].dch;
if (debug & DEBUG_L1OIP_MSG) if (debug & DEBUG_L1OIP_MSG)
@ -1437,13 +1432,11 @@ init_card(struct l1oip *hc, int pri, int bundle)
if (ret) if (ret)
return ret; return ret;
hc->keep_tl.function = (void *)l1oip_keepalive; timer_setup(&hc->keep_tl, l1oip_keepalive, 0);
hc->keep_tl.data = (ulong)hc;
init_timer(&hc->keep_tl);
hc->keep_tl.expires = jiffies + 2 * HZ; /* two seconds first time */ hc->keep_tl.expires = jiffies + 2 * HZ; /* two seconds first time */
add_timer(&hc->keep_tl); add_timer(&hc->keep_tl);
setup_timer(&hc->timeout_tl, (void *)l1oip_timeout, (ulong)hc); timer_setup(&hc->timeout_tl, l1oip_timeout, 0);
hc->timeout_on = 0; /* state that we have timer off */ hc->timeout_on = 0; /* state that we have timer off */
return 0; return 0;

View File

@ -162,9 +162,9 @@ mISDN_poll(struct file *filep, poll_table *wait)
} }
static void static void
dev_expire_timer(unsigned long data) dev_expire_timer(struct timer_list *t)
{ {
struct mISDNtimer *timer = (void *)data; struct mISDNtimer *timer = from_timer(timer, t, tl);
u_long flags; u_long flags;
spin_lock_irqsave(&timer->dev->lock, flags); spin_lock_irqsave(&timer->dev->lock, flags);
@ -189,7 +189,7 @@ misdn_add_timer(struct mISDNtimerdev *dev, int timeout)
if (!timer) if (!timer)
return -ENOMEM; return -ENOMEM;
timer->dev = dev; timer->dev = dev;
setup_timer(&timer->tl, dev_expire_timer, (long)timer); timer_setup(&timer->tl, dev_expire_timer, 0);
spin_lock_irq(&dev->lock); spin_lock_irq(&dev->lock);
id = timer->id = dev->next_id++; id = timer->id = dev->next_id++;
if (dev->next_id < 0) if (dev->next_id < 0)

View File

@ -483,6 +483,18 @@ config FUJITSU_ES
This driver provides support for Extended Socket network device This driver provides support for Extended Socket network device
on Extended Partitioning of FUJITSU PRIMEQUEST 2000 E2 series. on Extended Partitioning of FUJITSU PRIMEQUEST 2000 E2 series.
config THUNDERBOLT_NET
tristate "Networking over Thunderbolt cable"
depends on THUNDERBOLT && INET
help
Select this if you want to create network between two
computers over a Thunderbolt cable. The driver supports Apple
ThunderboltIP protocol and allows communication with any host
supporting the same protocol including Windows and macOS.
To compile this driver a module, choose M here. The module will be
called thunderbolt-net.
source "drivers/net/hyperv/Kconfig" source "drivers/net/hyperv/Kconfig"
endif # NETDEVICES endif # NETDEVICES

View File

@ -75,3 +75,6 @@ obj-$(CONFIG_HYPERV_NET) += hyperv/
obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
obj-$(CONFIG_FUJITSU_ES) += fjes/ obj-$(CONFIG_FUJITSU_ES) += fjes/
thunderbolt-net-y += thunderbolt.o
obj-$(CONFIG_THUNDERBOLT_NET) += thunderbolt-net.o

View File

@ -155,6 +155,7 @@ static int cops_irqlist[] = {
}; };
static struct timer_list cops_timer; static struct timer_list cops_timer;
static struct net_device *cops_timer_dev;
/* use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */ /* use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */
#ifndef COPS_DEBUG #ifndef COPS_DEBUG
@ -187,7 +188,7 @@ static void cops_load (struct net_device *dev);
static int cops_nodeid (struct net_device *dev, int nodeid); static int cops_nodeid (struct net_device *dev, int nodeid);
static irqreturn_t cops_interrupt (int irq, void *dev_id); static irqreturn_t cops_interrupt (int irq, void *dev_id);
static void cops_poll (unsigned long ltdev); static void cops_poll(struct timer_list *t);
static void cops_timeout(struct net_device *dev); static void cops_timeout(struct net_device *dev);
static void cops_rx (struct net_device *dev); static void cops_rx (struct net_device *dev);
static netdev_tx_t cops_send_packet (struct sk_buff *skb, static netdev_tx_t cops_send_packet (struct sk_buff *skb,
@ -424,9 +425,8 @@ static int cops_open(struct net_device *dev)
*/ */
if(lp->board==TANGENT) /* Poll 20 times per second */ if(lp->board==TANGENT) /* Poll 20 times per second */
{ {
init_timer(&cops_timer); cops_timer_dev = dev;
cops_timer.function = cops_poll; timer_setup(&cops_timer, cops_poll, 0);
cops_timer.data = (unsigned long)dev;
cops_timer.expires = jiffies + HZ/20; cops_timer.expires = jiffies + HZ/20;
add_timer(&cops_timer); add_timer(&cops_timer);
} }
@ -673,12 +673,11 @@ static int cops_nodeid (struct net_device *dev, int nodeid)
* Poll the Tangent type cards to see if we have work. * Poll the Tangent type cards to see if we have work.
*/ */
static void cops_poll(unsigned long ltdev) static void cops_poll(struct timer_list *unused)
{ {
int ioaddr, status; int ioaddr, status;
int boguscount = 0; int boguscount = 0;
struct net_device *dev = cops_timer_dev;
struct net_device *dev = (struct net_device *)ltdev;
del_timer(&cops_timer); del_timer(&cops_timer);

View File

@ -694,6 +694,7 @@ static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
/* end of idle handlers -- what should be seen is do_read, do_write */ /* end of idle handlers -- what should be seen is do_read, do_write */
static struct timer_list ltpc_timer; static struct timer_list ltpc_timer;
static struct net_device *ltpc_timer_dev;
static netdev_tx_t ltpc_xmit(struct sk_buff *skb, struct net_device *dev); static netdev_tx_t ltpc_xmit(struct sk_buff *skb, struct net_device *dev);
@ -867,10 +868,8 @@ static void set_multicast_list(struct net_device *dev)
static int ltpc_poll_counter; static int ltpc_poll_counter;
static void ltpc_poll(unsigned long l) static void ltpc_poll(struct timer_list *unused)
{ {
struct net_device *dev = (struct net_device *) l;
del_timer(&ltpc_timer); del_timer(&ltpc_timer);
if(debug & DEBUG_VERBOSE) { if(debug & DEBUG_VERBOSE) {
@ -880,14 +879,10 @@ static void ltpc_poll(unsigned long l)
} }
ltpc_poll_counter--; ltpc_poll_counter--;
} }
if (!dev)
return; /* we've been downed */
/* poll 20 times per second */ /* poll 20 times per second */
idle(dev); idle(ltpc_timer_dev);
ltpc_timer.expires = jiffies + HZ/20; ltpc_timer.expires = jiffies + HZ/20;
add_timer(&ltpc_timer); add_timer(&ltpc_timer);
} }
@ -1165,9 +1160,8 @@ struct net_device * __init ltpc_probe(void)
dev->irq = 0; dev->irq = 0;
/* polled mode -- 20 times per second */ /* polled mode -- 20 times per second */
/* this is really, really slow... should it poll more often? */ /* this is really, really slow... should it poll more often? */
init_timer(&ltpc_timer); ltpc_timer_dev = dev;
ltpc_timer.function=ltpc_poll; timer_setup(&ltpc_timer, ltpc_poll, 0);
ltpc_timer.data = (unsigned long) dev;
ltpc_timer.expires = jiffies + HZ/20; ltpc_timer.expires = jiffies + HZ/20;
add_timer(&ltpc_timer); add_timer(&ltpc_timer);
@ -1254,8 +1248,6 @@ static void __exit ltpc_cleanup(void)
if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n"); if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n");
unregister_netdev(dev_ltpc); unregister_netdev(dev_ltpc);
ltpc_timer.data = 0; /* signal the poll routine that we're done */
del_timer_sync(&ltpc_timer); del_timer_sync(&ltpc_timer);
if(debug & DEBUG_VERBOSE) printk("freeing irq\n"); if(debug & DEBUG_VERBOSE) printk("freeing irq\n");

View File

@ -382,9 +382,10 @@ static void arcdev_setup(struct net_device *dev)
dev->flags = IFF_BROADCAST; dev->flags = IFF_BROADCAST;
} }
static void arcnet_timer(unsigned long data) static void arcnet_timer(struct timer_list *t)
{ {
struct net_device *dev = (struct net_device *)data; struct arcnet_local *lp = from_timer(lp, t, timer);
struct net_device *dev = lp->dev;
if (!netif_carrier_ok(dev)) { if (!netif_carrier_ok(dev)) {
netif_carrier_on(dev); netif_carrier_on(dev);
@ -450,9 +451,7 @@ struct net_device *alloc_arcdev(const char *name)
lp->dev = dev; lp->dev = dev;
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
init_timer(&lp->timer); timer_setup(&lp->timer, arcnet_timer, 0);
lp->timer.data = (unsigned long) dev;
lp->timer.function = arcnet_timer;
} }
return dev; return dev;

View File

@ -1217,25 +1217,21 @@ static enum netdev_lag_tx_type bond_lag_tx_type(struct bonding *bond)
} }
} }
static int bond_master_upper_dev_link(struct bonding *bond, struct slave *slave) static int bond_master_upper_dev_link(struct bonding *bond, struct slave *slave,
struct netlink_ext_ack *extack)
{ {
struct netdev_lag_upper_info lag_upper_info; struct netdev_lag_upper_info lag_upper_info;
int err;
lag_upper_info.tx_type = bond_lag_tx_type(bond); lag_upper_info.tx_type = bond_lag_tx_type(bond);
err = netdev_master_upper_dev_link(slave->dev, bond->dev, slave,
&lag_upper_info); return netdev_master_upper_dev_link(slave->dev, bond->dev, slave,
if (err) &lag_upper_info, extack);
return err;
rtmsg_ifinfo(RTM_NEWLINK, slave->dev, IFF_SLAVE, GFP_KERNEL);
return 0;
} }
static void bond_upper_dev_unlink(struct bonding *bond, struct slave *slave) static void bond_upper_dev_unlink(struct bonding *bond, struct slave *slave)
{ {
netdev_upper_dev_unlink(slave->dev, bond->dev); netdev_upper_dev_unlink(slave->dev, bond->dev);
slave->dev->flags &= ~IFF_SLAVE; slave->dev->flags &= ~IFF_SLAVE;
rtmsg_ifinfo(RTM_NEWLINK, slave->dev, IFF_SLAVE, GFP_KERNEL);
} }
static struct slave *bond_alloc_slave(struct bonding *bond) static struct slave *bond_alloc_slave(struct bonding *bond)
@ -1328,7 +1324,8 @@ void bond_lower_state_changed(struct slave *slave)
} }
/* enslave device <slave> to bond device <master> */ /* enslave device <slave> to bond device <master> */
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
struct netlink_ext_ack *extack)
{ {
struct bonding *bond = netdev_priv(bond_dev); struct bonding *bond = netdev_priv(bond_dev);
const struct net_device_ops *slave_ops = slave_dev->netdev_ops; const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
@ -1346,12 +1343,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* already in-use? */ /* already in-use? */
if (netdev_is_rx_handler_busy(slave_dev)) { if (netdev_is_rx_handler_busy(slave_dev)) {
NL_SET_ERR_MSG(extack, "Device is in use and cannot be enslaved");
netdev_err(bond_dev, netdev_err(bond_dev,
"Error: Device is in use and cannot be enslaved\n"); "Error: Device is in use and cannot be enslaved\n");
return -EBUSY; return -EBUSY;
} }
if (bond_dev == slave_dev) { if (bond_dev == slave_dev) {
NL_SET_ERR_MSG(extack, "Cannot enslave bond to itself.");
netdev_err(bond_dev, "cannot enslave bond to itself.\n"); netdev_err(bond_dev, "cannot enslave bond to itself.\n");
return -EPERM; return -EPERM;
} }
@ -1362,6 +1361,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
netdev_dbg(bond_dev, "%s is NETIF_F_VLAN_CHALLENGED\n", netdev_dbg(bond_dev, "%s is NETIF_F_VLAN_CHALLENGED\n",
slave_dev->name); slave_dev->name);
if (vlan_uses_dev(bond_dev)) { if (vlan_uses_dev(bond_dev)) {
NL_SET_ERR_MSG(extack, "Can not enslave VLAN challenged device to VLAN enabled bond");
netdev_err(bond_dev, "Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", netdev_err(bond_dev, "Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
slave_dev->name, bond_dev->name); slave_dev->name, bond_dev->name);
return -EPERM; return -EPERM;
@ -1381,6 +1381,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* enslaving it; the old ifenslave will not. * enslaving it; the old ifenslave will not.
*/ */
if (slave_dev->flags & IFF_UP) { if (slave_dev->flags & IFF_UP) {
NL_SET_ERR_MSG(extack, "Device can not be enslaved while up");
netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n", netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n",
slave_dev->name); slave_dev->name);
return -EPERM; return -EPERM;
@ -1421,6 +1422,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_dev); bond_dev);
} }
} else if (bond_dev->type != slave_dev->type) { } else if (bond_dev->type != slave_dev->type) {
NL_SET_ERR_MSG(extack, "Device type is different from other slaves");
netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n", netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
slave_dev->name, slave_dev->type, bond_dev->type); slave_dev->name, slave_dev->type, bond_dev->type);
return -EINVAL; return -EINVAL;
@ -1428,6 +1430,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (slave_dev->type == ARPHRD_INFINIBAND && if (slave_dev->type == ARPHRD_INFINIBAND &&
BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
NL_SET_ERR_MSG(extack, "Only active-backup mode is supported for infiniband slaves");
netdev_warn(bond_dev, "Type (%d) supports only active-backup mode\n", netdev_warn(bond_dev, "Type (%d) supports only active-backup mode\n",
slave_dev->type); slave_dev->type);
res = -EOPNOTSUPP; res = -EOPNOTSUPP;
@ -1443,6 +1446,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond->params.fail_over_mac = BOND_FOM_ACTIVE; bond->params.fail_over_mac = BOND_FOM_ACTIVE;
netdev_warn(bond_dev, "Setting fail_over_mac to active for active-backup mode\n"); netdev_warn(bond_dev, "Setting fail_over_mac to active for active-backup mode\n");
} else { } else {
NL_SET_ERR_MSG(extack, "Slave device does not support setting the MAC address, but fail_over_mac is not set to active");
netdev_err(bond_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n"); netdev_err(bond_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n");
res = -EOPNOTSUPP; res = -EOPNOTSUPP;
goto err_undo_flags; goto err_undo_flags;
@ -1709,7 +1713,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_detach; goto err_detach;
} }
res = bond_master_upper_dev_link(bond, new_slave); res = bond_master_upper_dev_link(bond, new_slave, extack);
if (res) { if (res) {
netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res); netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res);
goto err_unregister; goto err_unregister;
@ -2492,7 +2496,8 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
struct slave *curr_active_slave, *curr_arp_slave; struct slave *curr_active_slave, *curr_arp_slave;
unsigned char *arp_ptr; unsigned char *arp_ptr;
__be32 sip, tip; __be32 sip, tip;
int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP); int is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
unsigned int alen;
if (!slave_do_arp_validate(bond, slave)) { if (!slave_do_arp_validate(bond, slave)) {
if ((slave_do_arp_validate_only(bond) && is_arp) || if ((slave_do_arp_validate_only(bond) && is_arp) ||
@ -3073,7 +3078,16 @@ static int bond_slave_netdev_event(unsigned long event,
break; break;
case NETDEV_UP: case NETDEV_UP:
case NETDEV_CHANGE: case NETDEV_CHANGE:
bond_update_speed_duplex(slave); /* For 802.3ad mode only:
* Getting invalid Speed/Duplex values here will put slave
* in weird state. So mark it as link-down for the time
* being and let link-monitoring (miimon) set it right when
* correct speeds/duplex are available.
*/
if (bond_update_speed_duplex(slave) &&
BOND_MODE(bond) == BOND_MODE_8023AD)
slave->link = BOND_LINK_DOWN;
if (BOND_MODE(bond) == BOND_MODE_8023AD) if (BOND_MODE(bond) == BOND_MODE_8023AD)
bond_3ad_adapter_speed_duplex_changed(slave); bond_3ad_adapter_speed_duplex_changed(slave);
/* Fallthrough */ /* Fallthrough */
@ -3483,7 +3497,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
switch (cmd) { switch (cmd) {
case BOND_ENSLAVE_OLD: case BOND_ENSLAVE_OLD:
case SIOCBONDENSLAVE: case SIOCBONDENSLAVE:
res = bond_enslave(bond_dev, slave_dev); res = bond_enslave(bond_dev, slave_dev, NULL);
break; break;
case BOND_RELEASE_OLD: case BOND_RELEASE_OLD:
case SIOCBONDRELEASE: case SIOCBONDRELEASE:

View File

@ -1383,7 +1383,7 @@ static int bond_option_slaves_set(struct bonding *bond,
switch (command[0]) { switch (command[0]) {
case '+': case '+':
netdev_dbg(bond->dev, "Adding slave %s\n", dev->name); netdev_dbg(bond->dev, "Adding slave %s\n", dev->name);
ret = bond_enslave(bond->dev, dev); ret = bond_enslave(bond->dev, dev, NULL);
break; break;
case '-': case '-':

View File

@ -1211,17 +1211,14 @@ static int cfhsi_open(struct net_device *ndev)
init_waitqueue_head(&cfhsi->flush_fifo_wait); init_waitqueue_head(&cfhsi->flush_fifo_wait);
/* Setup the inactivity timer. */ /* Setup the inactivity timer. */
init_timer(&cfhsi->inactivity_timer); setup_timer(&cfhsi->inactivity_timer, cfhsi_inactivity_tout,
cfhsi->inactivity_timer.data = (unsigned long)cfhsi; (unsigned long)cfhsi);
cfhsi->inactivity_timer.function = cfhsi_inactivity_tout;
/* Setup the slowpath RX timer. */ /* Setup the slowpath RX timer. */
init_timer(&cfhsi->rx_slowpath_timer); setup_timer(&cfhsi->rx_slowpath_timer, cfhsi_rx_slowpath,
cfhsi->rx_slowpath_timer.data = (unsigned long)cfhsi; (unsigned long)cfhsi);
cfhsi->rx_slowpath_timer.function = cfhsi_rx_slowpath;
/* Setup the aggregation timer. */ /* Setup the aggregation timer. */
init_timer(&cfhsi->aggregation_timer); setup_timer(&cfhsi->aggregation_timer, cfhsi_aggregation_tout,
cfhsi->aggregation_timer.data = (unsigned long)cfhsi; (unsigned long)cfhsi);
cfhsi->aggregation_timer.function = cfhsi_aggregation_tout;
/* Activate HSI interface. */ /* Activate HSI interface. */
res = cfhsi->ops->cfhsi_up(cfhsi->ops); res = cfhsi->ops->cfhsi_up(cfhsi->ops);

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