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:
commit
5bbcc0f595
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
|
@ -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).
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
|
@ -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.
|
||||||
|
|
|
@ -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 -
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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_.
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
42
MAINTAINERS
42
MAINTAINERS
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) &&
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(¶ms->otp_bdaddr, BDADDR_ANY)) {
|
if (!bacmp(¶ms->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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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(<pc_timer);
|
del_timer(<pc_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(<pc_timer);
|
add_timer(<pc_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(<pc_timer);
|
ltpc_timer_dev = dev;
|
||||||
ltpc_timer.function=ltpc_poll;
|
timer_setup(<pc_timer, ltpc_poll, 0);
|
||||||
ltpc_timer.data = (unsigned long) dev;
|
|
||||||
|
|
||||||
ltpc_timer.expires = jiffies + HZ/20;
|
ltpc_timer.expires = jiffies + HZ/20;
|
||||||
add_timer(<pc_timer);
|
add_timer(<pc_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(<pc_timer);
|
del_timer_sync(<pc_timer);
|
||||||
|
|
||||||
if(debug & DEBUG_VERBOSE) printk("freeing irq\n");
|
if(debug & DEBUG_VERBOSE) printk("freeing irq\n");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 '-':
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue