mirror of https://gitee.com/openkylin/linux.git
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) BPF debugger and asm tool by Daniel Borkmann. 2) Speed up create/bind in AF_PACKET, also from Daniel Borkmann. 3) Correct reciprocal_divide and update users, from Hannes Frederic Sowa and Daniel Borkmann. 4) Currently we only have a "set" operation for the hw timestamp socket ioctl, add a "get" operation to match. From Ben Hutchings. 5) Add better trace events for debugging driver datapath problems, also from Ben Hutchings. 6) Implement auto corking in TCP, from Eric Dumazet. Basically, if we have a small send and a previous packet is already in the qdisc or device queue, defer until TX completion or we get more data. 7) Allow userspace to manage ipv6 temporary addresses, from Jiri Pirko. 8) Add a qdisc bypass option for AF_PACKET sockets, from Daniel Borkmann. 9) Share IP header compression code between Bluetooth and IEEE802154 layers, from Jukka Rissanen. 10) Fix ipv6 router reachability probing, from Jiri Benc. 11) Allow packets to be captured on macvtap devices, from Vlad Yasevich. 12) Support tunneling in GRO layer, from Jerry Chu. 13) Allow bonding to be configured fully using netlink, from Scott Feldman. 14) Allow AF_PACKET users to obtain the VLAN TPID, just like they can already get the TCI. From Atzm Watanabe. 15) New "Heavy Hitter" qdisc, from Terry Lam. 16) Significantly improve the IPSEC support in pktgen, from Fan Du. 17) Allow ipv4 tunnels to cache routes, just like sockets. From Tom Herbert. 18) Add Proportional Integral Enhanced packet scheduler, from Vijay Subramanian. 19) Allow openvswitch to mmap'd netlink, from Thomas Graf. 20) Key TCP metrics blobs also by source address, not just destination address. From Christoph Paasch. 21) Support 10G in generic phylib. From Andy Fleming. 22) Try to short-circuit GRO flow compares using device provided RX hash, if provided. From Tom Herbert. The wireless and netfilter folks have been busy little bees too. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (2064 commits) net/cxgb4: Fix referencing freed adapter ipv6: reallocate addrconf router for ipv6 address when lo device up fib_frontend: fix possible NULL pointer dereference rtnetlink: remove IFLA_BOND_SLAVE definition rtnetlink: remove check for fill_slave_info in rtnl_have_link_slave_info qlcnic: update version to 5.3.55 qlcnic: Enhance logic to calculate msix vectors. qlcnic: Refactor interrupt coalescing code for all adapters. qlcnic: Update poll controller code path qlcnic: Interrupt code cleanup qlcnic: Enhance Tx timeout debugging. qlcnic: Use bool for rx_mac_learn. bonding: fix u64 division rtnetlink: add missing IFLA_BOND_AD_INFO_UNSPEC sfc: Use the correct maximum TX DMA ring size for SFC9100 Add Shradha Shah as the sfc driver maintainer. net/vxlan: Share RX skb de-marking and checksum checks with ovs tulip: cleanup by using ARRAY_SIZE() ip_tunnel: clear IPCB in ip_tunnel_xmit() in case dst_link_failure() is called net/cxgb4: Don't retrieve stats during recovery ...
This commit is contained in:
commit
4ba9920e5e
|
@ -68,6 +68,14 @@ Description:
|
||||||
Defines the penalty which will be applied to an
|
Defines the penalty which will be applied to an
|
||||||
originator message's tq-field on every hop.
|
originator message's tq-field on every hop.
|
||||||
|
|
||||||
|
What: /sys/class/net/<mesh_iface>/mesh/isolation_mark
|
||||||
|
Date: Nov 2013
|
||||||
|
Contact: Antonio Quartulli <antonio@meshcoding.com>
|
||||||
|
Description:
|
||||||
|
Defines the isolation mark (and its bitmask) which
|
||||||
|
is used to classify clients as "isolated" by the
|
||||||
|
Extended Isolation feature.
|
||||||
|
|
||||||
What: /sys/class/net/<mesh_iface>/mesh/network_coding
|
What: /sys/class/net/<mesh_iface>/mesh/network_coding
|
||||||
Date: Nov 2012
|
Date: Nov 2012
|
||||||
Contact: Martin Hundeboll <martin@hundeboll.net>
|
Contact: Martin Hundeboll <martin@hundeboll.net>
|
||||||
|
|
|
@ -6,6 +6,8 @@ tag network packets with a class identifier (classid).
|
||||||
|
|
||||||
The Traffic Controller (tc) can be used to assign
|
The Traffic Controller (tc) can be used to assign
|
||||||
different priorities to packets from different cgroups.
|
different priorities to packets from different cgroups.
|
||||||
|
Also, Netfilter (iptables) can use this tag to perform
|
||||||
|
actions on such packets.
|
||||||
|
|
||||||
Creating a net_cls cgroups instance creates a net_cls.classid file.
|
Creating a net_cls cgroups instance creates a net_cls.classid file.
|
||||||
This net_cls.classid value is initialized to 0.
|
This net_cls.classid value is initialized to 0.
|
||||||
|
@ -32,3 +34,6 @@ tc class add dev eth0 parent 10: classid 10:1 htb rate 40mbit
|
||||||
- creating traffic class 10:1
|
- creating traffic class 10:1
|
||||||
|
|
||||||
tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup
|
tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup
|
||||||
|
|
||||||
|
configuring iptables, basic example:
|
||||||
|
iptables -A OUTPUT -m cgroup ! --cgroup 0x100001 -j DROP
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
* Allwinner GMAC ethernet controller
|
||||||
|
|
||||||
|
This device is a platform glue layer for stmmac.
|
||||||
|
Please see stmmac.txt for the other unchanged properties.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Should be "allwinner,sun7i-a20-gmac"
|
||||||
|
- clocks: Should contain the GMAC main clock, and tx clock
|
||||||
|
The tx clock type should be "allwinner,sun7i-a20-gmac-clk"
|
||||||
|
- clock-names: Should contain the clock names "stmmaceth",
|
||||||
|
and "allwinner_gmac_tx"
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- phy-supply: phandle to a regulator if the PHY needs one
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
gmac: ethernet@01c50000 {
|
||||||
|
compatible = "allwinner,sun7i-a20-gmac";
|
||||||
|
reg = <0x01c50000 0x10000>,
|
||||||
|
<0x01c20164 0x4>;
|
||||||
|
interrupts = <0 85 1>;
|
||||||
|
interrupt-names = "macirq";
|
||||||
|
clocks = <&ahb_gates 49>, <&gmac_tx>;
|
||||||
|
clock-names = "stmmaceth", "allwinner_gmac_tx";
|
||||||
|
phy-mode = "mii";
|
||||||
|
};
|
|
@ -0,0 +1,25 @@
|
||||||
|
* Microchip MCP251X stand-alone CAN controller device tree bindings
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Should be one of the following:
|
||||||
|
- "microchip,mcp2510" for MCP2510.
|
||||||
|
- "microchip,mcp2515" for MCP2515.
|
||||||
|
- reg: SPI chip select.
|
||||||
|
- clocks: The clock feeding the CAN controller.
|
||||||
|
- interrupt-parent: The parent interrupt controller.
|
||||||
|
- interrupts: Should contain IRQ line for the CAN controller.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- vdd-supply: Regulator that powers the CAN controller.
|
||||||
|
- xceiver-supply: Regulator that powers the CAN transceiver.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
can0: can@1 {
|
||||||
|
compatible = "microchip,mcp2515";
|
||||||
|
reg = <1>;
|
||||||
|
clocks = <&clk24m>;
|
||||||
|
interrupt-parent = <&gpio4>;
|
||||||
|
interrupts = <13 0x2>;
|
||||||
|
vdd-supply = <®5v0>;
|
||||||
|
xceiver-supply = <®5v0>;
|
||||||
|
};
|
|
@ -12,8 +12,6 @@ Required properties:
|
||||||
- ti,davinci-ctrl-ram-size: size of control module ram
|
- ti,davinci-ctrl-ram-size: size of control module ram
|
||||||
- ti,davinci-rmii-en: use RMII
|
- ti,davinci-rmii-en: use RMII
|
||||||
- ti,davinci-no-bd-ram: has the emac controller BD RAM
|
- ti,davinci-no-bd-ram: has the emac controller BD RAM
|
||||||
- phy-handle: Contains a phandle to an Ethernet PHY.
|
|
||||||
if not, davinci_emac driver defaults to 100/FULL
|
|
||||||
- interrupts: interrupt mapping for the davinci emac interrupts sources:
|
- interrupts: interrupt mapping for the davinci emac interrupts sources:
|
||||||
4 sources: <Receive Threshold Interrupt
|
4 sources: <Receive Threshold Interrupt
|
||||||
Receive Interrupt
|
Receive Interrupt
|
||||||
|
@ -21,6 +19,8 @@ Required properties:
|
||||||
Miscellaneous Interrupt>
|
Miscellaneous Interrupt>
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
|
- phy-handle: Contains a phandle to an Ethernet PHY.
|
||||||
|
If absent, davinci_emac driver defaults to 100/FULL.
|
||||||
- local-mac-address : 6 bytes, mac address
|
- local-mac-address : 6 bytes, mac address
|
||||||
|
|
||||||
Example (enbw_cmc board):
|
Example (enbw_cmc board):
|
||||||
|
|
|
@ -19,6 +19,7 @@ Optional Properties:
|
||||||
specifications. If neither of these are specified, the default is to
|
specifications. If neither of these are specified, the default is to
|
||||||
assume clause 22. The compatible list may also contain other
|
assume clause 22. The compatible list may also contain other
|
||||||
elements.
|
elements.
|
||||||
|
- max-speed: Maximum PHY supported speed (10, 100, 1000...)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ Required properties:
|
||||||
property
|
property
|
||||||
- phy-mode: String, operation mode of the PHY interface.
|
- phy-mode: String, operation mode of the PHY interface.
|
||||||
Supported values are: "mii", "rmii", "gmii", "rgmii".
|
Supported values are: "mii", "rmii", "gmii", "rgmii".
|
||||||
- snps,phy-addr phy address to connect to.
|
|
||||||
- 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.
|
||||||
- snps,reset-delays-us is triplet of delays
|
- snps,reset-delays-us is triplet of delays
|
||||||
|
@ -30,6 +29,11 @@ Required properties:
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- mac-address: 6 bytes, mac address
|
- mac-address: 6 bytes, mac address
|
||||||
|
- resets: Should contain a phandle to the STMMAC reset signal, if any
|
||||||
|
- reset-names: Should contain the reset signal name "stmmaceth", if a
|
||||||
|
reset phandle is given
|
||||||
|
- max-frame-size: Maximum Transfer Unit (IEEE defined MTU), rather
|
||||||
|
than the maximum frame size.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
@ -40,5 +44,6 @@ Examples:
|
||||||
interrupts = <24 23>;
|
interrupts = <24 23>;
|
||||||
interrupt-names = "macirq", "eth_wake_irq";
|
interrupt-names = "macirq", "eth_wake_irq";
|
||||||
mac-address = [000000000000]; /* Filled in by U-Boot */
|
mac-address = [000000000000]; /* Filled in by U-Boot */
|
||||||
|
max-frame-size = <3800>;
|
||||||
phy-mode = "gmii";
|
phy-mode = "gmii";
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,11 +66,10 @@ All mesh wide settings can be found in batman's own interface
|
||||||
folder:
|
folder:
|
||||||
|
|
||||||
# ls /sys/class/net/bat0/mesh/
|
# ls /sys/class/net/bat0/mesh/
|
||||||
# aggregated_ogms gw_bandwidth log_level
|
#aggregated_ogms distributed_arp_table gw_sel_class orig_interval
|
||||||
# ap_isolation gw_mode orig_interval
|
#ap_isolation fragmentation hop_penalty routing_algo
|
||||||
# bonding gw_sel_class routing_algo
|
#bonding gw_bandwidth isolation_mark vlan0
|
||||||
# bridge_loop_avoidance hop_penalty fragmentation
|
#bridge_loop_avoidance gw_mode log_level
|
||||||
|
|
||||||
|
|
||||||
There is a special folder for debugging information:
|
There is a special folder for debugging information:
|
||||||
|
|
||||||
|
|
|
@ -657,7 +657,8 @@ primary
|
||||||
one slave is preferred over another, e.g., when one slave has
|
one slave is preferred over another, e.g., when one slave has
|
||||||
higher throughput than another.
|
higher throughput than another.
|
||||||
|
|
||||||
The primary option is only valid for active-backup mode.
|
The primary option is only valid for active-backup(1),
|
||||||
|
balance-tlb (5) and balance-alb (6) mode.
|
||||||
|
|
||||||
primary_reselect
|
primary_reselect
|
||||||
|
|
||||||
|
@ -853,6 +854,14 @@ resend_igmp
|
||||||
|
|
||||||
This option was added for bonding version 3.7.0.
|
This option was added for bonding version 3.7.0.
|
||||||
|
|
||||||
|
lp_interval
|
||||||
|
|
||||||
|
Specifies the number of seconds between instances where the bonding
|
||||||
|
driver sends learning packets to each slaves peer switch.
|
||||||
|
|
||||||
|
The valid range is 1 - 0x7fffffff; the default value is 1. This Option
|
||||||
|
has effect only in balance-tlb and balance-alb modes.
|
||||||
|
|
||||||
3. Configuring Bonding Devices
|
3. Configuring Bonding Devices
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,20 @@
|
||||||
|
|
||||||
can.txt
|
can.txt
|
||||||
|
|
||||||
Readme file for the Controller Area Network Protocol Family (aka Socket CAN)
|
Readme file for the Controller Area Network Protocol Family (aka SocketCAN)
|
||||||
|
|
||||||
This file contains
|
This file contains
|
||||||
|
|
||||||
1 Overview / What is Socket CAN
|
1 Overview / What is SocketCAN
|
||||||
|
|
||||||
2 Motivation / Why using the socket API
|
2 Motivation / Why using the socket API
|
||||||
|
|
||||||
3 Socket CAN concept
|
3 SocketCAN concept
|
||||||
3.1 receive lists
|
3.1 receive lists
|
||||||
3.2 local loopback of sent frames
|
3.2 local loopback of sent frames
|
||||||
3.3 network security issues (capabilities)
|
3.3 network problem notifications
|
||||||
3.4 network problem notifications
|
|
||||||
|
|
||||||
4 How to use Socket CAN
|
4 How to use SocketCAN
|
||||||
4.1 RAW protocol sockets with can_filters (SOCK_RAW)
|
4.1 RAW protocol sockets with can_filters (SOCK_RAW)
|
||||||
4.1.1 RAW socket option CAN_RAW_FILTER
|
4.1.1 RAW socket option CAN_RAW_FILTER
|
||||||
4.1.2 RAW socket option CAN_RAW_ERR_FILTER
|
4.1.2 RAW socket option CAN_RAW_ERR_FILTER
|
||||||
|
@ -34,7 +33,7 @@ This file contains
|
||||||
4.3 connected transport protocols (SOCK_SEQPACKET)
|
4.3 connected transport protocols (SOCK_SEQPACKET)
|
||||||
4.4 unconnected transport protocols (SOCK_DGRAM)
|
4.4 unconnected transport protocols (SOCK_DGRAM)
|
||||||
|
|
||||||
5 Socket CAN core module
|
5 SocketCAN core module
|
||||||
5.1 can.ko module params
|
5.1 can.ko module params
|
||||||
5.2 procfs content
|
5.2 procfs content
|
||||||
5.3 writing own CAN protocol modules
|
5.3 writing own CAN protocol modules
|
||||||
|
@ -51,20 +50,20 @@ This file contains
|
||||||
6.6 CAN FD (flexible data rate) driver support
|
6.6 CAN FD (flexible data rate) driver support
|
||||||
6.7 supported CAN hardware
|
6.7 supported CAN hardware
|
||||||
|
|
||||||
7 Socket CAN resources
|
7 SocketCAN resources
|
||||||
|
|
||||||
8 Credits
|
8 Credits
|
||||||
|
|
||||||
============================================================================
|
============================================================================
|
||||||
|
|
||||||
1. Overview / What is Socket CAN
|
1. Overview / What is SocketCAN
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
The socketcan package is an implementation of CAN protocols
|
The socketcan package is an implementation of CAN protocols
|
||||||
(Controller Area Network) for Linux. CAN is a networking technology
|
(Controller Area Network) for Linux. CAN is a networking technology
|
||||||
which has widespread use in automation, embedded devices, and
|
which has widespread use in automation, embedded devices, and
|
||||||
automotive fields. While there have been other CAN implementations
|
automotive fields. While there have been other CAN implementations
|
||||||
for Linux based on character devices, Socket CAN uses the Berkeley
|
for Linux based on character devices, SocketCAN uses the Berkeley
|
||||||
socket API, the Linux network stack and implements the CAN device
|
socket API, the Linux network stack and implements the CAN device
|
||||||
drivers as network interfaces. The CAN socket API has been designed
|
drivers as network interfaces. The CAN socket API has been designed
|
||||||
as similar as possible to the TCP/IP protocols to allow programmers,
|
as similar as possible to the TCP/IP protocols to allow programmers,
|
||||||
|
@ -74,7 +73,7 @@ sockets.
|
||||||
2. Motivation / Why using the socket API
|
2. Motivation / Why using the socket API
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
There have been CAN implementations for Linux before Socket CAN so the
|
There have been CAN implementations for Linux before SocketCAN so the
|
||||||
question arises, why we have started another project. Most existing
|
question arises, why we have started another project. Most existing
|
||||||
implementations come as a device driver for some CAN hardware, they
|
implementations come as a device driver for some CAN hardware, they
|
||||||
are based on character devices and provide comparatively little
|
are based on character devices and provide comparatively little
|
||||||
|
@ -89,10 +88,10 @@ the CAN controller requires employment of another device driver and
|
||||||
often the need for adaption of large parts of the application to the
|
often the need for adaption of large parts of the application to the
|
||||||
new driver's API.
|
new driver's API.
|
||||||
|
|
||||||
Socket CAN was designed to overcome all of these limitations. A new
|
SocketCAN was designed to overcome all of these limitations. A new
|
||||||
protocol family has been implemented which provides a socket interface
|
protocol family has been implemented which provides a socket interface
|
||||||
to user space applications and which builds upon the Linux network
|
to user space applications and which builds upon the Linux network
|
||||||
layer, so to use all of the provided queueing functionality. A device
|
layer, enabling use all of the provided queueing functionality. A device
|
||||||
driver for CAN controller hardware registers itself with the Linux
|
driver for CAN controller hardware registers itself with the Linux
|
||||||
network layer as a network device, so that CAN frames from the
|
network layer as a network device, so that CAN frames from the
|
||||||
controller can be passed up to the network layer and on to the CAN
|
controller can be passed up to the network layer and on to the CAN
|
||||||
|
@ -146,15 +145,15 @@ solution for a couple of reasons:
|
||||||
providing an API for device drivers to register with. However, then
|
providing an API for device drivers to register with. However, then
|
||||||
it would be no more difficult, or may be even easier, to use the
|
it would be no more difficult, or may be even easier, to use the
|
||||||
networking framework provided by the Linux kernel, and this is what
|
networking framework provided by the Linux kernel, and this is what
|
||||||
Socket CAN does.
|
SocketCAN does.
|
||||||
|
|
||||||
The use of the networking framework of the Linux kernel is just the
|
The use of the networking framework of the Linux kernel is just the
|
||||||
natural and most appropriate way to implement CAN for Linux.
|
natural and most appropriate way to implement CAN for Linux.
|
||||||
|
|
||||||
3. Socket CAN concept
|
3. SocketCAN concept
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
As described in chapter 2 it is the main goal of Socket CAN to
|
As described in chapter 2 it is the main goal of SocketCAN to
|
||||||
provide a socket interface to user space applications which builds
|
provide a socket interface to user space applications which builds
|
||||||
upon the Linux network layer. In contrast to the commonly known
|
upon the Linux network layer. In contrast to the commonly known
|
||||||
TCP/IP and ethernet networking, the CAN bus is a broadcast-only(!)
|
TCP/IP and ethernet networking, the CAN bus is a broadcast-only(!)
|
||||||
|
@ -168,11 +167,11 @@ solution for a couple of reasons:
|
||||||
|
|
||||||
The network transparent access of multiple applications leads to the
|
The network transparent access of multiple applications leads to the
|
||||||
problem that different applications may be interested in the same
|
problem that different applications may be interested in the same
|
||||||
CAN-IDs from the same CAN network interface. The Socket CAN core
|
CAN-IDs from the same CAN network interface. The SocketCAN core
|
||||||
module - which implements the protocol family CAN - provides several
|
module - which implements the protocol family CAN - provides several
|
||||||
high efficient receive lists for this reason. If e.g. a user space
|
high efficient receive lists for this reason. If e.g. a user space
|
||||||
application opens a CAN RAW socket, the raw protocol module itself
|
application opens a CAN RAW socket, the raw protocol module itself
|
||||||
requests the (range of) CAN-IDs from the Socket CAN core that are
|
requests the (range of) CAN-IDs from the SocketCAN core that are
|
||||||
requested by the user. The subscription and unsubscription of
|
requested by the user. The subscription and unsubscription of
|
||||||
CAN-IDs can be done for specific CAN interfaces or for all(!) known
|
CAN-IDs can be done for specific CAN interfaces or for all(!) known
|
||||||
CAN interfaces with the can_rx_(un)register() functions provided to
|
CAN interfaces with the can_rx_(un)register() functions provided to
|
||||||
|
@ -217,21 +216,7 @@ solution for a couple of reasons:
|
||||||
* = you really like to have this when you're running analyser tools
|
* = you really like to have this when you're running analyser tools
|
||||||
like 'candump' or 'cansniffer' on the (same) node.
|
like 'candump' or 'cansniffer' on the (same) node.
|
||||||
|
|
||||||
3.3 network security issues (capabilities)
|
3.3 network problem notifications
|
||||||
|
|
||||||
The Controller Area Network is a local field bus transmitting only
|
|
||||||
broadcast messages without any routing and security concepts.
|
|
||||||
In the majority of cases the user application has to deal with
|
|
||||||
raw CAN frames. Therefore it might be reasonable NOT to restrict
|
|
||||||
the CAN access only to the user root, as known from other networks.
|
|
||||||
Since the currently implemented CAN_RAW and CAN_BCM sockets can only
|
|
||||||
send and receive frames to/from CAN interfaces it does not affect
|
|
||||||
security of others networks to allow all users to access the CAN.
|
|
||||||
To enable non-root users to access CAN_RAW and CAN_BCM protocol
|
|
||||||
sockets the Kconfig options CAN_RAW_USER and/or CAN_BCM_USER may be
|
|
||||||
selected at kernel compile time.
|
|
||||||
|
|
||||||
3.4 network problem notifications
|
|
||||||
|
|
||||||
The use of the CAN bus may lead to several problems on the physical
|
The use of the CAN bus may lead to several problems on the physical
|
||||||
and media access control layer. Detecting and logging of these lower
|
and media access control layer. Detecting and logging of these lower
|
||||||
|
@ -251,11 +236,11 @@ solution for a couple of reasons:
|
||||||
by default. The format of the CAN error message frame is briefly
|
by default. The format of the CAN error message frame is briefly
|
||||||
described in the Linux header file "include/linux/can/error.h".
|
described in the Linux header file "include/linux/can/error.h".
|
||||||
|
|
||||||
4. How to use Socket CAN
|
4. How to use SocketCAN
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Like TCP/IP, you first need to open a socket for communicating over a
|
Like TCP/IP, you first need to open a socket for communicating over a
|
||||||
CAN network. Since Socket CAN implements a new protocol family, you
|
CAN network. Since SocketCAN implements a new protocol family, you
|
||||||
need to pass PF_CAN as the first argument to the socket(2) system
|
need to pass PF_CAN as the first argument to the socket(2) system
|
||||||
call. Currently, there are two CAN protocols to choose from, the raw
|
call. Currently, there are two CAN protocols to choose from, the raw
|
||||||
socket protocol and the broadcast manager (BCM). So to open a socket,
|
socket protocol and the broadcast manager (BCM). So to open a socket,
|
||||||
|
@ -286,8 +271,8 @@ solution for a couple of reasons:
|
||||||
};
|
};
|
||||||
|
|
||||||
The alignment of the (linear) payload data[] to a 64bit boundary
|
The alignment of the (linear) payload data[] to a 64bit boundary
|
||||||
allows the user to define own structs and unions to easily access the
|
allows the user to define their own structs and unions to easily access
|
||||||
CAN payload. There is no given byteorder on the CAN bus by
|
the CAN payload. There is no given byteorder on the CAN bus by
|
||||||
default. A read(2) system call on a CAN_RAW socket transfers a
|
default. A read(2) system call on a CAN_RAW socket transfers a
|
||||||
struct can_frame to the user space.
|
struct can_frame to the user space.
|
||||||
|
|
||||||
|
@ -479,7 +464,7 @@ solution for a couple of reasons:
|
||||||
|
|
||||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||||
|
|
||||||
To set the filters to zero filters is quite obsolete as not read
|
To set the filters to zero filters is quite obsolete as to not read
|
||||||
data causes the raw socket to discard the received CAN frames. But
|
data causes the raw socket to discard the received CAN frames. But
|
||||||
having this 'send only' use-case we may remove the receive list in the
|
having this 'send only' use-case we may remove the receive list in the
|
||||||
Kernel to save a little (really a very little!) CPU usage.
|
Kernel to save a little (really a very little!) CPU usage.
|
||||||
|
@ -814,17 +799,17 @@ solution for a couple of reasons:
|
||||||
4.4 unconnected transport protocols (SOCK_DGRAM)
|
4.4 unconnected transport protocols (SOCK_DGRAM)
|
||||||
|
|
||||||
|
|
||||||
5. Socket CAN core module
|
5. SocketCAN core module
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
The Socket CAN core module implements the protocol family
|
The SocketCAN core module implements the protocol family
|
||||||
PF_CAN. CAN protocol modules are loaded by the core module at
|
PF_CAN. CAN protocol modules are loaded by the core module at
|
||||||
runtime. The core module provides an interface for CAN protocol
|
runtime. The core module provides an interface for CAN protocol
|
||||||
modules to subscribe needed CAN IDs (see chapter 3.1).
|
modules to subscribe needed CAN IDs (see chapter 3.1).
|
||||||
|
|
||||||
5.1 can.ko module params
|
5.1 can.ko module params
|
||||||
|
|
||||||
- stats_timer: To calculate the Socket CAN core statistics
|
- stats_timer: To calculate the SocketCAN core statistics
|
||||||
(e.g. current/maximum frames per second) this 1 second timer is
|
(e.g. current/maximum frames per second) this 1 second timer is
|
||||||
invoked at can.ko module start time by default. This timer can be
|
invoked at can.ko module start time by default. This timer can be
|
||||||
disabled by using stattimer=0 on the module commandline.
|
disabled by using stattimer=0 on the module commandline.
|
||||||
|
@ -833,7 +818,7 @@ solution for a couple of reasons:
|
||||||
|
|
||||||
5.2 procfs content
|
5.2 procfs content
|
||||||
|
|
||||||
As described in chapter 3.1 the Socket CAN core uses several filter
|
As described in chapter 3.1 the SocketCAN core uses several filter
|
||||||
lists to deliver received CAN frames to CAN protocol modules. These
|
lists to deliver received CAN frames to CAN protocol modules. These
|
||||||
receive lists, their filters and the count of filter matches can be
|
receive lists, their filters and the count of filter matches can be
|
||||||
checked in the appropriate receive list. All entries contain the
|
checked in the appropriate receive list. All entries contain the
|
||||||
|
@ -860,15 +845,15 @@ solution for a couple of reasons:
|
||||||
|
|
||||||
Additional procfs files in /proc/net/can
|
Additional procfs files in /proc/net/can
|
||||||
|
|
||||||
stats - Socket CAN core statistics (rx/tx frames, match ratios, ...)
|
stats - SocketCAN core statistics (rx/tx frames, match ratios, ...)
|
||||||
reset_stats - manual statistic reset
|
reset_stats - manual statistic reset
|
||||||
version - prints the Socket CAN core version and the ABI version
|
version - prints the SocketCAN core version and the ABI version
|
||||||
|
|
||||||
5.3 writing own CAN protocol modules
|
5.3 writing own CAN protocol modules
|
||||||
|
|
||||||
To implement a new protocol in the protocol family PF_CAN a new
|
To implement a new protocol in the protocol family PF_CAN a new
|
||||||
protocol has to be defined in include/linux/can.h .
|
protocol has to be defined in include/linux/can.h .
|
||||||
The prototypes and definitions to use the Socket CAN core can be
|
The prototypes and definitions to use the SocketCAN core can be
|
||||||
accessed by including include/linux/can/core.h .
|
accessed by including include/linux/can/core.h .
|
||||||
In addition to functions that register the CAN protocol and the
|
In addition to functions that register the CAN protocol and the
|
||||||
CAN device notifier chain there are functions to subscribe CAN
|
CAN device notifier chain there are functions to subscribe CAN
|
||||||
|
@ -1105,7 +1090,7 @@ solution for a couple of reasons:
|
||||||
|
|
||||||
$ ip link set canX up type can bitrate 125000
|
$ ip link set canX up type can bitrate 125000
|
||||||
|
|
||||||
A device may enter the "bus-off" state if too much errors occurred on
|
A device may enter the "bus-off" state if too many errors occurred on
|
||||||
the CAN bus. Then no more messages are received or sent. An automatic
|
the CAN bus. Then no more messages are received or sent. An automatic
|
||||||
bus-off recovery can be enabled by setting the "restart-ms" to a
|
bus-off recovery can be enabled by setting the "restart-ms" to a
|
||||||
non-zero value, e.g.:
|
non-zero value, e.g.:
|
||||||
|
@ -1125,7 +1110,7 @@ solution for a couple of reasons:
|
||||||
|
|
||||||
CAN FD capable CAN controllers support two different bitrates for the
|
CAN FD capable CAN controllers support two different bitrates for the
|
||||||
arbitration phase and the payload phase of the CAN FD frame. Therefore a
|
arbitration phase and the payload phase of the CAN FD frame. Therefore a
|
||||||
second bittiming has to be specified in order to enable the CAN FD bitrate.
|
second bit timing has to be specified in order to enable the CAN FD bitrate.
|
||||||
|
|
||||||
Additionally CAN FD capable CAN controllers support up to 64 bytes of
|
Additionally CAN FD capable CAN controllers support up to 64 bytes of
|
||||||
payload. The representation of this length in can_frame.can_dlc and
|
payload. The representation of this length in can_frame.can_dlc and
|
||||||
|
@ -1150,21 +1135,16 @@ solution for a couple of reasons:
|
||||||
6.7 Supported CAN hardware
|
6.7 Supported CAN hardware
|
||||||
|
|
||||||
Please check the "Kconfig" file in "drivers/net/can" to get an actual
|
Please check the "Kconfig" file in "drivers/net/can" to get an actual
|
||||||
list of the support CAN hardware. On the Socket CAN project website
|
list of the support CAN hardware. On the SocketCAN project website
|
||||||
(see chapter 7) there might be further drivers available, also for
|
(see chapter 7) there might be further drivers available, also for
|
||||||
older kernel versions.
|
older kernel versions.
|
||||||
|
|
||||||
7. Socket CAN resources
|
7. SocketCAN resources
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
You can find further resources for Socket CAN like user space tools,
|
The Linux CAN / SocketCAN project ressources (project site / mailing list)
|
||||||
support for old kernel versions, more drivers, mailing lists, etc.
|
are referenced in the MAINTAINERS file in the Linux source tree.
|
||||||
at the BerliOS OSS project website for Socket CAN:
|
Search for CAN NETWORK [LAYERS|DRIVERS].
|
||||||
|
|
||||||
http://developer.berlios.de/projects/socketcan
|
|
||||||
|
|
||||||
If you have questions, bug fixes, etc., don't hesitate to post them to
|
|
||||||
the Socketcan-Users mailing list. But please search the archives first.
|
|
||||||
|
|
||||||
8. Credits
|
8. Credits
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -1,49 +1,563 @@
|
||||||
filter.txt: Linux Socket Filtering
|
Linux Socket Filtering aka Berkeley Packet Filter (BPF)
|
||||||
Written by: Jay Schulist <jschlst@samba.org>
|
=======================================================
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
============
|
------------
|
||||||
|
|
||||||
Linux Socket Filtering is derived from the Berkeley
|
Linux Socket Filtering (LSF) is derived from the Berkeley Packet Filter.
|
||||||
Packet Filter. There are some distinct differences between
|
Though there are some distinct differences between the BSD and Linux
|
||||||
the BSD and Linux Kernel Filtering.
|
Kernel filtering, but when we speak of BPF or LSF in Linux context, we
|
||||||
|
mean the very same mechanism of filtering in the Linux kernel.
|
||||||
|
|
||||||
Linux Socket Filtering (LSF) allows a user-space program to
|
BPF allows a user-space program to attach a filter onto any socket and
|
||||||
attach a filter onto any socket and allow or disallow certain
|
allow or disallow certain types of data to come through the socket. LSF
|
||||||
types of data to come through the socket. LSF follows exactly
|
follows exactly the same filter code structure as BSD's BPF, so referring
|
||||||
the same filter code structure as the BSD Berkeley Packet Filter
|
to the BSD bpf.4 manpage is very helpful in creating filters.
|
||||||
(BPF), so referring to the BSD bpf.4 manpage is very helpful in
|
|
||||||
creating filters.
|
|
||||||
|
|
||||||
LSF is much simpler than BPF. One does not have to worry about
|
On Linux, BPF is much simpler than on BSD. One does not have to worry
|
||||||
devices or anything like that. You simply create your filter
|
about devices or anything like that. You simply create your filter code,
|
||||||
code, send it to the kernel via the SO_ATTACH_FILTER option and
|
send it to the kernel via the SO_ATTACH_FILTER option and if your filter
|
||||||
if your filter code passes the kernel check on it, you then
|
code passes the kernel check on it, you then immediately begin filtering
|
||||||
immediately begin filtering data on that socket.
|
data on that socket.
|
||||||
|
|
||||||
You can also detach filters from your socket via the
|
You can also detach filters from your socket via the SO_DETACH_FILTER
|
||||||
SO_DETACH_FILTER option. This will probably not be used much
|
option. This will probably not be used much since when you close a socket
|
||||||
since when you close a socket that has a filter on it the
|
that has a filter on it the filter is automagically removed. The other
|
||||||
filter is automagically removed. The other less common case
|
less common case may be adding a different filter on the same socket where
|
||||||
may be adding a different filter on the same socket where you had another
|
you had another filter that is still running: the kernel takes care of
|
||||||
filter that is still running: the kernel takes care of removing
|
removing the old one and placing your new one in its place, assuming your
|
||||||
the old one and placing your new one in its place, assuming your
|
filter has passed the checks, otherwise if it fails the old filter will
|
||||||
filter has passed the checks, otherwise if it fails the old filter
|
remain on that socket.
|
||||||
will remain on that socket.
|
|
||||||
|
|
||||||
SO_LOCK_FILTER option allows to lock the filter attached to a
|
SO_LOCK_FILTER option allows to lock the filter attached to a socket. Once
|
||||||
socket. Once set, a filter cannot be removed or changed. This allows
|
set, a filter cannot be removed or changed. This allows one process to
|
||||||
one process to setup a socket, attach a filter, lock it then drop
|
setup a socket, attach a filter, lock it then drop privileges and be
|
||||||
privileges and be assured that the filter will be kept until the
|
assured that the filter will be kept until the socket is closed.
|
||||||
socket is closed.
|
|
||||||
|
|
||||||
Examples
|
The biggest user of this construct might be libpcap. Issuing a high-level
|
||||||
========
|
filter command like `tcpdump -i em1 port 22` passes through the libpcap
|
||||||
|
internal compiler that generates a structure that can eventually be loaded
|
||||||
|
via SO_ATTACH_FILTER to the kernel. `tcpdump -i em1 port 22 -ddd`
|
||||||
|
displays what is being placed into this structure.
|
||||||
|
|
||||||
Ioctls-
|
Although we were only speaking about sockets here, BPF in Linux is used
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter));
|
in many more places. There's xt_bpf for netfilter, cls_bpf in the kernel
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_DETACH_FILTER, &value, sizeof(value));
|
qdisc layer, SECCOMP-BPF (SECure COMPuting [1]), and lots of other places
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_LOCK_FILTER, &value, sizeof(value));
|
such as team driver, PTP code, etc where BPF is being used.
|
||||||
|
|
||||||
See the BSD bpf.4 manpage and the BSD Packet Filter paper written by
|
[1] Documentation/prctl/seccomp_filter.txt
|
||||||
Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
|
|
||||||
|
Original BPF paper:
|
||||||
|
|
||||||
|
Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new
|
||||||
|
architecture for user-level packet capture. In Proceedings of the
|
||||||
|
USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993
|
||||||
|
Conference Proceedings (USENIX'93). USENIX Association, Berkeley,
|
||||||
|
CA, USA, 2-2. [http://www.tcpdump.org/papers/bpf-usenix93.pdf]
|
||||||
|
|
||||||
|
Structure
|
||||||
|
---------
|
||||||
|
|
||||||
|
User space applications include <linux/filter.h> which contains the
|
||||||
|
following relevant structures:
|
||||||
|
|
||||||
|
struct sock_filter { /* Filter block */
|
||||||
|
__u16 code; /* Actual filter code */
|
||||||
|
__u8 jt; /* Jump true */
|
||||||
|
__u8 jf; /* Jump false */
|
||||||
|
__u32 k; /* Generic multiuse field */
|
||||||
|
};
|
||||||
|
|
||||||
|
Such a structure is assembled as an array of 4-tuples, that contains
|
||||||
|
a code, jt, jf and k value. jt and jf are jump offsets and k a generic
|
||||||
|
value to be used for a provided code.
|
||||||
|
|
||||||
|
struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
|
||||||
|
unsigned short len; /* Number of filter blocks */
|
||||||
|
struct sock_filter __user *filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
For socket filtering, a pointer to this structure (as shown in
|
||||||
|
follow-up example) is being passed to the kernel through setsockopt(2).
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
/* ... */
|
||||||
|
|
||||||
|
/* From the example above: tcpdump -i em1 port 22 -dd */
|
||||||
|
struct sock_filter code[] = {
|
||||||
|
{ 0x28, 0, 0, 0x0000000c },
|
||||||
|
{ 0x15, 0, 8, 0x000086dd },
|
||||||
|
{ 0x30, 0, 0, 0x00000014 },
|
||||||
|
{ 0x15, 2, 0, 0x00000084 },
|
||||||
|
{ 0x15, 1, 0, 0x00000006 },
|
||||||
|
{ 0x15, 0, 17, 0x00000011 },
|
||||||
|
{ 0x28, 0, 0, 0x00000036 },
|
||||||
|
{ 0x15, 14, 0, 0x00000016 },
|
||||||
|
{ 0x28, 0, 0, 0x00000038 },
|
||||||
|
{ 0x15, 12, 13, 0x00000016 },
|
||||||
|
{ 0x15, 0, 12, 0x00000800 },
|
||||||
|
{ 0x30, 0, 0, 0x00000017 },
|
||||||
|
{ 0x15, 2, 0, 0x00000084 },
|
||||||
|
{ 0x15, 1, 0, 0x00000006 },
|
||||||
|
{ 0x15, 0, 8, 0x00000011 },
|
||||||
|
{ 0x28, 0, 0, 0x00000014 },
|
||||||
|
{ 0x45, 6, 0, 0x00001fff },
|
||||||
|
{ 0xb1, 0, 0, 0x0000000e },
|
||||||
|
{ 0x48, 0, 0, 0x0000000e },
|
||||||
|
{ 0x15, 2, 0, 0x00000016 },
|
||||||
|
{ 0x48, 0, 0, 0x00000010 },
|
||||||
|
{ 0x15, 0, 1, 0x00000016 },
|
||||||
|
{ 0x06, 0, 0, 0x0000ffff },
|
||||||
|
{ 0x06, 0, 0, 0x00000000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sock_fprog bpf = {
|
||||||
|
.len = ARRAY_SIZE(code),
|
||||||
|
.filter = code,
|
||||||
|
};
|
||||||
|
|
||||||
|
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock < 0)
|
||||||
|
/* ... bail out ... */
|
||||||
|
|
||||||
|
ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
|
||||||
|
if (ret < 0)
|
||||||
|
/* ... bail out ... */
|
||||||
|
|
||||||
|
/* ... */
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
The above example code attaches a socket filter for a PF_PACKET socket
|
||||||
|
in order to let all IPv4/IPv6 packets with port 22 pass. The rest will
|
||||||
|
be dropped for this socket.
|
||||||
|
|
||||||
|
The setsockopt(2) call to SO_DETACH_FILTER doesn't need any arguments
|
||||||
|
and SO_LOCK_FILTER for preventing the filter to be detached, takes an
|
||||||
|
integer value with 0 or 1.
|
||||||
|
|
||||||
|
Note that socket filters are not restricted to PF_PACKET sockets only,
|
||||||
|
but can also be used on other socket families.
|
||||||
|
|
||||||
|
Summary of system calls:
|
||||||
|
|
||||||
|
* setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &val, sizeof(val));
|
||||||
|
* setsockopt(sockfd, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val));
|
||||||
|
* setsockopt(sockfd, SOL_SOCKET, SO_LOCK_FILTER, &val, sizeof(val));
|
||||||
|
|
||||||
|
Normally, most use cases for socket filtering on packet sockets will be
|
||||||
|
covered by libpcap in high-level syntax, so as an application developer
|
||||||
|
you should stick to that. libpcap wraps its own layer around all that.
|
||||||
|
|
||||||
|
Unless i) using/linking to libpcap is not an option, ii) the required BPF
|
||||||
|
filters use Linux extensions that are not supported by libpcap's compiler,
|
||||||
|
iii) a filter might be more complex and not cleanly implementable with
|
||||||
|
libpcap's compiler, or iv) particular filter codes should be optimized
|
||||||
|
differently than libpcap's internal compiler does; then in such cases
|
||||||
|
writing such a filter "by hand" can be of an alternative. For example,
|
||||||
|
xt_bpf and cls_bpf users might have requirements that could result in
|
||||||
|
more complex filter code, or one that cannot be expressed with libpcap
|
||||||
|
(e.g. different return codes for various code paths). Moreover, BPF JIT
|
||||||
|
implementors may wish to manually write test cases and thus need low-level
|
||||||
|
access to BPF code as well.
|
||||||
|
|
||||||
|
BPF engine and instruction set
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Under tools/net/ there's a small helper tool called bpf_asm which can
|
||||||
|
be used to write low-level filters for example scenarios mentioned in the
|
||||||
|
previous section. Asm-like syntax mentioned here has been implemented in
|
||||||
|
bpf_asm and will be used for further explanations (instead of dealing with
|
||||||
|
less readable opcodes directly, principles are the same). The syntax is
|
||||||
|
closely modelled after Steven McCanne's and Van Jacobson's BPF paper.
|
||||||
|
|
||||||
|
The BPF architecture consists of the following basic elements:
|
||||||
|
|
||||||
|
Element Description
|
||||||
|
|
||||||
|
A 32 bit wide accumulator
|
||||||
|
X 32 bit wide X register
|
||||||
|
M[] 16 x 32 bit wide misc registers aka "scratch memory
|
||||||
|
store", addressable from 0 to 15
|
||||||
|
|
||||||
|
A program, that is translated by bpf_asm into "opcodes" is an array that
|
||||||
|
consists of the following elements (as already mentioned):
|
||||||
|
|
||||||
|
op:16, jt:8, jf:8, k:32
|
||||||
|
|
||||||
|
The element op is a 16 bit wide opcode that has a particular instruction
|
||||||
|
encoded. jt and jf are two 8 bit wide jump targets, one for condition
|
||||||
|
"jump if true", the other one "jump if false". Eventually, element k
|
||||||
|
contains a miscellaneous argument that can be interpreted in different
|
||||||
|
ways depending on the given instruction in op.
|
||||||
|
|
||||||
|
The instruction set consists of load, store, branch, alu, miscellaneous
|
||||||
|
and return instructions that are also represented in bpf_asm syntax. This
|
||||||
|
table lists all bpf_asm instructions available resp. what their underlying
|
||||||
|
opcodes as defined in linux/filter.h stand for:
|
||||||
|
|
||||||
|
Instruction Addressing mode Description
|
||||||
|
|
||||||
|
ld 1, 2, 3, 4, 10 Load word into A
|
||||||
|
ldi 4 Load word into A
|
||||||
|
ldh 1, 2 Load half-word into A
|
||||||
|
ldb 1, 2 Load byte into A
|
||||||
|
ldx 3, 4, 5, 10 Load word into X
|
||||||
|
ldxi 4 Load word into X
|
||||||
|
ldxb 5 Load byte into X
|
||||||
|
|
||||||
|
st 3 Store A into M[]
|
||||||
|
stx 3 Store X into M[]
|
||||||
|
|
||||||
|
jmp 6 Jump to label
|
||||||
|
ja 6 Jump to label
|
||||||
|
jeq 7, 8 Jump on k == A
|
||||||
|
jneq 8 Jump on k != A
|
||||||
|
jne 8 Jump on k != A
|
||||||
|
jlt 8 Jump on k < A
|
||||||
|
jle 8 Jump on k <= A
|
||||||
|
jgt 7, 8 Jump on k > A
|
||||||
|
jge 7, 8 Jump on k >= A
|
||||||
|
jset 7, 8 Jump on k & A
|
||||||
|
|
||||||
|
add 0, 4 A + <x>
|
||||||
|
sub 0, 4 A - <x>
|
||||||
|
mul 0, 4 A * <x>
|
||||||
|
div 0, 4 A / <x>
|
||||||
|
mod 0, 4 A % <x>
|
||||||
|
neg 0, 4 !A
|
||||||
|
and 0, 4 A & <x>
|
||||||
|
or 0, 4 A | <x>
|
||||||
|
xor 0, 4 A ^ <x>
|
||||||
|
lsh 0, 4 A << <x>
|
||||||
|
rsh 0, 4 A >> <x>
|
||||||
|
|
||||||
|
tax Copy A into X
|
||||||
|
txa Copy X into A
|
||||||
|
|
||||||
|
ret 4, 9 Return
|
||||||
|
|
||||||
|
The next table shows addressing formats from the 2nd column:
|
||||||
|
|
||||||
|
Addressing mode Syntax Description
|
||||||
|
|
||||||
|
0 x/%x Register X
|
||||||
|
1 [k] BHW at byte offset k in the packet
|
||||||
|
2 [x + k] BHW at the offset X + k in the packet
|
||||||
|
3 M[k] Word at offset k in M[]
|
||||||
|
4 #k Literal value stored in k
|
||||||
|
5 4*([k]&0xf) Lower nibble * 4 at byte offset k in the packet
|
||||||
|
6 L Jump label L
|
||||||
|
7 #k,Lt,Lf Jump to Lt if true, otherwise jump to Lf
|
||||||
|
8 #k,Lt Jump to Lt if predicate is true
|
||||||
|
9 a/%a Accumulator A
|
||||||
|
10 extension BPF extension
|
||||||
|
|
||||||
|
The Linux kernel also has a couple of BPF extensions that are used along
|
||||||
|
with the class of load instructions by "overloading" the k argument with
|
||||||
|
a negative offset + a particular extension offset. The result of such BPF
|
||||||
|
extensions are loaded into A.
|
||||||
|
|
||||||
|
Possible BPF extensions are shown in the following table:
|
||||||
|
|
||||||
|
Extension Description
|
||||||
|
|
||||||
|
len skb->len
|
||||||
|
proto skb->protocol
|
||||||
|
type skb->pkt_type
|
||||||
|
poff Payload start offset
|
||||||
|
ifidx skb->dev->ifindex
|
||||||
|
nla Netlink attribute of type X with offset A
|
||||||
|
nlan Nested Netlink attribute of type X with offset A
|
||||||
|
mark skb->mark
|
||||||
|
queue skb->queue_mapping
|
||||||
|
hatype skb->dev->type
|
||||||
|
rxhash skb->rxhash
|
||||||
|
cpu raw_smp_processor_id()
|
||||||
|
vlan_tci vlan_tx_tag_get(skb)
|
||||||
|
vlan_pr vlan_tx_tag_present(skb)
|
||||||
|
|
||||||
|
These extensions can also be prefixed with '#'.
|
||||||
|
Examples for low-level BPF:
|
||||||
|
|
||||||
|
** ARP packets:
|
||||||
|
|
||||||
|
ldh [12]
|
||||||
|
jne #0x806, drop
|
||||||
|
ret #-1
|
||||||
|
drop: ret #0
|
||||||
|
|
||||||
|
** IPv4 TCP packets:
|
||||||
|
|
||||||
|
ldh [12]
|
||||||
|
jne #0x800, drop
|
||||||
|
ldb [23]
|
||||||
|
jneq #6, drop
|
||||||
|
ret #-1
|
||||||
|
drop: ret #0
|
||||||
|
|
||||||
|
** (Accelerated) VLAN w/ id 10:
|
||||||
|
|
||||||
|
ld vlan_tci
|
||||||
|
jneq #10, drop
|
||||||
|
ret #-1
|
||||||
|
drop: ret #0
|
||||||
|
|
||||||
|
** SECCOMP filter example:
|
||||||
|
|
||||||
|
ld [4] /* offsetof(struct seccomp_data, arch) */
|
||||||
|
jne #0xc000003e, bad /* AUDIT_ARCH_X86_64 */
|
||||||
|
ld [0] /* offsetof(struct seccomp_data, nr) */
|
||||||
|
jeq #15, good /* __NR_rt_sigreturn */
|
||||||
|
jeq #231, good /* __NR_exit_group */
|
||||||
|
jeq #60, good /* __NR_exit */
|
||||||
|
jeq #0, good /* __NR_read */
|
||||||
|
jeq #1, good /* __NR_write */
|
||||||
|
jeq #5, good /* __NR_fstat */
|
||||||
|
jeq #9, good /* __NR_mmap */
|
||||||
|
jeq #14, good /* __NR_rt_sigprocmask */
|
||||||
|
jeq #13, good /* __NR_rt_sigaction */
|
||||||
|
jeq #35, good /* __NR_nanosleep */
|
||||||
|
bad: ret #0 /* SECCOMP_RET_KILL */
|
||||||
|
good: ret #0x7fff0000 /* SECCOMP_RET_ALLOW */
|
||||||
|
|
||||||
|
The above example code can be placed into a file (here called "foo"), and
|
||||||
|
then be passed to the bpf_asm tool for generating opcodes, output that xt_bpf
|
||||||
|
and cls_bpf understands and can directly be loaded with. Example with above
|
||||||
|
ARP code:
|
||||||
|
|
||||||
|
$ ./bpf_asm foo
|
||||||
|
4,40 0 0 12,21 0 1 2054,6 0 0 4294967295,6 0 0 0,
|
||||||
|
|
||||||
|
In copy and paste C-like output:
|
||||||
|
|
||||||
|
$ ./bpf_asm -c foo
|
||||||
|
{ 0x28, 0, 0, 0x0000000c },
|
||||||
|
{ 0x15, 0, 1, 0x00000806 },
|
||||||
|
{ 0x06, 0, 0, 0xffffffff },
|
||||||
|
{ 0x06, 0, 0, 0000000000 },
|
||||||
|
|
||||||
|
In particular, as usage with xt_bpf or cls_bpf can result in more complex BPF
|
||||||
|
filters that might not be obvious at first, it's good to test filters before
|
||||||
|
attaching to a live system. For that purpose, there's a small tool called
|
||||||
|
bpf_dbg under tools/net/ in the kernel source directory. This debugger allows
|
||||||
|
for testing BPF filters against given pcap files, single stepping through the
|
||||||
|
BPF code on the pcap's packets and to do BPF machine register dumps.
|
||||||
|
|
||||||
|
Starting bpf_dbg is trivial and just requires issuing:
|
||||||
|
|
||||||
|
# ./bpf_dbg
|
||||||
|
|
||||||
|
In case input and output do not equal stdin/stdout, bpf_dbg takes an
|
||||||
|
alternative stdin source as a first argument, and an alternative stdout
|
||||||
|
sink as a second one, e.g. `./bpf_dbg test_in.txt test_out.txt`.
|
||||||
|
|
||||||
|
Other than that, a particular libreadline configuration can be set via
|
||||||
|
file "~/.bpf_dbg_init" and the command history is stored in the file
|
||||||
|
"~/.bpf_dbg_history".
|
||||||
|
|
||||||
|
Interaction in bpf_dbg happens through a shell that also has auto-completion
|
||||||
|
support (follow-up example commands starting with '>' denote bpf_dbg shell).
|
||||||
|
The usual workflow would be to ...
|
||||||
|
|
||||||
|
> load bpf 6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 65535,6 0 0 0
|
||||||
|
Loads a BPF filter from standard output of bpf_asm, or transformed via
|
||||||
|
e.g. `tcpdump -iem1 -ddd port 22 | tr '\n' ','`. Note that for JIT
|
||||||
|
debugging (next section), this command creates a temporary socket and
|
||||||
|
loads the BPF code into the kernel. Thus, this will also be useful for
|
||||||
|
JIT developers.
|
||||||
|
|
||||||
|
> load pcap foo.pcap
|
||||||
|
Loads standard tcpdump pcap file.
|
||||||
|
|
||||||
|
> run [<n>]
|
||||||
|
bpf passes:1 fails:9
|
||||||
|
Runs through all packets from a pcap to account how many passes and fails
|
||||||
|
the filter will generate. A limit of packets to traverse can be given.
|
||||||
|
|
||||||
|
> disassemble
|
||||||
|
l0: ldh [12]
|
||||||
|
l1: jeq #0x800, l2, l5
|
||||||
|
l2: ldb [23]
|
||||||
|
l3: jeq #0x1, l4, l5
|
||||||
|
l4: ret #0xffff
|
||||||
|
l5: ret #0
|
||||||
|
Prints out BPF code disassembly.
|
||||||
|
|
||||||
|
> dump
|
||||||
|
/* { op, jt, jf, k }, */
|
||||||
|
{ 0x28, 0, 0, 0x0000000c },
|
||||||
|
{ 0x15, 0, 3, 0x00000800 },
|
||||||
|
{ 0x30, 0, 0, 0x00000017 },
|
||||||
|
{ 0x15, 0, 1, 0x00000001 },
|
||||||
|
{ 0x06, 0, 0, 0x0000ffff },
|
||||||
|
{ 0x06, 0, 0, 0000000000 },
|
||||||
|
Prints out C-style BPF code dump.
|
||||||
|
|
||||||
|
> breakpoint 0
|
||||||
|
breakpoint at: l0: ldh [12]
|
||||||
|
> breakpoint 1
|
||||||
|
breakpoint at: l1: jeq #0x800, l2, l5
|
||||||
|
...
|
||||||
|
Sets breakpoints at particular BPF instructions. Issuing a `run` command
|
||||||
|
will walk through the pcap file continuing from the current packet and
|
||||||
|
break when a breakpoint is being hit (another `run` will continue from
|
||||||
|
the currently active breakpoint executing next instructions):
|
||||||
|
|
||||||
|
> run
|
||||||
|
-- register dump --
|
||||||
|
pc: [0] <-- program counter
|
||||||
|
code: [40] jt[0] jf[0] k[12] <-- plain BPF code of current instruction
|
||||||
|
curr: l0: ldh [12] <-- disassembly of current instruction
|
||||||
|
A: [00000000][0] <-- content of A (hex, decimal)
|
||||||
|
X: [00000000][0] <-- content of X (hex, decimal)
|
||||||
|
M[0,15]: [00000000][0] <-- folded content of M (hex, decimal)
|
||||||
|
-- packet dump -- <-- Current packet from pcap (hex)
|
||||||
|
len: 42
|
||||||
|
0: 00 19 cb 55 55 a4 00 14 a4 43 78 69 08 06 00 01
|
||||||
|
16: 08 00 06 04 00 01 00 14 a4 43 78 69 0a 3b 01 26
|
||||||
|
32: 00 00 00 00 00 00 0a 3b 01 01
|
||||||
|
(breakpoint)
|
||||||
|
>
|
||||||
|
|
||||||
|
> breakpoint
|
||||||
|
breakpoints: 0 1
|
||||||
|
Prints currently set breakpoints.
|
||||||
|
|
||||||
|
> step [-<n>, +<n>]
|
||||||
|
Performs single stepping through the BPF program from the current pc
|
||||||
|
offset. Thus, on each step invocation, above register dump is issued.
|
||||||
|
This can go forwards and backwards in time, a plain `step` will break
|
||||||
|
on the next BPF instruction, thus +1. (No `run` needs to be issued here.)
|
||||||
|
|
||||||
|
> select <n>
|
||||||
|
Selects a given packet from the pcap file to continue from. Thus, on
|
||||||
|
the next `run` or `step`, the BPF program is being evaluated against
|
||||||
|
the user pre-selected packet. Numbering starts just as in Wireshark
|
||||||
|
with index 1.
|
||||||
|
|
||||||
|
> quit
|
||||||
|
#
|
||||||
|
Exits bpf_dbg.
|
||||||
|
|
||||||
|
JIT compiler
|
||||||
|
------------
|
||||||
|
|
||||||
|
The Linux kernel has a built-in BPF JIT compiler for x86_64, SPARC, PowerPC,
|
||||||
|
ARM and s390 and can be enabled through CONFIG_BPF_JIT. The JIT compiler is
|
||||||
|
transparently invoked for each attached filter from user space or for internal
|
||||||
|
kernel users if it has been previously enabled by root:
|
||||||
|
|
||||||
|
echo 1 > /proc/sys/net/core/bpf_jit_enable
|
||||||
|
|
||||||
|
For JIT developers, doing audits etc, each compile run can output the generated
|
||||||
|
opcode image into the kernel log via:
|
||||||
|
|
||||||
|
echo 2 > /proc/sys/net/core/bpf_jit_enable
|
||||||
|
|
||||||
|
Example output from dmesg:
|
||||||
|
|
||||||
|
[ 3389.935842] flen=6 proglen=70 pass=3 image=ffffffffa0069c8f
|
||||||
|
[ 3389.935847] JIT code: 00000000: 55 48 89 e5 48 83 ec 60 48 89 5d f8 44 8b 4f 68
|
||||||
|
[ 3389.935849] JIT code: 00000010: 44 2b 4f 6c 4c 8b 87 d8 00 00 00 be 0c 00 00 00
|
||||||
|
[ 3389.935850] JIT code: 00000020: e8 1d 94 ff e0 3d 00 08 00 00 75 16 be 17 00 00
|
||||||
|
[ 3389.935851] JIT code: 00000030: 00 e8 28 94 ff e0 83 f8 01 75 07 b8 ff ff 00 00
|
||||||
|
[ 3389.935852] JIT code: 00000040: eb 02 31 c0 c9 c3
|
||||||
|
|
||||||
|
In the kernel source tree under tools/net/, there's bpf_jit_disasm for
|
||||||
|
generating disassembly out of the kernel log's hexdump:
|
||||||
|
|
||||||
|
# ./bpf_jit_disasm
|
||||||
|
70 bytes emitted from JIT compiler (pass:3, flen:6)
|
||||||
|
ffffffffa0069c8f + <x>:
|
||||||
|
0: push %rbp
|
||||||
|
1: mov %rsp,%rbp
|
||||||
|
4: sub $0x60,%rsp
|
||||||
|
8: mov %rbx,-0x8(%rbp)
|
||||||
|
c: mov 0x68(%rdi),%r9d
|
||||||
|
10: sub 0x6c(%rdi),%r9d
|
||||||
|
14: mov 0xd8(%rdi),%r8
|
||||||
|
1b: mov $0xc,%esi
|
||||||
|
20: callq 0xffffffffe0ff9442
|
||||||
|
25: cmp $0x800,%eax
|
||||||
|
2a: jne 0x0000000000000042
|
||||||
|
2c: mov $0x17,%esi
|
||||||
|
31: callq 0xffffffffe0ff945e
|
||||||
|
36: cmp $0x1,%eax
|
||||||
|
39: jne 0x0000000000000042
|
||||||
|
3b: mov $0xffff,%eax
|
||||||
|
40: jmp 0x0000000000000044
|
||||||
|
42: xor %eax,%eax
|
||||||
|
44: leaveq
|
||||||
|
45: retq
|
||||||
|
|
||||||
|
Issuing option `-o` will "annotate" opcodes to resulting assembler
|
||||||
|
instructions, which can be very useful for JIT developers:
|
||||||
|
|
||||||
|
# ./bpf_jit_disasm -o
|
||||||
|
70 bytes emitted from JIT compiler (pass:3, flen:6)
|
||||||
|
ffffffffa0069c8f + <x>:
|
||||||
|
0: push %rbp
|
||||||
|
55
|
||||||
|
1: mov %rsp,%rbp
|
||||||
|
48 89 e5
|
||||||
|
4: sub $0x60,%rsp
|
||||||
|
48 83 ec 60
|
||||||
|
8: mov %rbx,-0x8(%rbp)
|
||||||
|
48 89 5d f8
|
||||||
|
c: mov 0x68(%rdi),%r9d
|
||||||
|
44 8b 4f 68
|
||||||
|
10: sub 0x6c(%rdi),%r9d
|
||||||
|
44 2b 4f 6c
|
||||||
|
14: mov 0xd8(%rdi),%r8
|
||||||
|
4c 8b 87 d8 00 00 00
|
||||||
|
1b: mov $0xc,%esi
|
||||||
|
be 0c 00 00 00
|
||||||
|
20: callq 0xffffffffe0ff9442
|
||||||
|
e8 1d 94 ff e0
|
||||||
|
25: cmp $0x800,%eax
|
||||||
|
3d 00 08 00 00
|
||||||
|
2a: jne 0x0000000000000042
|
||||||
|
75 16
|
||||||
|
2c: mov $0x17,%esi
|
||||||
|
be 17 00 00 00
|
||||||
|
31: callq 0xffffffffe0ff945e
|
||||||
|
e8 28 94 ff e0
|
||||||
|
36: cmp $0x1,%eax
|
||||||
|
83 f8 01
|
||||||
|
39: jne 0x0000000000000042
|
||||||
|
75 07
|
||||||
|
3b: mov $0xffff,%eax
|
||||||
|
b8 ff ff 00 00
|
||||||
|
40: jmp 0x0000000000000044
|
||||||
|
eb 02
|
||||||
|
42: xor %eax,%eax
|
||||||
|
31 c0
|
||||||
|
44: leaveq
|
||||||
|
c9
|
||||||
|
45: retq
|
||||||
|
c3
|
||||||
|
|
||||||
|
For BPF JIT developers, bpf_jit_disasm, bpf_asm and bpf_dbg provides a useful
|
||||||
|
toolchain for developing and testing the kernel's JIT compiler.
|
||||||
|
|
||||||
|
Misc
|
||||||
|
----
|
||||||
|
|
||||||
|
Also trinity, the Linux syscall fuzzer, has built-in support for BPF and
|
||||||
|
SECCOMP-BPF kernel fuzzing.
|
||||||
|
|
||||||
|
Written by
|
||||||
|
----------
|
||||||
|
|
||||||
|
The document was written in the hope that it is found useful and in order
|
||||||
|
to give potential BPF hackers or security auditors a better overview of
|
||||||
|
the underlying architecture.
|
||||||
|
|
||||||
|
Jay Schulist <jschlst@samba.org>
|
||||||
|
Daniel Borkmann <dborkman@redhat.com>
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
Linux* Base Driver for Intel(R) Network Connection
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
Intel XL710 X710 Virtual Function Linux driver.
|
||||||
|
Copyright(c) 2013 Intel Corporation.
|
||||||
|
|
||||||
|
Contents
|
||||||
|
========
|
||||||
|
|
||||||
|
- Identifying Your Adapter
|
||||||
|
- Known Issues/Troubleshooting
|
||||||
|
- Support
|
||||||
|
|
||||||
|
This file describes the i40evf Linux* Base Driver for the Intel(R) XL710
|
||||||
|
X710 Virtual Function.
|
||||||
|
|
||||||
|
The i40evf driver supports XL710 and X710 virtual function devices that
|
||||||
|
can only be activated on kernels with CONFIG_PCI_IOV enabled.
|
||||||
|
|
||||||
|
The guest OS loading the i40evf driver must support MSI-X interrupts.
|
||||||
|
|
||||||
|
Identifying Your Adapter
|
||||||
|
========================
|
||||||
|
|
||||||
|
For more information on how to identify your adapter, go to the Adapter &
|
||||||
|
Driver ID Guide at:
|
||||||
|
|
||||||
|
http://support.intel.com/support/go/network/adapter/idguide.htm
|
||||||
|
|
||||||
|
Known Issues/Troubleshooting
|
||||||
|
============================
|
||||||
|
|
||||||
|
|
||||||
|
Support
|
||||||
|
=======
|
||||||
|
|
||||||
|
For general information, go to the Intel support website at:
|
||||||
|
|
||||||
|
http://support.intel.com
|
||||||
|
|
||||||
|
or the Intel Wired Networking project hosted by Sourceforge at:
|
||||||
|
|
||||||
|
http://sourceforge.net/projects/e1000
|
||||||
|
|
||||||
|
If an issue is identified with the released source code on the supported
|
||||||
|
kernel with a supported adapter, email the specific information related
|
||||||
|
to the issue to e1000-devel@lists.sf.net
|
|
@ -15,17 +15,47 @@ ip_default_ttl - INTEGER
|
||||||
forwarded) IP packets. Should be between 1 and 255 inclusive.
|
forwarded) IP packets. Should be between 1 and 255 inclusive.
|
||||||
Default: 64 (as recommended by RFC1700)
|
Default: 64 (as recommended by RFC1700)
|
||||||
|
|
||||||
ip_no_pmtu_disc - BOOLEAN
|
ip_no_pmtu_disc - INTEGER
|
||||||
Disable Path MTU Discovery. If enabled and a
|
Disable Path MTU Discovery. If enabled in mode 1 and a
|
||||||
fragmentation-required ICMP is received, the PMTU to this
|
fragmentation-required ICMP is received, the PMTU to this
|
||||||
destination will be set to min_pmtu (see below). You will need
|
destination will be set to min_pmtu (see below). You will need
|
||||||
to raise min_pmtu to the smallest interface MTU on your system
|
to raise min_pmtu to the smallest interface MTU on your system
|
||||||
manually if you want to avoid locally generated fragments.
|
manually if you want to avoid locally generated fragments.
|
||||||
|
|
||||||
|
In mode 2 incoming Path MTU Discovery messages will be
|
||||||
|
discarded. Outgoing frames are handled the same as in mode 1,
|
||||||
|
implicitly setting IP_PMTUDISC_DONT on every created socket.
|
||||||
|
|
||||||
|
Mode 3 is a hardend pmtu discover mode. The kernel will only
|
||||||
|
accept fragmentation-needed errors if the underlying protocol
|
||||||
|
can verify them besides a plain socket lookup. Current
|
||||||
|
protocols for which pmtu events will be honored are TCP, SCTP
|
||||||
|
and DCCP as they verify e.g. the sequence number or the
|
||||||
|
association. This mode should not be enabled globally but is
|
||||||
|
only intended to secure e.g. name servers in namespaces where
|
||||||
|
TCP path mtu must still work but path MTU information of other
|
||||||
|
protocols should be discarded. If enabled globally this mode
|
||||||
|
could break other protocols.
|
||||||
|
|
||||||
|
Possible values: 0-3
|
||||||
Default: FALSE
|
Default: FALSE
|
||||||
|
|
||||||
min_pmtu - INTEGER
|
min_pmtu - INTEGER
|
||||||
default 552 - minimum discovered Path MTU
|
default 552 - minimum discovered Path MTU
|
||||||
|
|
||||||
|
ip_forward_use_pmtu - BOOLEAN
|
||||||
|
By default we don't trust protocol path MTUs while forwarding
|
||||||
|
because they could be easily forged and can lead to unwanted
|
||||||
|
fragmentation by the router.
|
||||||
|
You only need to enable this if you have user-space software
|
||||||
|
which tries to discover path mtus by itself and depends on the
|
||||||
|
kernel honoring this information. This is normally not the
|
||||||
|
case.
|
||||||
|
Default: 0 (disabled)
|
||||||
|
Possible values:
|
||||||
|
0 - disabled
|
||||||
|
1 - enabled
|
||||||
|
|
||||||
route/max_size - INTEGER
|
route/max_size - INTEGER
|
||||||
Maximum number of routes allowed in the kernel. Increase
|
Maximum number of routes allowed in the kernel. Increase
|
||||||
this when using large numbers of interfaces and/or routes.
|
this when using large numbers of interfaces and/or routes.
|
||||||
|
@ -160,6 +190,16 @@ tcp_app_win - INTEGER
|
||||||
buffer. Value 0 is special, it means that nothing is reserved.
|
buffer. Value 0 is special, it means that nothing is reserved.
|
||||||
Default: 31
|
Default: 31
|
||||||
|
|
||||||
|
tcp_autocorking - BOOLEAN
|
||||||
|
Enable TCP auto corking :
|
||||||
|
When applications do consecutive small write()/sendmsg() system calls,
|
||||||
|
we try to coalesce these small writes as much as possible, to lower
|
||||||
|
total amount of sent packets. This is done if at least one prior
|
||||||
|
packet for the flow is waiting in Qdisc queues or device transmit
|
||||||
|
queue. Applications can still use TCP_CORK for optimal behavior
|
||||||
|
when they know how/when to uncork their sockets.
|
||||||
|
Default : 1
|
||||||
|
|
||||||
tcp_available_congestion_control - STRING
|
tcp_available_congestion_control - STRING
|
||||||
Shows the available congestion control choices that are registered.
|
Shows the available congestion control choices that are registered.
|
||||||
More congestion control algorithms may be available as modules,
|
More congestion control algorithms may be available as modules,
|
||||||
|
@ -1078,6 +1118,21 @@ bindv6only - BOOLEAN
|
||||||
|
|
||||||
Default: FALSE (as specified in RFC3493)
|
Default: FALSE (as specified in RFC3493)
|
||||||
|
|
||||||
|
flowlabel_consistency - BOOLEAN
|
||||||
|
Protect the consistency (and unicity) of flow label.
|
||||||
|
You have to disable it to use IPV6_FL_F_REFLECT flag on the
|
||||||
|
flow label manager.
|
||||||
|
TRUE: enabled
|
||||||
|
FALSE: disabled
|
||||||
|
Default: TRUE
|
||||||
|
|
||||||
|
anycast_src_echo_reply - BOOLEAN
|
||||||
|
Controls the use of anycast addresses as source addresses for ICMPv6
|
||||||
|
echo reply
|
||||||
|
TRUE: enabled
|
||||||
|
FALSE: disabled
|
||||||
|
Default: FALSE
|
||||||
|
|
||||||
IPv6 Fragmentation:
|
IPv6 Fragmentation:
|
||||||
|
|
||||||
ip6frag_high_thresh - INTEGER
|
ip6frag_high_thresh - INTEGER
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
Here documents known IPsec corner cases which need to be keep in mind when
|
||||||
|
deploy various IPsec configuration in real world production environment.
|
||||||
|
|
||||||
|
1. IPcomp: Small IP packet won't get compressed at sender, and failed on
|
||||||
|
policy check on receiver.
|
||||||
|
|
||||||
|
Quote from RFC3173:
|
||||||
|
2.2. Non-Expansion Policy
|
||||||
|
|
||||||
|
If the total size of a compressed payload and the IPComp header, as
|
||||||
|
defined in section 3, is not smaller than the size of the original
|
||||||
|
payload, the IP datagram MUST be sent in the original non-compressed
|
||||||
|
form. To clarify: If an IP datagram is sent non-compressed, no
|
||||||
|
|
||||||
|
IPComp header is added to the datagram. This policy ensures saving
|
||||||
|
the decompression processing cycles and avoiding incurring IP
|
||||||
|
datagram fragmentation when the expanded datagram is larger than the
|
||||||
|
MTU.
|
||||||
|
|
||||||
|
Small IP datagrams are likely to expand as a result of compression.
|
||||||
|
Therefore, a numeric threshold should be applied before compression,
|
||||||
|
where IP datagrams of size smaller than the threshold are sent in the
|
||||||
|
original form without attempting compression. The numeric threshold
|
||||||
|
is implementation dependent.
|
||||||
|
|
||||||
|
Current IPComp implementation is indeed by the book, while as in practice
|
||||||
|
when sending non-compressed packet to the peer(whether or not packet len
|
||||||
|
is smaller than the threshold or the compressed len is large than original
|
||||||
|
packet len), the packet is dropped when checking the policy as this packet
|
||||||
|
matches the selector but not coming from any XFRM layer, i.e., with no
|
||||||
|
security path. Such naked packet will not eventually make it to upper layer.
|
||||||
|
The result is much more wired to the user when ping peer with different
|
||||||
|
payload length.
|
||||||
|
|
||||||
|
One workaround is try to set "level use" for each policy if user observed
|
||||||
|
above scenario. The consequence of doing so is small packet(uncompressed)
|
||||||
|
will skip policy checking on receiver side.
|
|
@ -98,6 +98,11 @@ by the kernel.
|
||||||
The destruction of the socket and all associated resources
|
The destruction of the socket and all associated resources
|
||||||
is done by a simple call to close(fd).
|
is done by a simple call to close(fd).
|
||||||
|
|
||||||
|
Similarly as without PACKET_MMAP, it is possible to use one socket
|
||||||
|
for capture and transmission. This can be done by mapping the
|
||||||
|
allocated RX and TX buffer ring with a single mmap() call.
|
||||||
|
See "Mapping and use of the circular buffer (ring)".
|
||||||
|
|
||||||
Next I will describe PACKET_MMAP settings and its constraints,
|
Next I will describe PACKET_MMAP settings and its constraints,
|
||||||
also the mapping of the circular buffer in the user process and
|
also the mapping of the circular buffer in the user process and
|
||||||
the use of this buffer.
|
the use of this buffer.
|
||||||
|
@ -414,6 +419,19 @@ tp_block_size/tp_frame_size frames there will be a gap between
|
||||||
the frames. This is because a frame cannot be spawn across two
|
the frames. This is because a frame cannot be spawn across two
|
||||||
blocks.
|
blocks.
|
||||||
|
|
||||||
|
To use one socket for capture and transmission, the mapping of both the
|
||||||
|
RX and TX buffer ring has to be done with one call to mmap:
|
||||||
|
|
||||||
|
...
|
||||||
|
setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &foo, sizeof(foo));
|
||||||
|
setsockopt(fd, SOL_PACKET, PACKET_TX_RING, &bar, sizeof(bar));
|
||||||
|
...
|
||||||
|
rx_ring = mmap(0, size * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
tx_ring = rx_ring + size;
|
||||||
|
|
||||||
|
RX must be the first as the kernel maps the TX ring memory right
|
||||||
|
after the RX one.
|
||||||
|
|
||||||
At the beginning of each frame there is an status field (see
|
At the beginning of each frame there is an status field (see
|
||||||
struct tpacket_hdr). If this field is 0 means that the frame is ready
|
struct tpacket_hdr). If this field is 0 means that the frame is ready
|
||||||
to be used for the kernel, If not, there is a frame the user can read
|
to be used for the kernel, If not, there is a frame the user can read
|
||||||
|
@ -517,8 +535,6 @@ where 'tpacket_version' can be TPACKET_V1 (default), TPACKET_V2, TPACKET_V3.
|
||||||
TPACKET_V1:
|
TPACKET_V1:
|
||||||
- Default if not otherwise specified by setsockopt(2)
|
- Default if not otherwise specified by setsockopt(2)
|
||||||
- RX_RING, TX_RING available
|
- RX_RING, TX_RING available
|
||||||
- VLAN metadata information available for packets
|
|
||||||
(TP_STATUS_VLAN_VALID)
|
|
||||||
|
|
||||||
TPACKET_V1 --> TPACKET_V2:
|
TPACKET_V1 --> TPACKET_V2:
|
||||||
- Made 64 bit clean due to unsigned long usage in TPACKET_V1
|
- Made 64 bit clean due to unsigned long usage in TPACKET_V1
|
||||||
|
@ -526,6 +542,13 @@ TPACKET_V1 --> TPACKET_V2:
|
||||||
userspace and the like
|
userspace and the like
|
||||||
- Timestamp resolution in nanoseconds instead of microseconds
|
- Timestamp resolution in nanoseconds instead of microseconds
|
||||||
- RX_RING, TX_RING available
|
- RX_RING, TX_RING available
|
||||||
|
- VLAN metadata information available for packets
|
||||||
|
(TP_STATUS_VLAN_VALID, TP_STATUS_VLAN_TPID_VALID),
|
||||||
|
in the tpacket2_hdr structure:
|
||||||
|
- TP_STATUS_VLAN_VALID bit being set into the tp_status field indicates
|
||||||
|
that the tp_vlan_tci field has valid VLAN TCI value
|
||||||
|
- TP_STATUS_VLAN_TPID_VALID bit being set into the tp_status field
|
||||||
|
indicates that the tp_vlan_tpid field has valid VLAN TPID value
|
||||||
- How to switch to TPACKET_V2:
|
- How to switch to TPACKET_V2:
|
||||||
1. Replace struct tpacket_hdr by struct tpacket2_hdr
|
1. Replace struct tpacket_hdr by struct tpacket2_hdr
|
||||||
2. Query header len and save
|
2. Query header len and save
|
||||||
|
@ -952,6 +975,27 @@ int main(int argc, char **argp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
+ PACKET_QDISC_BYPASS
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
If there is a requirement to load the network with many packets in a similar
|
||||||
|
fashion as pktgen does, you might set the following option after socket
|
||||||
|
creation:
|
||||||
|
|
||||||
|
int one = 1;
|
||||||
|
setsockopt(fd, SOL_PACKET, PACKET_QDISC_BYPASS, &one, sizeof(one));
|
||||||
|
|
||||||
|
This has the side-effect, that packets sent through PF_PACKET will bypass the
|
||||||
|
kernel's qdisc layer and are forcedly pushed to the driver directly. Meaning,
|
||||||
|
packet are not buffered, tc disciplines are ignored, increased loss can occur
|
||||||
|
and such packets are also not visible to other PF_PACKET sockets anymore. So,
|
||||||
|
you have been warned; generally, this can be useful for stress testing various
|
||||||
|
components of a system.
|
||||||
|
|
||||||
|
On default, PACKET_QDISC_BYPASS is disabled and needs to be explicitly enabled
|
||||||
|
on PF_PACKET sockets.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
+ PACKET_TIMESTAMP
|
+ PACKET_TIMESTAMP
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
|
@ -255,7 +255,8 @@ Writing a PHY driver
|
||||||
|
|
||||||
config_init: configures PHY into a sane state after a reset.
|
config_init: configures PHY into a sane state after a reset.
|
||||||
For instance, a Davicom PHY requires descrambling disabled.
|
For instance, a Davicom PHY requires descrambling disabled.
|
||||||
probe: Does any setup needed by the driver
|
probe: Allocate phy->priv, optionally refuse to bind.
|
||||||
|
PHY may not have been reset or had fixups run yet.
|
||||||
suspend/resume: power management
|
suspend/resume: power management
|
||||||
config_aneg: Changes the speed/duplex/negotiation settings
|
config_aneg: Changes the speed/duplex/negotiation settings
|
||||||
read_status: Reads the current speed/duplex/negotiation settings
|
read_status: Reads the current speed/duplex/negotiation settings
|
||||||
|
|
|
@ -108,7 +108,9 @@ Examples:
|
||||||
MPLS_RND, VID_RND, SVID_RND
|
MPLS_RND, VID_RND, SVID_RND
|
||||||
QUEUE_MAP_RND # queue map random
|
QUEUE_MAP_RND # queue map random
|
||||||
QUEUE_MAP_CPU # queue map mirrors smp_processor_id()
|
QUEUE_MAP_CPU # queue map mirrors smp_processor_id()
|
||||||
|
IPSEC # Make IPsec encapsulation for packet
|
||||||
|
|
||||||
|
pgset spi SPI_VALUE Set specific SA used to transform packet.
|
||||||
|
|
||||||
pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
|
pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
|
||||||
cycle through the port range.
|
cycle through the port range.
|
||||||
|
@ -177,6 +179,18 @@ Note when adding devices to a specific CPU there good idea to also assign
|
||||||
/proc/irq/XX/smp_affinity so the TX-interrupts gets bound to the same CPU.
|
/proc/irq/XX/smp_affinity so the TX-interrupts gets bound to the same CPU.
|
||||||
as this reduces cache bouncing when freeing skb's.
|
as this reduces cache bouncing when freeing skb's.
|
||||||
|
|
||||||
|
Enable IPsec
|
||||||
|
============
|
||||||
|
Default IPsec transformation with ESP encapsulation plus Transport mode
|
||||||
|
could be enabled by simply setting:
|
||||||
|
|
||||||
|
pgset "flag IPSEC"
|
||||||
|
pgset "flows 1"
|
||||||
|
|
||||||
|
To avoid breaking existing testbed scripts for using AH type and tunnel mode,
|
||||||
|
user could use "pgset spi SPI_VALUE" to specify which formal of transformation
|
||||||
|
to employ.
|
||||||
|
|
||||||
|
|
||||||
Current commands and configuration options
|
Current commands and configuration options
|
||||||
==========================================
|
==========================================
|
||||||
|
@ -225,6 +239,7 @@ flag
|
||||||
UDPDST_RND
|
UDPDST_RND
|
||||||
MACSRC_RND
|
MACSRC_RND
|
||||||
MACDST_RND
|
MACDST_RND
|
||||||
|
IPSEC
|
||||||
|
|
||||||
dst_min
|
dst_min
|
||||||
dst_max
|
dst_max
|
||||||
|
|
|
@ -159,10 +159,10 @@ struct ieee80211_regdomain mydriver_jp_regdom = {
|
||||||
REG_RULE(2412-20, 2484+20, 40, 6, 20, 0),
|
REG_RULE(2412-20, 2484+20, 40, 6, 20, 0),
|
||||||
/* IEEE 802.11a, channels 34..48 */
|
/* IEEE 802.11a, channels 34..48 */
|
||||||
REG_RULE(5170-20, 5240+20, 40, 6, 20,
|
REG_RULE(5170-20, 5240+20, 40, 6, 20,
|
||||||
NL80211_RRF_PASSIVE_SCAN),
|
NL80211_RRF_NO_IR),
|
||||||
/* IEEE 802.11a, channels 52..64 */
|
/* IEEE 802.11a, channels 52..64 */
|
||||||
REG_RULE(5260-20, 5320+20, 40, 6, 20,
|
REG_RULE(5260-20, 5320+20, 40, 6, 20,
|
||||||
NL80211_RRF_NO_IBSS |
|
NL80211_RRF_NO_IR|
|
||||||
NL80211_RRF_DFS),
|
NL80211_RRF_DFS),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,8 +127,9 @@ struct plat_stmmacenet_data {
|
||||||
int riwt_off;
|
int riwt_off;
|
||||||
void (*fix_mac_speed)(void *priv, unsigned int speed);
|
void (*fix_mac_speed)(void *priv, unsigned int speed);
|
||||||
void (*bus_setup)(void __iomem *ioaddr);
|
void (*bus_setup)(void __iomem *ioaddr);
|
||||||
int (*init)(struct platform_device *pdev);
|
void *(*setup)(struct platform_device *pdev);
|
||||||
void (*exit)(struct platform_device *pdev);
|
int (*init)(struct platform_device *pdev, void *priv);
|
||||||
|
void (*exit)(struct platform_device *pdev, void *priv);
|
||||||
void *custom_cfg;
|
void *custom_cfg;
|
||||||
void *custom_data;
|
void *custom_data;
|
||||||
void *bsp_priv;
|
void *bsp_priv;
|
||||||
|
@ -169,10 +170,13 @@ Where:
|
||||||
o bus_setup: perform HW setup of the bus. For example, on some ST platforms
|
o bus_setup: perform HW setup of the bus. For example, on some ST platforms
|
||||||
this field is used to configure the AMBA bridge to generate more
|
this field is used to configure the AMBA bridge to generate more
|
||||||
efficient STBus traffic.
|
efficient STBus traffic.
|
||||||
o init/exit: callbacks used for calling a custom initialization;
|
o setup/init/exit: callbacks used for calling a custom initialization;
|
||||||
this is sometime necessary on some platforms (e.g. ST boxes)
|
this is sometime necessary on some platforms (e.g. ST boxes)
|
||||||
where the HW needs to have set some PIO lines or system cfg
|
where the HW needs to have set some PIO lines or system cfg
|
||||||
registers.
|
registers. setup should return a pointer to private data,
|
||||||
|
which will be stored in bsp_priv, and then passed to init and
|
||||||
|
exit callbacks. init/exit callbacks should not use or modify
|
||||||
|
platform data.
|
||||||
o custom_cfg/custom_data: this is a custom configuration that can be passed
|
o custom_cfg/custom_data: this is a custom configuration that can be passed
|
||||||
while initializing the resources.
|
while initializing the resources.
|
||||||
o bsp_priv: another private pointer.
|
o bsp_priv: another private pointer.
|
||||||
|
|
|
@ -85,7 +85,7 @@ Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
|
||||||
by the network device and will be empty without that support.
|
by the network device and will be empty without that support.
|
||||||
|
|
||||||
|
|
||||||
SIOCSHWTSTAMP:
|
SIOCSHWTSTAMP, SIOCGHWTSTAMP:
|
||||||
|
|
||||||
Hardware time stamping must also be initialized for each device driver
|
Hardware time stamping must also be initialized for each device driver
|
||||||
that is expected to do hardware time stamping. The parameter is defined in
|
that is expected to do hardware time stamping. The parameter is defined in
|
||||||
|
@ -115,6 +115,10 @@ Only a processes with admin rights may change the configuration. User
|
||||||
space is responsible to ensure that multiple processes don't interfere
|
space is responsible to ensure that multiple processes don't interfere
|
||||||
with each other and that the settings are reset.
|
with each other and that the settings are reset.
|
||||||
|
|
||||||
|
Any process can read the actual configuration by passing this
|
||||||
|
structure to ioctl(SIOCGHWTSTAMP) in the same way. However, this has
|
||||||
|
not been implemented in all drivers.
|
||||||
|
|
||||||
/* possible values for hwtstamp_config->tx_type */
|
/* possible values for hwtstamp_config->tx_type */
|
||||||
enum {
|
enum {
|
||||||
/*
|
/*
|
||||||
|
@ -157,7 +161,8 @@ DEVICE IMPLEMENTATION
|
||||||
|
|
||||||
A driver which supports hardware time stamping must support the
|
A driver which supports hardware time stamping must support the
|
||||||
SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
|
SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
|
||||||
the actual values as described in the section on SIOCSHWTSTAMP.
|
the actual values as described in the section on SIOCSHWTSTAMP. It
|
||||||
|
should also support SIOCGHWTSTAMP.
|
||||||
|
|
||||||
Time stamps for received packets must be stored in the skb. To get a pointer
|
Time stamps for received packets must be stored in the skb. To get a pointer
|
||||||
to the shared time stamp structure of the skb call skb_hwtstamps(). Then
|
to the shared time stamp structure of the skb call skb_hwtstamps(). Then
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
timestamping
|
timestamping
|
||||||
|
hwtstamp_config
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
obj- := dummy.o
|
obj- := dummy.o
|
||||||
|
|
||||||
# List of programs to build
|
# List of programs to build
|
||||||
hostprogs-y := timestamping
|
hostprogs-y := timestamping hwtstamp_config
|
||||||
|
|
||||||
# Tell kbuild to always build the programs
|
# Tell kbuild to always build the programs
|
||||||
always := $(hostprogs-y)
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
|
HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
|
||||||
|
HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f timestamping
|
rm -f timestamping hwtstamp_config
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
/* Test program for SIOC{G,S}HWTSTAMP
|
||||||
|
* Copyright 2013 Solarflare Communications
|
||||||
|
* Author: Ben Hutchings
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/net_tstamp.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
lookup_value(const char **names, int size, const char *name)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
|
||||||
|
for (value = 0; value < size; value++)
|
||||||
|
if (names[value] && strcasecmp(names[value], name) == 0)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
lookup_name(const char **names, int size, int value)
|
||||||
|
{
|
||||||
|
return (value >= 0 && value < size) ? names[value] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_names(FILE *f, const char **names, int size)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
|
||||||
|
for (value = 0; value < size; value++)
|
||||||
|
if (names[value])
|
||||||
|
fprintf(f, " %s\n", names[value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *tx_types[] = {
|
||||||
|
#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
|
||||||
|
TX_TYPE(OFF),
|
||||||
|
TX_TYPE(ON),
|
||||||
|
TX_TYPE(ONESTEP_SYNC)
|
||||||
|
#undef TX_TYPE
|
||||||
|
};
|
||||||
|
#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
|
||||||
|
|
||||||
|
static const char *rx_filters[] = {
|
||||||
|
#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
|
||||||
|
RX_FILTER(NONE),
|
||||||
|
RX_FILTER(ALL),
|
||||||
|
RX_FILTER(SOME),
|
||||||
|
RX_FILTER(PTP_V1_L4_EVENT),
|
||||||
|
RX_FILTER(PTP_V1_L4_SYNC),
|
||||||
|
RX_FILTER(PTP_V1_L4_DELAY_REQ),
|
||||||
|
RX_FILTER(PTP_V2_L4_EVENT),
|
||||||
|
RX_FILTER(PTP_V2_L4_SYNC),
|
||||||
|
RX_FILTER(PTP_V2_L4_DELAY_REQ),
|
||||||
|
RX_FILTER(PTP_V2_L2_EVENT),
|
||||||
|
RX_FILTER(PTP_V2_L2_SYNC),
|
||||||
|
RX_FILTER(PTP_V2_L2_DELAY_REQ),
|
||||||
|
RX_FILTER(PTP_V2_EVENT),
|
||||||
|
RX_FILTER(PTP_V2_SYNC),
|
||||||
|
RX_FILTER(PTP_V2_DELAY_REQ),
|
||||||
|
#undef RX_FILTER
|
||||||
|
};
|
||||||
|
#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
|
||||||
|
"tx_type is any of (case-insensitive):\n",
|
||||||
|
stderr);
|
||||||
|
list_names(stderr, tx_types, N_TX_TYPES);
|
||||||
|
fputs("rx_filter is any of (case-insensitive):\n", stderr);
|
||||||
|
list_names(stderr, rx_filters, N_RX_FILTERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
struct hwtstamp_config config;
|
||||||
|
const char *name;
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
|
||||||
|
usage();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 4) {
|
||||||
|
config.flags = 0;
|
||||||
|
config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
|
||||||
|
config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
|
||||||
|
if (config.tx_type < 0 || config.rx_filter < 0) {
|
||||||
|
usage();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(ifr.ifr_name, argv[1]);
|
||||||
|
ifr.ifr_data = (caddr_t)&config;
|
||||||
|
|
||||||
|
if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
|
||||||
|
perror("ioctl");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("flags = %#x\n", config.flags);
|
||||||
|
name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
|
||||||
|
if (name)
|
||||||
|
printf("tx_type = %s\n", name);
|
||||||
|
else
|
||||||
|
printf("tx_type = %d\n", config.tx_type);
|
||||||
|
name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
|
||||||
|
if (name)
|
||||||
|
printf("rx_filter = %s\n", name);
|
||||||
|
else
|
||||||
|
printf("rx_filter = %d\n", config.rx_filter);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
IBM s390 QDIO Ethernet Driver
|
||||||
|
|
||||||
|
HiperSockets Bridge Port Support
|
||||||
|
|
||||||
|
Uevents
|
||||||
|
|
||||||
|
To generate the events the device must be assigned a role of either
|
||||||
|
a primary or a secondary Bridge Port. For more information, see
|
||||||
|
"z/VM Connectivity, SC24-6174".
|
||||||
|
|
||||||
|
When run on HiperSockets Bridge Capable Port hardware, and the state
|
||||||
|
of some configured Bridge Port device on the channel changes, a udev
|
||||||
|
event with ACTION=CHANGE is emitted on behalf of the corresponding
|
||||||
|
ccwgroup device. The event has the following attributes:
|
||||||
|
|
||||||
|
BRIDGEPORT=statechange - indicates that the Bridge Port device changed
|
||||||
|
its state.
|
||||||
|
|
||||||
|
ROLE={primary|secondary|none} - the role assigned to the port.
|
||||||
|
|
||||||
|
STATE={active|standby|inactive} - the newly assumed state of the port.
|
||||||
|
|
||||||
|
When run on HiperSockets Bridge Capable Port hardware with host address
|
||||||
|
notifications enabled, a udev event with ACTION=CHANGE is emitted.
|
||||||
|
It is emitted on behalf of the corresponding ccwgroup device when a host
|
||||||
|
or a VLAN is registered or unregistered on the network served by the device.
|
||||||
|
The event has the following attributes:
|
||||||
|
|
||||||
|
BRIDGEDHOST={reset|register|deregister|abort} - host address
|
||||||
|
notifications are started afresh, a new host or VLAN is registered or
|
||||||
|
deregistered on the Bridge Port HiperSockets channel, or address
|
||||||
|
notifications are aborted.
|
||||||
|
|
||||||
|
VLAN=numeric-vlan-id - VLAN ID on which the event occurred. Not included
|
||||||
|
if no VLAN is involved in the event.
|
||||||
|
|
||||||
|
MAC=xx:xx:xx:xx:xx:xx - MAC address of the host that is being registered
|
||||||
|
or deregistered from the HiperSockets channel. Not reported if the
|
||||||
|
event reports the creation or destruction of a VLAN.
|
||||||
|
|
||||||
|
NTOK_BUSID=x.y.zzzz - device bus ID (CSSID, SSID and device number).
|
||||||
|
|
||||||
|
NTOK_IID=xx - device IID.
|
||||||
|
|
||||||
|
NTOK_CHPID=xx - device CHPID.
|
||||||
|
|
||||||
|
NTOK_CHID=xxxx - device channel ID.
|
||||||
|
|
||||||
|
Note that the NTOK_* attributes refer to devices other than the one
|
||||||
|
connected to the system on which the OS is running.
|
|
@ -137,24 +137,34 @@ Code that causes unaligned access
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
With the above in mind, let's move onto a real life example of a function
|
With the above in mind, let's move onto a real life example of a function
|
||||||
that can cause an unaligned memory access. The following function adapted
|
that can cause an unaligned memory access. The following function taken
|
||||||
from include/linux/etherdevice.h is an optimized routine to compare two
|
from include/linux/etherdevice.h is an optimized routine to compare two
|
||||||
ethernet MAC addresses for equality.
|
ethernet MAC addresses for equality.
|
||||||
|
|
||||||
unsigned int compare_ether_addr(const u8 *addr1, const u8 *addr2)
|
bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
|
||||||
{
|
{
|
||||||
const u16 *a = (const u16 *) addr1;
|
#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||||
const u16 *b = (const u16 *) addr2;
|
u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
|
||||||
|
((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
|
||||||
|
|
||||||
|
return fold == 0;
|
||||||
|
#else
|
||||||
|
const u16 *a = (const u16 *)addr1;
|
||||||
|
const u16 *b = (const u16 *)addr2;
|
||||||
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
|
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
In the above function, the reference to a[0] causes 2 bytes (16 bits) to
|
In the above function, when the hardware has efficient unaligned access
|
||||||
be read from memory starting at address addr1. Think about what would happen
|
capability, there is no issue with this code. But when the hardware isn't
|
||||||
if addr1 was an odd address such as 0x10003. (Hint: it'd be an unaligned
|
able to access memory on arbitrary boundaries, the reference to a[0] causes
|
||||||
access.)
|
2 bytes (16 bits) to be read from memory starting at address addr1.
|
||||||
|
|
||||||
|
Think about what would happen if addr1 was an odd address such as 0x10003.
|
||||||
|
(Hint: it'd be an unaligned access.)
|
||||||
|
|
||||||
Despite the potential unaligned access problems with the above function, it
|
Despite the potential unaligned access problems with the above function, it
|
||||||
is included in the kernel anyway but is understood to only work on
|
is included in the kernel anyway but is understood to only work normally on
|
||||||
16-bit-aligned addresses. It is up to the caller to ensure this alignment or
|
16-bit-aligned addresses. It is up to the caller to ensure this alignment or
|
||||||
not use this function at all. This alignment-unsafe function is still useful
|
not use this function at all. This alignment-unsafe function is still useful
|
||||||
as it is a decent optimization for the cases when you can ensure alignment,
|
as it is a decent optimization for the cases when you can ensure alignment,
|
||||||
|
|
33
MAINTAINERS
33
MAINTAINERS
|
@ -1473,7 +1473,7 @@ F: Documentation/aoe/
|
||||||
F: drivers/block/aoe/
|
F: drivers/block/aoe/
|
||||||
|
|
||||||
ATHEROS ATH GENERIC UTILITIES
|
ATHEROS ATH GENERIC UTILITIES
|
||||||
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
|
M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
|
||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/wireless/ath/*
|
F: drivers/net/wireless/ath/*
|
||||||
|
@ -1481,7 +1481,7 @@ F: drivers/net/wireless/ath/*
|
||||||
ATHEROS ATH5K WIRELESS DRIVER
|
ATHEROS ATH5K WIRELESS DRIVER
|
||||||
M: Jiri Slaby <jirislaby@gmail.com>
|
M: Jiri Slaby <jirislaby@gmail.com>
|
||||||
M: Nick Kossifidis <mickflemm@gmail.com>
|
M: Nick Kossifidis <mickflemm@gmail.com>
|
||||||
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
|
M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
|
||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
L: ath5k-devel@lists.ath5k.org
|
L: ath5k-devel@lists.ath5k.org
|
||||||
W: http://wireless.kernel.org/en/users/Drivers/ath5k
|
W: http://wireless.kernel.org/en/users/Drivers/ath5k
|
||||||
|
@ -1496,17 +1496,6 @@ T: git git://github.com/kvalo/ath.git
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/wireless/ath/ath6kl/
|
F: drivers/net/wireless/ath/ath6kl/
|
||||||
|
|
||||||
ATHEROS ATH9K WIRELESS DRIVER
|
|
||||||
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
|
|
||||||
M: Jouni Malinen <jouni@qca.qualcomm.com>
|
|
||||||
M: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
|
|
||||||
M: Senthil Balasubramanian <senthilb@qca.qualcomm.com>
|
|
||||||
L: linux-wireless@vger.kernel.org
|
|
||||||
L: ath9k-devel@lists.ath9k.org
|
|
||||||
W: http://wireless.kernel.org/en/users/Drivers/ath9k
|
|
||||||
S: Supported
|
|
||||||
F: drivers/net/wireless/ath/ath9k/
|
|
||||||
|
|
||||||
WILOCITY WIL6210 WIRELESS DRIVER
|
WILOCITY WIL6210 WIRELESS DRIVER
|
||||||
M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
|
M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
|
||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
|
@ -2061,6 +2050,7 @@ L: linux-can@vger.kernel.org
|
||||||
W: http://gitorious.org/linux-can
|
W: http://gitorious.org/linux-can
|
||||||
T: git git://gitorious.org/linux-can/linux-can-next.git
|
T: git git://gitorious.org/linux-can/linux-can-next.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
F: Documentation/networking/can.txt
|
||||||
F: net/can/
|
F: net/can/
|
||||||
F: include/linux/can/core.h
|
F: include/linux/can/core.h
|
||||||
F: include/uapi/linux/can.h
|
F: include/uapi/linux/can.h
|
||||||
|
@ -4523,7 +4513,7 @@ M: Deepak Saxena <dsaxena@plexity.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/char/hw_random/ixp4xx-rng.c
|
F: drivers/char/hw_random/ixp4xx-rng.c
|
||||||
|
|
||||||
INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf/i40e)
|
INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf/i40e/i40evf)
|
||||||
M: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
|
M: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
|
||||||
M: Jesse Brandeburg <jesse.brandeburg@intel.com>
|
M: Jesse Brandeburg <jesse.brandeburg@intel.com>
|
||||||
M: Bruce Allan <bruce.w.allan@intel.com>
|
M: Bruce Allan <bruce.w.allan@intel.com>
|
||||||
|
@ -4532,6 +4522,7 @@ M: Don Skidmore <donald.c.skidmore@intel.com>
|
||||||
M: Greg Rose <gregory.v.rose@intel.com>
|
M: Greg Rose <gregory.v.rose@intel.com>
|
||||||
M: Alex Duyck <alexander.h.duyck@intel.com>
|
M: Alex Duyck <alexander.h.duyck@intel.com>
|
||||||
M: John Ronciak <john.ronciak@intel.com>
|
M: John Ronciak <john.ronciak@intel.com>
|
||||||
|
M: Mitch Williams <mitch.a.williams@intel.com>
|
||||||
L: e1000-devel@lists.sourceforge.net
|
L: e1000-devel@lists.sourceforge.net
|
||||||
W: http://www.intel.com/support/feedback.htm
|
W: http://www.intel.com/support/feedback.htm
|
||||||
W: http://e1000.sourceforge.net/
|
W: http://e1000.sourceforge.net/
|
||||||
|
@ -4547,6 +4538,7 @@ F: Documentation/networking/ixgb.txt
|
||||||
F: Documentation/networking/ixgbe.txt
|
F: Documentation/networking/ixgbe.txt
|
||||||
F: Documentation/networking/ixgbevf.txt
|
F: Documentation/networking/ixgbevf.txt
|
||||||
F: Documentation/networking/i40e.txt
|
F: Documentation/networking/i40e.txt
|
||||||
|
F: Documentation/networking/i40evf.txt
|
||||||
F: drivers/net/ethernet/intel/
|
F: drivers/net/ethernet/intel/
|
||||||
|
|
||||||
INTEL-MID GPIO DRIVER
|
INTEL-MID GPIO DRIVER
|
||||||
|
@ -7041,6 +7033,14 @@ T: git git://linuxtv.org/anttip/media_tree.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/media/tuners/qt1010*
|
F: drivers/media/tuners/qt1010*
|
||||||
|
|
||||||
|
QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
|
||||||
|
M: QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
|
||||||
|
L: linux-wireless@vger.kernel.org
|
||||||
|
L: ath9k-devel@lists.ath9k.org
|
||||||
|
W: http://wireless.kernel.org/en/users/Drivers/ath9k
|
||||||
|
S: Supported
|
||||||
|
F: drivers/net/wireless/ath/ath9k/
|
||||||
|
|
||||||
QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
|
QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
|
||||||
M: Kalle Valo <kvalo@qca.qualcomm.com>
|
M: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||||
L: ath10k@lists.infradead.org
|
L: ath10k@lists.infradead.org
|
||||||
|
@ -7702,7 +7702,7 @@ F: drivers/net/ethernet/emulex/benet/
|
||||||
|
|
||||||
SFC NETWORK DRIVER
|
SFC NETWORK DRIVER
|
||||||
M: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
|
M: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
|
||||||
M: Ben Hutchings <bhutchings@solarflare.com>
|
M: Shradha Shah <sshah@solarflare.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/ethernet/sfc/
|
F: drivers/net/ethernet/sfc/
|
||||||
|
@ -8695,12 +8695,11 @@ S: Maintained
|
||||||
F: sound/soc/codecs/twl4030*
|
F: sound/soc/codecs/twl4030*
|
||||||
|
|
||||||
TI WILINK WIRELESS DRIVERS
|
TI WILINK WIRELESS DRIVERS
|
||||||
M: Luciano Coelho <luca@coelho.fi>
|
|
||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
W: http://wireless.kernel.org/en/users/Drivers/wl12xx
|
W: http://wireless.kernel.org/en/users/Drivers/wl12xx
|
||||||
W: http://wireless.kernel.org/en/users/Drivers/wl1251
|
W: http://wireless.kernel.org/en/users/Drivers/wl1251
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
|
||||||
S: Maintained
|
S: Orphan
|
||||||
F: drivers/net/wireless/ti/
|
F: drivers/net/wireless/ti/
|
||||||
F: include/linux/wl12xx.h
|
F: include/linux/wl12xx.h
|
||||||
|
|
||||||
|
|
|
@ -4,3 +4,4 @@ generic-y += clkdev.h
|
||||||
generic-y += exec.h
|
generic-y += exec.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -85,4 +85,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _UAPI_ASM_SOCKET_H */
|
#endif /* _UAPI_ASM_SOCKET_H */
|
||||||
|
|
|
@ -12,6 +12,7 @@ generic-y += fcntl.h
|
||||||
generic-y += fb.h
|
generic-y += fb.h
|
||||||
generic-y += ftrace.h
|
generic-y += ftrace.h
|
||||||
generic-y += hardirq.h
|
generic-y += hardirq.h
|
||||||
|
generic-y += hash.h
|
||||||
generic-y += hw_irq.h
|
generic-y += hw_irq.h
|
||||||
generic-y += ioctl.h
|
generic-y += ioctl.h
|
||||||
generic-y += ioctls.h
|
generic-y += ioctls.h
|
||||||
|
|
|
@ -34,3 +34,4 @@ generic-y += timex.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += unaligned.h
|
generic-y += unaligned.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -50,3 +50,4 @@ generic-y += user.h
|
||||||
generic-y += vga.h
|
generic-y += vga.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -18,3 +18,4 @@ generic-y += sections.h
|
||||||
generic-y += topology.h
|
generic-y += topology.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -78,4 +78,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _UAPI__ASM_AVR32_SOCKET_H */
|
#endif /* _UAPI__ASM_AVR32_SOCKET_H */
|
||||||
|
|
|
@ -45,3 +45,4 @@ generic-y += unaligned.h
|
||||||
generic-y += user.h
|
generic-y += user.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -117,7 +117,7 @@ static struct stmmac_dma_cfg eth_dma_cfg = {
|
||||||
.pbl = 2,
|
.pbl = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
int stmmac_ptp_clk_init(struct platform_device *pdev)
|
int stmmac_ptp_clk_init(struct platform_device *pdev, void *priv)
|
||||||
{
|
{
|
||||||
bfin_write32(PADS0_EMAC_PTP_CLKSEL, 0);
|
bfin_write32(PADS0_EMAC_PTP_CLKSEL, 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -57,3 +57,4 @@ generic-y += user.h
|
||||||
generic-y += vga.h
|
generic-y += vga.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -6,6 +6,7 @@ header-y += arch-v32/
|
||||||
generic-y += barrier.h
|
generic-y += barrier.h
|
||||||
generic-y += clkdev.h
|
generic-y += clkdev.h
|
||||||
generic-y += exec.h
|
generic-y += exec.h
|
||||||
|
generic-y += hash.h
|
||||||
generic-y += kvm_para.h
|
generic-y += kvm_para.h
|
||||||
generic-y += linkage.h
|
generic-y += linkage.h
|
||||||
generic-y += module.h
|
generic-y += module.h
|
||||||
|
|
|
@ -80,6 +80,8 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,3 +3,4 @@ generic-y += clkdev.h
|
||||||
generic-y += exec.h
|
generic-y += exec.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -78,5 +78,7 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ generic-y += fb.h
|
||||||
generic-y += fcntl.h
|
generic-y += fcntl.h
|
||||||
generic-y += ftrace.h
|
generic-y += ftrace.h
|
||||||
generic-y += hardirq.h
|
generic-y += hardirq.h
|
||||||
|
generic-y += hash.h
|
||||||
generic-y += hw_irq.h
|
generic-y += hw_irq.h
|
||||||
generic-y += ioctl.h
|
generic-y += ioctl.h
|
||||||
generic-y += ioctls.h
|
generic-y += ioctls.h
|
||||||
|
|
|
@ -4,4 +4,5 @@ generic-y += exec.h
|
||||||
generic-y += kvm_para.h
|
generic-y += kvm_para.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
generic-y += vtime.h
|
generic-y += vtime.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -87,4 +87,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _ASM_IA64_SOCKET_H */
|
#endif /* _ASM_IA64_SOCKET_H */
|
||||||
|
|
|
@ -4,3 +4,4 @@ generic-y += exec.h
|
||||||
generic-y += module.h
|
generic-y += module.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -78,4 +78,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _ASM_M32R_SOCKET_H */
|
#endif /* _ASM_M32R_SOCKET_H */
|
||||||
|
|
|
@ -32,3 +32,4 @@ generic-y += types.h
|
||||||
generic-y += word-at-a-time.h
|
generic-y += word-at-a-time.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -53,3 +53,4 @@ generic-y += user.h
|
||||||
generic-y += vga.h
|
generic-y += vga.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
generic-y += barrier.h
|
generic-y += barrier.h
|
||||||
generic-y += clkdev.h
|
generic-y += clkdev.h
|
||||||
generic-y += exec.h
|
generic-y += exec.h
|
||||||
|
generic-y += hash.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += syscalls.h
|
generic-y += syscalls.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
|
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/phy_fixed.h>
|
||||||
#include <linux/ssb/ssb.h>
|
#include <linux/ssb/ssb.h>
|
||||||
#include <linux/ssb/ssb_embedded.h>
|
#include <linux/ssb/ssb_embedded.h>
|
||||||
#include <linux/bcma/bcma_soc.h>
|
#include <linux/bcma/bcma_soc.h>
|
||||||
|
@ -225,6 +228,12 @@ void __init plat_mem_setup(void)
|
||||||
bcm47xx_board_detect();
|
bcm47xx_board_detect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct fixed_phy_status bcm47xx_fixed_phy_status __initdata = {
|
||||||
|
.link = 1,
|
||||||
|
.speed = SPEED_100,
|
||||||
|
.duplex = DUPLEX_FULL,
|
||||||
|
};
|
||||||
|
|
||||||
static int __init bcm47xx_register_bus_complete(void)
|
static int __init bcm47xx_register_bus_complete(void)
|
||||||
{
|
{
|
||||||
switch (bcm47xx_bus_type) {
|
switch (bcm47xx_bus_type) {
|
||||||
|
@ -239,6 +248,7 @@ static int __init bcm47xx_register_bus_complete(void)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
device_initcall(bcm47xx_register_bus_complete);
|
device_initcall(bcm47xx_register_bus_complete);
|
||||||
|
|
|
@ -14,3 +14,4 @@ generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
generic-y += ucontext.h
|
generic-y += ucontext.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -96,4 +96,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _UAPI_ASM_SOCKET_H */
|
#endif /* _UAPI_ASM_SOCKET_H */
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
generic-y += barrier.h
|
generic-y += barrier.h
|
||||||
generic-y += clkdev.h
|
generic-y += clkdev.h
|
||||||
generic-y += exec.h
|
generic-y += exec.h
|
||||||
|
generic-y += hash.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
|
|
@ -78,4 +78,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
|
@ -69,3 +69,4 @@ generic-y += vga.h
|
||||||
generic-y += word-at-a-time.h
|
generic-y += word-at-a-time.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -6,3 +6,4 @@ generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \
|
||||||
poll.h xor.h clkdev.h exec.h
|
poll.h xor.h clkdev.h exec.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -77,4 +77,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 0x4028
|
#define SO_MAX_PACING_RATE 0x4028
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 0x4029
|
||||||
|
|
||||||
#endif /* _UAPI_ASM_SOCKET_H */
|
#endif /* _UAPI_ASM_SOCKET_H */
|
||||||
|
|
|
@ -3,4 +3,5 @@ generic-y += clkdev.h
|
||||||
generic-y += rwsem.h
|
generic-y += rwsem.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
generic-y += vtime.h
|
generic-y += vtime.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -85,4 +85,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _ASM_POWERPC_SOCKET_H */
|
#endif /* _ASM_POWERPC_SOCKET_H */
|
||||||
|
|
|
@ -3,3 +3,4 @@
|
||||||
generic-y += clkdev.h
|
generic-y += clkdev.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -84,4 +84,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
|
@ -3,6 +3,8 @@ header-y +=
|
||||||
|
|
||||||
generic-y += barrier.h
|
generic-y += barrier.h
|
||||||
generic-y += clkdev.h
|
generic-y += clkdev.h
|
||||||
|
generic-y += hash.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
|
||||||
|
|
|
@ -35,3 +35,4 @@ generic-y += trace_clock.h
|
||||||
generic-y += ucontext.h
|
generic-y += ucontext.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -17,3 +17,4 @@ generic-y += trace_clock.h
|
||||||
generic-y += types.h
|
generic-y += types.h
|
||||||
generic-y += word-at-a-time.h
|
generic-y += word-at-a-time.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -74,6 +74,8 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 0x0031
|
#define SO_MAX_PACING_RATE 0x0031
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 0x0032
|
||||||
|
|
||||||
/* Security levels - as per NRL IPv6 - don't actually do anything */
|
/* Security levels - as per NRL IPv6 - don't actually do anything */
|
||||||
#define SO_SECURITY_AUTHENTICATION 0x5001
|
#define SO_SECURITY_AUTHENTICATION 0x5001
|
||||||
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
|
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
|
||||||
|
|
|
@ -39,3 +39,4 @@ generic-y += trace_clock.h
|
||||||
generic-y += types.h
|
generic-y += types.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -4,3 +4,4 @@ generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h
|
||||||
generic-y += switch_to.h clkdev.h
|
generic-y += switch_to.h clkdev.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -61,3 +61,4 @@ generic-y += user.h
|
||||||
generic-y += vga.h
|
generic-y += vga.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef _ASM_X86_HASH_H
|
||||||
|
#define _ASM_X86_HASH_H
|
||||||
|
|
||||||
|
struct fast_hash_ops;
|
||||||
|
extern void setup_arch_fast_hash(struct fast_hash_ops *ops);
|
||||||
|
|
||||||
|
#endif /* _ASM_X86_HASH_H */
|
|
@ -24,7 +24,7 @@ lib-$(CONFIG_SMP) += rwlock.o
|
||||||
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
|
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
|
||||||
lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
|
lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
|
||||||
|
|
||||||
obj-y += msr.o msr-reg.o msr-reg-export.o
|
obj-y += msr.o msr-reg.o msr-reg-export.o hash.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_X86_32),y)
|
ifeq ($(CONFIG_X86_32),y)
|
||||||
obj-y += atomic64_32.o
|
obj-y += atomic64_32.o
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Some portions derived from code covered by the following notice:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Intel Corporation. All rights reserved.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/hash.h>
|
||||||
|
|
||||||
|
#include <asm/processor.h>
|
||||||
|
#include <asm/cpufeature.h>
|
||||||
|
#include <asm/hash.h>
|
||||||
|
|
||||||
|
static inline u32 crc32_u32(u32 crc, u32 val)
|
||||||
|
{
|
||||||
|
asm ("crc32l %1,%0\n" : "+r" (crc) : "rm" (val));
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 intel_crc4_2_hash(const void *data, u32 len, u32 seed)
|
||||||
|
{
|
||||||
|
const u32 *p32 = (const u32 *) data;
|
||||||
|
u32 i, tmp = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len / 4; i++)
|
||||||
|
seed = crc32_u32(*p32++, seed);
|
||||||
|
|
||||||
|
switch (3 - (len & 0x03)) {
|
||||||
|
case 0:
|
||||||
|
tmp |= *((const u8 *) p32 + 2) << 16;
|
||||||
|
/* fallthrough */
|
||||||
|
case 1:
|
||||||
|
tmp |= *((const u8 *) p32 + 1) << 8;
|
||||||
|
/* fallthrough */
|
||||||
|
case 2:
|
||||||
|
tmp |= *((const u8 *) p32);
|
||||||
|
seed = crc32_u32(tmp, seed);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 intel_crc4_2_hash2(const u32 *data, u32 len, u32 seed)
|
||||||
|
{
|
||||||
|
const u32 *p32 = (const u32 *) data;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
seed = crc32_u32(*p32++, seed);
|
||||||
|
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_arch_fast_hash(struct fast_hash_ops *ops)
|
||||||
|
{
|
||||||
|
if (cpu_has_xmm4_2) {
|
||||||
|
ops->hash = intel_crc4_2_hash;
|
||||||
|
ops->hash2 = intel_crc4_2_hash2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,3 +28,4 @@ generic-y += topology.h
|
||||||
generic-y += trace_clock.h
|
generic-y += trace_clock.h
|
||||||
generic-y += xor.h
|
generic-y += xor.h
|
||||||
generic-y += preempt.h
|
generic-y += preempt.h
|
||||||
|
generic-y += hash.h
|
||||||
|
|
|
@ -89,4 +89,6 @@
|
||||||
|
|
||||||
#define SO_MAX_PACING_RATE 47
|
#define SO_MAX_PACING_RATE 47
|
||||||
|
|
||||||
|
#define SO_BPF_EXTENSIONS 48
|
||||||
|
|
||||||
#endif /* _XTENSA_SOCKET_H */
|
#endif /* _XTENSA_SOCKET_H */
|
||||||
|
|
|
@ -419,7 +419,6 @@ static void he_remove_one(struct pci_dev *pci_dev)
|
||||||
atm_dev_deregister(atm_dev);
|
atm_dev_deregister(atm_dev);
|
||||||
kfree(he_dev);
|
kfree(he_dev);
|
||||||
|
|
||||||
pci_set_drvdata(pci_dev, NULL);
|
|
||||||
pci_disable_device(pci_dev);
|
pci_disable_device(pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
#include "nicstar.h"
|
#include "nicstar.h"
|
||||||
#ifdef CONFIG_ATM_NICSTAR_USE_SUNI
|
#ifdef CONFIG_ATM_NICSTAR_USE_SUNI
|
||||||
#include "suni.h"
|
#include "suni.h"
|
||||||
|
@ -781,8 +782,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev)
|
||||||
if (mac[i] == NULL || !mac_pton(mac[i], card->atmdev->esi)) {
|
if (mac[i] == NULL || !mac_pton(mac[i], card->atmdev->esi)) {
|
||||||
nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,
|
nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,
|
||||||
card->atmdev->esi, 6);
|
card->atmdev->esi, 6);
|
||||||
if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) ==
|
if (ether_addr_equal(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00")) {
|
||||||
0) {
|
|
||||||
nicstar_read_eprom(card->membase,
|
nicstar_read_eprom(card->membase,
|
||||||
NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT,
|
NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT,
|
||||||
card->atmdev->esi, 6);
|
card->atmdev->esi, 6);
|
||||||
|
|
|
@ -1335,7 +1335,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
|
|
||||||
out_unmap_both:
|
out_unmap_both:
|
||||||
kfree(card->dma_bounce);
|
kfree(card->dma_bounce);
|
||||||
pci_set_drvdata(dev, NULL);
|
|
||||||
pci_iounmap(dev, card->buffers);
|
pci_iounmap(dev, card->buffers);
|
||||||
out_unmap_config:
|
out_unmap_config:
|
||||||
pci_iounmap(dev, card->config_regs);
|
pci_iounmap(dev, card->config_regs);
|
||||||
|
@ -1457,7 +1456,6 @@ static void fpga_remove(struct pci_dev *dev)
|
||||||
pci_release_regions(dev);
|
pci_release_regions(dev);
|
||||||
pci_disable_device(dev);
|
pci_disable_device(dev);
|
||||||
|
|
||||||
pci_set_drvdata(dev, NULL);
|
|
||||||
kfree(card);
|
kfree(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,6 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
|
||||||
int bcma_bus_suspend(struct bcma_bus *bus);
|
int bcma_bus_suspend(struct bcma_bus *bus);
|
||||||
int bcma_bus_resume(struct bcma_bus *bus);
|
int bcma_bus_resume(struct bcma_bus *bus);
|
||||||
#endif
|
#endif
|
||||||
struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
|
||||||
u8 unit);
|
|
||||||
|
|
||||||
/* scan.c */
|
/* scan.c */
|
||||||
int bcma_bus_scan(struct bcma_bus *bus);
|
int bcma_bus_scan(struct bcma_bus *bus);
|
||||||
|
|
|
@ -38,7 +38,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
|
||||||
{ "M25P32", 0x15, 0x10000, 64, },
|
{ "M25P32", 0x15, 0x10000, 64, },
|
||||||
{ "M25P64", 0x16, 0x10000, 128, },
|
{ "M25P64", 0x16, 0x10000, 128, },
|
||||||
{ "M25FL128", 0x17, 0x10000, 256, },
|
{ "M25FL128", 0x17, 0x10000, 256, },
|
||||||
{ 0 },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
|
static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
|
||||||
|
@ -56,7 +56,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
|
||||||
{ "SST25VF016", 0x41, 0x1000, 512, },
|
{ "SST25VF016", 0x41, 0x1000, 512, },
|
||||||
{ "SST25VF032", 0x4a, 0x1000, 1024, },
|
{ "SST25VF032", 0x4a, 0x1000, 1024, },
|
||||||
{ "SST25VF064", 0x4b, 0x1000, 2048, },
|
{ "SST25VF064", 0x4b, 0x1000, 2048, },
|
||||||
{ 0 },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
|
static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
|
||||||
|
@ -67,7 +67,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
|
||||||
{ "AT45DB161", 0x2c, 512, 4096, },
|
{ "AT45DB161", 0x2c, 512, 4096, },
|
||||||
{ "AT45DB321", 0x34, 512, 8192, },
|
{ "AT45DB321", 0x34, 512, 8192, },
|
||||||
{ "AT45DB642", 0x3c, 1024, 8192, },
|
{ "AT45DB642", 0x3c, 1024, 8192, },
|
||||||
{ 0 },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
|
static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
|
||||||
|
|
|
@ -238,7 +238,6 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
|
||||||
pci_release_regions(dev);
|
pci_release_regions(dev);
|
||||||
pci_disable_device(dev);
|
pci_disable_device(dev);
|
||||||
kfree(bus);
|
kfree(bus);
|
||||||
pci_set_drvdata(dev, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
@ -270,7 +269,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
|
||||||
|
|
||||||
#endif /* CONFIG_PM_SLEEP */
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
|
static const struct pci_device_id bcma_pci_bridge_tbl[] = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
|
||||||
|
|
|
@ -78,18 +78,6 @@ static u16 bcma_cc_core_id(struct bcma_bus *bus)
|
||||||
return BCMA_CORE_CHIPCOMMON;
|
return BCMA_CORE_CHIPCOMMON;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
|
||||||
{
|
|
||||||
struct bcma_device *core;
|
|
||||||
|
|
||||||
list_for_each_entry(core, &bus->cores, list) {
|
|
||||||
if (core->id.id == coreid)
|
|
||||||
return core;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(bcma_find_core);
|
|
||||||
|
|
||||||
struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||||
u8 unit)
|
u8 unit)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +89,7 @@ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(bcma_find_core_unit);
|
||||||
|
|
||||||
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
|
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
|
||||||
int timeout)
|
int timeout)
|
||||||
|
@ -176,6 +165,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
|
||||||
bcma_err(bus,
|
bcma_err(bus,
|
||||||
"Could not register dev for core 0x%03X\n",
|
"Could not register dev for core 0x%03X\n",
|
||||||
core->id.id);
|
core->id.id);
|
||||||
|
put_device(&core->dev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
core->dev_registered = true;
|
core->dev_registered = true;
|
||||||
|
|
|
@ -83,6 +83,7 @@ static const struct usb_device_id ath3k_table[] = {
|
||||||
{ USB_DEVICE(0x04CA, 0x3005) },
|
{ USB_DEVICE(0x04CA, 0x3005) },
|
||||||
{ USB_DEVICE(0x04CA, 0x3006) },
|
{ USB_DEVICE(0x04CA, 0x3006) },
|
||||||
{ USB_DEVICE(0x04CA, 0x3008) },
|
{ USB_DEVICE(0x04CA, 0x3008) },
|
||||||
|
{ USB_DEVICE(0x04CA, 0x300b) },
|
||||||
{ USB_DEVICE(0x13d3, 0x3362) },
|
{ USB_DEVICE(0x13d3, 0x3362) },
|
||||||
{ USB_DEVICE(0x0CF3, 0xE004) },
|
{ USB_DEVICE(0x0CF3, 0xE004) },
|
||||||
{ USB_DEVICE(0x0CF3, 0xE005) },
|
{ USB_DEVICE(0x0CF3, 0xE005) },
|
||||||
|
@ -97,6 +98,7 @@ static const struct usb_device_id ath3k_table[] = {
|
||||||
{ USB_DEVICE(0x13d3, 0x3402) },
|
{ USB_DEVICE(0x13d3, 0x3402) },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3121) },
|
{ USB_DEVICE(0x0cf3, 0x3121) },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe003) },
|
{ USB_DEVICE(0x0cf3, 0xe003) },
|
||||||
|
{ USB_DEVICE(0x0489, 0xe05f) },
|
||||||
|
|
||||||
/* Atheros AR5BBU12 with sflash firmware */
|
/* Atheros AR5BBU12 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||||
|
@ -126,6 +128,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
||||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||||
|
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
||||||
|
@ -140,6 +143,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
||||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
||||||
|
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||||
|
|
||||||
/* Atheros AR5BBU22 with sflash firmware */
|
/* Atheros AR5BBU22 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <linux/ctype.h>
|
|
||||||
#include <linux/firmware.h>
|
|
||||||
|
|
||||||
#define BTM_HEADER_LEN 4
|
#define BTM_HEADER_LEN 4
|
||||||
#define BTM_UPLD_SIZE 2312
|
#define BTM_UPLD_SIZE 2312
|
||||||
|
@ -43,8 +41,6 @@ struct btmrvl_thread {
|
||||||
struct btmrvl_device {
|
struct btmrvl_device {
|
||||||
void *card;
|
void *card;
|
||||||
struct hci_dev *hcidev;
|
struct hci_dev *hcidev;
|
||||||
struct device *dev;
|
|
||||||
const char *cal_data;
|
|
||||||
|
|
||||||
u8 dev_type;
|
u8 dev_type;
|
||||||
|
|
||||||
|
@ -90,12 +86,12 @@ struct btmrvl_private {
|
||||||
|
|
||||||
#define MRVL_VENDOR_PKT 0xFE
|
#define MRVL_VENDOR_PKT 0xFE
|
||||||
|
|
||||||
/* Bluetooth commands */
|
/* Vendor specific Bluetooth commands */
|
||||||
#define BT_CMD_AUTO_SLEEP_MODE 0x23
|
#define BT_CMD_AUTO_SLEEP_MODE 0xFC23
|
||||||
#define BT_CMD_HOST_SLEEP_CONFIG 0x59
|
#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59
|
||||||
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
|
#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A
|
||||||
#define BT_CMD_MODULE_CFG_REQ 0x5B
|
#define BT_CMD_MODULE_CFG_REQ 0xFC5B
|
||||||
#define BT_CMD_LOAD_CONFIG_DATA 0x61
|
#define BT_CMD_LOAD_CONFIG_DATA 0xFC61
|
||||||
|
|
||||||
/* Sub-commands: Module Bringup/Shutdown Request/Response */
|
/* Sub-commands: Module Bringup/Shutdown Request/Response */
|
||||||
#define MODULE_BRINGUP_REQ 0xF1
|
#define MODULE_BRINGUP_REQ 0xF1
|
||||||
|
@ -104,6 +100,11 @@ struct btmrvl_private {
|
||||||
|
|
||||||
#define MODULE_SHUTDOWN_REQ 0xF2
|
#define MODULE_SHUTDOWN_REQ 0xF2
|
||||||
|
|
||||||
|
/* Vendor specific Bluetooth events */
|
||||||
|
#define BT_EVENT_AUTO_SLEEP_MODE 0x23
|
||||||
|
#define BT_EVENT_HOST_SLEEP_CONFIG 0x59
|
||||||
|
#define BT_EVENT_HOST_SLEEP_ENABLE 0x5A
|
||||||
|
#define BT_EVENT_MODULE_CFG_REQ 0x5B
|
||||||
#define BT_EVENT_POWER_STATE 0x20
|
#define BT_EVENT_POWER_STATE 0x20
|
||||||
|
|
||||||
/* Bluetooth Power States */
|
/* Bluetooth Power States */
|
||||||
|
@ -111,8 +112,6 @@ struct btmrvl_private {
|
||||||
#define BT_PS_DISABLE 0x03
|
#define BT_PS_DISABLE 0x03
|
||||||
#define BT_PS_SLEEP 0x01
|
#define BT_PS_SLEEP 0x01
|
||||||
|
|
||||||
#define OGF 0x3F
|
|
||||||
|
|
||||||
/* Host Sleep states */
|
/* Host Sleep states */
|
||||||
#define HS_ACTIVATED 0x01
|
#define HS_ACTIVATED 0x01
|
||||||
#define HS_DEACTIVATED 0x00
|
#define HS_DEACTIVATED 0x00
|
||||||
|
@ -121,7 +120,7 @@ struct btmrvl_private {
|
||||||
#define PS_SLEEP 0x01
|
#define PS_SLEEP 0x01
|
||||||
#define PS_AWAKE 0x00
|
#define PS_AWAKE 0x00
|
||||||
|
|
||||||
#define BT_CMD_DATA_SIZE 32
|
#define BT_CAL_HDR_LEN 4
|
||||||
#define BT_CAL_DATA_SIZE 28
|
#define BT_CAL_DATA_SIZE 28
|
||||||
|
|
||||||
struct btmrvl_event {
|
struct btmrvl_event {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
|
|
||||||
|
@ -50,12 +50,10 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||||
|
|
||||||
if (hdr->evt == HCI_EV_CMD_COMPLETE) {
|
if (hdr->evt == HCI_EV_CMD_COMPLETE) {
|
||||||
struct hci_ev_cmd_complete *ec;
|
struct hci_ev_cmd_complete *ec;
|
||||||
u16 opcode, ocf, ogf;
|
u16 opcode;
|
||||||
|
|
||||||
ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
|
ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
|
||||||
opcode = __le16_to_cpu(ec->opcode);
|
opcode = __le16_to_cpu(ec->opcode);
|
||||||
ocf = hci_opcode_ocf(opcode);
|
|
||||||
ogf = hci_opcode_ogf(opcode);
|
|
||||||
|
|
||||||
if (priv->btmrvl_dev.sendcmdflag) {
|
if (priv->btmrvl_dev.sendcmdflag) {
|
||||||
priv->btmrvl_dev.sendcmdflag = false;
|
priv->btmrvl_dev.sendcmdflag = false;
|
||||||
|
@ -63,9 +61,8 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||||
wake_up_interruptible(&priv->adapter->cmd_wait_q);
|
wake_up_interruptible(&priv->adapter->cmd_wait_q);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ogf == OGF) {
|
if (hci_opcode_ogf(opcode) == 0x3F) {
|
||||||
BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x",
|
BT_DBG("vendor event skipped: opcode=%#4.4x", opcode);
|
||||||
ogf, ocf);
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +86,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event->data[0]) {
|
switch (event->data[0]) {
|
||||||
case BT_CMD_AUTO_SLEEP_MODE:
|
case BT_EVENT_AUTO_SLEEP_MODE:
|
||||||
if (!event->data[2]) {
|
if (!event->data[2]) {
|
||||||
if (event->data[1] == BT_PS_ENABLE)
|
if (event->data[1] == BT_PS_ENABLE)
|
||||||
adapter->psmode = 1;
|
adapter->psmode = 1;
|
||||||
|
@ -102,7 +99,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BT_CMD_HOST_SLEEP_CONFIG:
|
case BT_EVENT_HOST_SLEEP_CONFIG:
|
||||||
if (!event->data[3])
|
if (!event->data[3])
|
||||||
BT_DBG("gpio=%x, gap=%x", event->data[1],
|
BT_DBG("gpio=%x, gap=%x", event->data[1],
|
||||||
event->data[2]);
|
event->data[2]);
|
||||||
|
@ -110,7 +107,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||||
BT_DBG("HSCFG command failed");
|
BT_DBG("HSCFG command failed");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BT_CMD_HOST_SLEEP_ENABLE:
|
case BT_EVENT_HOST_SLEEP_ENABLE:
|
||||||
if (!event->data[1]) {
|
if (!event->data[1]) {
|
||||||
adapter->hs_state = HS_ACTIVATED;
|
adapter->hs_state = HS_ACTIVATED;
|
||||||
if (adapter->psmode)
|
if (adapter->psmode)
|
||||||
|
@ -121,7 +118,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BT_CMD_MODULE_CFG_REQ:
|
case BT_EVENT_MODULE_CFG_REQ:
|
||||||
if (priv->btmrvl_dev.sendcmdflag &&
|
if (priv->btmrvl_dev.sendcmdflag &&
|
||||||
event->data[1] == MODULE_BRINGUP_REQ) {
|
event->data[1] == MODULE_BRINGUP_REQ) {
|
||||||
BT_DBG("EVENT:%s",
|
BT_DBG("EVENT:%s",
|
||||||
|
@ -166,7 +163,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(btmrvl_process_event);
|
EXPORT_SYMBOL_GPL(btmrvl_process_event);
|
||||||
|
|
||||||
static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
|
static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
|
||||||
const void *param, u8 len)
|
const void *param, u8 len)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -179,7 +176,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
|
hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
|
||||||
hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
|
hdr->opcode = cpu_to_le16(opcode);
|
||||||
hdr->plen = len;
|
hdr->plen = len;
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
|
@ -417,127 +414,62 @@ static int btmrvl_open(struct hci_dev *hdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int btmrvl_download_cal_data(struct btmrvl_private *priv,
|
||||||
* This function parses provided calibration data input. It should contain
|
u8 *data, int len)
|
||||||
* hex bytes separated by space or new line character. Here is an example.
|
|
||||||
* 00 1C 01 37 FF FF FF FF 02 04 7F 01
|
|
||||||
* CE BA 00 00 00 2D C6 C0 00 00 00 00
|
|
||||||
* 00 F0 00 00
|
|
||||||
*/
|
|
||||||
static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
|
|
||||||
{
|
{
|
||||||
const u8 *s = src;
|
|
||||||
u8 *d = dst;
|
|
||||||
int ret;
|
int ret;
|
||||||
u8 tmp[3];
|
|
||||||
|
|
||||||
tmp[2] = '\0';
|
|
||||||
while ((s - src) <= len - 2) {
|
|
||||||
if (isspace(*s)) {
|
|
||||||
s++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isxdigit(*s)) {
|
|
||||||
if ((d - dst) >= dst_size) {
|
|
||||||
BT_ERR("calibration data file too big!!!");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(tmp, s, 2);
|
|
||||||
|
|
||||||
ret = kstrtou8(tmp, 16, d++);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
s += 2;
|
|
||||||
} else {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (d == dst)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int btmrvl_load_cal_data(struct btmrvl_private *priv,
|
|
||||||
u8 *config_data)
|
|
||||||
{
|
|
||||||
int i, ret;
|
|
||||||
u8 data[BT_CMD_DATA_SIZE];
|
|
||||||
|
|
||||||
data[0] = 0x00;
|
data[0] = 0x00;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
data[2] = 0x00;
|
data[2] = 0x00;
|
||||||
data[3] = BT_CMD_DATA_SIZE - 4;
|
data[3] = len;
|
||||||
|
|
||||||
/* Swap cal-data bytes. Each four bytes are swapped. Considering 4
|
|
||||||
* byte SDIO header offset, mapping of input and output bytes will be
|
|
||||||
* {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4},
|
|
||||||
* {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */
|
|
||||||
for (i = 4; i < BT_CMD_DATA_SIZE; i++)
|
|
||||||
data[i] = config_data[(i / 4) * 8 - 1 - i];
|
|
||||||
|
|
||||||
print_hex_dump_bytes("Calibration data: ",
|
print_hex_dump_bytes("Calibration data: ",
|
||||||
DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE);
|
DUMP_PREFIX_OFFSET, data, BT_CAL_HDR_LEN + len);
|
||||||
|
|
||||||
ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
|
ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
|
||||||
BT_CMD_DATA_SIZE);
|
BT_CAL_HDR_LEN + len);
|
||||||
if (ret)
|
if (ret)
|
||||||
BT_ERR("Failed to download caibration data\n");
|
BT_ERR("Failed to download caibration data\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int btmrvl_cal_data_dt(struct btmrvl_private *priv)
|
||||||
btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size)
|
|
||||||
{
|
{
|
||||||
u8 cal_data[BT_CAL_DATA_SIZE];
|
struct device_node *dt_node;
|
||||||
|
u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
|
||||||
|
const char name[] = "btmrvl_caldata";
|
||||||
|
const char property[] = "btmrvl,caldata";
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data));
|
dt_node = of_find_node_by_name(NULL, name);
|
||||||
|
if (!dt_node)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
ret = of_property_read_u8_array(dt_node, property,
|
||||||
|
cal_data + BT_CAL_HDR_LEN,
|
||||||
|
BT_CAL_DATA_SIZE);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = btmrvl_load_cal_data(priv, cal_data);
|
BT_DBG("Use cal data from device tree");
|
||||||
|
ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
BT_ERR("Fail to load calibrate data");
|
BT_ERR("Fail to download calibrate data");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btmrvl_cal_data_config(struct btmrvl_private *priv)
|
|
||||||
{
|
|
||||||
const struct firmware *cfg;
|
|
||||||
int ret;
|
|
||||||
const char *cal_data = priv->btmrvl_dev.cal_data;
|
|
||||||
|
|
||||||
if (!cal_data)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev);
|
|
||||||
if (ret < 0) {
|
|
||||||
BT_DBG("Failed to get %s file, skipping cal data download",
|
|
||||||
cal_data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size);
|
|
||||||
release_firmware(cfg);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int btmrvl_setup(struct hci_dev *hdev)
|
static int btmrvl_setup(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
||||||
|
|
||||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||||
|
|
||||||
if (btmrvl_cal_data_config(priv))
|
btmrvl_cal_data_dt(priv);
|
||||||
BT_ERR("Set cal data failed");
|
|
||||||
|
|
||||||
priv->btmrvl_dev.psmode = 1;
|
priv->btmrvl_dev.psmode = 1;
|
||||||
btmrvl_enable_ps(priv);
|
btmrvl_enable_ps(priv);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* this warranty disclaimer.
|
* this warranty disclaimer.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
#include <linux/firmware.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <linux/mmc/sdio_ids.h>
|
#include <linux/mmc/sdio_ids.h>
|
||||||
|
@ -101,7 +102,6 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
|
||||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||||
.helper = "mrvl/sd8688_helper.bin",
|
.helper = "mrvl/sd8688_helper.bin",
|
||||||
.firmware = "mrvl/sd8688.bin",
|
.firmware = "mrvl/sd8688.bin",
|
||||||
.cal_data = NULL,
|
|
||||||
.reg = &btmrvl_reg_8688,
|
.reg = &btmrvl_reg_8688,
|
||||||
.sd_blksz_fw_dl = 64,
|
.sd_blksz_fw_dl = 64,
|
||||||
};
|
};
|
||||||
|
@ -109,7 +109,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
||||||
.helper = NULL,
|
.helper = NULL,
|
||||||
.firmware = "mrvl/sd8787_uapsta.bin",
|
.firmware = "mrvl/sd8787_uapsta.bin",
|
||||||
.cal_data = NULL,
|
|
||||||
.reg = &btmrvl_reg_87xx,
|
.reg = &btmrvl_reg_87xx,
|
||||||
.sd_blksz_fw_dl = 256,
|
.sd_blksz_fw_dl = 256,
|
||||||
};
|
};
|
||||||
|
@ -117,7 +116,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
||||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
|
||||||
.helper = NULL,
|
.helper = NULL,
|
||||||
.firmware = "mrvl/sd8797_uapsta.bin",
|
.firmware = "mrvl/sd8797_uapsta.bin",
|
||||||
.cal_data = "mrvl/sd8797_caldata.conf",
|
|
||||||
.reg = &btmrvl_reg_87xx,
|
.reg = &btmrvl_reg_87xx,
|
||||||
.sd_blksz_fw_dl = 256,
|
.sd_blksz_fw_dl = 256,
|
||||||
};
|
};
|
||||||
|
@ -125,7 +123,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
|
||||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
|
||||||
.helper = NULL,
|
.helper = NULL,
|
||||||
.firmware = "mrvl/sd8897_uapsta.bin",
|
.firmware = "mrvl/sd8897_uapsta.bin",
|
||||||
.cal_data = NULL,
|
|
||||||
.reg = &btmrvl_reg_88xx,
|
.reg = &btmrvl_reg_88xx,
|
||||||
.sd_blksz_fw_dl = 256,
|
.sd_blksz_fw_dl = 256,
|
||||||
};
|
};
|
||||||
|
@ -1007,7 +1004,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||||
struct btmrvl_sdio_device *data = (void *) id->driver_data;
|
struct btmrvl_sdio_device *data = (void *) id->driver_data;
|
||||||
card->helper = data->helper;
|
card->helper = data->helper;
|
||||||
card->firmware = data->firmware;
|
card->firmware = data->firmware;
|
||||||
card->cal_data = data->cal_data;
|
|
||||||
card->reg = data->reg;
|
card->reg = data->reg;
|
||||||
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
|
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
|
||||||
}
|
}
|
||||||
|
@ -1036,8 +1032,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||||
}
|
}
|
||||||
|
|
||||||
card->priv = priv;
|
card->priv = priv;
|
||||||
priv->btmrvl_dev.dev = &card->func->dev;
|
|
||||||
priv->btmrvl_dev.cal_data = card->cal_data;
|
|
||||||
|
|
||||||
/* Initialize the interface specific function pointers */
|
/* Initialize the interface specific function pointers */
|
||||||
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
|
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
|
||||||
|
@ -1220,5 +1214,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8688.bin");
|
MODULE_FIRMWARE("mrvl/sd8688.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
|
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8797_caldata.conf");
|
|
||||||
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
|
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
|
||||||
|
|
|
@ -85,7 +85,6 @@ struct btmrvl_sdio_card {
|
||||||
u32 ioport;
|
u32 ioport;
|
||||||
const char *helper;
|
const char *helper;
|
||||||
const char *firmware;
|
const char *firmware;
|
||||||
const char *cal_data;
|
|
||||||
const struct btmrvl_sdio_card_reg *reg;
|
const struct btmrvl_sdio_card_reg *reg;
|
||||||
u16 sd_blksz_fw_dl;
|
u16 sd_blksz_fw_dl;
|
||||||
u8 rx_unit;
|
u8 rx_unit;
|
||||||
|
@ -95,7 +94,6 @@ struct btmrvl_sdio_card {
|
||||||
struct btmrvl_sdio_device {
|
struct btmrvl_sdio_device {
|
||||||
const char *helper;
|
const char *helper;
|
||||||
const char *firmware;
|
const char *firmware;
|
||||||
const char *cal_data;
|
|
||||||
const struct btmrvl_sdio_card_reg *reg;
|
const struct btmrvl_sdio_card_reg *reg;
|
||||||
u16 sd_blksz_fw_dl;
|
u16 sd_blksz_fw_dl;
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,6 +73,7 @@ struct btsdio_data {
|
||||||
#define REG_CL_INTRD 0x13 /* Interrupt Clear */
|
#define REG_CL_INTRD 0x13 /* Interrupt Clear */
|
||||||
#define REG_EN_INTRD 0x14 /* Interrupt Enable */
|
#define REG_EN_INTRD 0x14 /* Interrupt Enable */
|
||||||
#define REG_MD_STAT 0x20 /* Bluetooth Mode Status */
|
#define REG_MD_STAT 0x20 /* Bluetooth Mode Status */
|
||||||
|
#define REG_MD_SET 0x20 /* Bluetooth Mode Set */
|
||||||
|
|
||||||
static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
|
static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
@ -212,7 +213,7 @@ static int btsdio_open(struct hci_dev *hdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->func->class == SDIO_CLASS_BT_B)
|
if (data->func->class == SDIO_CLASS_BT_B)
|
||||||
sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL);
|
sdio_writeb(data->func, 0x00, REG_MD_SET, NULL);
|
||||||
|
|
||||||
sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL);
|
sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL);
|
||||||
|
|
||||||
|
@ -333,6 +334,9 @@ static int btsdio_probe(struct sdio_func *func,
|
||||||
hdev->flush = btsdio_flush;
|
hdev->flush = btsdio_flush;
|
||||||
hdev->send = btsdio_send_frame;
|
hdev->send = btsdio_send_frame;
|
||||||
|
|
||||||
|
if (func->vendor == 0x0104 && func->device == 0x00c5)
|
||||||
|
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||||
|
|
||||||
err = hci_register_dev(hdev);
|
err = hci_register_dev(hdev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
|
|
@ -150,6 +150,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||||
|
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
||||||
|
@ -164,6 +165,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
||||||
|
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||||
|
|
||||||
/* Atheros AR5BBU12 with sflash firmware */
|
/* Atheros AR5BBU12 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||||
|
@ -224,6 +226,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||||
|
|
||||||
/* Intel Bluetooth device */
|
/* Intel Bluetooth device */
|
||||||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
|
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
|
||||||
|
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
|
||||||
|
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
@ -962,6 +965,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int btusb_setup_csr(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct hci_rp_read_local_version *rp;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
|
||||||
|
HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb));
|
||||||
|
return -PTR_ERR(skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
rp = (struct hci_rp_read_local_version *) skb->data;
|
||||||
|
|
||||||
|
if (!rp->status) {
|
||||||
|
if (le16_to_cpu(rp->manufacturer) != 10) {
|
||||||
|
/* Clear the reset quirk since this is not an actual
|
||||||
|
* early Bluetooth 1.1 device from CSR.
|
||||||
|
*/
|
||||||
|
clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||||
|
|
||||||
|
/* These fake CSR controllers have all a broken
|
||||||
|
* stored link key handling and so just disable it.
|
||||||
|
*/
|
||||||
|
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY,
|
||||||
|
&hdev->quirks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = -bt_to_errno(rp->status);
|
||||||
|
|
||||||
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct intel_version {
|
struct intel_version {
|
||||||
u8 status;
|
u8 status;
|
||||||
u8 hw_platform;
|
u8 hw_platform;
|
||||||
|
@ -1436,8 +1478,10 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
if (id->driver_info & BTUSB_BCM92035)
|
if (id->driver_info & BTUSB_BCM92035)
|
||||||
hdev->setup = btusb_setup_bcm92035;
|
hdev->setup = btusb_setup_bcm92035;
|
||||||
|
|
||||||
if (id->driver_info & BTUSB_INTEL)
|
if (id->driver_info & BTUSB_INTEL) {
|
||||||
|
usb_enable_autosuspend(data->udev);
|
||||||
hdev->setup = btusb_setup_intel;
|
hdev->setup = btusb_setup_intel;
|
||||||
|
}
|
||||||
|
|
||||||
/* Interface numbers are hardcoded in the specification */
|
/* Interface numbers are hardcoded in the specification */
|
||||||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||||
|
@ -1460,10 +1504,15 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
|
|
||||||
if (id->driver_info & BTUSB_CSR) {
|
if (id->driver_info & BTUSB_CSR) {
|
||||||
struct usb_device *udev = data->udev;
|
struct usb_device *udev = data->udev;
|
||||||
|
u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
|
||||||
|
|
||||||
/* Old firmware would otherwise execute USB reset */
|
/* Old firmware would otherwise execute USB reset */
|
||||||
if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
|
if (bcdDevice < 0x117)
|
||||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||||
|
|
||||||
|
/* Fake CSR devices with broken commands */
|
||||||
|
if (bcdDevice <= 0x100)
|
||||||
|
hdev->setup = btusb_setup_csr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id->driver_info & BTUSB_SNIFFER) {
|
if (id->driver_info & BTUSB_SNIFFER) {
|
||||||
|
|
|
@ -141,22 +141,28 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ssize_t vhci_get_user(struct vhci_data *data,
|
static inline ssize_t vhci_get_user(struct vhci_data *data,
|
||||||
const char __user *buf, size_t count)
|
const struct iovec *iov,
|
||||||
|
unsigned long count)
|
||||||
{
|
{
|
||||||
|
size_t len = iov_length(iov, count);
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
__u8 pkt_type, dev_type;
|
__u8 pkt_type, dev_type;
|
||||||
|
unsigned long i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (count < 2 || count > HCI_MAX_FRAME_SIZE)
|
if (len < 2 || len > HCI_MAX_FRAME_SIZE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
skb = bt_skb_alloc(count, GFP_KERNEL);
|
skb = bt_skb_alloc(len, GFP_KERNEL);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (copy_from_user(skb_put(skb, count), buf, count)) {
|
for (i = 0; i < count; i++) {
|
||||||
kfree_skb(skb);
|
if (copy_from_user(skb_put(skb, iov[i].iov_len),
|
||||||
return -EFAULT;
|
iov[i].iov_base, iov[i].iov_len)) {
|
||||||
|
kfree_skb(skb);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt_type = *((__u8 *) skb->data);
|
pkt_type = *((__u8 *) skb->data);
|
||||||
|
@ -205,7 +211,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ret < 0) ? ret : count;
|
return (ret < 0) ? ret : len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ssize_t vhci_put_user(struct vhci_data *data,
|
static inline ssize_t vhci_put_user(struct vhci_data *data,
|
||||||
|
@ -272,12 +278,13 @@ static ssize_t vhci_read(struct file *file,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t vhci_write(struct file *file,
|
static ssize_t vhci_write(struct kiocb *iocb, const struct iovec *iov,
|
||||||
const char __user *buf, size_t count, loff_t *pos)
|
unsigned long count, loff_t pos)
|
||||||
{
|
{
|
||||||
|
struct file *file = iocb->ki_filp;
|
||||||
struct vhci_data *data = file->private_data;
|
struct vhci_data *data = file->private_data;
|
||||||
|
|
||||||
return vhci_get_user(data, buf, count);
|
return vhci_get_user(data, iov, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int vhci_poll(struct file *file, poll_table *wait)
|
static unsigned int vhci_poll(struct file *file, poll_table *wait)
|
||||||
|
@ -342,7 +349,7 @@ static int vhci_release(struct inode *inode, struct file *file)
|
||||||
static const struct file_operations vhci_fops = {
|
static const struct file_operations vhci_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.read = vhci_read,
|
.read = vhci_read,
|
||||||
.write = vhci_write,
|
.aio_write = vhci_write,
|
||||||
.poll = vhci_poll,
|
.poll = vhci_poll,
|
||||||
.open = vhci_open,
|
.open = vhci_open,
|
||||||
.release = vhci_release,
|
.release = vhci_release,
|
||||||
|
|
|
@ -2357,7 +2357,7 @@ static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
|
||||||
|
|
||||||
inet_get_local_port_range(&init_net, &low, &high);
|
inet_get_local_port_range(&init_net, &low, &high);
|
||||||
remaining = (high - low) + 1;
|
remaining = (high - low) + 1;
|
||||||
rover = net_random() % remaining + low;
|
rover = prandom_u32() % remaining + low;
|
||||||
retry:
|
retry:
|
||||||
if (last_used_port != rover &&
|
if (last_used_port != rover &&
|
||||||
!idr_find(ps, (unsigned short) rover)) {
|
!idr_find(ps, (unsigned short) rover)) {
|
||||||
|
|
|
@ -1371,7 +1371,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||||
eth = eth_hdr(skb);
|
eth = eth_hdr(skb);
|
||||||
|
|
||||||
if (*eth->h_dest & 1) {
|
if (*eth->h_dest & 1) {
|
||||||
if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
|
if (ether_addr_equal(eth->h_dest, dev->broadcast))
|
||||||
skb->pkt_type = PACKET_BROADCAST;
|
skb->pkt_type = PACKET_BROADCAST;
|
||||||
else
|
else
|
||||||
skb->pkt_type = PACKET_MULTICAST;
|
skb->pkt_type = PACKET_MULTICAST;
|
||||||
|
@ -1382,7 +1382,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
|
else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
|
||||||
if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
|
if (!ether_addr_equal(eth->h_dest, dev->dev_addr))
|
||||||
skb->pkt_type = PACKET_OTHERHOST;
|
skb->pkt_type = PACKET_OTHERHOST;
|
||||||
}
|
}
|
||||||
if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
|
if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
|
||||||
|
|
|
@ -135,7 +135,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (msg->msg_name) {
|
if (msg->msg_name) {
|
||||||
struct sockaddr_mISDN *maddr = msg->msg_name;
|
DECLARE_SOCKADDR(struct sockaddr_mISDN *, maddr, msg->msg_name);
|
||||||
|
|
||||||
maddr->family = AF_ISDN;
|
maddr->family = AF_ISDN;
|
||||||
maddr->dev = _pms(sk)->dev->id;
|
maddr->dev = _pms(sk)->dev->id;
|
||||||
|
@ -179,7 +179,6 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
struct sockaddr_mISDN *maddr;
|
|
||||||
|
|
||||||
if (*debug & DEBUG_SOCKET)
|
if (*debug & DEBUG_SOCKET)
|
||||||
printk(KERN_DEBUG "%s: len %d flags %x ch %d proto %x\n",
|
printk(KERN_DEBUG "%s: len %d flags %x ch %d proto %x\n",
|
||||||
|
@ -214,7 +213,7 @@ mISDN_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
|
|
||||||
if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
|
if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
|
||||||
/* if we have a address, we use it */
|
/* if we have a address, we use it */
|
||||||
maddr = (struct sockaddr_mISDN *)msg->msg_name;
|
DECLARE_SOCKADDR(struct sockaddr_mISDN *, maddr, msg->msg_name);
|
||||||
mISDN_HEAD_ID(skb) = maddr->channel;
|
mISDN_HEAD_ID(skb) = maddr->channel;
|
||||||
} else { /* use default for L2 messages */
|
} else { /* use default for L2 messages */
|
||||||
if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
|
if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
|
||||||
|
|
|
@ -57,7 +57,7 @@ int indicate_status(int card, int event, ulong Channel, char *Data)
|
||||||
memcpy(&cmd.parm.setup, Data, sizeof(cmd.parm.setup));
|
memcpy(&cmd.parm.setup, Data, sizeof(cmd.parm.setup));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
strcpy(cmd.parm.num, Data);
|
strlcpy(cmd.parm.num, Data, sizeof(cmd.parm.num));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
|
||||||
eth = eth_hdr(skb);
|
eth = eth_hdr(skb);
|
||||||
|
|
||||||
if (*eth->h_dest & 1) {
|
if (*eth->h_dest & 1) {
|
||||||
if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
|
if(ether_addr_equal(eth->h_dest,dev->broadcast))
|
||||||
skb->pkt_type=PACKET_BROADCAST;
|
skb->pkt_type=PACKET_BROADCAST;
|
||||||
else
|
else
|
||||||
skb->pkt_type=PACKET_MULTICAST;
|
skb->pkt_type=PACKET_MULTICAST;
|
||||||
|
@ -674,11 +674,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
||||||
if (priv->rx_mode != RX_MODE_PROMISC) {
|
if (priv->rx_mode != RX_MODE_PROMISC) {
|
||||||
if (priv->ule_skb->data[0] & 0x01) {
|
if (priv->ule_skb->data[0] & 0x01) {
|
||||||
/* multicast or broadcast */
|
/* multicast or broadcast */
|
||||||
if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
|
if (!ether_addr_equal(priv->ule_skb->data, bc_addr)) {
|
||||||
/* multicast */
|
/* multicast */
|
||||||
if (priv->rx_mode == RX_MODE_MULTI) {
|
if (priv->rx_mode == RX_MODE_MULTI) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
|
for(i = 0; i < priv->multi_num &&
|
||||||
|
!ether_addr_equal(priv->ule_skb->data,
|
||||||
|
priv->multi_macs[i]); i++)
|
||||||
;
|
;
|
||||||
if (i == priv->multi_num)
|
if (i == priv->multi_num)
|
||||||
drop = 1;
|
drop = 1;
|
||||||
|
@ -688,7 +690,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
||||||
}
|
}
|
||||||
/* else: broadcast */
|
/* else: broadcast */
|
||||||
}
|
}
|
||||||
else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
|
else if (!ether_addr_equal(priv->ule_skb->data, dev->dev_addr))
|
||||||
drop = 1;
|
drop = 1;
|
||||||
/* else: destination address matches the MAC address of our receiver device */
|
/* else: destination address matches the MAC address of our receiver device */
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,6 +236,7 @@ config VETH
|
||||||
config VIRTIO_NET
|
config VIRTIO_NET
|
||||||
tristate "Virtio network driver"
|
tristate "Virtio network driver"
|
||||||
depends on VIRTIO
|
depends on VIRTIO
|
||||||
|
select AVERAGE
|
||||||
---help---
|
---help---
|
||||||
This is the virtual network driver for virtio. It can be used with
|
This is the virtual network driver for virtio. It can be used with
|
||||||
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
|
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
|
||||||
|
|
|
@ -32,39 +32,12 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
|
#include <net/Space.h>
|
||||||
|
|
||||||
/* A unified ethernet device probe. This is the easiest way to have every
|
/* A unified ethernet device probe. This is the easiest way to have every
|
||||||
ethernet adaptor have the name "eth[0123...]".
|
ethernet adaptor have the name "eth[0123...]".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern struct net_device *hp100_probe(int unit);
|
|
||||||
extern struct net_device *ultra_probe(int unit);
|
|
||||||
extern struct net_device *wd_probe(int unit);
|
|
||||||
extern struct net_device *ne_probe(int unit);
|
|
||||||
extern struct net_device *fmv18x_probe(int unit);
|
|
||||||
extern struct net_device *i82596_probe(int unit);
|
|
||||||
extern struct net_device *ni65_probe(int unit);
|
|
||||||
extern struct net_device *sonic_probe(int unit);
|
|
||||||
extern struct net_device *smc_init(int unit);
|
|
||||||
extern struct net_device *atarilance_probe(int unit);
|
|
||||||
extern struct net_device *sun3lance_probe(int unit);
|
|
||||||
extern struct net_device *sun3_82586_probe(int unit);
|
|
||||||
extern struct net_device *apne_probe(int unit);
|
|
||||||
extern struct net_device *cs89x0_probe(int unit);
|
|
||||||
extern struct net_device *mvme147lance_probe(int unit);
|
|
||||||
extern struct net_device *tc515_probe(int unit);
|
|
||||||
extern struct net_device *lance_probe(int unit);
|
|
||||||
extern struct net_device *mac8390_probe(int unit);
|
|
||||||
extern struct net_device *mac89x0_probe(int unit);
|
|
||||||
extern struct net_device *cops_probe(int unit);
|
|
||||||
extern struct net_device *ltpc_probe(void);
|
|
||||||
|
|
||||||
/* Fibre Channel adapters */
|
|
||||||
extern int iph5526_probe(struct net_device *dev);
|
|
||||||
|
|
||||||
/* SBNI adapters */
|
|
||||||
extern int sbni_probe(int unit);
|
|
||||||
|
|
||||||
struct devprobe2 {
|
struct devprobe2 {
|
||||||
struct net_device *(*probe)(int unit);
|
struct net_device *(*probe)(int unit);
|
||||||
int status; /* non-zero if autoprobe has failed */
|
int status; /* non-zero if autoprobe has failed */
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
* **********************
|
* **********************
|
||||||
*/
|
*/
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
obj-$(CONFIG_BONDING) += bonding.o
|
obj-$(CONFIG_BONDING) += bonding.o
|
||||||
|
|
||||||
bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o bond_netlink.o bond_options.o
|
bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_sysfs_slave.o bond_debugfs.o bond_netlink.o bond_options.o
|
||||||
|
|
||||||
proc-$(CONFIG_PROC_FS) += bond_procfs.o
|
proc-$(CONFIG_PROC_FS) += bond_procfs.o
|
||||||
bonding-objs += $(proc-y)
|
bonding-objs += $(proc-y)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -265,7 +265,7 @@ struct ad_slave_info {
|
||||||
|
|
||||||
// ================= AD Exported functions to the main bonding code ==================
|
// ================= AD Exported functions to the main bonding code ==================
|
||||||
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
|
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
|
||||||
int bond_3ad_bind_slave(struct slave *slave);
|
void bond_3ad_bind_slave(struct slave *slave);
|
||||||
void bond_3ad_unbind_slave(struct slave *slave);
|
void bond_3ad_unbind_slave(struct slave *slave);
|
||||||
void bond_3ad_state_machine_handler(struct work_struct *);
|
void bond_3ad_state_machine_handler(struct work_struct *);
|
||||||
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
|
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
*
|
||||||
* The full GNU General Public License is included in this distribution in the
|
* The full GNU General Public License is included in this distribution in the
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
|
@ -470,7 +469,7 @@ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
|
||||||
|
|
||||||
/* slave being removed should not be active at this point
|
/* slave being removed should not be active at this point
|
||||||
*
|
*
|
||||||
* Caller must hold bond lock for read
|
* Caller must hold rtnl.
|
||||||
*/
|
*/
|
||||||
static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
|
static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
|
||||||
{
|
{
|
||||||
|
@ -816,7 +815,7 @@ static void rlb_rebalance(struct bonding *bond)
|
||||||
for (; hash_index != RLB_NULL_INDEX;
|
for (; hash_index != RLB_NULL_INDEX;
|
||||||
hash_index = client_info->used_next) {
|
hash_index = client_info->used_next) {
|
||||||
client_info = &(bond_info->rx_hashtbl[hash_index]);
|
client_info = &(bond_info->rx_hashtbl[hash_index]);
|
||||||
assigned_slave = rlb_next_rx_slave(bond);
|
assigned_slave = __rlb_next_rx_slave(bond);
|
||||||
if (assigned_slave && (client_info->slave != assigned_slave)) {
|
if (assigned_slave && (client_info->slave != assigned_slave)) {
|
||||||
client_info->slave = assigned_slave;
|
client_info->slave = assigned_slave;
|
||||||
client_info->ntt = 1;
|
client_info->ntt = 1;
|
||||||
|
@ -1372,7 +1371,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
|
||||||
int do_tx_balance = 1;
|
int do_tx_balance = 1;
|
||||||
u32 hash_index = 0;
|
u32 hash_index = 0;
|
||||||
const u8 *hash_start = NULL;
|
const u8 *hash_start = NULL;
|
||||||
int res = 1;
|
|
||||||
struct ipv6hdr *ip6hdr;
|
struct ipv6hdr *ip6hdr;
|
||||||
|
|
||||||
skb_reset_mac_header(skb);
|
skb_reset_mac_header(skb);
|
||||||
|
@ -1470,7 +1468,8 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
|
||||||
ETH_ALEN);
|
ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = bond_dev_queue_xmit(bond, skb, tx_slave->dev);
|
bond_dev_queue_xmit(bond, skb, tx_slave->dev);
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
if (tx_slave) {
|
if (tx_slave) {
|
||||||
_lock_tx_hashtbl(bond);
|
_lock_tx_hashtbl(bond);
|
||||||
|
@ -1479,11 +1478,9 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res) {
|
/* no suitable interface, frame not sent */
|
||||||
/* no suitable interface, frame not sent */
|
kfree_skb(skb);
|
||||||
kfree_skb(skb);
|
out:
|
||||||
}
|
|
||||||
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1495,14 +1492,14 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
struct list_head *iter;
|
struct list_head *iter;
|
||||||
struct slave *slave;
|
struct slave *slave;
|
||||||
|
|
||||||
read_lock(&bond->lock);
|
|
||||||
|
|
||||||
if (!bond_has_slaves(bond)) {
|
if (!bond_has_slaves(bond)) {
|
||||||
bond_info->tx_rebalance_counter = 0;
|
bond_info->tx_rebalance_counter = 0;
|
||||||
bond_info->lp_counter = 0;
|
bond_info->lp_counter = 0;
|
||||||
goto re_arm;
|
goto re_arm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
bond_info->tx_rebalance_counter++;
|
bond_info->tx_rebalance_counter++;
|
||||||
bond_info->lp_counter++;
|
bond_info->lp_counter++;
|
||||||
|
|
||||||
|
@ -1515,7 +1512,7 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
*/
|
*/
|
||||||
read_lock(&bond->curr_slave_lock);
|
read_lock(&bond->curr_slave_lock);
|
||||||
|
|
||||||
bond_for_each_slave(bond, slave, iter)
|
bond_for_each_slave_rcu(bond, slave, iter)
|
||||||
alb_send_learning_packets(slave, slave->dev->dev_addr);
|
alb_send_learning_packets(slave, slave->dev->dev_addr);
|
||||||
|
|
||||||
read_unlock(&bond->curr_slave_lock);
|
read_unlock(&bond->curr_slave_lock);
|
||||||
|
@ -1528,7 +1525,7 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
|
|
||||||
read_lock(&bond->curr_slave_lock);
|
read_lock(&bond->curr_slave_lock);
|
||||||
|
|
||||||
bond_for_each_slave(bond, slave, iter) {
|
bond_for_each_slave_rcu(bond, slave, iter) {
|
||||||
tlb_clear_slave(bond, slave, 1);
|
tlb_clear_slave(bond, slave, 1);
|
||||||
if (slave == bond->curr_active_slave) {
|
if (slave == bond->curr_active_slave) {
|
||||||
SLAVE_TLB_INFO(slave).load =
|
SLAVE_TLB_INFO(slave).load =
|
||||||
|
@ -1552,11 +1549,9 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
* dev_set_promiscuity requires rtnl and
|
* dev_set_promiscuity requires rtnl and
|
||||||
* nothing else. Avoid race with bond_close.
|
* nothing else. Avoid race with bond_close.
|
||||||
*/
|
*/
|
||||||
read_unlock(&bond->lock);
|
rcu_read_unlock();
|
||||||
if (!rtnl_trylock()) {
|
if (!rtnl_trylock())
|
||||||
read_lock(&bond->lock);
|
|
||||||
goto re_arm;
|
goto re_arm;
|
||||||
}
|
|
||||||
|
|
||||||
bond_info->rlb_promisc_timeout_counter = 0;
|
bond_info->rlb_promisc_timeout_counter = 0;
|
||||||
|
|
||||||
|
@ -1568,7 +1563,7 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
bond_info->primary_is_promisc = 0;
|
bond_info->primary_is_promisc = 0;
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
read_lock(&bond->lock);
|
rcu_read_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bond_info->rlb_rebalance) {
|
if (bond_info->rlb_rebalance) {
|
||||||
|
@ -1590,11 +1585,9 @@ void bond_alb_monitor(struct work_struct *work)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
re_arm:
|
re_arm:
|
||||||
queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
|
queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
|
||||||
|
|
||||||
read_unlock(&bond->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assumption: called before the slave is attached to the bond
|
/* assumption: called before the slave is attached to the bond
|
||||||
|
@ -1680,14 +1673,11 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
|
||||||
* If new_slave is NULL, caller must hold curr_slave_lock or
|
* If new_slave is NULL, caller must hold curr_slave_lock or
|
||||||
* bond->lock for write.
|
* bond->lock for write.
|
||||||
*
|
*
|
||||||
* If new_slave is not NULL, caller must hold RTNL, bond->lock for
|
* If new_slave is not NULL, caller must hold RTNL, curr_slave_lock
|
||||||
* read and curr_slave_lock for write. Processing here may sleep, so
|
* for write. Processing here may sleep, so no other locks may be held.
|
||||||
* no other locks may be held.
|
|
||||||
*/
|
*/
|
||||||
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
|
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
|
||||||
__releases(&bond->curr_slave_lock)
|
__releases(&bond->curr_slave_lock)
|
||||||
__releases(&bond->lock)
|
|
||||||
__acquires(&bond->lock)
|
|
||||||
__acquires(&bond->curr_slave_lock)
|
__acquires(&bond->curr_slave_lock)
|
||||||
{
|
{
|
||||||
struct slave *swap_slave;
|
struct slave *swap_slave;
|
||||||
|
@ -1723,7 +1713,6 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
|
||||||
tlb_clear_slave(bond, new_slave, 1);
|
tlb_clear_slave(bond, new_slave, 1);
|
||||||
|
|
||||||
write_unlock_bh(&bond->curr_slave_lock);
|
write_unlock_bh(&bond->curr_slave_lock);
|
||||||
read_unlock(&bond->lock);
|
|
||||||
|
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
|
@ -1749,11 +1738,9 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
|
||||||
/* swap mac address */
|
/* swap mac address */
|
||||||
alb_swap_mac_addr(swap_slave, new_slave);
|
alb_swap_mac_addr(swap_slave, new_slave);
|
||||||
alb_fasten_mac_swap(bond, swap_slave, new_slave);
|
alb_fasten_mac_swap(bond, swap_slave, new_slave);
|
||||||
read_lock(&bond->lock);
|
|
||||||
} else {
|
} else {
|
||||||
/* set the new_slave to the bond mac address */
|
/* set the new_slave to the bond mac address */
|
||||||
alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
|
alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
|
||||||
read_lock(&bond->lock);
|
|
||||||
alb_send_learning_packets(new_slave, bond->dev->dev_addr);
|
alb_send_learning_packets(new_slave, bond->dev->dev_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
*
|
||||||
* The full GNU General Public License is included in this distribution in the
|
* The full GNU General Public License is included in this distribution in the
|
||||||
* file called LICENSE.
|
* file called LICENSE.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue