mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Here is my initial pull request for the networking subsystem during this merge window: 1) Support for ESN in AH (RFC 4302) from Fan Du. 2) Add full kernel doc for ethtool command structures, from Ben Hutchings. 3) Add BCM7xxx PHY driver, from Florian Fainelli. 4) Export computed TCP rate information in netlink socket dumps, from Eric Dumazet. 5) Allow IPSEC SA to be dumped partially using a filter, from Nicolas Dichtel. 6) Convert many drivers to pci_enable_msix_range(), from Alexander Gordeev. 7) Record SKB timestamps more efficiently, from Eric Dumazet. 8) Switch to microsecond resolution for TCP round trip times, also from Eric Dumazet. 9) Clean up and fix 6lowpan fragmentation handling by making use of the existing inet_frag api for it's implementation. 10) Add TX grant mapping to xen-netback driver, from Zoltan Kiss. 11) Auto size SKB lengths when composing netlink messages based upon past message sizes used, from Eric Dumazet. 12) qdisc dumps can take a long time, add a cond_resched(), From Eric Dumazet. 13) Sanitize netpoll core and drivers wrt. SKB handling semantics. Get rid of never-used-in-tree netpoll RX handling. From Eric W Biederman. 14) Support inter-address-family and namespace changing in VTI tunnel driver(s). From Steffen Klassert. 15) Add Altera TSE driver, from Vince Bridgers. 16) Optimizing csum_replace2() so that it doesn't adjust the checksum by checksumming the entire header, from Eric Dumazet. 17) Expand BPF internal implementation for faster interpreting, more direct translations into JIT'd code, and much cleaner uses of BPF filtering in non-socket ocntexts. From Daniel Borkmann and Alexei Starovoitov" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1976 commits) netpoll: Use skb_irq_freeable to make zap_completion_queue safe. net: Add a test to see if a skb is freeable in irq context qlcnic: Fix build failure due to undefined reference to `vxlan_get_rx_port' net: ptp: move PTP classifier in its own file net: sxgbe: make "core_ops" static net: sxgbe: fix logical vs bitwise operation net: sxgbe: sxgbe_mdio_register() frees the bus Call efx_set_channels() before efx->type->dimension_resources() xen-netback: disable rogue vif in kthread context net/mlx4: Set proper build dependancy with vxlan be2net: fix build dependency on VxLAN mac802154: make csma/cca parameters per-wpan mac802154: allow only one WPAN to be up at any given time net: filter: minor: fix kdoc in __sk_run_filter netlink: don't compare the nul-termination in nla_strcmp can: c_can: Avoid led toggling for every packet. can: c_can: Simplify TX interrupt cleanup can: c_can: Store dlc private can: c_can: Reduce register access can: c_can: Make the code readable ...
This commit is contained in:
commit
cd6362befe
@ -7,3 +7,23 @@ Description:
|
||||
by the device during bus enumeration, encoded in hexadecimal.
|
||||
This ID is used to match the device with the appropriate
|
||||
driver.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../phy_interface
|
||||
Date: February 2014
|
||||
KernelVersion: 3.15
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
This attribute contains the PHY interface as configured by the
|
||||
Ethernet driver during bus enumeration, encoded in string.
|
||||
This interface mode is used to configure the Ethernet MAC with the
|
||||
appropriate mode for its data lines to the PHY hardware.
|
||||
|
||||
What: /sys/bus/mdio_bus/devices/.../phy_has_fixups
|
||||
Date: February 2014
|
||||
KernelVersion: 3.15
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
This attribute contains the boolean value whether a given PHY
|
||||
device has had any "fixup" workaround running on it, encoded as
|
||||
a boolean. This information is provided to help troubleshooting
|
||||
PHY configurations.
|
||||
|
199
Documentation/ABI/testing/sysfs-class-net
Normal file
199
Documentation/ABI/testing/sysfs-class-net
Normal file
@ -0,0 +1,199 @@
|
||||
What: /sys/class/net/<iface>/addr_assign_type
|
||||
Date: July 2010
|
||||
KernelVersion: 3.2
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the address assignment type. Possible values are:
|
||||
0: permanent address
|
||||
1: randomly generated
|
||||
2: stolen from another device
|
||||
3: set using dev_set_mac_address
|
||||
|
||||
What: /sys/class/net/<iface>/addr_len
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the hardware address size in bytes.
|
||||
Values vary based on the lower-level protocol used by the
|
||||
interface (Ethernet, FDDI, ATM, IEEE 802.15.4...). See
|
||||
include/uapi/linux/if_*.h for actual values.
|
||||
|
||||
What: /sys/class/net/<iface>/address
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Hardware address currently assigned to this interface.
|
||||
Format is a string, e.g: 00:11:22:33:44:55 for an Ethernet MAC
|
||||
address.
|
||||
|
||||
What: /sys/class/net/<iface>/broadcast
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Hardware broadcast address for this interface. Format is a
|
||||
string, e.g: ff:ff:ff:ff:ff:ff for an Ethernet broadcast MAC
|
||||
address.
|
||||
|
||||
What: /sys/class/net/<iface>/carrier
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the current physical link state of the interface.
|
||||
Posssible values are:
|
||||
0: physical link is down
|
||||
1: physical link is up
|
||||
|
||||
Note: some special devices, e.g: bonding and team drivers will
|
||||
allow this attribute to be written to force a link state for
|
||||
operating correctly and designating another fallback interface.
|
||||
|
||||
What: /sys/class/net/<iface>/dev_id
|
||||
Date: April 2008
|
||||
KernelVersion: 2.6.26
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the device unique identifier. Format is an hexadecimal
|
||||
value. This is used to disambiguate interfaces which might be
|
||||
stacked (e.g: VLAN interfaces) but still have the same MAC
|
||||
address as their parent device.
|
||||
|
||||
What: /sys/class/net/<iface>/dormant
|
||||
Date: March 2006
|
||||
KernelVersion: 2.6.17
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates whether the interface is in dormant state. Possible
|
||||
values are:
|
||||
0: interface is not dormant
|
||||
1: interface is dormant
|
||||
|
||||
This attribute can be used by supplicant software to signal that
|
||||
the device is not usable unless some supplicant-based
|
||||
authentication is performed (e.g: 802.1x). 'link_mode' attribute
|
||||
will also reflect the dormant state.
|
||||
|
||||
What: /sys/clas/net/<iface>/duplex
|
||||
Date: October 2009
|
||||
KernelVersion: 2.6.33
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface latest or current duplex value. Possible
|
||||
values are:
|
||||
half: half duplex
|
||||
full: full duplex
|
||||
|
||||
Note: This attribute is only valid for interfaces that implement
|
||||
the ethtool get_settings method (mostly Ethernet).
|
||||
|
||||
What: /sys/class/net/<iface>/flags
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface flags as a bitmask in hexadecimal. See
|
||||
include/uapi/linux/if.h for a list of all possible values and
|
||||
the flags semantics.
|
||||
|
||||
What: /sys/class/net/<iface>/ifalias
|
||||
Date: September 2008
|
||||
KernelVersion: 2.6.28
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates/stores an interface alias name as a string. This can
|
||||
be used for system management purposes.
|
||||
|
||||
What: /sys/class/net/<iface>/ifindex
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the system-wide interface unique index identifier as a
|
||||
decimal number. This attribute is used for mapping an interface
|
||||
identifier to an interface name. It is used throughout the
|
||||
networking stack for specifying the interface specific
|
||||
requests/events.
|
||||
|
||||
What: /sys/class/net/<iface>/iflink
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the system-wide interface unique index identifier a
|
||||
the interface is linked to. Format is decimal. This attribute is
|
||||
used to resolve interfaces chaining, linking and stacking.
|
||||
Physical interfaces have the same 'ifindex' and 'iflink' values.
|
||||
|
||||
What: /sys/class/net/<iface>/link_mode
|
||||
Date: March 2006
|
||||
KernelVersion: 2.6.17
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface link mode, as a decimal number. This
|
||||
attribute should be used in conjunction with 'dormant' attribute
|
||||
to determine the interface usability. Possible values:
|
||||
0: default link mode
|
||||
1: dormant link mode
|
||||
|
||||
What: /sys/class/net/<iface>/mtu
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface currently configured MTU value, in
|
||||
bytes, and in decimal format. Specific values depends on the
|
||||
lower-level interface protocol used. Ethernet devices will show
|
||||
a 'mtu' attribute value of 1500 unless changed.
|
||||
|
||||
What: /sys/calss/net/<iface>/netdev_group
|
||||
Date: January 2011
|
||||
KernelVersion: 2.6.39
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface network device group, as a decimal
|
||||
integer. Default value is 0 which corresponds to the initial
|
||||
network devices group. The group can be changed to affect
|
||||
routing decisions (see: net/ipv4/fib_rules and
|
||||
net/ipv6/fib6_rules.c).
|
||||
|
||||
What: /sys/class/net/<iface>/operstate
|
||||
Date: March 2006
|
||||
KernelVersion: 2.6.17
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface RFC2863 operational state as a string.
|
||||
Possible values are:
|
||||
"unknown", "notpresent", "down", "lowerlayerdown", "testing",
|
||||
"dormant", "up".
|
||||
|
||||
What: /sys/class/net/<iface>/speed
|
||||
Date: October 2009
|
||||
KernelVersion: 2.6.33
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface latest or current speed value. Value is
|
||||
an integer representing the link speed in Mbits/sec.
|
||||
|
||||
Note: this attribute is only valid for interfaces that implement
|
||||
the ethtool get_settings method (mostly Ethernet ).
|
||||
|
||||
What: /sys/class/net/<iface>/tx_queue_len
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface transmit queue len in number of packets,
|
||||
as an integer value. Value depend on the type of interface,
|
||||
Ethernet network adapters have a default value of 1000 unless
|
||||
configured otherwise
|
||||
|
||||
What: /sys/class/net/<iface>/type
|
||||
Date: April 2005
|
||||
KernelVersion: 2.6.12
|
||||
Contact: netdev@vger.kernel.org
|
||||
Description:
|
||||
Indicates the interface protocol type as a decimal value. See
|
||||
include/uapi/linux/if_arp.h for all possible values.
|
@ -76,6 +76,15 @@ Description:
|
||||
is used to classify clients as "isolated" by the
|
||||
Extended Isolation feature.
|
||||
|
||||
What: /sys/class/net/<mesh_iface>/mesh/multicast_mode
|
||||
Date: Feb 2014
|
||||
Contact: Linus Lüssing <linus.luessing@web.de>
|
||||
Description:
|
||||
Indicates whether multicast optimizations are enabled
|
||||
or disabled. If set to zero then all nodes in the
|
||||
mesh are going to use classic flooding for any
|
||||
multicast packet with no optimizations.
|
||||
|
||||
What: /sys/class/net/<mesh_iface>/mesh/network_coding
|
||||
Date: Nov 2012
|
||||
Contact: Martin Hundeboll <martin@hundeboll.net>
|
||||
|
@ -54,6 +54,26 @@ Description:
|
||||
This file contains the number of programmable periodic
|
||||
output channels offered by the PTP hardware clock.
|
||||
|
||||
What: /sys/class/ptp/ptpN/n_pins
|
||||
Date: March 2014
|
||||
Contact: Richard Cochran <richardcochran@gmail.com>
|
||||
Description:
|
||||
This file contains the number of programmable pins
|
||||
offered by the PTP hardware clock.
|
||||
|
||||
What: /sys/class/ptp/ptpN/pins
|
||||
Date: March 2014
|
||||
Contact: Richard Cochran <richardcochran@gmail.com>
|
||||
Description:
|
||||
This directory contains one file for each programmable
|
||||
pin offered by the PTP hardware clock. The file name
|
||||
is the hardware dependent pin name. Reading from this
|
||||
file produces two numbers, the assigned function (see
|
||||
the PTP_PF_ enumeration values in linux/ptp_clock.h)
|
||||
and the channel number. The function and channel
|
||||
assignment may be changed by two writing numbers into
|
||||
the file.
|
||||
|
||||
What: /sys/class/ptp/ptpN/pps_avaiable
|
||||
Date: September 2010
|
||||
Contact: Richard Cochran <richardcochran@gmail.com>
|
||||
|
@ -98,6 +98,8 @@
|
||||
!Finclude/net/cfg80211.h priv_to_wiphy
|
||||
!Finclude/net/cfg80211.h set_wiphy_dev
|
||||
!Finclude/net/cfg80211.h wdev_priv
|
||||
!Finclude/net/cfg80211.h ieee80211_iface_limit
|
||||
!Finclude/net/cfg80211.h ieee80211_iface_combination
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>Actions and configuration</title>
|
||||
|
@ -353,6 +353,7 @@ Your cooperation is appreciated.
|
||||
133 = /dev/exttrp External device trap
|
||||
134 = /dev/apm_bios Advanced Power Management BIOS
|
||||
135 = /dev/rtc Real Time Clock
|
||||
137 = /dev/vhci Bluetooth virtual HCI driver
|
||||
139 = /dev/openprom SPARC OpenBoot PROM
|
||||
140 = /dev/relay8 Berkshire Products Octal relay card
|
||||
141 = /dev/relay16 Berkshire Products ISO-16 relay card
|
||||
|
@ -5,13 +5,9 @@ Required properties:
|
||||
"allwinner,sun4i-emac")
|
||||
- reg: address and length of the register set for the device.
|
||||
- interrupts: interrupt for the device
|
||||
- phy: A phandle to a phy node defining the PHY address (as the reg
|
||||
property, a single integer).
|
||||
- phy: see ethernet.txt file in the same directory.
|
||||
- clocks: A phandle to the reference clock for this device
|
||||
|
||||
Optional properties:
|
||||
- (local-)mac-address: mac address to be used by this driver
|
||||
|
||||
Example:
|
||||
|
||||
emac: ethernet@01c0b000 {
|
||||
|
114
Documentation/devicetree/bindings/net/altera_tse.txt
Normal file
114
Documentation/devicetree/bindings/net/altera_tse.txt
Normal file
@ -0,0 +1,114 @@
|
||||
* Altera Triple-Speed Ethernet MAC driver (TSE)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "altr,tse-1.0" for legacy SGDMA based TSE, and should
|
||||
be "altr,tse-msgdma-1.0" for the preferred MSGDMA based TSE.
|
||||
ALTR is supported for legacy device trees, but is deprecated.
|
||||
altr should be used for all new designs.
|
||||
- reg: Address and length of the register set for the device. It contains
|
||||
the information of registers in the same order as described by reg-names
|
||||
- reg-names: Should contain the reg names
|
||||
"control_port": MAC configuration space region
|
||||
"tx_csr": xDMA Tx dispatcher control and status space region
|
||||
"tx_desc": MSGDMA Tx dispatcher descriptor space region
|
||||
"rx_csr" : xDMA Rx dispatcher control and status space region
|
||||
"rx_desc": MSGDMA Rx dispatcher descriptor space region
|
||||
"rx_resp": MSGDMA Rx dispatcher response space region
|
||||
"s1": SGDMA descriptor memory
|
||||
- interrupts: Should contain the TSE interrupts and it's mode.
|
||||
- interrupt-names: Should contain the interrupt names
|
||||
"rx_irq": xDMA Rx dispatcher interrupt
|
||||
"tx_irq": xDMA Tx dispatcher interrupt
|
||||
- rx-fifo-depth: MAC receive FIFO buffer depth in bytes
|
||||
- tx-fifo-depth: MAC transmit FIFO buffer depth in bytes
|
||||
- phy-mode: See ethernet.txt in the same directory.
|
||||
- phy-handle: See ethernet.txt in the same directory.
|
||||
- phy-addr: See ethernet.txt in the same directory. A configuration should
|
||||
include phy-handle or phy-addr.
|
||||
- altr,has-supplementary-unicast:
|
||||
If present, TSE supports additional unicast addresses.
|
||||
Otherwise additional unicast addresses are not supported.
|
||||
- altr,has-hash-multicast-filter:
|
||||
If present, TSE supports a hash based multicast filter.
|
||||
Otherwise, hash-based multicast filtering is not supported.
|
||||
|
||||
- mdio device tree subnode: When the TSE has a phy connected to its local
|
||||
mdio, there must be device tree subnode with the following
|
||||
required properties:
|
||||
|
||||
- compatible: Must be "altr,tse-mdio".
|
||||
- #address-cells: Must be <1>.
|
||||
- #size-cells: Must be <0>.
|
||||
|
||||
For each phy on the mdio bus, there must be a node with the following
|
||||
fields:
|
||||
|
||||
- reg: phy id used to communicate to phy.
|
||||
- device_type: Must be "ethernet-phy".
|
||||
|
||||
Optional properties:
|
||||
- local-mac-address: See ethernet.txt in the same directory.
|
||||
- max-frame-size: See ethernet.txt in the same directory.
|
||||
|
||||
Example:
|
||||
|
||||
tse_sub_0_eth_tse_0: ethernet@0x1,00000000 {
|
||||
compatible = "altr,tse-msgdma-1.0";
|
||||
reg = <0x00000001 0x00000000 0x00000400>,
|
||||
<0x00000001 0x00000460 0x00000020>,
|
||||
<0x00000001 0x00000480 0x00000020>,
|
||||
<0x00000001 0x000004A0 0x00000008>,
|
||||
<0x00000001 0x00000400 0x00000020>,
|
||||
<0x00000001 0x00000420 0x00000020>;
|
||||
reg-names = "control_port", "rx_csr", "rx_desc", "rx_resp", "tx_csr", "tx_desc";
|
||||
interrupt-parent = <&hps_0_arm_gic_0>;
|
||||
interrupts = <0 41 4>, <0 40 4>;
|
||||
interrupt-names = "rx_irq", "tx_irq";
|
||||
rx-fifo-depth = <2048>;
|
||||
tx-fifo-depth = <2048>;
|
||||
address-bits = <48>;
|
||||
max-frame-size = <1500>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
phy-mode = "gmii";
|
||||
altr,has-supplementary-unicast;
|
||||
altr,has-hash-multicast-filter;
|
||||
phy-handle = <&phy0>;
|
||||
mdio {
|
||||
compatible = "altr,tse-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0x0>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <0x1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
tse_sub_1_eth_tse_0: ethernet@0x1,00001000 {
|
||||
compatible = "altr,tse-msgdma-1.0";
|
||||
reg = <0x00000001 0x00001000 0x00000400>,
|
||||
<0x00000001 0x00001460 0x00000020>,
|
||||
<0x00000001 0x00001480 0x00000020>,
|
||||
<0x00000001 0x000014A0 0x00000008>,
|
||||
<0x00000001 0x00001400 0x00000020>,
|
||||
<0x00000001 0x00001420 0x00000020>;
|
||||
reg-names = "control_port", "rx_csr", "rx_desc", "rx_resp", "tx_csr", "tx_desc";
|
||||
interrupt-parent = <&hps_0_arm_gic_0>;
|
||||
interrupts = <0 43 4>, <0 42 4>;
|
||||
interrupt-names = "rx_irq", "tx_irq";
|
||||
rx-fifo-depth = <2048>;
|
||||
tx-fifo-depth = <2048>;
|
||||
address-bits = <48>;
|
||||
max-frame-size = <1500>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
phy-mode = "gmii";
|
||||
altr,has-supplementary-unicast;
|
||||
altr,has-hash-multicast-filter;
|
||||
phy-handle = <&phy1>;
|
||||
};
|
@ -6,19 +6,12 @@ Required properties:
|
||||
- interrupts: Should contain the EMAC interrupts
|
||||
- clock-frequency: CPU frequency. It is needed to calculate and set polling
|
||||
period of EMAC.
|
||||
- max-speed: Maximum supported data-rate in Mbit/s. In some HW configurations
|
||||
bandwidth of external memory controller might be a limiting factor. That's why
|
||||
it's required to specify which data-rate is supported on current SoC or FPGA.
|
||||
For example if only 10 Mbit/s is supported (10BASE-T) set "10". If 100 Mbit/s is
|
||||
supported (100BASE-TX) set "100".
|
||||
- phy: PHY device attached to the EMAC via MDIO bus
|
||||
- max-speed: see ethernet.txt file in the same directory.
|
||||
- phy: see ethernet.txt file in the same directory.
|
||||
|
||||
Child nodes of the driver are the individual PHY devices connected to the
|
||||
MDIO bus. They must have a "reg" property given the PHY address on the MDIO bus.
|
||||
|
||||
Optional properties:
|
||||
- mac-address: 6 bytes, mac address
|
||||
|
||||
Examples:
|
||||
|
||||
ethernet@c0fc2000 {
|
||||
|
121
Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt
Normal file
121
Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt
Normal file
@ -0,0 +1,121 @@
|
||||
* Broadcom BCM7xxx Ethernet Controller (GENET)
|
||||
|
||||
Required properties:
|
||||
- compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2",
|
||||
"brcm,genet-v3", "brcm,genet-v4".
|
||||
- reg: address and length of the register set for the device
|
||||
- interrupts: must be two cells, the first cell is the general purpose
|
||||
interrupt line, while the second cell is the interrupt for the ring
|
||||
RX and TX queues operating in ring mode
|
||||
- phy-mode: see ethernet.txt file in the same directory
|
||||
- #address-cells: should be 1
|
||||
- #size-cells: should be 1
|
||||
|
||||
Optional properties:
|
||||
- clocks: When provided, must be two phandles to the functional clocks nodes
|
||||
of the GENET block. The first phandle is the main GENET clock used during
|
||||
normal operation, while the second phandle is the Wake-on-LAN clock.
|
||||
- clock-names: When provided, names of the functional clock phandles, first
|
||||
name should be "enet" and second should be "enet-wol".
|
||||
|
||||
- phy-handle: See ethernet.txt file in the same directory; used to describe
|
||||
configurations where a PHY (internal or external) is used.
|
||||
|
||||
- fixed-link: When the GENET interface is connected to a MoCA hardware block or
|
||||
when operating in a RGMII to RGMII type of connection, or when the MDIO bus is
|
||||
voluntarily disabled, this property should be used to describe the "fixed link".
|
||||
See Documentation/devicetree/bindings/net/fsl-tsec-phy.txt for information on
|
||||
the property specifics
|
||||
|
||||
Required child nodes:
|
||||
|
||||
- mdio bus node: this node should always be present regarless of the PHY
|
||||
configuration of the GENET instance
|
||||
|
||||
MDIO bus node required properties:
|
||||
|
||||
- compatible: should contain one of "brcm,genet-mdio-v1", "brcm,genet-mdio-v2"
|
||||
"brcm,genet-mdio-v3", "brcm,genet-mdio-v4", the version has to match the
|
||||
parent node compatible property (e.g: brcm,genet-v4 pairs with
|
||||
brcm,genet-mdio-v4)
|
||||
- reg: address and length relative to the parent node base register address
|
||||
- #address-cells: address cell for MDIO bus addressing, should be 1
|
||||
- #size-cells: size of the cells for MDIO bus addressing, should be 0
|
||||
|
||||
Ethernet PHY node properties:
|
||||
|
||||
See Documentation/devicetree/bindings/net/phy.txt for the list of required and
|
||||
optional properties.
|
||||
|
||||
Internal Gigabit PHY example:
|
||||
|
||||
ethernet@f0b60000 {
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&phy1>;
|
||||
mac-address = [ 00 10 18 36 23 1a ];
|
||||
compatible = "brcm,genet-v4";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
reg = <0xf0b60000 0xfc4c>;
|
||||
interrupts = <0x0 0x14 0x0>, <0x0 0x15 0x0>;
|
||||
|
||||
mdio@e14 {
|
||||
compatible = "brcm,genet-mdio-v4";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
reg = <0xe14 0x8>;
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
max-speed = <1000>;
|
||||
reg = <0x1>;
|
||||
compatible = "brcm,28nm-gphy", "ethernet-phy-ieee802.3-c22";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
MoCA interface / MAC to MAC example:
|
||||
|
||||
ethernet@f0b80000 {
|
||||
phy-mode = "moca";
|
||||
fixed-link = <1 0 1000 0 0>;
|
||||
mac-address = [ 00 10 18 36 24 1a ];
|
||||
compatible = "brcm,genet-v4";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
reg = <0xf0b80000 0xfc4c>;
|
||||
interrupts = <0x0 0x16 0x0>, <0x0 0x17 0x0>;
|
||||
|
||||
mdio@e14 {
|
||||
compatible = "brcm,genet-mdio-v4";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
reg = <0xe14 0x8>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
External MDIO-connected Gigabit PHY/switch:
|
||||
|
||||
ethernet@f0ba0000 {
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <&phy0>;
|
||||
mac-address = [ 00 10 18 36 26 1a ];
|
||||
compatible = "brcm,genet-v4";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
reg = <0xf0ba0000 0xfc4c>;
|
||||
interrupts = <0x0 0x18 0x0>, <0x0 0x19 0x0>;
|
||||
|
||||
mdio@0e14 {
|
||||
compatible = "brcm,genet-mdio-v4";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
reg = <0xe14 0x8>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
max-speed = <1000>;
|
||||
reg = <0x0>;
|
||||
compatible = "brcm,bcm53125", "ethernet-phy-ieee802.3-c22";
|
||||
};
|
||||
};
|
||||
};
|
@ -12,6 +12,10 @@ Required properties:
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reg-io-width : Specify the size (in bytes) of the IO accesses that
|
||||
should be performed on the device. Valid value is 1, 2 or 4.
|
||||
Default to 1 (8 bits).
|
||||
|
||||
- nxp,external-clock-frequency : Frequency of the external oscillator
|
||||
clock in Hz. Note that the internal clock frequency used by the
|
||||
SJA1000 is half of that value. If not specified, a default value
|
||||
|
@ -18,12 +18,7 @@ Properties:
|
||||
- interrupts: Two interrupt specifiers. The first is the MIX
|
||||
interrupt routing and the second the routing for the AGL interrupts.
|
||||
|
||||
- mac-address: Optional, the MAC address to assign to the device.
|
||||
|
||||
- local-mac-address: Optional, the MAC address to assign to the device
|
||||
if mac-address is not specified.
|
||||
|
||||
- phy-handle: Optional, a phandle for the PHY device connected to this device.
|
||||
- phy-handle: Optional, see ethernet.txt file in the same directory.
|
||||
|
||||
Example:
|
||||
ethernet@1070000100800 {
|
||||
|
@ -35,12 +35,7 @@ Properties for PIP port which is a child the PIP interface:
|
||||
|
||||
- reg: The port number within the interface group.
|
||||
|
||||
- mac-address: Optional, the MAC address to assign to the device.
|
||||
|
||||
- local-mac-address: Optional, the MAC address to assign to the device
|
||||
if mac-address is not specified.
|
||||
|
||||
- phy-handle: Optional, a phandle for the PHY device connected to this device.
|
||||
- phy-handle: Optional, see ethernet.txt file in the same directory.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -6,11 +6,7 @@ Required properties:
|
||||
or the generic form: "cdns,emac".
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupts: Should contain macb interrupt
|
||||
- phy-mode: String, operation mode of the PHY interface.
|
||||
Supported values are: "mii", "rmii".
|
||||
|
||||
Optional properties:
|
||||
- local-mac-address: 6 bytes, mac address
|
||||
- phy-mode: see ethernet.txt file in the same directory.
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -28,9 +28,8 @@ Optional properties:
|
||||
Slave Properties:
|
||||
Required properties:
|
||||
- phy_id : Specifies slave phy id
|
||||
- phy-mode : The interface between the SoC and the PHY (a string
|
||||
that of_get_phy_mode() can understand)
|
||||
- mac-address : Specifies slave MAC address
|
||||
- phy-mode : See ethernet.txt file in the same directory
|
||||
- mac-address : See ethernet.txt file in the same directory
|
||||
|
||||
Optional properties:
|
||||
- dual_emac_res_vlan : Specifies VID to be used to segregate the ports
|
||||
|
@ -9,8 +9,6 @@ Required properties:
|
||||
- interrupts : interrupt specifier specific to interrupt controller
|
||||
|
||||
Optional properties:
|
||||
- local-mac-address : A bytestring of 6 bytes specifying Ethernet MAC address
|
||||
to use (from firmware or bootloader)
|
||||
- davicom,no-eeprom : Configuration EEPROM is not available
|
||||
- davicom,ext-phy : Use external PHY
|
||||
|
||||
|
@ -17,9 +17,8 @@ Required properties:
|
||||
Miscellaneous Interrupt>
|
||||
|
||||
Optional properties:
|
||||
- phy-handle: Contains a phandle to an Ethernet PHY.
|
||||
- phy-handle: See ethernet.txt file in the same directory.
|
||||
If absent, davinci_emac driver defaults to 100/FULL.
|
||||
- local-mac-address : 6 bytes, mac address
|
||||
- ti,davinci-rmii-en: 1 byte, 1 means use RMII
|
||||
- ti,davinci-no-bd-ram: boolean, does EMAC have BD RAM?
|
||||
|
||||
|
25
Documentation/devicetree/bindings/net/ethernet.txt
Normal file
25
Documentation/devicetree/bindings/net/ethernet.txt
Normal file
@ -0,0 +1,25 @@
|
||||
The following properties are common to the Ethernet controllers:
|
||||
|
||||
- local-mac-address: array of 6 bytes, specifies the MAC address that was
|
||||
assigned to the network device;
|
||||
- mac-address: array of 6 bytes, specifies the MAC address that was last used by
|
||||
the boot program; should be used in cases where the MAC address assigned to
|
||||
the device by the boot program is different from the "local-mac-address"
|
||||
property;
|
||||
- max-speed: number, specifies maximum speed in Mbit/s supported by the device;
|
||||
- max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than
|
||||
the maximum frame size (there's contradiction in ePAPR).
|
||||
- phy-mode: string, operation mode of the PHY interface; supported values are
|
||||
"mii", "gmii", "sgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id",
|
||||
"rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto
|
||||
standard property;
|
||||
- phy-connection-type: the same as "phy-mode" property but described in ePAPR;
|
||||
- phy-handle: phandle, specifies a reference to a node representing a PHY
|
||||
device; this property is described in ePAPR and so preferred;
|
||||
- phy: the same as "phy-handle" property, not recommended for new bindings.
|
||||
- phy-device: the same as "phy-handle" property, not recommended for new
|
||||
bindings.
|
||||
|
||||
Child nodes of the Ethernet controller are typically the individual PHY devices
|
||||
connected via the MDIO bus (sometimes the MDIO bus controller is separate).
|
||||
They are described in the phy.txt file in this same directory.
|
@ -4,12 +4,9 @@ Required properties:
|
||||
- compatible : Should be "fsl,<soc>-fec"
|
||||
- reg : Address and length of the register set for the device
|
||||
- interrupts : Should contain fec interrupt
|
||||
- phy-mode : String, operation mode of the PHY interface.
|
||||
Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
|
||||
"rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
|
||||
- phy-mode : See ethernet.txt file in the same directory
|
||||
|
||||
Optional properties:
|
||||
- local-mac-address : 6 bytes, mac address
|
||||
- phy-reset-gpios : Should specify the gpio for phy reset
|
||||
- phy-reset-duration : Reset duration in milliseconds. Should present
|
||||
only if property "phy-reset-gpios" is available. Missing the property
|
||||
|
@ -38,22 +38,17 @@ Properties:
|
||||
- model : Model of the device. Can be "TSEC", "eTSEC", or "FEC"
|
||||
- compatible : Should be "gianfar"
|
||||
- reg : Offset and length of the register set for the device
|
||||
- local-mac-address : List of bytes representing the ethernet address of
|
||||
this controller
|
||||
- interrupts : For FEC devices, the first interrupt is the device's
|
||||
interrupt. For TSEC and eTSEC devices, the first interrupt is
|
||||
transmit, the second is receive, and the third is error.
|
||||
- phy-handle : The phandle for the PHY connected to this ethernet
|
||||
controller.
|
||||
- phy-handle : See ethernet.txt file in the same directory.
|
||||
- fixed-link : <a b c d e> where a is emulated phy id - choose any,
|
||||
but unique to the all specified fixed-links, b is duplex - 0 half,
|
||||
1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
|
||||
pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
|
||||
- phy-connection-type : a string naming the controller/PHY interface type,
|
||||
i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
|
||||
"tbi", or "rtbi". This property is only really needed if the connection
|
||||
is of type "rgmii-id", as all other connection types are detected by
|
||||
hardware.
|
||||
- phy-connection-type : See ethernet.txt file in the same directory.
|
||||
This property is only really needed if the connection is of type
|
||||
"rgmii-id", as all other connection types are detected by hardware.
|
||||
- fsl,magic-packet : If present, indicates that the hardware supports
|
||||
waking up via magic packet.
|
||||
- bd-stash : If present, indicates that the hardware supports stashing
|
||||
|
@ -6,10 +6,9 @@ Required properties:
|
||||
- interrupts: Should contain ethernet controller interrupt
|
||||
|
||||
Optional properties:
|
||||
- phy-mode: String, operation mode of the PHY interface.
|
||||
Supported values are: "mii", "rmii" (default)
|
||||
- phy-mode: See ethernet.txt file in the same directory. If the property is
|
||||
absent, "rmii" is assumed.
|
||||
- use-iram: Use LPC32xx internal SRAM (IRAM) for DMA buffering
|
||||
- local-mac-address : 6 bytes, mac address
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -8,16 +8,12 @@ Required properties:
|
||||
the Cadence GEM, or the generic form: "cdns,gem".
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupts: Should contain macb interrupt
|
||||
- phy-mode: String, operation mode of the PHY interface.
|
||||
Supported values are: "mii", "rmii", "gmii", "rgmii".
|
||||
- phy-mode: See ethernet.txt file in the same directory.
|
||||
- clock-names: Tuple listing input clock names.
|
||||
Required elements: 'pclk', 'hclk'
|
||||
Optional elements: 'tx_clk'
|
||||
- clocks: Phandles to input clocks.
|
||||
|
||||
Optional properties:
|
||||
- local-mac-address: 6 bytes, mac address
|
||||
|
||||
Examples:
|
||||
|
||||
macb0: ethernet@fffc4000 {
|
||||
|
@ -4,10 +4,8 @@ Required properties:
|
||||
- compatible: should be "marvell,armada-370-neta".
|
||||
- reg: address and length of the register set for the device.
|
||||
- interrupts: interrupt for the device
|
||||
- phy: A phandle to a phy node defining the PHY address (as the reg
|
||||
property, a single integer).
|
||||
- phy-mode: The interface between the SoC and the PHY (a string that
|
||||
of_get_phy_mode() can understand)
|
||||
- phy: See ethernet.txt file in the same directory.
|
||||
- phy-mode: See ethernet.txt file in the same directory
|
||||
- clocks: a pointer to the reference clock for this device.
|
||||
|
||||
Example:
|
||||
|
@ -36,7 +36,7 @@ Required port properties:
|
||||
"marvell,kirkwood-eth-port".
|
||||
- reg: port number relative to ethernet controller, shall be 0, 1, or 2.
|
||||
- interrupts: port interrupt.
|
||||
- local-mac-address: 6 bytes MAC address.
|
||||
- local-mac-address: See ethernet.txt file in the same directory.
|
||||
|
||||
Optional port properties:
|
||||
- marvell,tx-queue-size: size of the transmit ring buffer.
|
||||
@ -48,7 +48,7 @@ Optional port properties:
|
||||
|
||||
and
|
||||
|
||||
- phy-handle: phandle reference to ethernet PHY.
|
||||
- phy-handle: See ethernet.txt file in the same directory.
|
||||
|
||||
or
|
||||
|
||||
|
@ -6,5 +6,4 @@ Required properties:
|
||||
- interrupts : interrupt connection
|
||||
|
||||
Optional properties:
|
||||
- local-mac-address : Ethernet mac address to use
|
||||
- vdd-supply: supply for Ethernet mac
|
||||
|
18
Documentation/devicetree/bindings/net/micrel.txt
Normal file
18
Documentation/devicetree/bindings/net/micrel.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Micrel PHY properties.
|
||||
|
||||
These properties cover the base properties Micrel PHYs.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- micrel,led-mode : LED mode value to set for PHYs with configurable LEDs.
|
||||
|
||||
Configure the LED mode with single value. The list of PHYs and
|
||||
the bits that are currently supported:
|
||||
|
||||
KSZ8001: register 0x1e, bits 15..14
|
||||
KSZ8041: register 0x1e, bits 15..14
|
||||
KSZ8021: register 0x1f, bits 5..4
|
||||
KSZ8031: register 0x1f, bits 5..4
|
||||
KSZ8051: register 0x1f, bits 5..4
|
||||
|
||||
See the respective PHY datasheet for the mode values.
|
34
Documentation/devicetree/bindings/net/nfc/trf7970a.txt
Normal file
34
Documentation/devicetree/bindings/net/nfc/trf7970a.txt
Normal file
@ -0,0 +1,34 @@
|
||||
* Texas Instruments TRF7970A RFID/NFC/15693 Transceiver
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "ti,trf7970a".
|
||||
- spi-max-frequency: Maximum SPI frequency (<= 2000000).
|
||||
- interrupt-parent: phandle of parent interrupt handler.
|
||||
- interrupts: A single interrupt specifier.
|
||||
- ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on the
|
||||
TRF7970A.
|
||||
- vin-supply: Regulator for supply voltage to VIN pin
|
||||
|
||||
Optional SoC Specific Properties:
|
||||
- pinctrl-names: Contains only one value - "default".
|
||||
- pintctrl-0: Specifies the pin control groups used for this controller.
|
||||
|
||||
Example (for ARM-based BeagleBone with TRF7970A on SPI1):
|
||||
|
||||
&spi1 {
|
||||
status = "okay";
|
||||
|
||||
nfc@0 {
|
||||
compatible = "ti,trf7970a";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&trf7970a_default>;
|
||||
spi-max-frequency = <2000000>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <14 0>;
|
||||
ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>,
|
||||
<&gpio2 5 GPIO_ACTIVE_LOW>;
|
||||
vin-supply = <&ldo3_reg>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
@ -21,10 +21,18 @@ Optional Properties:
|
||||
elements.
|
||||
- max-speed: Maximum PHY supported speed (10, 100, 1000...)
|
||||
|
||||
If the phy's identifier is known then the list may contain an entry
|
||||
of the form: "ethernet-phy-idAAAA.BBBB" where
|
||||
AAAA - The value of the 16 bit Phy Identifier 1 register as
|
||||
4 hex digits. This is the chip vendor OUI bits 3:18
|
||||
BBBB - The value of the 16 bit Phy Identifier 2 register as
|
||||
4 hex digits. This is the chip vendor OUI bits 19:24,
|
||||
followed by 10 bits of a vendor specific ID.
|
||||
|
||||
Example:
|
||||
|
||||
ethernet-phy@0 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
compatible = "ethernet-phy-id0141.0e90", "ethernet-phy-ieee802.3-c22";
|
||||
interrupt-parent = <40000>;
|
||||
interrupts = <35 1>;
|
||||
reg = <0>;
|
||||
|
52
Documentation/devicetree/bindings/net/samsung-sxgbe.txt
Normal file
52
Documentation/devicetree/bindings/net/samsung-sxgbe.txt
Normal file
@ -0,0 +1,52 @@
|
||||
* Samsung 10G Ethernet driver (SXGBE)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "samsung,sxgbe-v2.0a"
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
- interrupts: Should contain the SXGBE interrupts
|
||||
These interrupts are ordered by fixed and follows variable
|
||||
trasmit DMA interrupts, receive DMA interrupts and lpi interrupt.
|
||||
index 0 - this is fixed common interrupt of SXGBE and it is always
|
||||
available.
|
||||
index 1 to 25 - 8 variable trasmit interrupts, variable 16 receive interrupts
|
||||
and 1 optional lpi interrupt.
|
||||
- phy-mode: String, operation mode of the PHY interface.
|
||||
Supported values are: "sgmii", "xgmii".
|
||||
- samsung,pbl: Integer, Programmable Burst Length.
|
||||
Supported values are 1, 2, 4, 8, 16, or 32.
|
||||
- samsung,burst-map: Integer, Program the possible bursts supported by sxgbe
|
||||
This is an interger and represents allowable DMA bursts when fixed burst.
|
||||
Allowable range is 0x01-0x3F. When this field is set fixed burst is enabled.
|
||||
When fixed length is needed for burst mode, it can be set within allowable
|
||||
range.
|
||||
|
||||
Optional properties:
|
||||
- mac-address: 6 bytes, mac address
|
||||
- max-frame-size: Maximum Transfer Unit (IEEE defined MTU), rather
|
||||
than the maximum frame size.
|
||||
|
||||
Example:
|
||||
|
||||
aliases {
|
||||
ethernet0 = <&sxgbe0>;
|
||||
};
|
||||
|
||||
sxgbe0: ethernet@1a040000 {
|
||||
compatible = "samsung,sxgbe-v2.0a";
|
||||
reg = <0 0x1a040000 0 0x10000>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 209 4>, <0 185 4>, <0 186 4>, <0 187 4>,
|
||||
<0 188 4>, <0 189 4>, <0 190 4>, <0 191 4>,
|
||||
<0 192 4>, <0 193 4>, <0 194 4>, <0 195 4>,
|
||||
<0 196 4>, <0 197 4>, <0 198 4>, <0 199 4>,
|
||||
<0 200 4>, <0 201 4>, <0 202 4>, <0 203 4>,
|
||||
<0 204 4>, <0 205 4>, <0 206 4>, <0 207 4>,
|
||||
<0 208 4>, <0 210 4>;
|
||||
samsung,pbl = <0x08>
|
||||
samsung,burst-map = <0x20>
|
||||
mac-address = [ 00 11 22 33 44 55 ]; /* Filled in by U-Boot */
|
||||
max-frame-size = <9000>;
|
||||
phy-mode = "xgmii";
|
||||
};
|
55
Documentation/devicetree/bindings/net/sh_eth.txt
Normal file
55
Documentation/devicetree/bindings/net/sh_eth.txt
Normal file
@ -0,0 +1,55 @@
|
||||
* Renesas Electronics SH EtherMAC
|
||||
|
||||
This file provides information on what the device node for the SH EtherMAC
|
||||
interface contains.
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,gether-r8a7740" if the device is a part of R8A7740 SoC.
|
||||
"renesas,ether-r8a7778" if the device is a part of R8A7778 SoC.
|
||||
"renesas,ether-r8a7779" if the device is a part of R8A7779 SoC.
|
||||
"renesas,ether-r8a7790" if the device is a part of R8A7790 SoC.
|
||||
"renesas,ether-r8a7791" if the device is a part of R8A7791 SoC.
|
||||
"renesas,ether-r7s72100" if the device is a part of R7S72100 SoC.
|
||||
- reg: offset and length of (1) the E-DMAC/feLic register block (required),
|
||||
(2) the TSU register block (optional).
|
||||
- interrupts: interrupt specifier for the sole interrupt.
|
||||
- phy-mode: see ethernet.txt file in the same directory.
|
||||
- phy-handle: see ethernet.txt file in the same directory.
|
||||
- #address-cells: number of address cells for the MDIO bus, must be equal to 1.
|
||||
- #size-cells: number of size cells on the MDIO bus, must be equal to 0.
|
||||
- clocks: clock phandle and specifier pair.
|
||||
- pinctrl-0: phandle, referring to a default pin configuration node.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: the phandle for the interrupt controller that services
|
||||
interrupts for this device.
|
||||
- pinctrl-names: pin configuration state name ("default").
|
||||
- renesas,no-ether-link: boolean, specify when a board does not provide a proper
|
||||
Ether LINK signal.
|
||||
- renesas,ether-link-active-low: boolean, specify when the Ether LINK signal is
|
||||
active-low instead of normal active-high.
|
||||
|
||||
Example (Lager board):
|
||||
|
||||
ethernet@ee700000 {
|
||||
compatible = "renesas,ether-r8a7790";
|
||||
reg = <0 0xee700000 0 0x400>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&mstp8_clks R8A7790_CLK_ETHER>;
|
||||
phy-mode = "rmii";
|
||||
phy-handle = <&phy1>;
|
||||
pinctrl-0 = <ðer_pins>;
|
||||
pinctrl-names = "default";
|
||||
renesas,ether-link-active-low;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
interrupt-parent = <&irqc0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
||||
pinctrl-0 = <&phy1_pins>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
};
|
@ -6,8 +6,7 @@ Required properties:
|
||||
- interrupts : interrupt connection
|
||||
|
||||
Optional properties:
|
||||
- phy-device : phandle to Ethernet phy
|
||||
- local-mac-address : Ethernet mac address to use
|
||||
- phy-device : see ethernet.txt file in the same directory
|
||||
- reg-io-width : Mask of sizes (in bytes) of the IO accesses that
|
||||
are supported on the device. Valid value for SMSC LAN91c111 are
|
||||
1, 2 or 4. If it's omitted or invalid, the size would be 2 meaning
|
||||
|
@ -6,9 +6,7 @@ Required properties:
|
||||
- interrupts : Should contain SMSC LAN interrupt line
|
||||
- interrupt-parent : Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
- phy-mode : String, operation mode of the PHY interface.
|
||||
Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
|
||||
"rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
|
||||
- phy-mode : See ethernet.txt file in the same directory
|
||||
|
||||
Optional properties:
|
||||
- reg-shift : Specify the quantity to shift the register offsets by
|
||||
@ -23,7 +21,6 @@ Optional properties:
|
||||
external PHY
|
||||
- smsc,save-mac-address : Indicates that mac address needs to be saved
|
||||
before resetting the controller
|
||||
- local-mac-address : 6 bytes, mac address
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -10,8 +10,7 @@ Required properties:
|
||||
- interrupt-names: Should contain the interrupt names "macirq"
|
||||
"eth_wake_irq" if this interrupt is supported in the "interrupts"
|
||||
property
|
||||
- phy-mode: String, operation mode of the PHY interface.
|
||||
Supported values are: "mii", "rmii", "gmii", "rgmii".
|
||||
- phy-mode: See ethernet.txt file in the same directory.
|
||||
- snps,reset-gpio gpio number for phy reset.
|
||||
- snps,reset-active-low boolean flag to indicate if phy reset is active low.
|
||||
- snps,reset-delays-us is triplet of delays
|
||||
@ -28,12 +27,10 @@ Required properties:
|
||||
ignored if force_thresh_dma_mode is set.
|
||||
|
||||
Optional properties:
|
||||
- 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.
|
||||
- max-frame-size: See ethernet.txt file in the same directory
|
||||
|
||||
Examples:
|
||||
|
||||
|
39
Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt
Normal file
39
Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt
Normal file
@ -0,0 +1,39 @@
|
||||
* Texas Instruments wl1251 wireless lan controller
|
||||
|
||||
The wl1251 chip can be connected via SPI or via SDIO. This
|
||||
document describes the binding for the SPI connected chip.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "ti,wl1251"
|
||||
- reg : Chip select address of device
|
||||
- spi-max-frequency : Maximum SPI clocking speed of device in Hz
|
||||
- interrupts : Should contain interrupt line
|
||||
- interrupt-parent : Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
- vio-supply : phandle to regulator providing VIO
|
||||
- ti,power-gpio : GPIO connected to chip's PMEN pin
|
||||
|
||||
Optional properties:
|
||||
- ti,wl1251-has-eeprom : boolean, the wl1251 has an eeprom connected, which
|
||||
provides configuration data (calibration, MAC, ...)
|
||||
- Please consult Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
for optional SPI connection related properties,
|
||||
|
||||
Examples:
|
||||
|
||||
&spi1 {
|
||||
wl1251@0 {
|
||||
compatible = "ti,wl1251";
|
||||
|
||||
reg = <0>;
|
||||
spi-max-frequency = <48000000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <10 IRQ_TYPE_NONE>; /* gpio line 42 */
|
||||
|
||||
vio-supply = <&vio>;
|
||||
ti,power-gpio = <&gpio3 23 GPIO_ACTIVE_HIGH>; /* 87 */
|
||||
};
|
||||
};
|
263
Documentation/networking/altera_tse.txt
Normal file
263
Documentation/networking/altera_tse.txt
Normal file
@ -0,0 +1,263 @@
|
||||
Altera Triple-Speed Ethernet MAC driver
|
||||
|
||||
Copyright (C) 2008-2014 Altera Corporation
|
||||
|
||||
This is the driver for the Altera Triple-Speed Ethernet (TSE) controllers
|
||||
using the SGDMA and MSGDMA soft DMA IP components. The driver uses the
|
||||
platform bus to obtain component resources. The designs used to test this
|
||||
driver were built for a Cyclone(R) V SOC FPGA board, a Cyclone(R) V FPGA board,
|
||||
and tested with ARM and NIOS processor hosts seperately. The anticipated use
|
||||
cases are simple communications between an embedded system and an external peer
|
||||
for status and simple configuration of the embedded system.
|
||||
|
||||
For more information visit www.altera.com and www.rocketboards.org. Support
|
||||
forums for the driver may be found on www.rocketboards.org, and a design used
|
||||
to test this driver may be found there as well. Support is also available from
|
||||
the maintainer of this driver, found in MAINTAINERS.
|
||||
|
||||
The Triple-Speed Ethernet, SGDMA, and MSGDMA components are all soft IP
|
||||
components that can be assembled and built into an FPGA using the Altera
|
||||
Quartus toolchain. Quartus 13.1 and 14.0 were used to build the design that
|
||||
this driver was tested against. The sopc2dts tool is used to create the
|
||||
device tree for the driver, and may be found at rocketboards.org.
|
||||
|
||||
The driver probe function examines the device tree and determines if the
|
||||
Triple-Speed Ethernet instance is using an SGDMA or MSGDMA component. The
|
||||
probe function then installs the appropriate set of DMA routines to
|
||||
initialize, setup transmits, receives, and interrupt handling primitives for
|
||||
the respective configurations.
|
||||
|
||||
The SGDMA component is to be deprecated in the near future (over the next 1-2
|
||||
years as of this writing in early 2014) in favor of the MSGDMA component.
|
||||
SGDMA support is included for existing designs and reference in case a
|
||||
developer wishes to support their own soft DMA logic and driver support. Any
|
||||
new designs should not use the SGDMA.
|
||||
|
||||
The SGDMA supports only a single transmit or receive operation at a time, and
|
||||
therefore will not perform as well compared to the MSGDMA soft IP. Please
|
||||
visit www.altera.com for known, documented SGDMA errata.
|
||||
|
||||
Scatter-gather DMA is not supported by the SGDMA or MSGDMA at this time.
|
||||
Scatter-gather DMA will be added to a future maintenance update to this
|
||||
driver.
|
||||
|
||||
Jumbo frames are not supported at this time.
|
||||
|
||||
The driver limits PHY operations to 10/100Mbps, and has not yet been fully
|
||||
tested for 1Gbps. This support will be added in a future maintenance update.
|
||||
|
||||
1) Kernel Configuration
|
||||
The kernel configuration option is ALTERA_TSE:
|
||||
Device Drivers ---> Network device support ---> Ethernet driver support --->
|
||||
Altera Triple-Speed Ethernet MAC support (ALTERA_TSE)
|
||||
|
||||
2) Driver parameters list:
|
||||
debug: message level (0: no output, 16: all);
|
||||
dma_rx_num: Number of descriptors in the RX list (default is 64);
|
||||
dma_tx_num: Number of descriptors in the TX list (default is 64).
|
||||
|
||||
3) Command line options
|
||||
Driver parameters can be also passed in command line by using:
|
||||
altera_tse=dma_rx_num:128,dma_tx_num:512
|
||||
|
||||
4) Driver information and notes
|
||||
|
||||
4.1) Transmit process
|
||||
When the driver's transmit routine is called by the kernel, it sets up a
|
||||
transmit descriptor by calling the underlying DMA transmit routine (SGDMA or
|
||||
MSGDMA), and initites a transmit operation. Once the transmit is complete, an
|
||||
interrupt is driven by the transmit DMA logic. The driver handles the transmit
|
||||
completion in the context of the interrupt handling chain by recycling
|
||||
resource required to send and track the requested transmit operation.
|
||||
|
||||
4.2) Receive process
|
||||
The driver will post receive buffers to the receive DMA logic during driver
|
||||
intialization. Receive buffers may or may not be queued depending upon the
|
||||
underlying DMA logic (MSGDMA is able queue receive buffers, SGDMA is not able
|
||||
to queue receive buffers to the SGDMA receive logic). When a packet is
|
||||
received, the DMA logic generates an interrupt. The driver handles a receive
|
||||
interrupt by obtaining the DMA receive logic status, reaping receive
|
||||
completions until no more receive completions are available.
|
||||
|
||||
4.3) Interrupt Mitigation
|
||||
The driver is able to mitigate the number of its DMA interrupts
|
||||
using NAPI for receive operations. Interrupt mitigation is not yet supported
|
||||
for transmit operations, but will be added in a future maintenance release.
|
||||
|
||||
4.4) Ethtool support
|
||||
Ethtool is supported. Driver statistics and internal errors can be taken using:
|
||||
ethtool -S ethX command. It is possible to dump registers etc.
|
||||
|
||||
4.5) PHY Support
|
||||
The driver is compatible with PAL to work with PHY and GPHY devices.
|
||||
|
||||
4.7) List of source files:
|
||||
o Kconfig
|
||||
o Makefile
|
||||
o altera_tse_main.c: main network device driver
|
||||
o altera_tse_ethtool.c: ethtool support
|
||||
o altera_tse.h: private driver structure and common definitions
|
||||
o altera_msgdma.h: MSGDMA implementation function definitions
|
||||
o altera_sgdma.h: SGDMA implementation function definitions
|
||||
o altera_msgdma.c: MSGDMA implementation
|
||||
o altera_sgdma.c: SGDMA implementation
|
||||
o altera_sgdmahw.h: SGDMA register and descriptor definitions
|
||||
o altera_msgdmahw.h: MSGDMA register and descriptor definitions
|
||||
o altera_utils.c: Driver utility functions
|
||||
o altera_utils.h: Driver utility function definitions
|
||||
|
||||
5) Debug Information
|
||||
|
||||
The driver exports debug information such as internal statistics,
|
||||
debug information, MAC and DMA registers etc.
|
||||
|
||||
A user may use the ethtool support to get statistics:
|
||||
e.g. using: ethtool -S ethX (that shows the statistics counters)
|
||||
or sees the MAC registers: e.g. using: ethtool -d ethX
|
||||
|
||||
The developer can also use the "debug" module parameter to get
|
||||
further debug information.
|
||||
|
||||
6) Statistics Support
|
||||
|
||||
The controller and driver support a mix of IEEE standard defined statistics,
|
||||
RFC defined statistics, and driver or Altera defined statistics. The four
|
||||
specifications containing the standard definitions for these statistics are
|
||||
as follows:
|
||||
|
||||
o IEEE 802.3-2012 - IEEE Standard for Ethernet.
|
||||
o RFC 2863 found at http://www.rfc-editor.org/rfc/rfc2863.txt.
|
||||
o RFC 2819 found at http://www.rfc-editor.org/rfc/rfc2819.txt.
|
||||
o Altera Triple Speed Ethernet User Guide, found at http://www.altera.com
|
||||
|
||||
The statistics supported by the TSE and the device driver are as follows:
|
||||
|
||||
"tx_packets" is equivalent to aFramesTransmittedOK defined in IEEE 802.3-2012,
|
||||
Section 5.2.2.1.2. This statistics is the count of frames that are successfully
|
||||
transmitted.
|
||||
|
||||
"rx_packets" is equivalent to aFramesReceivedOK defined in IEEE 802.3-2012,
|
||||
Section 5.2.2.1.5. This statistic is the count of frames that are successfully
|
||||
received. This count does not include any error packets such as CRC errors,
|
||||
length errors, or alignment errors.
|
||||
|
||||
"rx_crc_errors" is equivalent to aFrameCheckSequenceErrors defined in IEEE
|
||||
802.3-2012, Section 5.2.2.1.6. This statistic is the count of frames that are
|
||||
an integral number of bytes in length and do not pass the CRC test as the frame
|
||||
is received.
|
||||
|
||||
"rx_align_errors" is equivalent to aAlignmentErrors defined in IEEE 802.3-2012,
|
||||
Section 5.2.2.1.7. This statistic is the count of frames that are not an
|
||||
integral number of bytes in length and do not pass the CRC test as the frame is
|
||||
received.
|
||||
|
||||
"tx_bytes" is equivalent to aOctetsTransmittedOK defined in IEEE 802.3-2012,
|
||||
Section 5.2.2.1.8. This statistic is the count of data and pad bytes
|
||||
successfully transmitted from the interface.
|
||||
|
||||
"rx_bytes" is equivalent to aOctetsReceivedOK defined in IEEE 802.3-2012,
|
||||
Section 5.2.2.1.14. This statistic is the count of data and pad bytes
|
||||
successfully received by the controller.
|
||||
|
||||
"tx_pause" is equivalent to aPAUSEMACCtrlFramesTransmitted defined in IEEE
|
||||
802.3-2012, Section 30.3.4.2. This statistic is a count of PAUSE frames
|
||||
transmitted from the network controller.
|
||||
|
||||
"rx_pause" is equivalent to aPAUSEMACCtrlFramesReceived defined in IEEE
|
||||
802.3-2012, Section 30.3.4.3. This statistic is a count of PAUSE frames
|
||||
received by the network controller.
|
||||
|
||||
"rx_errors" is equivalent to ifInErrors defined in RFC 2863. This statistic is
|
||||
a count of the number of packets received containing errors that prevented the
|
||||
packet from being delivered to a higher level protocol.
|
||||
|
||||
"tx_errors" is equivalent to ifOutErrors defined in RFC 2863. This statistic
|
||||
is a count of the number of packets that could not be transmitted due to errors.
|
||||
|
||||
"rx_unicast" is equivalent to ifInUcastPkts defined in RFC 2863. This
|
||||
statistic is a count of the number of packets received that were not addressed
|
||||
to the broadcast address or a multicast group.
|
||||
|
||||
"rx_multicast" is equivalent to ifInMulticastPkts defined in RFC 2863. This
|
||||
statistic is a count of the number of packets received that were addressed to
|
||||
a multicast address group.
|
||||
|
||||
"rx_broadcast" is equivalent to ifInBroadcastPkts defined in RFC 2863. This
|
||||
statistic is a count of the number of packets received that were addressed to
|
||||
the broadcast address.
|
||||
|
||||
"tx_discards" is equivalent to ifOutDiscards defined in RFC 2863. This
|
||||
statistic is the number of outbound packets not transmitted even though an
|
||||
error was not detected. An example of a reason this might occur is to free up
|
||||
internal buffer space.
|
||||
|
||||
"tx_unicast" is equivalent to ifOutUcastPkts defined in RFC 2863. This
|
||||
statistic counts the number of packets transmitted that were not addressed to
|
||||
a multicast group or broadcast address.
|
||||
|
||||
"tx_multicast" is equivalent to ifOutMulticastPkts defined in RFC 2863. This
|
||||
statistic counts the number of packets transmitted that were addressed to a
|
||||
multicast group.
|
||||
|
||||
"tx_broadcast" is equivalent to ifOutBroadcastPkts defined in RFC 2863. This
|
||||
statistic counts the number of packets transmitted that were addressed to a
|
||||
broadcast address.
|
||||
|
||||
"ether_drops" is equivalent to etherStatsDropEvents defined in RFC 2819.
|
||||
This statistic counts the number of packets dropped due to lack of internal
|
||||
controller resources.
|
||||
|
||||
"rx_total_bytes" is equivalent to etherStatsOctets defined in RFC 2819.
|
||||
This statistic counts the total number of bytes received by the controller,
|
||||
including error and discarded packets.
|
||||
|
||||
"rx_total_packets" is equivalent to etherStatsPkts defined in RFC 2819.
|
||||
This statistic counts the total number of packets received by the controller,
|
||||
including error, discarded, unicast, multicast, and broadcast packets.
|
||||
|
||||
"rx_undersize" is equivalent to etherStatsUndersizePkts defined in RFC 2819.
|
||||
This statistic counts the number of correctly formed packets received less
|
||||
than 64 bytes long.
|
||||
|
||||
"rx_oversize" is equivalent to etherStatsOversizePkts defined in RFC 2819.
|
||||
This statistic counts the number of correctly formed packets greater than 1518
|
||||
bytes long.
|
||||
|
||||
"rx_64_bytes" is equivalent to etherStatsPkts64Octets defined in RFC 2819.
|
||||
This statistic counts the total number of packets received that were 64 octets
|
||||
in length.
|
||||
|
||||
"rx_65_127_bytes" is equivalent to etherStatsPkts65to127Octets defined in RFC
|
||||
2819. This statistic counts the total number of packets received that were
|
||||
between 65 and 127 octets in length inclusive.
|
||||
|
||||
"rx_128_255_bytes" is equivalent to etherStatsPkts128to255Octets defined in
|
||||
RFC 2819. This statistic is the total number of packets received that were
|
||||
between 128 and 255 octets in length inclusive.
|
||||
|
||||
"rx_256_511_bytes" is equivalent to etherStatsPkts256to511Octets defined in
|
||||
RFC 2819. This statistic is the total number of packets received that were
|
||||
between 256 and 511 octets in length inclusive.
|
||||
|
||||
"rx_512_1023_bytes" is equivalent to etherStatsPkts512to1023Octets defined in
|
||||
RFC 2819. This statistic is the total number of packets received that were
|
||||
between 512 and 1023 octets in length inclusive.
|
||||
|
||||
"rx_1024_1518_bytes" is equivalent to etherStatsPkts1024to1518Octets define
|
||||
in RFC 2819. This statistic is the total number of packets received that were
|
||||
between 1024 and 1518 octets in length inclusive.
|
||||
|
||||
"rx_gte_1519_bytes" is a statistic defined specific to the behavior of the
|
||||
Altera TSE. This statistics counts the number of received good and errored
|
||||
frames between the length of 1519 and the maximum frame length configured
|
||||
in the frm_length register. See the Altera TSE User Guide for More details.
|
||||
|
||||
"rx_jabbers" is equivalent to etherStatsJabbers defined in RFC 2819. This
|
||||
statistic is the total number of packets received that were longer than 1518
|
||||
octets, and had either a bad CRC with an integral number of octets (CRC Error)
|
||||
or a bad CRC with a non-integral number of octets (Alignment Error).
|
||||
|
||||
"rx_runts" is equivalent to etherStatsFragments defined in RFC 2819. This
|
||||
statistic is the total number of packets received that were less than 64 octets
|
||||
in length and had either a bad CRC with an integral number of octets (CRC
|
||||
error) or a bad CRC with a non-integral number of octets (Alignment Error).
|
@ -270,16 +270,15 @@ arp_ip_target
|
||||
arp_validate
|
||||
|
||||
Specifies whether or not ARP probes and replies should be
|
||||
validated in the active-backup mode. This causes the ARP
|
||||
monitor to examine the incoming ARP requests and replies, and
|
||||
only consider a slave to be up if it is receiving the
|
||||
appropriate ARP traffic.
|
||||
validated in any mode that supports arp monitoring, or whether
|
||||
non-ARP traffic should be filtered (disregarded) for link
|
||||
monitoring purposes.
|
||||
|
||||
Possible values are:
|
||||
|
||||
none or 0
|
||||
|
||||
No validation is performed. This is the default.
|
||||
No validation or filtering is performed.
|
||||
|
||||
active or 1
|
||||
|
||||
@ -293,31 +292,68 @@ arp_validate
|
||||
|
||||
Validation is performed for all slaves.
|
||||
|
||||
For the active slave, the validation checks ARP replies to
|
||||
confirm that they were generated by an arp_ip_target. Since
|
||||
backup slaves do not typically receive these replies, the
|
||||
validation performed for backup slaves is on the ARP request
|
||||
sent out via the active slave. It is possible that some
|
||||
switch or network configurations may result in situations
|
||||
wherein the backup slaves do not receive the ARP requests; in
|
||||
such a situation, validation of backup slaves must be
|
||||
disabled.
|
||||
filter or 4
|
||||
|
||||
The validation of ARP requests on backup slaves is mainly
|
||||
helping bonding to decide which slaves are more likely to
|
||||
work in case of the active slave failure, it doesn't really
|
||||
guarantee that the backup slave will work if it's selected
|
||||
as the next active slave.
|
||||
Filtering is applied to all slaves. No validation is
|
||||
performed.
|
||||
|
||||
This option is useful in network configurations in which
|
||||
multiple bonding hosts are concurrently issuing ARPs to one or
|
||||
more targets beyond a common switch. Should the link between
|
||||
the switch and target fail (but not the switch itself), the
|
||||
probe traffic generated by the multiple bonding instances will
|
||||
fool the standard ARP monitor into considering the links as
|
||||
still up. Use of the arp_validate option can resolve this, as
|
||||
the ARP monitor will only consider ARP requests and replies
|
||||
associated with its own instance of bonding.
|
||||
filter_active or 5
|
||||
|
||||
Filtering is applied to all slaves, validation is performed
|
||||
only for the active slave.
|
||||
|
||||
filter_backup or 6
|
||||
|
||||
Filtering is applied to all slaves, validation is performed
|
||||
only for backup slaves.
|
||||
|
||||
Validation:
|
||||
|
||||
Enabling validation causes the ARP monitor to examine the incoming
|
||||
ARP requests and replies, and only consider a slave to be up if it
|
||||
is receiving the appropriate ARP traffic.
|
||||
|
||||
For an active slave, the validation checks ARP replies to confirm
|
||||
that they were generated by an arp_ip_target. Since backup slaves
|
||||
do not typically receive these replies, the validation performed
|
||||
for backup slaves is on the broadcast ARP request sent out via the
|
||||
active slave. It is possible that some switch or network
|
||||
configurations may result in situations wherein the backup slaves
|
||||
do not receive the ARP requests; in such a situation, validation
|
||||
of backup slaves must be disabled.
|
||||
|
||||
The validation of ARP requests on backup slaves is mainly helping
|
||||
bonding to decide which slaves are more likely to work in case of
|
||||
the active slave failure, it doesn't really guarantee that the
|
||||
backup slave will work if it's selected as the next active slave.
|
||||
|
||||
Validation is useful in network configurations in which multiple
|
||||
bonding hosts are concurrently issuing ARPs to one or more targets
|
||||
beyond a common switch. Should the link between the switch and
|
||||
target fail (but not the switch itself), the probe traffic
|
||||
generated by the multiple bonding instances will fool the standard
|
||||
ARP monitor into considering the links as still up. Use of
|
||||
validation can resolve this, as the ARP monitor will only consider
|
||||
ARP requests and replies associated with its own instance of
|
||||
bonding.
|
||||
|
||||
Filtering:
|
||||
|
||||
Enabling filtering causes the ARP monitor to only use incoming ARP
|
||||
packets for link availability purposes. Arriving packets that are
|
||||
not ARPs are delivered normally, but do not count when determining
|
||||
if a slave is available.
|
||||
|
||||
Filtering operates by only considering the reception of ARP
|
||||
packets (any ARP packet, regardless of source or destination) when
|
||||
determining if a slave has received traffic for link availability
|
||||
purposes.
|
||||
|
||||
Filtering is useful in network configurations in which significant
|
||||
levels of third party broadcast traffic would fool the standard
|
||||
ARP monitor into considering the links as still up. Use of
|
||||
filtering can resolve this, as only ARP traffic is considered for
|
||||
link availability purposes.
|
||||
|
||||
This option was added in bonding version 3.1.0.
|
||||
|
||||
|
@ -1017,7 +1017,7 @@ solution for a couple of reasons:
|
||||
in case of a bus-off condition after the specified delay time
|
||||
in milliseconds. By default it's off.
|
||||
|
||||
"bitrate 125000 sample_point 0.875"
|
||||
"bitrate 125000 sample-point 0.875"
|
||||
Shows the real bit-rate in bits/sec and the sample-point in the
|
||||
range 0.000..0.999. If the calculation of bit-timing parameters
|
||||
is enabled in the kernel (CONFIG_CAN_CALC_BITTIMING=y), the
|
||||
|
@ -546,6 +546,130 @@ ffffffffa0069c8f + <x>:
|
||||
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.
|
||||
|
||||
BPF kernel internals
|
||||
--------------------
|
||||
Internally, for the kernel interpreter, a different BPF instruction set
|
||||
format with similar underlying principles from BPF described in previous
|
||||
paragraphs is being used. However, the instruction set format is modelled
|
||||
closer to the underlying architecture to mimic native instruction sets, so
|
||||
that a better performance can be achieved (more details later).
|
||||
|
||||
It is designed to be JITed with one to one mapping, which can also open up
|
||||
the possibility for GCC/LLVM compilers to generate optimized BPF code through
|
||||
a BPF backend that performs almost as fast as natively compiled code.
|
||||
|
||||
The new instruction set was originally designed with the possible goal in
|
||||
mind to write programs in "restricted C" and compile into BPF with a optional
|
||||
GCC/LLVM backend, so that it can just-in-time map to modern 64-bit CPUs with
|
||||
minimal performance overhead over two steps, that is, C -> BPF -> native code.
|
||||
|
||||
Currently, the new format is being used for running user BPF programs, which
|
||||
includes seccomp BPF, classic socket filters, cls_bpf traffic classifier,
|
||||
team driver's classifier for its load-balancing mode, netfilter's xt_bpf
|
||||
extension, PTP dissector/classifier, and much more. They are all internally
|
||||
converted by the kernel into the new instruction set representation and run
|
||||
in the extended interpreter. For in-kernel handlers, this all works
|
||||
transparently by using sk_unattached_filter_create() for setting up the
|
||||
filter, resp. sk_unattached_filter_destroy() for destroying it. The macro
|
||||
SK_RUN_FILTER(filter, ctx) transparently invokes the right BPF function to
|
||||
run the filter. 'filter' is a pointer to struct sk_filter that we got from
|
||||
sk_unattached_filter_create(), and 'ctx' the given context (e.g. skb pointer).
|
||||
All constraints and restrictions from sk_chk_filter() apply before a
|
||||
conversion to the new layout is being done behind the scenes!
|
||||
|
||||
Currently, for JITing, the user BPF format is being used and current BPF JIT
|
||||
compilers reused whenever possible. In other words, we do not (yet!) perform
|
||||
a JIT compilation in the new layout, however, future work will successively
|
||||
migrate traditional JIT compilers into the new instruction format as well, so
|
||||
that they will profit from the very same benefits. Thus, when speaking about
|
||||
JIT in the following, a JIT compiler (TBD) for the new instruction format is
|
||||
meant in this context.
|
||||
|
||||
Some core changes of the new internal format:
|
||||
|
||||
- Number of registers increase from 2 to 10:
|
||||
|
||||
The old format had two registers A and X, and a hidden frame pointer. The
|
||||
new layout extends this to be 10 internal registers and a read-only frame
|
||||
pointer. Since 64-bit CPUs are passing arguments to functions via registers
|
||||
the number of args from BPF program to in-kernel function is restricted
|
||||
to 5 and one register is used to accept return value from an in-kernel
|
||||
function. Natively, x86_64 passes first 6 arguments in registers, aarch64/
|
||||
sparcv9/mips64 have 7 - 8 registers for arguments; x86_64 has 6 callee saved
|
||||
registers, and aarch64/sparcv9/mips64 have 11 or more callee saved registers.
|
||||
|
||||
Therefore, BPF calling convention is defined as:
|
||||
|
||||
* R0 - return value from in-kernel function
|
||||
* R1 - R5 - arguments from BPF program to in-kernel function
|
||||
* R6 - R9 - callee saved registers that in-kernel function will preserve
|
||||
* R10 - read-only frame pointer to access stack
|
||||
|
||||
Thus, all BPF registers map one to one to HW registers on x86_64, aarch64,
|
||||
etc, and BPF calling convention maps directly to ABIs used by the kernel on
|
||||
64-bit architectures.
|
||||
|
||||
On 32-bit architectures JIT may map programs that use only 32-bit arithmetic
|
||||
and may let more complex programs to be interpreted.
|
||||
|
||||
R0 - R5 are scratch registers and BPF program needs spill/fill them if
|
||||
necessary across calls. Note that there is only one BPF program (== one BPF
|
||||
main routine) and it cannot call other BPF functions, it can only call
|
||||
predefined in-kernel functions, though.
|
||||
|
||||
- Register width increases from 32-bit to 64-bit:
|
||||
|
||||
Still, the semantics of the original 32-bit ALU operations are preserved
|
||||
via 32-bit subregisters. All BPF registers are 64-bit with 32-bit lower
|
||||
subregisters that zero-extend into 64-bit if they are being written to.
|
||||
That behavior maps directly to x86_64 and arm64 subregister definition, but
|
||||
makes other JITs more difficult.
|
||||
|
||||
32-bit architectures run 64-bit internal BPF programs via interpreter.
|
||||
Their JITs may convert BPF programs that only use 32-bit subregisters into
|
||||
native instruction set and let the rest being interpreted.
|
||||
|
||||
Operation is 64-bit, because on 64-bit architectures, pointers are also
|
||||
64-bit wide, and we want to pass 64-bit values in/out of kernel functions,
|
||||
so 32-bit BPF registers would otherwise require to define register-pair
|
||||
ABI, thus, there won't be able to use a direct BPF register to HW register
|
||||
mapping and JIT would need to do combine/split/move operations for every
|
||||
register in and out of the function, which is complex, bug prone and slow.
|
||||
Another reason is the use of atomic 64-bit counters.
|
||||
|
||||
- Conditional jt/jf targets replaced with jt/fall-through:
|
||||
|
||||
While the original design has constructs such as "if (cond) jump_true;
|
||||
else jump_false;", they are being replaced into alternative constructs like
|
||||
"if (cond) jump_true; /* else fall-through */".
|
||||
|
||||
- Introduces bpf_call insn and register passing convention for zero overhead
|
||||
calls from/to other kernel functions:
|
||||
|
||||
After a kernel function call, R1 - R5 are reset to unreadable and R0 has a
|
||||
return type of the function. Since R6 - R9 are callee saved, their state is
|
||||
preserved across the call.
|
||||
|
||||
Also in the new design, BPF is limited to 4096 insns, which means that any
|
||||
program will terminate quickly and will only call a fixed number of kernel
|
||||
functions. Original BPF and the new format are two operand instructions,
|
||||
which helps to do one-to-one mapping between BPF insn and x86 insn during JIT.
|
||||
|
||||
The input context pointer for invoking the interpreter function is generic,
|
||||
its content is defined by a specific use case. For seccomp register R1 points
|
||||
to seccomp_data, for converted BPF filters R1 points to a skb.
|
||||
|
||||
A program, that is translated internally consists of the following elements:
|
||||
|
||||
op:16, jt:8, jf:8, k:32 ==> op:8, a_reg:4, x_reg:4, off:16, imm:32
|
||||
|
||||
Just like the original BPF, the new format runs within a controlled environment,
|
||||
is deterministic and the kernel can easily prove that. The safety of the program
|
||||
can be determined in two steps: first step does depth-first-search to disallow
|
||||
loops and other CFG validation; second step starts from the first insn and
|
||||
descends all possible paths. It simulates execution of every insn and observes
|
||||
the state change of registers and stack.
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
@ -561,3 +685,4 @@ the underlying architecture.
|
||||
|
||||
Jay Schulist <jschlst@samba.org>
|
||||
Daniel Borkmann <dborkman@redhat.com>
|
||||
Alexei Starovoitov <ast@plumgrid.com>
|
||||
|
@ -1,38 +1,8 @@
|
||||
The Gianfar Ethernet Driver
|
||||
Sysfs File description
|
||||
|
||||
Author: Andy Fleming <afleming@freescale.com>
|
||||
Updated: 2005-07-28
|
||||
|
||||
SYSFS
|
||||
|
||||
Several of the features of the gianfar driver are controlled
|
||||
through sysfs files. These are:
|
||||
|
||||
bd_stash:
|
||||
To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
|
||||
bd_stash, echo 'off' or '0' to disable
|
||||
|
||||
rx_stash_len:
|
||||
To stash the first n bytes of the packet in L2, echo the number
|
||||
of bytes to buf_stash_len. echo 0 to disable.
|
||||
|
||||
WARNING: You could really screw these up if you set them too low or high!
|
||||
fifo_threshold:
|
||||
To change the number of bytes the controller needs in the
|
||||
fifo before it starts transmission, echo the number of bytes to
|
||||
fifo_thresh. Range should be 0-511.
|
||||
|
||||
fifo_starve:
|
||||
When the FIFO has less than this many bytes during a transmit, it
|
||||
enters starve mode, and increases the priority of TX memory
|
||||
transactions. To change, echo the number of bytes to
|
||||
fifo_starve. Range should be 0-511.
|
||||
|
||||
fifo_starve_off:
|
||||
Once in starve mode, the FIFO remains there until it has this
|
||||
many bytes. To change, echo the number of bytes to
|
||||
fifo_starve_off. Range should be 0-511.
|
||||
|
||||
CHECKSUM OFFLOADING
|
||||
|
||||
|
@ -36,54 +36,6 @@ Default Value: 0
|
||||
This parameter adds support for SR-IOV. It causes the driver to spawn up to
|
||||
max_vfs worth of virtual function.
|
||||
|
||||
QueuePairs
|
||||
----------
|
||||
Valid Range: 0-1
|
||||
Default Value: 1 (TX and RX will be paired onto one interrupt vector)
|
||||
|
||||
If set to 0, when MSI-X is enabled, the TX and RX will attempt to occupy
|
||||
separate vectors.
|
||||
|
||||
This option can be overridden to 1 if there are not sufficient interrupts
|
||||
available. This can occur if any combination of RSS, VMDQ, and max_vfs
|
||||
results in more than 4 queues being used.
|
||||
|
||||
Node
|
||||
----
|
||||
Valid Range: 0-n
|
||||
Default Value: -1 (off)
|
||||
|
||||
0 - n: where n is the number of the NUMA node that should be used to
|
||||
allocate memory for this adapter port.
|
||||
-1: uses the driver default of allocating memory on whichever processor is
|
||||
running insmod/modprobe.
|
||||
|
||||
The Node parameter will allow you to pick which NUMA node you want to have
|
||||
the adapter allocate memory from. All driver structures, in-memory queues,
|
||||
and receive buffers will be allocated on the node specified. This parameter
|
||||
is only useful when interrupt affinity is specified, otherwise some portion
|
||||
of the time the interrupt could run on a different core than the memory is
|
||||
allocated on, causing slower memory access and impacting throughput, CPU, or
|
||||
both.
|
||||
|
||||
EEE
|
||||
---
|
||||
Valid Range: 0-1
|
||||
Default Value: 1 (enabled)
|
||||
|
||||
A link between two EEE-compliant devices will result in periodic bursts of
|
||||
data followed by long periods where in the link is in an idle state. This Low
|
||||
Power Idle (LPI) state is supported in both 1Gbps and 100Mbps link speeds.
|
||||
NOTE: EEE support requires autonegotiation.
|
||||
|
||||
DMAC
|
||||
----
|
||||
Valid Range: 0-1
|
||||
Default Value: 1 (enabled)
|
||||
Enables or disables DMA Coalescing feature.
|
||||
|
||||
|
||||
|
||||
Additional Configurations
|
||||
=========================
|
||||
|
||||
|
@ -48,7 +48,7 @@ The MDIO bus
|
||||
time, so it is safe for them to block, waiting for an interrupt to signal
|
||||
the operation is complete
|
||||
|
||||
2) A reset function is necessary. This is used to return the bus to an
|
||||
2) A reset function is optional. This is used to return the bus to an
|
||||
initialized state.
|
||||
|
||||
3) A probe function is needed. This function should set up anything the bus
|
||||
@ -253,16 +253,25 @@ Writing a PHY driver
|
||||
|
||||
Each driver consists of a number of function pointers:
|
||||
|
||||
soft_reset: perform a PHY software reset
|
||||
config_init: configures PHY into a sane state after a reset.
|
||||
For instance, a Davicom PHY requires descrambling disabled.
|
||||
probe: Allocate phy->priv, optionally refuse to bind.
|
||||
PHY may not have been reset or had fixups run yet.
|
||||
suspend/resume: power management
|
||||
config_aneg: Changes the speed/duplex/negotiation settings
|
||||
aneg_done: Determines the auto-negotiation result
|
||||
read_status: Reads the current speed/duplex/negotiation settings
|
||||
ack_interrupt: Clear a pending interrupt
|
||||
did_interrupt: Checks if the PHY generated an interrupt
|
||||
config_intr: Enable or disable interrupts
|
||||
remove: Does any driver take-down
|
||||
ts_info: Queries about the HW timestamping status
|
||||
hwtstamp: Set the PHY HW timestamping configuration
|
||||
rxtstamp: Requests a receive timestamp at the PHY level for a 'skb'
|
||||
txtsamp: Requests a transmit timestamp at the PHY level for a 'skb'
|
||||
set_wol: Enable Wake-on-LAN at the PHY level
|
||||
get_wol: Get the Wake-on-LAN status at the PHY level
|
||||
|
||||
Of these, only config_aneg and read_status are required to be
|
||||
assigned by the driver code. The rest are optional. Also, it is
|
||||
|
@ -102,13 +102,18 @@ Examples:
|
||||
The 'minimum' MAC is what you set with dstmac.
|
||||
|
||||
pgset "flag [name]" Set a flag to determine behaviour. Current flags
|
||||
are: IPSRC_RND #IP Source is random (between min/max),
|
||||
IPDST_RND, UDPSRC_RND,
|
||||
UDPDST_RND, MACSRC_RND, MACDST_RND
|
||||
are: IPSRC_RND # IP source is random (between min/max)
|
||||
IPDST_RND # IP destination is random
|
||||
UDPSRC_RND, UDPDST_RND,
|
||||
MACSRC_RND, MACDST_RND
|
||||
TXSIZE_RND, IPV6,
|
||||
MPLS_RND, VID_RND, SVID_RND
|
||||
FLOW_SEQ,
|
||||
QUEUE_MAP_RND # queue map random
|
||||
QUEUE_MAP_CPU # queue map mirrors smp_processor_id()
|
||||
IPSEC # Make IPsec encapsulation for packet
|
||||
UDPCSUM,
|
||||
IPSEC # IPsec encapsulation (needs CONFIG_XFRM)
|
||||
NODE_ALLOC # node specific memory allocation
|
||||
|
||||
pgset spi SPI_VALUE Set specific SA used to transform packet.
|
||||
|
||||
@ -233,13 +238,22 @@ udp_dst_max
|
||||
|
||||
flag
|
||||
IPSRC_RND
|
||||
TXSIZE_RND
|
||||
IPDST_RND
|
||||
UDPSRC_RND
|
||||
UDPDST_RND
|
||||
MACSRC_RND
|
||||
MACDST_RND
|
||||
TXSIZE_RND
|
||||
IPV6
|
||||
MPLS_RND
|
||||
VID_RND
|
||||
SVID_RND
|
||||
FLOW_SEQ
|
||||
QUEUE_MAP_RND
|
||||
QUEUE_MAP_CPU
|
||||
UDPCSUM
|
||||
IPSEC
|
||||
NODE_ALLOC
|
||||
|
||||
dst_min
|
||||
dst_max
|
||||
|
@ -27,6 +27,8 @@ Contents of this document:
|
||||
|
||||
(*) AF_RXRPC kernel interface.
|
||||
|
||||
(*) Configurable parameters.
|
||||
|
||||
|
||||
========
|
||||
OVERVIEW
|
||||
@ -864,3 +866,82 @@ The kernel interface functions are as follows:
|
||||
|
||||
This is used to allocate a null RxRPC key that can be used to indicate
|
||||
anonymous security for a particular domain.
|
||||
|
||||
|
||||
=======================
|
||||
CONFIGURABLE PARAMETERS
|
||||
=======================
|
||||
|
||||
The RxRPC protocol driver has a number of configurable parameters that can be
|
||||
adjusted through sysctls in /proc/net/rxrpc/:
|
||||
|
||||
(*) req_ack_delay
|
||||
|
||||
The amount of time in milliseconds after receiving a packet with the
|
||||
request-ack flag set before we honour the flag and actually send the
|
||||
requested ack.
|
||||
|
||||
Usually the other side won't stop sending packets until the advertised
|
||||
reception window is full (to a maximum of 255 packets), so delaying the
|
||||
ACK permits several packets to be ACK'd in one go.
|
||||
|
||||
(*) soft_ack_delay
|
||||
|
||||
The amount of time in milliseconds after receiving a new packet before we
|
||||
generate a soft-ACK to tell the sender that it doesn't need to resend.
|
||||
|
||||
(*) idle_ack_delay
|
||||
|
||||
The amount of time in milliseconds after all the packets currently in the
|
||||
received queue have been consumed before we generate a hard-ACK to tell
|
||||
the sender it can free its buffers, assuming no other reason occurs that
|
||||
we would send an ACK.
|
||||
|
||||
(*) resend_timeout
|
||||
|
||||
The amount of time in milliseconds after transmitting a packet before we
|
||||
transmit it again, assuming no ACK is received from the receiver telling
|
||||
us they got it.
|
||||
|
||||
(*) max_call_lifetime
|
||||
|
||||
The maximum amount of time in seconds that a call may be in progress
|
||||
before we preemptively kill it.
|
||||
|
||||
(*) dead_call_expiry
|
||||
|
||||
The amount of time in seconds before we remove a dead call from the call
|
||||
list. Dead calls are kept around for a little while for the purpose of
|
||||
repeating ACK and ABORT packets.
|
||||
|
||||
(*) connection_expiry
|
||||
|
||||
The amount of time in seconds after a connection was last used before we
|
||||
remove it from the connection list. Whilst a connection is in existence,
|
||||
it serves as a placeholder for negotiated security; when it is deleted,
|
||||
the security must be renegotiated.
|
||||
|
||||
(*) transport_expiry
|
||||
|
||||
The amount of time in seconds after a transport was last used before we
|
||||
remove it from the transport list. Whilst a transport is in existence, it
|
||||
serves to anchor the peer data and keeps the connection ID counter.
|
||||
|
||||
(*) rxrpc_rx_window_size
|
||||
|
||||
The size of the receive window in packets. This is the maximum number of
|
||||
unconsumed received packets we're willing to hold in memory for any
|
||||
particular call.
|
||||
|
||||
(*) rxrpc_rx_mtu
|
||||
|
||||
The maximum packet MTU size that we're willing to receive in bytes. This
|
||||
indicates to the peer whether we're willing to accept jumbo packets.
|
||||
|
||||
(*) rxrpc_rx_jumbo_max
|
||||
|
||||
The maximum number of packets that we're willing to accept in a jumbo
|
||||
packet. Non-terminal packets in a jumbo packet must contain a four byte
|
||||
header plus exactly 1412 bytes of data. The terminal packet must contain
|
||||
a four byte header plus any amount of data. In any event, a jumbo packet
|
||||
may not exceed rxrpc_rx_mtu in size.
|
||||
|
@ -30,7 +30,7 @@ A congestion control mechanism can be registered through functions in
|
||||
tcp_cong.c. The functions used by the congestion control mechanism are
|
||||
registered via passing a tcp_congestion_ops struct to
|
||||
tcp_register_congestion_control. As a minimum name, ssthresh,
|
||||
cong_avoid, min_cwnd must be valid.
|
||||
cong_avoid must be valid.
|
||||
|
||||
Private data for a congestion control mechanism is stored in tp->ca_priv.
|
||||
tcp_ca(tp) returns a pointer to this space. This is preallocated space - it
|
||||
|
@ -202,6 +202,9 @@ Time stamps for outgoing packets are to be generated as follows:
|
||||
and not free the skb. A driver not supporting hardware time stamping doesn't
|
||||
do that. A driver must never touch sk_buff::tstamp! It is used to store
|
||||
software generated time stamps by the network subsystem.
|
||||
- Driver should call skb_tx_timestamp() as close to passing sk_buff to hardware
|
||||
as possible. skb_tx_timestamp() provides a software time stamp if requested
|
||||
and hardware timestamping is not possible (SKBTX_IN_PROGRESS not set).
|
||||
- As soon as the driver has sent the packet and/or obtained a
|
||||
hardware time stamp for it, it passes the time stamp back by
|
||||
calling skb_hwtstamp_tx() with the original skb, the raw
|
||||
@ -212,6 +215,3 @@ Time stamps for outgoing packets are to be generated as follows:
|
||||
this would occur at a later time in the processing pipeline than other
|
||||
software time stamping and therefore could lead to unexpected deltas
|
||||
between time stamps.
|
||||
- If the driver did not set the SKBTX_IN_PROGRESS flag (see above), then
|
||||
dev_hard_start_xmit() checks whether software time stamping
|
||||
is wanted as fallback and potentially generates the time stamp.
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
@ -120,11 +121,19 @@ static void usage(char *progname)
|
||||
" -i val index for event/trigger\n"
|
||||
" -k val measure the time offset between system and phc clock\n"
|
||||
" for 'val' times (Maximum 25)\n"
|
||||
" -l list the current pin configuration\n"
|
||||
" -L pin,val configure pin index 'pin' with function 'val'\n"
|
||||
" the channel index is taken from the '-i' option\n"
|
||||
" 'val' specifies the auxiliary function:\n"
|
||||
" 0 - none\n"
|
||||
" 1 - external time stamp\n"
|
||||
" 2 - periodic output\n"
|
||||
" -p val enable output with a period of 'val' nanoseconds\n"
|
||||
" -P val enable or disable (val=1|0) the system clock PPS\n"
|
||||
" -s set the ptp clock time from the system time\n"
|
||||
" -S set the system time from the ptp clock time\n"
|
||||
" -t val shift the ptp clock time by 'val' seconds\n",
|
||||
" -t val shift the ptp clock time by 'val' seconds\n"
|
||||
" -T val set the ptp clock time to 'val' seconds\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
@ -134,6 +143,7 @@ int main(int argc, char *argv[])
|
||||
struct ptp_extts_event event;
|
||||
struct ptp_extts_request extts_request;
|
||||
struct ptp_perout_request perout_request;
|
||||
struct ptp_pin_desc desc;
|
||||
struct timespec ts;
|
||||
struct timex tx;
|
||||
|
||||
@ -156,12 +166,15 @@ int main(int argc, char *argv[])
|
||||
int extts = 0;
|
||||
int gettime = 0;
|
||||
int index = 0;
|
||||
int list_pins = 0;
|
||||
int oneshot = 0;
|
||||
int pct_offset = 0;
|
||||
int n_samples = 0;
|
||||
int periodic = 0;
|
||||
int perout = -1;
|
||||
int pin_index = -1, pin_func;
|
||||
int pps = -1;
|
||||
int seconds = 0;
|
||||
int settime = 0;
|
||||
|
||||
int64_t t1, t2, tp;
|
||||
@ -169,7 +182,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
progname = progname ? 1+progname : argv[0];
|
||||
while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:p:P:sSt:v"))) {
|
||||
while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:lL:p:P:sSt:T:v"))) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
oneshot = atoi(optarg);
|
||||
@ -199,6 +212,16 @@ int main(int argc, char *argv[])
|
||||
pct_offset = 1;
|
||||
n_samples = atoi(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
list_pins = 1;
|
||||
break;
|
||||
case 'L':
|
||||
cnt = sscanf(optarg, "%d,%d", &pin_index, &pin_func);
|
||||
if (cnt != 2) {
|
||||
usage(progname);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
perout = atoi(optarg);
|
||||
break;
|
||||
@ -214,6 +237,10 @@ int main(int argc, char *argv[])
|
||||
case 't':
|
||||
adjtime = atoi(optarg);
|
||||
break;
|
||||
case 'T':
|
||||
settime = 3;
|
||||
seconds = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
usage(progname);
|
||||
return 0;
|
||||
@ -245,12 +272,14 @@ int main(int argc, char *argv[])
|
||||
" %d programmable alarms\n"
|
||||
" %d external time stamp channels\n"
|
||||
" %d programmable periodic signals\n"
|
||||
" %d pulse per second\n",
|
||||
" %d pulse per second\n"
|
||||
" %d programmable pins\n",
|
||||
caps.max_adj,
|
||||
caps.n_alarm,
|
||||
caps.n_ext_ts,
|
||||
caps.n_per_out,
|
||||
caps.pps);
|
||||
caps.pps,
|
||||
caps.n_pins);
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,6 +333,16 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (settime == 3) {
|
||||
ts.tv_sec = seconds;
|
||||
ts.tv_nsec = 0;
|
||||
if (clock_settime(clkid, &ts)) {
|
||||
perror("clock_settime");
|
||||
} else {
|
||||
puts("set time okay");
|
||||
}
|
||||
}
|
||||
|
||||
if (extts) {
|
||||
memset(&extts_request, 0, sizeof(extts_request));
|
||||
extts_request.index = index;
|
||||
@ -331,6 +370,24 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (list_pins) {
|
||||
int n_pins = 0;
|
||||
if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) {
|
||||
perror("PTP_CLOCK_GETCAPS");
|
||||
} else {
|
||||
n_pins = caps.n_pins;
|
||||
}
|
||||
for (i = 0; i < n_pins; i++) {
|
||||
desc.index = i;
|
||||
if (ioctl(fd, PTP_PIN_GETFUNC, &desc)) {
|
||||
perror("PTP_PIN_GETFUNC");
|
||||
break;
|
||||
}
|
||||
printf("name %s index %u func %u chan %u\n",
|
||||
desc.name, desc.index, desc.func, desc.chan);
|
||||
}
|
||||
}
|
||||
|
||||
if (oneshot) {
|
||||
install_handler(SIGALRM, handle_alarm);
|
||||
/* Create a timer. */
|
||||
@ -392,6 +449,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (pin_index >= 0) {
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.index = pin_index;
|
||||
desc.func = pin_func;
|
||||
desc.chan = index;
|
||||
if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) {
|
||||
perror("PTP_PIN_SETFUNC");
|
||||
} else {
|
||||
puts("set pin function okay");
|
||||
}
|
||||
}
|
||||
|
||||
if (pps != -1) {
|
||||
int enable = pps ? 1 : 0;
|
||||
if (ioctl(fd, PTP_ENABLE_PPS, enable)) {
|
||||
@ -428,14 +497,14 @@ int main(int argc, char *argv[])
|
||||
interval = t2 - t1;
|
||||
offset = (t2 + t1) / 2 - tp;
|
||||
|
||||
printf("system time: %ld.%ld\n",
|
||||
printf("system time: %" PRId64 ".%u\n",
|
||||
(pct+2*i)->sec, (pct+2*i)->nsec);
|
||||
printf("phc time: %ld.%ld\n",
|
||||
printf("phc time: %" PRId64 ".%u\n",
|
||||
(pct+2*i+1)->sec, (pct+2*i+1)->nsec);
|
||||
printf("system time: %ld.%ld\n",
|
||||
printf("system time: %" PRId64 ".%u\n",
|
||||
(pct+2*i+2)->sec, (pct+2*i+2)->nsec);
|
||||
printf("system/phc clock time offset is %ld ns\n"
|
||||
"system clock time delay is %ld ns\n",
|
||||
printf("system/phc clock time offset is %" PRId64 " ns\n"
|
||||
"system clock time delay is %" PRId64 " ns\n",
|
||||
offset, interval);
|
||||
}
|
||||
|
||||
|
31
MAINTAINERS
31
MAINTAINERS
@ -536,6 +536,13 @@ S: Odd Fixes
|
||||
L: linux-alpha@vger.kernel.org
|
||||
F: arch/alpha/
|
||||
|
||||
ALTERA TRIPLE SPEED ETHERNET DRIVER
|
||||
M: Vince Bridgers <vbridgers2013@gmail.com
|
||||
L: netdev@vger.kernel.org
|
||||
L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/altera/
|
||||
|
||||
ALTERA UART/JTAG UART SERIAL DRIVERS
|
||||
M: Tobias Klauser <tklauser@distanz.ch>
|
||||
L: linux-serial@vger.kernel.org
|
||||
@ -1848,6 +1855,12 @@ L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/broadcom/b44.*
|
||||
|
||||
BROADCOM GENET ETHERNET DRIVER
|
||||
M: Florian Fainelli <f.fainelli@gmail.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/broadcom/genet/
|
||||
|
||||
BROADCOM BNX2 GIGABIT ETHERNET DRIVER
|
||||
M: Michael Chan <mchan@broadcom.com>
|
||||
L: netdev@vger.kernel.org
|
||||
@ -6043,6 +6056,7 @@ L: netdev@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
|
||||
S: Maintained
|
||||
F: net/core/flow.c
|
||||
F: net/xfrm/
|
||||
F: net/key/
|
||||
F: net/ipv4/xfrm*
|
||||
@ -6118,6 +6132,7 @@ F: include/net/nfc/
|
||||
F: include/uapi/linux/nfc.h
|
||||
F: drivers/nfc/
|
||||
F: include/linux/platform_data/pn544.h
|
||||
F: Documentation/devicetree/bindings/net/nfc/
|
||||
|
||||
NFS, SUNRPC, AND LOCKD CLIENTS
|
||||
M: Trond Myklebust <trond.myklebust@primarydata.com>
|
||||
@ -7077,13 +7092,8 @@ F: Documentation/networking/LICENSE.qla3xxx
|
||||
F: drivers/net/ethernet/qlogic/qla3xxx.*
|
||||
|
||||
QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
|
||||
M: Himanshu Madhani <himanshu.madhani@qlogic.com>
|
||||
M: Rajesh Borundia <rajesh.borundia@qlogic.com>
|
||||
M: Shahed Shaikh <shahed.shaikh@qlogic.com>
|
||||
M: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
|
||||
M: Sony Chacko <sony.chacko@qlogic.com>
|
||||
M: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
|
||||
M: linux-driver@qlogic.com
|
||||
M: Dept-HSGLinuxNICDev@qlogic.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/qlogic/qlcnic/
|
||||
@ -7579,6 +7589,15 @@ S: Supported
|
||||
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
|
||||
F: drivers/clk/samsung/
|
||||
|
||||
SAMSUNG SXGBE DRIVERS
|
||||
M: Byungho An <bh74.an@samsung.com>
|
||||
M: Girish K S <ks.giri@samsung.com>
|
||||
M: Siva Reddy Kallam <siva.kallam@samsung.com>
|
||||
M: Vipul Pandya <vipul.pandya@samsung.com>
|
||||
S: Supported
|
||||
L: netdev@vger.kernel.org
|
||||
F: drivers/net/ethernet/samsung/sxgbe/
|
||||
|
||||
SERIAL DRIVERS
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
L: linux-serial@vger.kernel.org
|
||||
|
@ -536,11 +536,13 @@ static struct spi_board_info omap3pandora_spi_board_info[] __initdata = {
|
||||
|
||||
static void __init pandora_wl1251_init(void)
|
||||
{
|
||||
struct wl12xx_platform_data pandora_wl1251_pdata;
|
||||
struct wl1251_platform_data pandora_wl1251_pdata;
|
||||
int ret;
|
||||
|
||||
memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata));
|
||||
|
||||
pandora_wl1251_pdata.power_gpio = -1;
|
||||
|
||||
ret = gpio_request_one(PANDORA_WIFI_IRQ_GPIO, GPIOF_IN, "wl1251 irq");
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
@ -550,7 +552,7 @@ static void __init pandora_wl1251_init(void)
|
||||
goto fail_irq;
|
||||
|
||||
pandora_wl1251_pdata.use_eeprom = true;
|
||||
ret = wl12xx_set_platform_data(&pandora_wl1251_pdata);
|
||||
ret = wl1251_set_platform_data(&pandora_wl1251_pdata);
|
||||
if (ret < 0)
|
||||
goto fail_irq;
|
||||
|
||||
|
@ -84,7 +84,7 @@ enum {
|
||||
RX51_SPI_MIPID, /* LCD panel */
|
||||
};
|
||||
|
||||
static struct wl12xx_platform_data wl1251_pdata;
|
||||
static struct wl1251_platform_data wl1251_pdata;
|
||||
static struct tsc2005_platform_data tsc2005_pdata;
|
||||
|
||||
#if defined(CONFIG_SENSORS_LIS3_I2C) || defined(CONFIG_SENSORS_LIS3_I2C_MODULE)
|
||||
@ -1173,13 +1173,7 @@ static inline void board_smc91x_init(void)
|
||||
|
||||
#endif
|
||||
|
||||
static void rx51_wl1251_set_power(bool enable)
|
||||
{
|
||||
gpio_set_value(RX51_WL1251_POWER_GPIO, enable);
|
||||
}
|
||||
|
||||
static struct gpio rx51_wl1251_gpios[] __initdata = {
|
||||
{ RX51_WL1251_POWER_GPIO, GPIOF_OUT_INIT_LOW, "wl1251 power" },
|
||||
{ RX51_WL1251_IRQ_GPIO, GPIOF_IN, "wl1251 irq" },
|
||||
};
|
||||
|
||||
@ -1196,17 +1190,16 @@ static void __init rx51_init_wl1251(void)
|
||||
if (irq < 0)
|
||||
goto err_irq;
|
||||
|
||||
wl1251_pdata.set_power = rx51_wl1251_set_power;
|
||||
wl1251_pdata.power_gpio = RX51_WL1251_POWER_GPIO;
|
||||
rx51_peripherals_spi_board_info[RX51_SPI_WL1251].irq = irq;
|
||||
|
||||
return;
|
||||
|
||||
err_irq:
|
||||
gpio_free(RX51_WL1251_IRQ_GPIO);
|
||||
gpio_free(RX51_WL1251_POWER_GPIO);
|
||||
error:
|
||||
printk(KERN_ERR "wl1251 board initialisation failed\n");
|
||||
wl1251_pdata.set_power = NULL;
|
||||
wl1251_pdata.power_gpio = -1;
|
||||
|
||||
/*
|
||||
* Now rx51_peripherals_spi_board_info[1].irq is zero and
|
||||
|
@ -825,8 +825,8 @@ b_epilogue:
|
||||
break;
|
||||
case BPF_S_ANC_RXHASH:
|
||||
ctx->seen |= SEEN_SKB;
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
|
||||
off = offsetof(struct sk_buff, rxhash);
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
|
||||
off = offsetof(struct sk_buff, hash);
|
||||
emit(ARM_LDR_I(r_A, r_skb, off), ctx);
|
||||
break;
|
||||
case BPF_S_ANC_VLAN_TAG:
|
||||
@ -925,6 +925,7 @@ void bpf_jit_compile(struct sk_filter *fp)
|
||||
bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
|
||||
|
||||
fp->bpf_func = (void *)ctx.target;
|
||||
fp->jited = 1;
|
||||
out:
|
||||
kfree(ctx.offsets);
|
||||
return;
|
||||
@ -932,7 +933,7 @@ out:
|
||||
|
||||
void bpf_jit_free(struct sk_filter *fp)
|
||||
{
|
||||
if (fp->bpf_func != sk_run_filter)
|
||||
if (fp->jited)
|
||||
module_free(NULL, fp->bpf_func);
|
||||
kfree(fp);
|
||||
}
|
||||
|
@ -390,9 +390,9 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
|
||||
mark));
|
||||
break;
|
||||
case BPF_S_ANC_RXHASH:
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
|
||||
PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
|
||||
rxhash));
|
||||
hash));
|
||||
break;
|
||||
case BPF_S_ANC_VLAN_TAG:
|
||||
case BPF_S_ANC_VLAN_TAG_PRESENT:
|
||||
@ -689,6 +689,7 @@ void bpf_jit_compile(struct sk_filter *fp)
|
||||
((u64 *)image)[0] = (u64)code_base;
|
||||
((u64 *)image)[1] = local_paca->kernel_toc;
|
||||
fp->bpf_func = (void *)image;
|
||||
fp->jited = 1;
|
||||
}
|
||||
out:
|
||||
kfree(addrs);
|
||||
@ -697,7 +698,7 @@ out:
|
||||
|
||||
void bpf_jit_free(struct sk_filter *fp)
|
||||
{
|
||||
if (fp->bpf_func != sk_run_filter)
|
||||
if (fp->jited)
|
||||
module_free(NULL, fp->bpf_func);
|
||||
kfree(fp);
|
||||
}
|
||||
|
@ -737,10 +737,10 @@ call_fn: /* lg %r1,<d(function)>(%r13) */
|
||||
/* icm %r5,3,<d(type)>(%r1) */
|
||||
EMIT4_DISP(0xbf531000, offsetof(struct net_device, type));
|
||||
break;
|
||||
case BPF_S_ANC_RXHASH: /* A = skb->rxhash */
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
|
||||
/* l %r5,<d(rxhash)>(%r2) */
|
||||
EMIT4_DISP(0x58502000, offsetof(struct sk_buff, rxhash));
|
||||
case BPF_S_ANC_RXHASH: /* A = skb->hash */
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
|
||||
/* l %r5,<d(hash)>(%r2) */
|
||||
EMIT4_DISP(0x58502000, offsetof(struct sk_buff, hash));
|
||||
break;
|
||||
case BPF_S_ANC_VLAN_TAG:
|
||||
case BPF_S_ANC_VLAN_TAG_PRESENT:
|
||||
@ -877,6 +877,7 @@ void bpf_jit_compile(struct sk_filter *fp)
|
||||
if (jit.start) {
|
||||
set_memory_ro((unsigned long)header, header->pages);
|
||||
fp->bpf_func = (void *) jit.start;
|
||||
fp->jited = 1;
|
||||
}
|
||||
out:
|
||||
kfree(addrs);
|
||||
@ -887,10 +888,12 @@ void bpf_jit_free(struct sk_filter *fp)
|
||||
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
|
||||
struct bpf_binary_header *header = (void *)addr;
|
||||
|
||||
if (fp->bpf_func == sk_run_filter)
|
||||
if (!fp->jited)
|
||||
goto free_filter;
|
||||
|
||||
set_memory_rw(addr, header->pages);
|
||||
module_free(NULL, header);
|
||||
|
||||
free_filter:
|
||||
kfree(fp);
|
||||
}
|
||||
|
@ -618,7 +618,7 @@ void bpf_jit_compile(struct sk_filter *fp)
|
||||
emit_load16(r_A, struct net_device, type, r_A);
|
||||
break;
|
||||
case BPF_S_ANC_RXHASH:
|
||||
emit_skb_load32(rxhash, r_A);
|
||||
emit_skb_load32(hash, r_A);
|
||||
break;
|
||||
case BPF_S_ANC_VLAN_TAG:
|
||||
case BPF_S_ANC_VLAN_TAG_PRESENT:
|
||||
@ -809,6 +809,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
|
||||
if (image) {
|
||||
bpf_flush_icache(image, image + proglen);
|
||||
fp->bpf_func = (void *)image;
|
||||
fp->jited = 1;
|
||||
}
|
||||
out:
|
||||
kfree(addrs);
|
||||
@ -817,7 +818,7 @@ out:
|
||||
|
||||
void bpf_jit_free(struct sk_filter *fp)
|
||||
{
|
||||
if (fp->bpf_func != sk_run_filter)
|
||||
if (fp->jited)
|
||||
module_free(NULL, fp->bpf_func);
|
||||
kfree(fp);
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
dev_consume_skb_any(skb);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
@ -553,13 +553,13 @@ void bpf_jit_compile(struct sk_filter *fp)
|
||||
}
|
||||
break;
|
||||
case BPF_S_ANC_RXHASH:
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
|
||||
if (is_imm8(offsetof(struct sk_buff, rxhash))) {
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
|
||||
if (is_imm8(offsetof(struct sk_buff, hash))) {
|
||||
/* mov off8(%rdi),%eax */
|
||||
EMIT3(0x8b, 0x47, offsetof(struct sk_buff, rxhash));
|
||||
EMIT3(0x8b, 0x47, offsetof(struct sk_buff, hash));
|
||||
} else {
|
||||
EMIT2(0x8b, 0x87);
|
||||
EMIT(offsetof(struct sk_buff, rxhash), 4);
|
||||
EMIT(offsetof(struct sk_buff, hash), 4);
|
||||
}
|
||||
break;
|
||||
case BPF_S_ANC_QUEUE:
|
||||
@ -772,6 +772,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
|
||||
bpf_flush_icache(header, image + proglen);
|
||||
set_memory_ro((unsigned long)header, header->pages);
|
||||
fp->bpf_func = (void *)image;
|
||||
fp->jited = 1;
|
||||
}
|
||||
out:
|
||||
kfree(addrs);
|
||||
@ -791,7 +792,7 @@ static void bpf_jit_free_deferred(struct work_struct *work)
|
||||
|
||||
void bpf_jit_free(struct sk_filter *fp)
|
||||
{
|
||||
if (fp->bpf_func != sk_run_filter) {
|
||||
if (fp->jited) {
|
||||
INIT_WORK(&fp->work, bpf_jit_free_deferred);
|
||||
schedule_work(&fp->work);
|
||||
} else {
|
||||
|
@ -435,9 +435,9 @@ static inline uint64_t blkg_stat_read(struct blkg_stat *stat)
|
||||
uint64_t v;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_bh(&stat->syncp);
|
||||
start = u64_stats_fetch_begin_irq(&stat->syncp);
|
||||
v = stat->cnt;
|
||||
} while (u64_stats_fetch_retry_bh(&stat->syncp, start));
|
||||
} while (u64_stats_fetch_retry_irq(&stat->syncp, start));
|
||||
|
||||
return v;
|
||||
}
|
||||
@ -508,9 +508,9 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat)
|
||||
struct blkg_rwstat tmp;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_bh(&rwstat->syncp);
|
||||
start = u64_stats_fetch_begin_irq(&rwstat->syncp);
|
||||
tmp = *rwstat;
|
||||
} while (u64_stats_fetch_retry_bh(&rwstat->syncp, start));
|
||||
} while (u64_stats_fetch_retry_irq(&rwstat->syncp, start));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
@ -1925,7 +1925,7 @@ static int ucode_init(loader_block *lb, amb_dev *dev)
|
||||
const struct firmware *fw;
|
||||
unsigned long start_address;
|
||||
const struct ihex_binrec *rec;
|
||||
const char *errmsg = 0;
|
||||
const char *errmsg = NULL;
|
||||
int res;
|
||||
|
||||
res = request_ihex_firmware(&fw, "atmsar11.fw", &dev->pci_dev->dev);
|
||||
|
@ -736,8 +736,8 @@ static void process_txdone_queue (struct fs_dev *dev, struct queue *q)
|
||||
|
||||
skb = td->skb;
|
||||
if (skb == FS_VCC (ATM_SKB(skb)->vcc)->last_skb) {
|
||||
wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait);
|
||||
FS_VCC (ATM_SKB(skb)->vcc)->last_skb = NULL;
|
||||
wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait);
|
||||
}
|
||||
td->dev->ntxpckts--;
|
||||
|
||||
@ -1123,7 +1123,7 @@ static void fs_close(struct atm_vcc *atm_vcc)
|
||||
this sleep_on, we'll lose any reference to these packets. Memory leak!
|
||||
On the other hand, it's awfully convenient that we can abort a "close" that
|
||||
is taking too long. Maybe just use non-interruptible sleep on? -- REW */
|
||||
interruptible_sleep_on (& vcc->close_wait);
|
||||
wait_event_interruptible(vcc->close_wait, !vcc->last_skb);
|
||||
}
|
||||
|
||||
txtp = &atm_vcc->qos.txtp;
|
||||
@ -2000,7 +2000,7 @@ static void firestream_remove_one(struct pci_dev *pdev)
|
||||
|
||||
fs_dprintk (FS_DEBUG_CLEANUP, "Freeing irq%d.\n", dev->irq);
|
||||
free_irq (dev->irq, dev);
|
||||
del_timer (&dev->timer);
|
||||
del_timer_sync (&dev->timer);
|
||||
|
||||
atm_dev_deregister(dev->atm_dev);
|
||||
free_queue (dev, &dev->hp_txq);
|
||||
|
@ -368,9 +368,9 @@ EXPORT_SYMBOL(idt77105_init);
|
||||
|
||||
static void __exit idt77105_exit(void)
|
||||
{
|
||||
/* turn off timers */
|
||||
del_timer(&stats_timer);
|
||||
del_timer(&restart_timer);
|
||||
/* turn off timers */
|
||||
del_timer_sync(&stats_timer);
|
||||
del_timer_sync(&restart_timer);
|
||||
}
|
||||
|
||||
module_exit(idt77105_exit);
|
||||
|
@ -639,9 +639,9 @@ static int ns_init_card(int i, struct pci_dev *pcidev)
|
||||
card->hbnr.init = NUM_HB;
|
||||
card->hbnr.max = MAX_HB;
|
||||
|
||||
card->sm_handle = 0x00000000;
|
||||
card->sm_handle = NULL;
|
||||
card->sm_addr = 0x00000000;
|
||||
card->lg_handle = 0x00000000;
|
||||
card->lg_handle = NULL;
|
||||
card->lg_addr = 0x00000000;
|
||||
|
||||
card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */
|
||||
@ -979,7 +979,7 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
|
||||
addr2 = card->sm_addr;
|
||||
handle2 = card->sm_handle;
|
||||
card->sm_addr = 0x00000000;
|
||||
card->sm_handle = 0x00000000;
|
||||
card->sm_handle = NULL;
|
||||
} else { /* (!sm_addr) */
|
||||
|
||||
card->sm_addr = addr1;
|
||||
@ -993,7 +993,7 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
|
||||
addr2 = card->lg_addr;
|
||||
handle2 = card->lg_handle;
|
||||
card->lg_addr = 0x00000000;
|
||||
card->lg_handle = 0x00000000;
|
||||
card->lg_handle = NULL;
|
||||
} else { /* (!lg_addr) */
|
||||
|
||||
card->lg_addr = addr1;
|
||||
@ -1739,10 +1739,10 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
|
||||
}
|
||||
|
||||
scq->full = 1;
|
||||
spin_unlock_irqrestore(&scq->lock, flags);
|
||||
interruptible_sleep_on_timeout(&scq->scqfull_waitq,
|
||||
SCQFULL_TIMEOUT);
|
||||
spin_lock_irqsave(&scq->lock, flags);
|
||||
wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
|
||||
scq->tail != scq->next,
|
||||
scq->lock,
|
||||
SCQFULL_TIMEOUT);
|
||||
|
||||
if (scq->full) {
|
||||
spin_unlock_irqrestore(&scq->lock, flags);
|
||||
@ -1789,10 +1789,10 @@ static int push_scqe(ns_dev * card, vc_map * vc, scq_info * scq, ns_scqe * tbd,
|
||||
scq->full = 1;
|
||||
if (has_run++)
|
||||
break;
|
||||
spin_unlock_irqrestore(&scq->lock, flags);
|
||||
interruptible_sleep_on_timeout(&scq->scqfull_waitq,
|
||||
SCQFULL_TIMEOUT);
|
||||
spin_lock_irqsave(&scq->lock, flags);
|
||||
wait_event_interruptible_lock_irq_timeout(scq->scqfull_waitq,
|
||||
scq->tail != scq->next,
|
||||
scq->lock,
|
||||
SCQFULL_TIMEOUT);
|
||||
}
|
||||
|
||||
if (!scq->full) {
|
||||
|
@ -760,7 +760,7 @@ static irqreturn_t solos_irq(int irq, void *dev_id)
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
void solos_bh(unsigned long card_arg)
|
||||
static void solos_bh(unsigned long card_arg)
|
||||
{
|
||||
struct solos_card *card = (void *)card_arg;
|
||||
uint32_t card_flags;
|
||||
|
@ -218,7 +218,14 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC)
|
||||
chip->to_irq = bcma_gpio_to_irq;
|
||||
#endif
|
||||
chip->ngpio = 16;
|
||||
switch (cc->core->bus->chipinfo.id) {
|
||||
case BCMA_CHIP_ID_BCM5357:
|
||||
chip->ngpio = 32;
|
||||
break;
|
||||
default:
|
||||
chip->ngpio = 16;
|
||||
}
|
||||
|
||||
/* There is just one SoC in one device and its GPIO addresses should be
|
||||
* deterministic to address them more easily. The other buses could get
|
||||
* a random base number. */
|
||||
|
@ -62,50 +62,54 @@ static const struct usb_device_id ath3k_table[] = {
|
||||
{ USB_DEVICE(0x0CF3, 0x3000) },
|
||||
|
||||
/* Atheros AR3011 with sflash firmware*/
|
||||
{ USB_DEVICE(0x0489, 0xE027) },
|
||||
{ USB_DEVICE(0x0489, 0xE03D) },
|
||||
{ USB_DEVICE(0x0930, 0x0215) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3002) },
|
||||
{ USB_DEVICE(0x0CF3, 0xE019) },
|
||||
{ USB_DEVICE(0x13d3, 0x3304) },
|
||||
{ USB_DEVICE(0x0930, 0x0215) },
|
||||
{ USB_DEVICE(0x0489, 0xE03D) },
|
||||
{ USB_DEVICE(0x0489, 0xE027) },
|
||||
|
||||
/* Atheros AR9285 Malbec with sflash firmware */
|
||||
{ USB_DEVICE(0x03F0, 0x311D) },
|
||||
|
||||
/* Atheros AR3012 with sflash firmware*/
|
||||
{ USB_DEVICE(0x0CF3, 0x0036) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3004) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3008) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
||||
{ USB_DEVICE(0x0CF3, 0x817a) },
|
||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||
{ USB_DEVICE(0x0489, 0xe04d) },
|
||||
{ USB_DEVICE(0x0489, 0xe04e) },
|
||||
{ USB_DEVICE(0x0489, 0xe057) },
|
||||
{ USB_DEVICE(0x0489, 0xe056) },
|
||||
{ USB_DEVICE(0x0489, 0xe05f) },
|
||||
{ USB_DEVICE(0x04c5, 0x1330) },
|
||||
{ USB_DEVICE(0x04CA, 0x3004) },
|
||||
{ USB_DEVICE(0x04CA, 0x3005) },
|
||||
{ USB_DEVICE(0x04CA, 0x3006) },
|
||||
{ USB_DEVICE(0x04CA, 0x3008) },
|
||||
{ USB_DEVICE(0x04CA, 0x300b) },
|
||||
{ USB_DEVICE(0x13d3, 0x3362) },
|
||||
{ USB_DEVICE(0x0CF3, 0xE004) },
|
||||
{ USB_DEVICE(0x0CF3, 0xE005) },
|
||||
{ USB_DEVICE(0x0930, 0x0219) },
|
||||
{ USB_DEVICE(0x0930, 0x0220) },
|
||||
{ USB_DEVICE(0x0489, 0xe057) },
|
||||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x0489, 0xe04e) },
|
||||
{ USB_DEVICE(0x0489, 0xe056) },
|
||||
{ USB_DEVICE(0x0489, 0xe04d) },
|
||||
{ USB_DEVICE(0x04c5, 0x1330) },
|
||||
{ USB_DEVICE(0x13d3, 0x3402) },
|
||||
{ USB_DEVICE(0x0b05, 0x17d0) },
|
||||
{ USB_DEVICE(0x0CF3, 0x0036) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3004) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3005) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3008) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311E) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311F) },
|
||||
{ USB_DEVICE(0x0cf3, 0x3121) },
|
||||
{ USB_DEVICE(0x0CF3, 0x817a) },
|
||||
{ USB_DEVICE(0x0cf3, 0xe003) },
|
||||
{ USB_DEVICE(0x0489, 0xe05f) },
|
||||
{ USB_DEVICE(0x0CF3, 0xE004) },
|
||||
{ USB_DEVICE(0x0CF3, 0xE005) },
|
||||
{ USB_DEVICE(0x13d3, 0x3362) },
|
||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x13d3, 0x3402) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE03C) },
|
||||
{ USB_DEVICE(0x0489, 0xE036) },
|
||||
{ USB_DEVICE(0x0489, 0xE03C) },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
@ -118,36 +122,40 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
|
||||
static const struct usb_device_id ath3k_blist_tbl[] = {
|
||||
|
||||
/* Atheros AR3012 with sflash firmware*/
|
||||
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3006), .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(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
@ -174,10 +182,9 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
||||
}
|
||||
|
||||
memcpy(send_buf, firmware->data, 20);
|
||||
if ((err = usb_control_msg(udev, pipe,
|
||||
USB_REQ_DFU_DNLOAD,
|
||||
USB_TYPE_VENDOR, 0, 0,
|
||||
send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
|
||||
err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR,
|
||||
0, 0, send_buf, 20, USB_CTRL_SET_TIMEOUT);
|
||||
if (err < 0) {
|
||||
BT_ERR("Can't change to loading configuration err");
|
||||
goto error;
|
||||
}
|
||||
@ -360,7 +367,7 @@ static int ath3k_load_patch(struct usb_device *udev)
|
||||
}
|
||||
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
|
||||
fw_version.rom_version);
|
||||
le32_to_cpu(fw_version.rom_version));
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
if (ret < 0) {
|
||||
@ -422,7 +429,7 @@ static int ath3k_load_syscfg(struct usb_device *udev)
|
||||
}
|
||||
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
|
||||
fw_version.rom_version, clk_value, ".dfu");
|
||||
le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
if (ret < 0) {
|
||||
|
@ -131,8 +131,11 @@ static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
|
||||
|
||||
BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
|
||||
|
||||
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
|
||||
return -ENOMEM;
|
||||
if (!urb) {
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
|
||||
|
||||
@ -218,8 +221,11 @@ static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
|
||||
|
||||
BT_DBG("bfusb %p urb %p", data, urb);
|
||||
|
||||
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
|
||||
return -ENOMEM;
|
||||
if (!urb) {
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb = bt_skb_alloc(size, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
|
@ -257,7 +257,8 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
|
||||
ready_bit = XMIT_BUF_ONE_READY;
|
||||
}
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq))))
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
if (bt_cb(skb)->pkt_type & 0x80) {
|
||||
@ -391,7 +392,8 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
|
||||
if (info->rx_skb == NULL) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return;
|
||||
}
|
||||
@ -566,7 +568,8 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
|
||||
/* Ericsson baud rate command */
|
||||
unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };
|
||||
|
||||
if (!(skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return -1;
|
||||
}
|
||||
@ -898,7 +901,7 @@ static void bluecard_release(struct pcmcia_device *link)
|
||||
|
||||
bluecard_close(info);
|
||||
|
||||
del_timer(&(info->timer));
|
||||
del_timer_sync(&(info->timer));
|
||||
|
||||
pcmcia_disable_device(link);
|
||||
}
|
||||
|
@ -193,8 +193,8 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
|
||||
if (!pcmcia_dev_present(info->p_dev))
|
||||
break;
|
||||
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq)))) {
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb) {
|
||||
clear_bit(XMIT_SENDING, &(info->tx_state));
|
||||
break;
|
||||
}
|
||||
@ -238,7 +238,8 @@ static void bt3c_receive(bt3c_info_t *info)
|
||||
if (info->rx_skb == NULL) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return;
|
||||
}
|
||||
|
@ -59,12 +59,13 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||
priv->btmrvl_dev.sendcmdflag = false;
|
||||
priv->adapter->cmd_complete = true;
|
||||
wake_up_interruptible(&priv->adapter->cmd_wait_q);
|
||||
}
|
||||
|
||||
if (hci_opcode_ogf(opcode) == 0x3F) {
|
||||
BT_DBG("vendor event skipped: opcode=%#4.4x", opcode);
|
||||
kfree_skb(skb);
|
||||
return false;
|
||||
if (hci_opcode_ogf(opcode) == 0x3F) {
|
||||
BT_DBG("vendor event skipped: opcode=%#4.4x",
|
||||
opcode);
|
||||
kfree_skb(skb);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,8 @@ static void btuart_write_wakeup(btuart_info_t *info)
|
||||
if (!pcmcia_dev_present(info->p_dev))
|
||||
return;
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq))))
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
/* Send frame */
|
||||
@ -190,7 +191,8 @@ static void btuart_receive(btuart_info_t *info)
|
||||
if (info->rx_skb == NULL) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
return;
|
||||
}
|
||||
|
@ -101,21 +101,24 @@ static const struct usb_device_id btusb_table[] = {
|
||||
{ USB_DEVICE(0x0c10, 0x0000) },
|
||||
|
||||
/* Broadcom BCM20702A0 */
|
||||
{ USB_DEVICE(0x0489, 0xe042) },
|
||||
{ USB_DEVICE(0x04ca, 0x2003) },
|
||||
{ USB_DEVICE(0x0b05, 0x17b5) },
|
||||
{ USB_DEVICE(0x0b05, 0x17cb) },
|
||||
{ USB_DEVICE(0x04ca, 0x2003) },
|
||||
{ USB_DEVICE(0x0489, 0xe042) },
|
||||
{ USB_DEVICE(0x413c, 0x8197) },
|
||||
|
||||
/* Foxconn - Hon Hai */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
|
||||
|
||||
/*Broadcom devices with vendor specific id */
|
||||
/* Broadcom devices with vendor specific id */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
|
||||
|
||||
/* Belkin F8065bf - Broadcom based */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
|
||||
|
||||
/* IMC Networks - Broadcom based */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
@ -129,55 +132,59 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Atheros 3011 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Atheros AR9285 Malbec with sflash firmware */
|
||||
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Atheros 3012 with sflash firmware */
|
||||
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3006), .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(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
|
||||
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||
|
||||
/* Broadcom BCM2045 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
|
||||
|
@ -153,7 +153,8 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
|
||||
if (!pcmcia_dev_present(info->p_dev))
|
||||
return;
|
||||
|
||||
if (!(skb = skb_dequeue(&(info->txq))))
|
||||
skb = skb_dequeue(&(info->txq));
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
/* Send frame */
|
||||
@ -215,13 +216,15 @@ static void dtl1_receive(dtl1_info_t *info)
|
||||
info->hdev->stat.byte_rx++;
|
||||
|
||||
/* Allocate packet */
|
||||
if (info->rx_skb == NULL)
|
||||
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
|
||||
if (info->rx_skb == NULL) {
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!info->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
info->rx_state = RECV_WAIT_NSH;
|
||||
info->rx_count = NSHL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
|
||||
nsh = (nsh_t *)info->rx_skb->data;
|
||||
|
@ -291,7 +291,8 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
|
||||
/* First of all, check for unreliable messages in the queue,
|
||||
since they have priority */
|
||||
|
||||
if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) {
|
||||
skb = skb_dequeue(&bcsp->unrel);
|
||||
if (skb != NULL) {
|
||||
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
kfree_skb(skb);
|
||||
@ -308,16 +309,20 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
|
||||
|
||||
spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
|
||||
|
||||
if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) {
|
||||
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
__skb_queue_tail(&bcsp->unack, skb);
|
||||
mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
|
||||
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
|
||||
return nskb;
|
||||
} else {
|
||||
skb_queue_head(&bcsp->rel, skb);
|
||||
BT_ERR("Could not dequeue pkt because alloc_skb failed");
|
||||
if (bcsp->unack.qlen < BCSP_TXWINSIZE) {
|
||||
skb = skb_dequeue(&bcsp->rel);
|
||||
if (skb != NULL) {
|
||||
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len,
|
||||
bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
__skb_queue_tail(&bcsp->unack, skb);
|
||||
mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
|
||||
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
|
||||
return nskb;
|
||||
} else {
|
||||
skb_queue_head(&bcsp->rel, skb);
|
||||
BT_ERR("Could not dequeue pkt because alloc_skb failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,6 +720,9 @@ static int bcsp_open(struct hci_uart *hu)
|
||||
static int bcsp_close(struct hci_uart *hu)
|
||||
{
|
||||
struct bcsp_struct *bcsp = hu->priv;
|
||||
|
||||
del_timer_sync(&bcsp->tbcsp);
|
||||
|
||||
hu->priv = NULL;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
@ -722,7 +730,6 @@ static int bcsp_close(struct hci_uart *hu)
|
||||
skb_queue_purge(&bcsp->unack);
|
||||
skb_queue_purge(&bcsp->rel);
|
||||
skb_queue_purge(&bcsp->unrel);
|
||||
del_timer(&bcsp->tbcsp);
|
||||
|
||||
kfree(bcsp);
|
||||
return 0;
|
||||
|
@ -206,12 +206,12 @@ static int h5_close(struct hci_uart *hu)
|
||||
{
|
||||
struct h5 *h5 = hu->priv;
|
||||
|
||||
del_timer_sync(&h5->timer);
|
||||
|
||||
skb_queue_purge(&h5->unack);
|
||||
skb_queue_purge(&h5->rel);
|
||||
skb_queue_purge(&h5->unrel);
|
||||
|
||||
del_timer(&h5->timer);
|
||||
|
||||
kfree(h5);
|
||||
|
||||
return 0;
|
||||
@ -673,7 +673,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
|
||||
return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2);
|
||||
}
|
||||
|
||||
if ((skb = skb_dequeue(&h5->unrel)) != NULL) {
|
||||
skb = skb_dequeue(&h5->unrel);
|
||||
if (skb != NULL) {
|
||||
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
|
||||
skb->data, skb->len);
|
||||
if (nskb) {
|
||||
@ -690,7 +691,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
|
||||
if (h5->unack.qlen >= h5->tx_win)
|
||||
goto unlock;
|
||||
|
||||
if ((skb = skb_dequeue(&h5->rel)) != NULL) {
|
||||
skb = skb_dequeue(&h5->rel);
|
||||
if (skb != NULL) {
|
||||
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
|
||||
skb->data, skb->len);
|
||||
if (nskb) {
|
||||
|
@ -271,7 +271,8 @@ static int hci_uart_tty_open(struct tty_struct *tty)
|
||||
if (tty->ops->write == NULL)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
|
||||
hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL);
|
||||
if (!hu) {
|
||||
BT_ERR("Can't allocate control structure");
|
||||
return -ENFILE;
|
||||
}
|
||||
@ -569,7 +570,8 @@ static int __init hci_uart_init(void)
|
||||
hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
|
||||
hci_uart_ldisc.owner = THIS_MODULE;
|
||||
|
||||
if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
|
||||
err = tty_register_ldisc(N_HCI, &hci_uart_ldisc);
|
||||
if (err) {
|
||||
BT_ERR("HCI line discipline registration failed. (%d)", err);
|
||||
return err;
|
||||
}
|
||||
@ -614,7 +616,8 @@ static void __exit hci_uart_exit(void)
|
||||
#endif
|
||||
|
||||
/* Release tty registration of line discipline */
|
||||
if ((err = tty_unregister_ldisc(N_HCI)))
|
||||
err = tty_unregister_ldisc(N_HCI);
|
||||
if (err)
|
||||
BT_ERR("Can't unregister HCI line discipline (%d)", err);
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,7 @@ static const struct file_operations vhci_fops = {
|
||||
static struct miscdevice vhci_miscdev= {
|
||||
.name = "vhci",
|
||||
.fops = &vhci_fops,
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.minor = VHCI_MINOR,
|
||||
};
|
||||
|
||||
static int __init vhci_init(void)
|
||||
@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("devname:vhci");
|
||||
MODULE_ALIAS_MISCDEV(VHCI_MINOR);
|
||||
|
@ -145,7 +145,6 @@ static int cn_call_callback(struct sk_buff *skb)
|
||||
spin_unlock_bh(&dev->cbdev->queue_lock);
|
||||
|
||||
if (cbq != NULL) {
|
||||
err = 0;
|
||||
cbq->callback(msg, nsp);
|
||||
kfree_skb(skb);
|
||||
cn_queue_release_callback(cbq);
|
||||
|
@ -1647,6 +1647,15 @@ static inline int act_open_has_tid(int status)
|
||||
status != CPL_ERR_ARP_MISS;
|
||||
}
|
||||
|
||||
/* Returns whether a CPL status conveys negative advice.
|
||||
*/
|
||||
static int is_neg_adv(unsigned int status)
|
||||
{
|
||||
return status == CPL_ERR_RTX_NEG_ADVICE ||
|
||||
status == CPL_ERR_PERSIST_NEG_ADVICE ||
|
||||
status == CPL_ERR_KEEPALV_NEG_ADVICE;
|
||||
}
|
||||
|
||||
#define ACT_OPEN_RETRY_COUNT 2
|
||||
|
||||
static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
|
||||
@ -1835,7 +1844,7 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid,
|
||||
status, status2errno(status));
|
||||
|
||||
if (status == CPL_ERR_RTX_NEG_ADVICE) {
|
||||
if (is_neg_adv(status)) {
|
||||
printk(KERN_WARNING MOD "Connection problems for atid %u\n",
|
||||
atid);
|
||||
return 0;
|
||||
@ -2265,15 +2274,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether an ABORT_REQ_RSS message is a negative advice.
|
||||
*/
|
||||
static int is_neg_adv_abort(unsigned int status)
|
||||
{
|
||||
return status == CPL_ERR_RTX_NEG_ADVICE ||
|
||||
status == CPL_ERR_PERSIST_NEG_ADVICE;
|
||||
}
|
||||
|
||||
static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct cpl_abort_req_rss *req = cplhdr(skb);
|
||||
@ -2287,7 +2287,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
unsigned int tid = GET_TID(req);
|
||||
|
||||
ep = lookup_tid(t, tid);
|
||||
if (is_neg_adv_abort(req->status)) {
|
||||
if (is_neg_adv(req->status)) {
|
||||
PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
|
||||
ep->hwtid);
|
||||
return 0;
|
||||
@ -3570,7 +3570,7 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
if (is_neg_adv_abort(req->status)) {
|
||||
if (is_neg_adv(req->status)) {
|
||||
PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
|
||||
ep->hwtid);
|
||||
kfree_skb(skb);
|
||||
|
@ -64,6 +64,10 @@ struct uld_ctx {
|
||||
static LIST_HEAD(uld_ctx_list);
|
||||
static DEFINE_MUTEX(dev_mutex);
|
||||
|
||||
#define DB_FC_RESUME_SIZE 64
|
||||
#define DB_FC_RESUME_DELAY 1
|
||||
#define DB_FC_DRAIN_THRESH 0
|
||||
|
||||
static struct dentry *c4iw_debugfs_root;
|
||||
|
||||
struct c4iw_debugfs_data {
|
||||
@ -282,7 +286,7 @@ static const struct file_operations stag_debugfs_fops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static char *db_state_str[] = {"NORMAL", "FLOW_CONTROL", "RECOVERY"};
|
||||
static char *db_state_str[] = {"NORMAL", "FLOW_CONTROL", "RECOVERY", "STOPPED"};
|
||||
|
||||
static int stats_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
@ -311,9 +315,10 @@ static int stats_show(struct seq_file *seq, void *v)
|
||||
seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full);
|
||||
seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty);
|
||||
seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop);
|
||||
seq_printf(seq, " DB State: %s Transitions %llu\n",
|
||||
seq_printf(seq, " DB State: %s Transitions %llu FC Interruptions %llu\n",
|
||||
db_state_str[dev->db_state],
|
||||
dev->rdev.stats.db_state_transitions);
|
||||
dev->rdev.stats.db_state_transitions,
|
||||
dev->rdev.stats.db_fc_interruptions);
|
||||
seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full);
|
||||
seq_printf(seq, "ACT_OFLD_CONN_FAILS: %10llu\n",
|
||||
dev->rdev.stats.act_ofld_conn_fails);
|
||||
@ -643,6 +648,12 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
|
||||
printk(KERN_ERR MOD "error %d initializing ocqp pool\n", err);
|
||||
goto err4;
|
||||
}
|
||||
rdev->status_page = (struct t4_dev_status_page *)
|
||||
__get_free_page(GFP_KERNEL);
|
||||
if (!rdev->status_page) {
|
||||
pr_err(MOD "error allocating status page\n");
|
||||
goto err4;
|
||||
}
|
||||
return 0;
|
||||
err4:
|
||||
c4iw_rqtpool_destroy(rdev);
|
||||
@ -656,6 +667,7 @@ err1:
|
||||
|
||||
static void c4iw_rdev_close(struct c4iw_rdev *rdev)
|
||||
{
|
||||
free_page((unsigned long)rdev->status_page);
|
||||
c4iw_pblpool_destroy(rdev);
|
||||
c4iw_rqtpool_destroy(rdev);
|
||||
c4iw_destroy_resource(&rdev->resource);
|
||||
@ -703,18 +715,6 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
|
||||
pr_info("%s: On-Chip Queues not supported on this device.\n",
|
||||
pci_name(infop->pdev));
|
||||
|
||||
if (!is_t4(infop->adapter_type)) {
|
||||
if (!allow_db_fc_on_t5) {
|
||||
db_fc_threshold = 100000;
|
||||
pr_info("DB Flow Control Disabled.\n");
|
||||
}
|
||||
|
||||
if (!allow_db_coalescing_on_t5) {
|
||||
db_coalescing_threshold = -1;
|
||||
pr_info("DB Coalescing Disabled.\n");
|
||||
}
|
||||
}
|
||||
|
||||
devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
|
||||
if (!devp) {
|
||||
printk(KERN_ERR MOD "Cannot allocate ib device\n");
|
||||
@ -749,6 +749,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
|
||||
spin_lock_init(&devp->lock);
|
||||
mutex_init(&devp->rdev.stats.lock);
|
||||
mutex_init(&devp->db_mutex);
|
||||
INIT_LIST_HEAD(&devp->db_fc_list);
|
||||
|
||||
if (c4iw_debugfs_root) {
|
||||
devp->debugfs_root = debugfs_create_dir(
|
||||
@ -977,13 +978,16 @@ static int disable_qp_db(int id, void *p, void *data)
|
||||
|
||||
static void stop_queues(struct uld_ctx *ctx)
|
||||
{
|
||||
spin_lock_irq(&ctx->dev->lock);
|
||||
if (ctx->dev->db_state == NORMAL) {
|
||||
ctx->dev->rdev.stats.db_state_transitions++;
|
||||
ctx->dev->db_state = FLOW_CONTROL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctx->dev->lock, flags);
|
||||
ctx->dev->rdev.stats.db_state_transitions++;
|
||||
ctx->dev->db_state = STOPPED;
|
||||
if (ctx->dev->rdev.flags & T4_STATUS_PAGE_DISABLED)
|
||||
idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
|
||||
}
|
||||
spin_unlock_irq(&ctx->dev->lock);
|
||||
else
|
||||
ctx->dev->rdev.status_page->db_off = 1;
|
||||
spin_unlock_irqrestore(&ctx->dev->lock, flags);
|
||||
}
|
||||
|
||||
static int enable_qp_db(int id, void *p, void *data)
|
||||
@ -994,15 +998,70 @@ static int enable_qp_db(int id, void *p, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void resume_rc_qp(struct c4iw_qp *qp)
|
||||
{
|
||||
spin_lock(&qp->lock);
|
||||
t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc);
|
||||
qp->wq.sq.wq_pidx_inc = 0;
|
||||
t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc);
|
||||
qp->wq.rq.wq_pidx_inc = 0;
|
||||
spin_unlock(&qp->lock);
|
||||
}
|
||||
|
||||
static void resume_a_chunk(struct uld_ctx *ctx)
|
||||
{
|
||||
int i;
|
||||
struct c4iw_qp *qp;
|
||||
|
||||
for (i = 0; i < DB_FC_RESUME_SIZE; i++) {
|
||||
qp = list_first_entry(&ctx->dev->db_fc_list, struct c4iw_qp,
|
||||
db_fc_entry);
|
||||
list_del_init(&qp->db_fc_entry);
|
||||
resume_rc_qp(qp);
|
||||
if (list_empty(&ctx->dev->db_fc_list))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void resume_queues(struct uld_ctx *ctx)
|
||||
{
|
||||
spin_lock_irq(&ctx->dev->lock);
|
||||
if (ctx->dev->qpcnt <= db_fc_threshold &&
|
||||
ctx->dev->db_state == FLOW_CONTROL) {
|
||||
ctx->dev->db_state = NORMAL;
|
||||
ctx->dev->rdev.stats.db_state_transitions++;
|
||||
idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
|
||||
if (ctx->dev->db_state != STOPPED)
|
||||
goto out;
|
||||
ctx->dev->db_state = FLOW_CONTROL;
|
||||
while (1) {
|
||||
if (list_empty(&ctx->dev->db_fc_list)) {
|
||||
WARN_ON(ctx->dev->db_state != FLOW_CONTROL);
|
||||
ctx->dev->db_state = NORMAL;
|
||||
ctx->dev->rdev.stats.db_state_transitions++;
|
||||
if (ctx->dev->rdev.flags & T4_STATUS_PAGE_DISABLED) {
|
||||
idr_for_each(&ctx->dev->qpidr, enable_qp_db,
|
||||
NULL);
|
||||
} else {
|
||||
ctx->dev->rdev.status_page->db_off = 0;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1)
|
||||
< (ctx->dev->rdev.lldi.dbfifo_int_thresh <<
|
||||
DB_FC_DRAIN_THRESH)) {
|
||||
resume_a_chunk(ctx);
|
||||
}
|
||||
if (!list_empty(&ctx->dev->db_fc_list)) {
|
||||
spin_unlock_irq(&ctx->dev->lock);
|
||||
if (DB_FC_RESUME_DELAY) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(DB_FC_RESUME_DELAY);
|
||||
}
|
||||
spin_lock_irq(&ctx->dev->lock);
|
||||
if (ctx->dev->db_state != FLOW_CONTROL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (ctx->dev->db_state != NORMAL)
|
||||
ctx->dev->rdev.stats.db_fc_interruptions++;
|
||||
spin_unlock_irq(&ctx->dev->lock);
|
||||
}
|
||||
|
||||
@ -1028,12 +1087,12 @@ static int count_qps(int id, void *p, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deref_qps(struct qp_list qp_list)
|
||||
static void deref_qps(struct qp_list *qp_list)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < qp_list.idx; idx++)
|
||||
c4iw_qp_rem_ref(&qp_list.qps[idx]->ibqp);
|
||||
for (idx = 0; idx < qp_list->idx; idx++)
|
||||
c4iw_qp_rem_ref(&qp_list->qps[idx]->ibqp);
|
||||
}
|
||||
|
||||
static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list)
|
||||
@ -1044,17 +1103,22 @@ static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list)
|
||||
for (idx = 0; idx < qp_list->idx; idx++) {
|
||||
struct c4iw_qp *qp = qp_list->qps[idx];
|
||||
|
||||
spin_lock_irq(&qp->rhp->lock);
|
||||
spin_lock(&qp->lock);
|
||||
ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0],
|
||||
qp->wq.sq.qid,
|
||||
t4_sq_host_wq_pidx(&qp->wq),
|
||||
t4_sq_wq_size(&qp->wq));
|
||||
if (ret) {
|
||||
printk(KERN_ERR MOD "%s: Fatal error - "
|
||||
pr_err(KERN_ERR MOD "%s: Fatal error - "
|
||||
"DB overflow recovery failed - "
|
||||
"error syncing SQ qid %u\n",
|
||||
pci_name(ctx->lldi.pdev), qp->wq.sq.qid);
|
||||
spin_unlock(&qp->lock);
|
||||
spin_unlock_irq(&qp->rhp->lock);
|
||||
return;
|
||||
}
|
||||
qp->wq.sq.wq_pidx_inc = 0;
|
||||
|
||||
ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0],
|
||||
qp->wq.rq.qid,
|
||||
@ -1062,12 +1126,17 @@ static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list)
|
||||
t4_rq_wq_size(&qp->wq));
|
||||
|
||||
if (ret) {
|
||||
printk(KERN_ERR MOD "%s: Fatal error - "
|
||||
pr_err(KERN_ERR MOD "%s: Fatal error - "
|
||||
"DB overflow recovery failed - "
|
||||
"error syncing RQ qid %u\n",
|
||||
pci_name(ctx->lldi.pdev), qp->wq.rq.qid);
|
||||
spin_unlock(&qp->lock);
|
||||
spin_unlock_irq(&qp->rhp->lock);
|
||||
return;
|
||||
}
|
||||
qp->wq.rq.wq_pidx_inc = 0;
|
||||
spin_unlock(&qp->lock);
|
||||
spin_unlock_irq(&qp->rhp->lock);
|
||||
|
||||
/* Wait for the dbfifo to drain */
|
||||
while (cxgb4_dbfifo_count(qp->rhp->rdev.lldi.ports[0], 1) > 0) {
|
||||
@ -1083,36 +1152,22 @@ static void recover_queues(struct uld_ctx *ctx)
|
||||
struct qp_list qp_list;
|
||||
int ret;
|
||||
|
||||
/* lock out kernel db ringers */
|
||||
mutex_lock(&ctx->dev->db_mutex);
|
||||
|
||||
/* put all queues in to recovery mode */
|
||||
spin_lock_irq(&ctx->dev->lock);
|
||||
ctx->dev->db_state = RECOVERY;
|
||||
ctx->dev->rdev.stats.db_state_transitions++;
|
||||
idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
|
||||
spin_unlock_irq(&ctx->dev->lock);
|
||||
|
||||
/* slow everybody down */
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(usecs_to_jiffies(1000));
|
||||
|
||||
/* Wait for the dbfifo to completely drain. */
|
||||
while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(usecs_to_jiffies(10));
|
||||
}
|
||||
|
||||
/* flush the SGE contexts */
|
||||
ret = cxgb4_flush_eq_cache(ctx->dev->rdev.lldi.ports[0]);
|
||||
if (ret) {
|
||||
printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n",
|
||||
pci_name(ctx->lldi.pdev));
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Count active queues so we can build a list of queues to recover */
|
||||
spin_lock_irq(&ctx->dev->lock);
|
||||
WARN_ON(ctx->dev->db_state != STOPPED);
|
||||
ctx->dev->db_state = RECOVERY;
|
||||
idr_for_each(&ctx->dev->qpidr, count_qps, &count);
|
||||
|
||||
qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC);
|
||||
@ -1120,7 +1175,7 @@ static void recover_queues(struct uld_ctx *ctx)
|
||||
printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n",
|
||||
pci_name(ctx->lldi.pdev));
|
||||
spin_unlock_irq(&ctx->dev->lock);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
qp_list.idx = 0;
|
||||
|
||||
@ -1133,29 +1188,13 @@ static void recover_queues(struct uld_ctx *ctx)
|
||||
recover_lost_dbs(ctx, &qp_list);
|
||||
|
||||
/* we're almost done! deref the qps and clean up */
|
||||
deref_qps(qp_list);
|
||||
deref_qps(&qp_list);
|
||||
kfree(qp_list.qps);
|
||||
|
||||
/* Wait for the dbfifo to completely drain again */
|
||||
while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(usecs_to_jiffies(10));
|
||||
}
|
||||
|
||||
/* resume the queues */
|
||||
spin_lock_irq(&ctx->dev->lock);
|
||||
if (ctx->dev->qpcnt > db_fc_threshold)
|
||||
ctx->dev->db_state = FLOW_CONTROL;
|
||||
else {
|
||||
ctx->dev->db_state = NORMAL;
|
||||
idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
|
||||
}
|
||||
ctx->dev->rdev.stats.db_state_transitions++;
|
||||
WARN_ON(ctx->dev->db_state != RECOVERY);
|
||||
ctx->dev->db_state = STOPPED;
|
||||
spin_unlock_irq(&ctx->dev->lock);
|
||||
|
||||
out:
|
||||
/* start up kernel db ringers again */
|
||||
mutex_unlock(&ctx->dev->db_mutex);
|
||||
}
|
||||
|
||||
static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
|
||||
@ -1165,9 +1204,7 @@ static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
|
||||
switch (control) {
|
||||
case CXGB4_CONTROL_DB_FULL:
|
||||
stop_queues(ctx);
|
||||
mutex_lock(&ctx->dev->rdev.stats.lock);
|
||||
ctx->dev->rdev.stats.db_full++;
|
||||
mutex_unlock(&ctx->dev->rdev.stats.lock);
|
||||
break;
|
||||
case CXGB4_CONTROL_DB_EMPTY:
|
||||
resume_queues(ctx);
|
||||
|
@ -109,6 +109,7 @@ struct c4iw_dev_ucontext {
|
||||
|
||||
enum c4iw_rdev_flags {
|
||||
T4_FATAL_ERROR = (1<<0),
|
||||
T4_STATUS_PAGE_DISABLED = (1<<1),
|
||||
};
|
||||
|
||||
struct c4iw_stat {
|
||||
@ -130,6 +131,7 @@ struct c4iw_stats {
|
||||
u64 db_empty;
|
||||
u64 db_drop;
|
||||
u64 db_state_transitions;
|
||||
u64 db_fc_interruptions;
|
||||
u64 tcam_full;
|
||||
u64 act_ofld_conn_fails;
|
||||
u64 pas_ofld_conn_fails;
|
||||
@ -150,6 +152,7 @@ struct c4iw_rdev {
|
||||
unsigned long oc_mw_pa;
|
||||
void __iomem *oc_mw_kva;
|
||||
struct c4iw_stats stats;
|
||||
struct t4_dev_status_page *status_page;
|
||||
};
|
||||
|
||||
static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
|
||||
@ -211,7 +214,8 @@ static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev,
|
||||
enum db_state {
|
||||
NORMAL = 0,
|
||||
FLOW_CONTROL = 1,
|
||||
RECOVERY = 2
|
||||
RECOVERY = 2,
|
||||
STOPPED = 3
|
||||
};
|
||||
|
||||
struct c4iw_dev {
|
||||
@ -225,10 +229,10 @@ struct c4iw_dev {
|
||||
struct mutex db_mutex;
|
||||
struct dentry *debugfs_root;
|
||||
enum db_state db_state;
|
||||
int qpcnt;
|
||||
struct idr hwtid_idr;
|
||||
struct idr atid_idr;
|
||||
struct idr stid_idr;
|
||||
struct list_head db_fc_list;
|
||||
};
|
||||
|
||||
static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
|
||||
@ -432,6 +436,7 @@ struct c4iw_qp_attributes {
|
||||
|
||||
struct c4iw_qp {
|
||||
struct ib_qp ibqp;
|
||||
struct list_head db_fc_entry;
|
||||
struct c4iw_dev *rhp;
|
||||
struct c4iw_ep *ep;
|
||||
struct c4iw_qp_attributes attr;
|
||||
|
@ -106,15 +106,56 @@ static struct ib_ucontext *c4iw_alloc_ucontext(struct ib_device *ibdev,
|
||||
{
|
||||
struct c4iw_ucontext *context;
|
||||
struct c4iw_dev *rhp = to_c4iw_dev(ibdev);
|
||||
static int warned;
|
||||
struct c4iw_alloc_ucontext_resp uresp;
|
||||
int ret = 0;
|
||||
struct c4iw_mm_entry *mm = NULL;
|
||||
|
||||
PDBG("%s ibdev %p\n", __func__, ibdev);
|
||||
context = kzalloc(sizeof(*context), GFP_KERNEL);
|
||||
if (!context)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (!context) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
c4iw_init_dev_ucontext(&rhp->rdev, &context->uctx);
|
||||
INIT_LIST_HEAD(&context->mmaps);
|
||||
spin_lock_init(&context->mmap_lock);
|
||||
|
||||
if (udata->outlen < sizeof(uresp)) {
|
||||
if (!warned++)
|
||||
pr_err(MOD "Warning - downlevel libcxgb4 (non-fatal), device status page disabled.");
|
||||
rhp->rdev.flags |= T4_STATUS_PAGE_DISABLED;
|
||||
} else {
|
||||
mm = kmalloc(sizeof(*mm), GFP_KERNEL);
|
||||
if (!mm) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
uresp.status_page_size = PAGE_SIZE;
|
||||
|
||||
spin_lock(&context->mmap_lock);
|
||||
uresp.status_page_key = context->key;
|
||||
context->key += PAGE_SIZE;
|
||||
spin_unlock(&context->mmap_lock);
|
||||
|
||||
ret = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
|
||||
if (ret)
|
||||
goto err_mm;
|
||||
|
||||
mm->key = uresp.status_page_key;
|
||||
mm->addr = virt_to_phys(rhp->rdev.status_page);
|
||||
mm->len = PAGE_SIZE;
|
||||
insert_mmap(context, mm);
|
||||
}
|
||||
return &context->ibucontext;
|
||||
err_mm:
|
||||
kfree(mm);
|
||||
err_free:
|
||||
kfree(context);
|
||||
err:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
|
||||
|
@ -638,6 +638,46 @@ void c4iw_qp_rem_ref(struct ib_qp *qp)
|
||||
wake_up(&(to_c4iw_qp(qp)->wait));
|
||||
}
|
||||
|
||||
static void add_to_fc_list(struct list_head *head, struct list_head *entry)
|
||||
{
|
||||
if (list_empty(entry))
|
||||
list_add_tail(entry, head);
|
||||
}
|
||||
|
||||
static int ring_kernel_sq_db(struct c4iw_qp *qhp, u16 inc)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qhp->rhp->lock, flags);
|
||||
spin_lock(&qhp->lock);
|
||||
if (qhp->rhp->db_state == NORMAL) {
|
||||
t4_ring_sq_db(&qhp->wq, inc);
|
||||
} else {
|
||||
add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
|
||||
qhp->wq.sq.wq_pidx_inc += inc;
|
||||
}
|
||||
spin_unlock(&qhp->lock);
|
||||
spin_unlock_irqrestore(&qhp->rhp->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qhp->rhp->lock, flags);
|
||||
spin_lock(&qhp->lock);
|
||||
if (qhp->rhp->db_state == NORMAL) {
|
||||
t4_ring_rq_db(&qhp->wq, inc);
|
||||
} else {
|
||||
add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
|
||||
qhp->wq.rq.wq_pidx_inc += inc;
|
||||
}
|
||||
spin_unlock(&qhp->lock);
|
||||
spin_unlock_irqrestore(&qhp->rhp->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
struct ib_send_wr **bad_wr)
|
||||
{
|
||||
@ -750,9 +790,13 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
t4_sq_produce(&qhp->wq, len16);
|
||||
idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
|
||||
}
|
||||
if (t4_wq_db_enabled(&qhp->wq))
|
||||
if (!qhp->rhp->rdev.status_page->db_off) {
|
||||
t4_ring_sq_db(&qhp->wq, idx);
|
||||
spin_unlock_irqrestore(&qhp->lock, flag);
|
||||
spin_unlock_irqrestore(&qhp->lock, flag);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&qhp->lock, flag);
|
||||
ring_kernel_sq_db(qhp, idx);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -812,9 +856,13 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
|
||||
wr = wr->next;
|
||||
num_wrs--;
|
||||
}
|
||||
if (t4_wq_db_enabled(&qhp->wq))
|
||||
if (!qhp->rhp->rdev.status_page->db_off) {
|
||||
t4_ring_rq_db(&qhp->wq, idx);
|
||||
spin_unlock_irqrestore(&qhp->lock, flag);
|
||||
spin_unlock_irqrestore(&qhp->lock, flag);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&qhp->lock, flag);
|
||||
ring_kernel_rq_db(qhp, idx);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1200,35 +1248,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the library when the qp has user dbs disabled due to
|
||||
* a DB_FULL condition. This function will single-thread all user
|
||||
* DB rings to avoid overflowing the hw db-fifo.
|
||||
*/
|
||||
static int ring_kernel_db(struct c4iw_qp *qhp, u32 qid, u16 inc)
|
||||
{
|
||||
int delay = db_delay_usecs;
|
||||
|
||||
mutex_lock(&qhp->rhp->db_mutex);
|
||||
do {
|
||||
|
||||
/*
|
||||
* The interrupt threshold is dbfifo_int_thresh << 6. So
|
||||
* make sure we don't cross that and generate an interrupt.
|
||||
*/
|
||||
if (cxgb4_dbfifo_count(qhp->rhp->rdev.lldi.ports[0], 1) <
|
||||
(qhp->rhp->rdev.lldi.dbfifo_int_thresh << 5)) {
|
||||
writel(QID(qid) | PIDX(inc), qhp->wq.db);
|
||||
break;
|
||||
}
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout(usecs_to_jiffies(delay));
|
||||
delay = min(delay << 1, 2000);
|
||||
} while (1);
|
||||
mutex_unlock(&qhp->rhp->db_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
|
||||
enum c4iw_qp_attr_mask mask,
|
||||
struct c4iw_qp_attributes *attrs,
|
||||
@ -1278,11 +1297,11 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
|
||||
}
|
||||
|
||||
if (mask & C4IW_QP_ATTR_SQ_DB) {
|
||||
ret = ring_kernel_db(qhp, qhp->wq.sq.qid, attrs->sq_db_inc);
|
||||
ret = ring_kernel_sq_db(qhp, attrs->sq_db_inc);
|
||||
goto out;
|
||||
}
|
||||
if (mask & C4IW_QP_ATTR_RQ_DB) {
|
||||
ret = ring_kernel_db(qhp, qhp->wq.rq.qid, attrs->rq_db_inc);
|
||||
ret = ring_kernel_rq_db(qhp, attrs->rq_db_inc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1465,14 +1484,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int enable_qp_db(int id, void *p, void *data)
|
||||
{
|
||||
struct c4iw_qp *qp = p;
|
||||
|
||||
t4_enable_wq_db(&qp->wq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c4iw_destroy_qp(struct ib_qp *ib_qp)
|
||||
{
|
||||
struct c4iw_dev *rhp;
|
||||
@ -1490,22 +1501,15 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
|
||||
c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
|
||||
wait_event(qhp->wait, !qhp->ep);
|
||||
|
||||
spin_lock_irq(&rhp->lock);
|
||||
remove_handle_nolock(rhp, &rhp->qpidr, qhp->wq.sq.qid);
|
||||
rhp->qpcnt--;
|
||||
BUG_ON(rhp->qpcnt < 0);
|
||||
if (rhp->qpcnt <= db_fc_threshold && rhp->db_state == FLOW_CONTROL) {
|
||||
rhp->rdev.stats.db_state_transitions++;
|
||||
rhp->db_state = NORMAL;
|
||||
idr_for_each(&rhp->qpidr, enable_qp_db, NULL);
|
||||
}
|
||||
if (db_coalescing_threshold >= 0)
|
||||
if (rhp->qpcnt <= db_coalescing_threshold)
|
||||
cxgb4_enable_db_coalescing(rhp->rdev.lldi.ports[0]);
|
||||
spin_unlock_irq(&rhp->lock);
|
||||
remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
|
||||
atomic_dec(&qhp->refcnt);
|
||||
wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
|
||||
|
||||
spin_lock_irq(&rhp->lock);
|
||||
if (!list_empty(&qhp->db_fc_entry))
|
||||
list_del_init(&qhp->db_fc_entry);
|
||||
spin_unlock_irq(&rhp->lock);
|
||||
|
||||
ucontext = ib_qp->uobject ?
|
||||
to_c4iw_ucontext(ib_qp->uobject->context) : NULL;
|
||||
destroy_qp(&rhp->rdev, &qhp->wq,
|
||||
@ -1516,14 +1520,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disable_qp_db(int id, void *p, void *data)
|
||||
{
|
||||
struct c4iw_qp *qp = p;
|
||||
|
||||
t4_disable_wq_db(&qp->wq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
@ -1610,20 +1606,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
|
||||
init_waitqueue_head(&qhp->wait);
|
||||
atomic_set(&qhp->refcnt, 1);
|
||||
|
||||
spin_lock_irq(&rhp->lock);
|
||||
if (rhp->db_state != NORMAL)
|
||||
t4_disable_wq_db(&qhp->wq);
|
||||
rhp->qpcnt++;
|
||||
if (rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) {
|
||||
rhp->rdev.stats.db_state_transitions++;
|
||||
rhp->db_state = FLOW_CONTROL;
|
||||
idr_for_each(&rhp->qpidr, disable_qp_db, NULL);
|
||||
}
|
||||
if (db_coalescing_threshold >= 0)
|
||||
if (rhp->qpcnt > db_coalescing_threshold)
|
||||
cxgb4_disable_db_coalescing(rhp->rdev.lldi.ports[0]);
|
||||
ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
|
||||
spin_unlock_irq(&rhp->lock);
|
||||
ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
@ -1709,6 +1692,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
|
||||
}
|
||||
qhp->ibqp.qp_num = qhp->wq.sq.qid;
|
||||
init_timer(&(qhp->timer));
|
||||
INIT_LIST_HEAD(&qhp->db_fc_entry);
|
||||
PDBG("%s qhp %p sq_num_entries %d, rq_num_entries %d qpid 0x%0x\n",
|
||||
__func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
|
||||
qhp->wq.sq.qid);
|
||||
|
@ -300,6 +300,7 @@ struct t4_sq {
|
||||
u16 cidx;
|
||||
u16 pidx;
|
||||
u16 wq_pidx;
|
||||
u16 wq_pidx_inc;
|
||||
u16 flags;
|
||||
short flush_cidx;
|
||||
};
|
||||
@ -324,6 +325,7 @@ struct t4_rq {
|
||||
u16 cidx;
|
||||
u16 pidx;
|
||||
u16 wq_pidx;
|
||||
u16 wq_pidx_inc;
|
||||
};
|
||||
|
||||
struct t4_wq {
|
||||
@ -609,3 +611,7 @@ static inline void t4_set_cq_in_error(struct t4_cq *cq)
|
||||
((struct t4_status_page *)&cq->queue[cq->size])->qp_err = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct t4_dev_status_page {
|
||||
u8 db_off;
|
||||
};
|
||||
|
@ -70,4 +70,9 @@ struct c4iw_create_qp_resp {
|
||||
__u32 qid_mask;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
struct c4iw_alloc_ucontext_resp {
|
||||
__u64 status_page_key;
|
||||
__u32 status_page_size;
|
||||
};
|
||||
#endif
|
||||
|
@ -154,7 +154,7 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
|
||||
continue;
|
||||
|
||||
slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
|
||||
if (slave_id >= dev->dev->num_slaves)
|
||||
if (slave_id >= dev->dev->num_vfs + 1)
|
||||
return;
|
||||
tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
|
||||
form_cache_ag = get_cached_alias_guid(dev, port_num,
|
||||
|
@ -61,6 +61,11 @@ struct cm_generic_msg {
|
||||
__be32 remote_comm_id;
|
||||
};
|
||||
|
||||
struct cm_sidr_generic_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
__be32 request_id;
|
||||
};
|
||||
|
||||
struct cm_req_msg {
|
||||
unsigned char unused[0x60];
|
||||
union ib_gid primary_path_sgid;
|
||||
@ -69,28 +74,62 @@ struct cm_req_msg {
|
||||
|
||||
static void set_local_comm_id(struct ib_mad *mad, u32 cm_id)
|
||||
{
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
msg->local_comm_id = cpu_to_be32(cm_id);
|
||||
if (mad->mad_hdr.attr_id == CM_SIDR_REQ_ATTR_ID) {
|
||||
struct cm_sidr_generic_msg *msg =
|
||||
(struct cm_sidr_generic_msg *)mad;
|
||||
msg->request_id = cpu_to_be32(cm_id);
|
||||
} else if (mad->mad_hdr.attr_id == CM_SIDR_REP_ATTR_ID) {
|
||||
pr_err("trying to set local_comm_id in SIDR_REP\n");
|
||||
return;
|
||||
} else {
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
msg->local_comm_id = cpu_to_be32(cm_id);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 get_local_comm_id(struct ib_mad *mad)
|
||||
{
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
|
||||
return be32_to_cpu(msg->local_comm_id);
|
||||
if (mad->mad_hdr.attr_id == CM_SIDR_REQ_ATTR_ID) {
|
||||
struct cm_sidr_generic_msg *msg =
|
||||
(struct cm_sidr_generic_msg *)mad;
|
||||
return be32_to_cpu(msg->request_id);
|
||||
} else if (mad->mad_hdr.attr_id == CM_SIDR_REP_ATTR_ID) {
|
||||
pr_err("trying to set local_comm_id in SIDR_REP\n");
|
||||
return -1;
|
||||
} else {
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
return be32_to_cpu(msg->local_comm_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_remote_comm_id(struct ib_mad *mad, u32 cm_id)
|
||||
{
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
msg->remote_comm_id = cpu_to_be32(cm_id);
|
||||
if (mad->mad_hdr.attr_id == CM_SIDR_REP_ATTR_ID) {
|
||||
struct cm_sidr_generic_msg *msg =
|
||||
(struct cm_sidr_generic_msg *)mad;
|
||||
msg->request_id = cpu_to_be32(cm_id);
|
||||
} else if (mad->mad_hdr.attr_id == CM_SIDR_REQ_ATTR_ID) {
|
||||
pr_err("trying to set remote_comm_id in SIDR_REQ\n");
|
||||
return;
|
||||
} else {
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
msg->remote_comm_id = cpu_to_be32(cm_id);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 get_remote_comm_id(struct ib_mad *mad)
|
||||
{
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
|
||||
return be32_to_cpu(msg->remote_comm_id);
|
||||
if (mad->mad_hdr.attr_id == CM_SIDR_REP_ATTR_ID) {
|
||||
struct cm_sidr_generic_msg *msg =
|
||||
(struct cm_sidr_generic_msg *)mad;
|
||||
return be32_to_cpu(msg->request_id);
|
||||
} else if (mad->mad_hdr.attr_id == CM_SIDR_REQ_ATTR_ID) {
|
||||
pr_err("trying to set remote_comm_id in SIDR_REQ\n");
|
||||
return -1;
|
||||
} else {
|
||||
struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
|
||||
return be32_to_cpu(msg->remote_comm_id);
|
||||
}
|
||||
}
|
||||
|
||||
static union ib_gid gid_from_req_msg(struct ib_device *ibdev, struct ib_mad *mad)
|
||||
@ -282,19 +321,21 @@ int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id
|
||||
u32 sl_cm_id;
|
||||
int pv_cm_id = -1;
|
||||
|
||||
sl_cm_id = get_local_comm_id(mad);
|
||||
|
||||
if (mad->mad_hdr.attr_id == CM_REQ_ATTR_ID ||
|
||||
mad->mad_hdr.attr_id == CM_REP_ATTR_ID) {
|
||||
mad->mad_hdr.attr_id == CM_REP_ATTR_ID ||
|
||||
mad->mad_hdr.attr_id == CM_SIDR_REQ_ATTR_ID) {
|
||||
sl_cm_id = get_local_comm_id(mad);
|
||||
id = id_map_alloc(ibdev, slave_id, sl_cm_id);
|
||||
if (IS_ERR(id)) {
|
||||
mlx4_ib_warn(ibdev, "%s: id{slave: %d, sl_cm_id: 0x%x} Failed to id_map_alloc\n",
|
||||
__func__, slave_id, sl_cm_id);
|
||||
return PTR_ERR(id);
|
||||
}
|
||||
} else if (mad->mad_hdr.attr_id == CM_REJ_ATTR_ID) {
|
||||
} else if (mad->mad_hdr.attr_id == CM_REJ_ATTR_ID ||
|
||||
mad->mad_hdr.attr_id == CM_SIDR_REP_ATTR_ID) {
|
||||
return 0;
|
||||
} else {
|
||||
sl_cm_id = get_local_comm_id(mad);
|
||||
id = id_map_get(ibdev, &pv_cm_id, slave_id, sl_cm_id);
|
||||
}
|
||||
|
||||
@ -315,14 +356,18 @@ int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id
|
||||
}
|
||||
|
||||
int mlx4_ib_demux_cm_handler(struct ib_device *ibdev, int port, int *slave,
|
||||
struct ib_mad *mad)
|
||||
struct ib_mad *mad)
|
||||
{
|
||||
u32 pv_cm_id;
|
||||
struct id_map_entry *id;
|
||||
|
||||
if (mad->mad_hdr.attr_id == CM_REQ_ATTR_ID) {
|
||||
if (mad->mad_hdr.attr_id == CM_REQ_ATTR_ID ||
|
||||
mad->mad_hdr.attr_id == CM_SIDR_REQ_ATTR_ID) {
|
||||
union ib_gid gid;
|
||||
|
||||
if (!slave)
|
||||
return 0;
|
||||
|
||||
gid = gid_from_req_msg(ibdev, mad);
|
||||
*slave = mlx4_ib_find_real_gid(ibdev, port, gid.global.interface_id);
|
||||
if (*slave < 0) {
|
||||
@ -341,7 +386,8 @@ int mlx4_ib_demux_cm_handler(struct ib_device *ibdev, int port, int *slave,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
*slave = id->slave_id;
|
||||
if (slave)
|
||||
*slave = id->slave_id;
|
||||
set_remote_comm_id(mad, id->sl_cm_id);
|
||||
|
||||
if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID)
|
||||
|
@ -564,7 +564,7 @@ static int mlx4_ib_ipoib_csum_ok(__be16 status, __be16 checksum)
|
||||
}
|
||||
|
||||
static int use_tunnel_data(struct mlx4_ib_qp *qp, struct mlx4_ib_cq *cq, struct ib_wc *wc,
|
||||
unsigned tail, struct mlx4_cqe *cqe)
|
||||
unsigned tail, struct mlx4_cqe *cqe, int is_eth)
|
||||
{
|
||||
struct mlx4_ib_proxy_sqp_hdr *hdr;
|
||||
|
||||
@ -574,12 +574,20 @@ static int use_tunnel_data(struct mlx4_ib_qp *qp, struct mlx4_ib_cq *cq, struct
|
||||
DMA_FROM_DEVICE);
|
||||
hdr = (struct mlx4_ib_proxy_sqp_hdr *) (qp->sqp_proxy_rcv[tail].addr);
|
||||
wc->pkey_index = be16_to_cpu(hdr->tun.pkey_index);
|
||||
wc->slid = be16_to_cpu(hdr->tun.slid_mac_47_32);
|
||||
wc->sl = (u8) (be16_to_cpu(hdr->tun.sl_vid) >> 12);
|
||||
wc->src_qp = be32_to_cpu(hdr->tun.flags_src_qp) & 0xFFFFFF;
|
||||
wc->wc_flags |= (hdr->tun.g_ml_path & 0x80) ? (IB_WC_GRH) : 0;
|
||||
wc->dlid_path_bits = 0;
|
||||
|
||||
if (is_eth) {
|
||||
wc->vlan_id = be16_to_cpu(hdr->tun.sl_vid);
|
||||
memcpy(&(wc->smac[0]), (char *)&hdr->tun.mac_31_0, 4);
|
||||
memcpy(&(wc->smac[4]), (char *)&hdr->tun.slid_mac_47_32, 2);
|
||||
wc->wc_flags |= (IB_WC_WITH_VLAN | IB_WC_WITH_SMAC);
|
||||
} else {
|
||||
wc->slid = be16_to_cpu(hdr->tun.slid_mac_47_32);
|
||||
wc->sl = (u8) (be16_to_cpu(hdr->tun.sl_vid) >> 12);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -594,6 +602,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
|
||||
struct mlx4_srq *msrq = NULL;
|
||||
int is_send;
|
||||
int is_error;
|
||||
int is_eth;
|
||||
u32 g_mlpath_rqpn;
|
||||
u16 wqe_ctr;
|
||||
unsigned tail = 0;
|
||||
@ -778,11 +787,15 @@ repoll:
|
||||
break;
|
||||
}
|
||||
|
||||
is_eth = (rdma_port_get_link_layer(wc->qp->device,
|
||||
(*cur_qp)->port) ==
|
||||
IB_LINK_LAYER_ETHERNET);
|
||||
if (mlx4_is_mfunc(to_mdev(cq->ibcq.device)->dev)) {
|
||||
if ((*cur_qp)->mlx4_ib_qp_type &
|
||||
(MLX4_IB_QPT_PROXY_SMI_OWNER |
|
||||
MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI))
|
||||
return use_tunnel_data(*cur_qp, cq, wc, tail, cqe);
|
||||
return use_tunnel_data(*cur_qp, cq, wc, tail,
|
||||
cqe, is_eth);
|
||||
}
|
||||
|
||||
wc->slid = be16_to_cpu(cqe->rlid);
|
||||
@ -793,20 +806,21 @@ repoll:
|
||||
wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
|
||||
wc->wc_flags |= mlx4_ib_ipoib_csum_ok(cqe->status,
|
||||
cqe->checksum) ? IB_WC_IP_CSUM_OK : 0;
|
||||
if (rdma_port_get_link_layer(wc->qp->device,
|
||||
(*cur_qp)->port) == IB_LINK_LAYER_ETHERNET)
|
||||
if (is_eth) {
|
||||
wc->sl = be16_to_cpu(cqe->sl_vid) >> 13;
|
||||
else
|
||||
wc->sl = be16_to_cpu(cqe->sl_vid) >> 12;
|
||||
if (be32_to_cpu(cqe->vlan_my_qpn) & MLX4_CQE_VLAN_PRESENT_MASK) {
|
||||
wc->vlan_id = be16_to_cpu(cqe->sl_vid) &
|
||||
MLX4_CQE_VID_MASK;
|
||||
if (be32_to_cpu(cqe->vlan_my_qpn) &
|
||||
MLX4_CQE_VLAN_PRESENT_MASK) {
|
||||
wc->vlan_id = be16_to_cpu(cqe->sl_vid) &
|
||||
MLX4_CQE_VID_MASK;
|
||||
} else {
|
||||
wc->vlan_id = 0xffff;
|
||||
}
|
||||
memcpy(wc->smac, cqe->smac, ETH_ALEN);
|
||||
wc->wc_flags |= (IB_WC_WITH_VLAN | IB_WC_WITH_SMAC);
|
||||
} else {
|
||||
wc->sl = be16_to_cpu(cqe->sl_vid) >> 12;
|
||||
wc->vlan_id = 0xffff;
|
||||
}
|
||||
wc->wc_flags |= IB_WC_WITH_VLAN;
|
||||
memcpy(wc->smac, cqe->smac, ETH_ALEN);
|
||||
wc->wc_flags |= IB_WC_WITH_SMAC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -467,6 +467,7 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
|
||||
int ret = 0;
|
||||
u16 tun_pkey_ix;
|
||||
u16 cached_pkey;
|
||||
u8 is_eth = dev->dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH;
|
||||
|
||||
if (dest_qpt > IB_QPT_GSI)
|
||||
return -EINVAL;
|
||||
@ -509,6 +510,10 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
|
||||
* The driver will set the force loopback bit in post_send */
|
||||
memset(&attr, 0, sizeof attr);
|
||||
attr.port_num = port;
|
||||
if (is_eth) {
|
||||
memcpy(&attr.grh.dgid.raw[0], &grh->dgid.raw[0], 16);
|
||||
attr.ah_flags = IB_AH_GRH;
|
||||
}
|
||||
ah = ib_create_ah(tun_ctx->pd, &attr);
|
||||
if (IS_ERR(ah))
|
||||
return -ENOMEM;
|
||||
@ -540,11 +545,36 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
|
||||
|
||||
/* adjust tunnel data */
|
||||
tun_mad->hdr.pkey_index = cpu_to_be16(tun_pkey_ix);
|
||||
tun_mad->hdr.sl_vid = cpu_to_be16(((u16)(wc->sl)) << 12);
|
||||
tun_mad->hdr.slid_mac_47_32 = cpu_to_be16(wc->slid);
|
||||
tun_mad->hdr.flags_src_qp = cpu_to_be32(wc->src_qp & 0xFFFFFF);
|
||||
tun_mad->hdr.g_ml_path = (grh && (wc->wc_flags & IB_WC_GRH)) ? 0x80 : 0;
|
||||
|
||||
if (is_eth) {
|
||||
u16 vlan = 0;
|
||||
if (mlx4_get_slave_default_vlan(dev->dev, port, slave, &vlan,
|
||||
NULL)) {
|
||||
/* VST mode */
|
||||
if (vlan != wc->vlan_id)
|
||||
/* Packet vlan is not the VST-assigned vlan.
|
||||
* Drop the packet.
|
||||
*/
|
||||
goto out;
|
||||
else
|
||||
/* Remove the vlan tag before forwarding
|
||||
* the packet to the VF.
|
||||
*/
|
||||
vlan = 0xffff;
|
||||
} else {
|
||||
vlan = wc->vlan_id;
|
||||
}
|
||||
|
||||
tun_mad->hdr.sl_vid = cpu_to_be16(vlan);
|
||||
memcpy((char *)&tun_mad->hdr.mac_31_0, &(wc->smac[0]), 4);
|
||||
memcpy((char *)&tun_mad->hdr.slid_mac_47_32, &(wc->smac[4]), 2);
|
||||
} else {
|
||||
tun_mad->hdr.sl_vid = cpu_to_be16(((u16)(wc->sl)) << 12);
|
||||
tun_mad->hdr.slid_mac_47_32 = cpu_to_be16(wc->slid);
|
||||
}
|
||||
|
||||
ib_dma_sync_single_for_device(&dev->ib_dev,
|
||||
tun_qp->tx_ring[tun_tx_ix].buf.map,
|
||||
sizeof (struct mlx4_rcv_tunnel_mad),
|
||||
@ -580,6 +610,41 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
|
||||
int err;
|
||||
int slave;
|
||||
u8 *slave_id;
|
||||
int is_eth = 0;
|
||||
|
||||
if (rdma_port_get_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND)
|
||||
is_eth = 0;
|
||||
else
|
||||
is_eth = 1;
|
||||
|
||||
if (is_eth) {
|
||||
if (!(wc->wc_flags & IB_WC_GRH)) {
|
||||
mlx4_ib_warn(ibdev, "RoCE grh not present.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_CM) {
|
||||
mlx4_ib_warn(ibdev, "RoCE mgmt class is not CM\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mlx4_get_slave_from_roce_gid(dev->dev, port, grh->dgid.raw, &slave)) {
|
||||
mlx4_ib_warn(ibdev, "failed matching grh\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
if (slave >= dev->dev->caps.sqp_demux) {
|
||||
mlx4_ib_warn(ibdev, "slave id: %d is bigger than allowed:%d\n",
|
||||
slave, dev->dev->caps.sqp_demux);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (mlx4_ib_demux_cm_handler(ibdev, port, NULL, mad))
|
||||
return 0;
|
||||
|
||||
err = mlx4_ib_send_to_slave(dev, slave, port, wc->qp->qp_type, wc, grh, mad);
|
||||
if (err)
|
||||
pr_debug("failed sending to slave %d via tunnel qp (%d)\n",
|
||||
slave, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initially assume that this mad is for us */
|
||||
slave = mlx4_master_func_num(dev->dev);
|
||||
@ -1076,8 +1141,9 @@ static int is_proxy_qp0(struct mlx4_ib_dev *dev, int qpn, int slave)
|
||||
|
||||
|
||||
int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
|
||||
enum ib_qp_type dest_qpt, u16 pkey_index, u32 remote_qpn,
|
||||
u32 qkey, struct ib_ah_attr *attr, struct ib_mad *mad)
|
||||
enum ib_qp_type dest_qpt, u16 pkey_index,
|
||||
u32 remote_qpn, u32 qkey, struct ib_ah_attr *attr,
|
||||
u8 *s_mac, struct ib_mad *mad)
|
||||
{
|
||||
struct ib_sge list;
|
||||
struct ib_send_wr wr, *bad_wr;
|
||||
@ -1166,6 +1232,9 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
|
||||
wr.num_sge = 1;
|
||||
wr.opcode = IB_WR_SEND;
|
||||
wr.send_flags = IB_SEND_SIGNALED;
|
||||
if (s_mac)
|
||||
memcpy(to_mah(ah)->av.eth.s_mac, s_mac, 6);
|
||||
|
||||
|
||||
ret = ib_post_send(send_qp, &wr, &bad_wr);
|
||||
out:
|
||||
@ -1174,6 +1243,22 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_slave_base_gid_ix(struct mlx4_ib_dev *dev, int slave, int port)
|
||||
{
|
||||
if (rdma_port_get_link_layer(&dev->ib_dev, port) == IB_LINK_LAYER_INFINIBAND)
|
||||
return slave;
|
||||
return mlx4_get_base_gid_ix(dev->dev, slave, port);
|
||||
}
|
||||
|
||||
static void fill_in_real_sgid_index(struct mlx4_ib_dev *dev, int slave, int port,
|
||||
struct ib_ah_attr *ah_attr)
|
||||
{
|
||||
if (rdma_port_get_link_layer(&dev->ib_dev, port) == IB_LINK_LAYER_INFINIBAND)
|
||||
ah_attr->grh.sgid_index = slave;
|
||||
else
|
||||
ah_attr->grh.sgid_index += get_slave_base_gid_ix(dev, slave, port);
|
||||
}
|
||||
|
||||
static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc *wc)
|
||||
{
|
||||
struct mlx4_ib_dev *dev = to_mdev(ctx->ib_dev);
|
||||
@ -1184,6 +1269,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
|
||||
struct ib_ah_attr ah_attr;
|
||||
u8 *slave_id;
|
||||
int slave;
|
||||
int port;
|
||||
|
||||
/* Get slave that sent this packet */
|
||||
if (wc->src_qp < dev->dev->phys_caps.base_proxy_sqpn ||
|
||||
@ -1260,12 +1346,18 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
|
||||
memcpy(&ah.av, &tunnel->hdr.av, sizeof (struct mlx4_av));
|
||||
ah.ibah.device = ctx->ib_dev;
|
||||
mlx4_ib_query_ah(&ah.ibah, &ah_attr);
|
||||
if ((ah_attr.ah_flags & IB_AH_GRH) &&
|
||||
(ah_attr.grh.sgid_index != slave)) {
|
||||
mlx4_ib_warn(ctx->ib_dev, "slave:%d accessed invalid sgid_index:%d\n",
|
||||
slave, ah_attr.grh.sgid_index);
|
||||
if (ah_attr.ah_flags & IB_AH_GRH)
|
||||
fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr);
|
||||
|
||||
port = mlx4_slave_convert_port(dev->dev, slave, ah_attr.port_num);
|
||||
if (port < 0)
|
||||
return;
|
||||
}
|
||||
ah_attr.port_num = port;
|
||||
memcpy(ah_attr.dmac, tunnel->hdr.mac, 6);
|
||||
ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan);
|
||||
/* if slave have default vlan use it */
|
||||
mlx4_get_slave_default_vlan(dev->dev, ctx->port, slave,
|
||||
&ah_attr.vlan_id, &ah_attr.sl);
|
||||
|
||||
mlx4_ib_send_to_wire(dev, slave, ctx->port,
|
||||
is_proxy_qp0(dev, wc->src_qp, slave) ?
|
||||
@ -1273,7 +1365,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
|
||||
be16_to_cpu(tunnel->hdr.pkey_index),
|
||||
be32_to_cpu(tunnel->hdr.remote_qpn),
|
||||
be32_to_cpu(tunnel->hdr.qkey),
|
||||
&ah_attr, &tunnel->mad);
|
||||
&ah_attr, wc->smac, &tunnel->mad);
|
||||
}
|
||||
|
||||
static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
|
||||
@ -1850,7 +1942,15 @@ static int mlx4_ib_alloc_demux_ctx(struct mlx4_ib_dev *dev,
|
||||
ctx->port = port;
|
||||
ctx->ib_dev = &dev->ib_dev;
|
||||
|
||||
for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
|
||||
for (i = 0;
|
||||
i < min(dev->dev->caps.sqp_demux, (u16)(dev->dev->num_vfs + 1));
|
||||
i++) {
|
||||
struct mlx4_active_ports actv_ports =
|
||||
mlx4_get_active_ports(dev->dev, i);
|
||||
|
||||
if (!test_bit(port - 1, actv_ports.ports))
|
||||
continue;
|
||||
|
||||
ret = alloc_pv_object(dev, i, port, &ctx->tun[i]);
|
||||
if (ret) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -1546,7 +1546,7 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev,
|
||||
iboe = &ibdev->iboe;
|
||||
spin_lock(&iboe->lock);
|
||||
|
||||
for (port = 1; port <= MLX4_MAX_PORTS; ++port)
|
||||
for (port = 1; port <= ibdev->dev->caps.num_ports; ++port)
|
||||
if ((netif_is_bond_master(real_dev) &&
|
||||
(real_dev == iboe->masters[port - 1])) ||
|
||||
(!netif_is_bond_master(real_dev) &&
|
||||
@ -1569,14 +1569,14 @@ static u8 mlx4_ib_get_dev_port(struct net_device *dev,
|
||||
|
||||
iboe = &ibdev->iboe;
|
||||
|
||||
for (port = 1; port <= MLX4_MAX_PORTS; ++port)
|
||||
for (port = 1; port <= ibdev->dev->caps.num_ports; ++port)
|
||||
if ((netif_is_bond_master(real_dev) &&
|
||||
(real_dev == iboe->masters[port - 1])) ||
|
||||
(!netif_is_bond_master(real_dev) &&
|
||||
(real_dev == iboe->netdevs[port - 1])))
|
||||
break;
|
||||
|
||||
if ((port == 0) || (port > MLX4_MAX_PORTS))
|
||||
if ((port == 0) || (port > ibdev->dev->caps.num_ports))
|
||||
return 0;
|
||||
else
|
||||
return port;
|
||||
@ -1626,7 +1626,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev,
|
||||
union ib_gid gid;
|
||||
|
||||
|
||||
if ((port == 0) || (port > MLX4_MAX_PORTS))
|
||||
if ((port == 0) || (port > ibdev->dev->caps.num_ports))
|
||||
return;
|
||||
|
||||
/* IPv4 gids */
|
||||
@ -1888,14 +1888,6 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
|
||||
|
||||
pr_info_once("%s", mlx4_ib_version);
|
||||
|
||||
mlx4_foreach_non_ib_transport_port(i, dev)
|
||||
num_ports++;
|
||||
|
||||
if (mlx4_is_mfunc(dev) && num_ports) {
|
||||
dev_err(&dev->pdev->dev, "RoCE is not supported over SRIOV as yet\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
num_ports = 0;
|
||||
mlx4_foreach_ib_transport_port(i, dev)
|
||||
num_ports++;
|
||||
@ -2331,17 +2323,24 @@ static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init)
|
||||
struct mlx4_dev *dev = ibdev->dev;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct mlx4_active_ports actv_ports;
|
||||
unsigned int ports;
|
||||
unsigned int first_port;
|
||||
|
||||
if (!mlx4_is_master(dev))
|
||||
return;
|
||||
|
||||
dm = kcalloc(dev->caps.num_ports, sizeof *dm, GFP_ATOMIC);
|
||||
actv_ports = mlx4_get_active_ports(dev, slave);
|
||||
ports = bitmap_weight(actv_ports.ports, dev->caps.num_ports);
|
||||
first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports);
|
||||
|
||||
dm = kcalloc(ports, sizeof(*dm), GFP_ATOMIC);
|
||||
if (!dm) {
|
||||
pr_err("failed to allocate memory for tunneling qp update\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->caps.num_ports; i++) {
|
||||
for (i = 0; i < ports; i++) {
|
||||
dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC);
|
||||
if (!dm[i]) {
|
||||
pr_err("failed to allocate memory for tunneling qp update work struct\n");
|
||||
@ -2353,9 +2352,9 @@ static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init)
|
||||
}
|
||||
}
|
||||
/* initialize or tear down tunnel QPs for the slave */
|
||||
for (i = 0; i < dev->caps.num_ports; i++) {
|
||||
for (i = 0; i < ports; i++) {
|
||||
INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work);
|
||||
dm[i]->port = i + 1;
|
||||
dm[i]->port = first_port + i + 1;
|
||||
dm[i]->slave = slave;
|
||||
dm[i]->do_init = do_init;
|
||||
dm[i]->dev = ibdev;
|
||||
|
@ -215,8 +215,9 @@ static int send_mad_to_wire(struct mlx4_ib_demux_ctx *ctx, struct ib_mad *mad)
|
||||
}
|
||||
mlx4_ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
|
||||
spin_unlock(&dev->sm_lock);
|
||||
return mlx4_ib_send_to_wire(dev, mlx4_master_func_num(dev->dev), ctx->port,
|
||||
IB_QPT_GSI, 0, 1, IB_QP1_QKEY, &ah_attr, mad);
|
||||
return mlx4_ib_send_to_wire(dev, mlx4_master_func_num(dev->dev),
|
||||
ctx->port, IB_QPT_GSI, 0, 1, IB_QP1_QKEY,
|
||||
&ah_attr, NULL, mad);
|
||||
}
|
||||
|
||||
static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
|
||||
|
@ -241,6 +241,22 @@ struct mlx4_ib_proxy_sqp_hdr {
|
||||
struct mlx4_rcv_tunnel_hdr tun;
|
||||
} __packed;
|
||||
|
||||
struct mlx4_roce_smac_vlan_info {
|
||||
u64 smac;
|
||||
int smac_index;
|
||||
int smac_port;
|
||||
u64 candidate_smac;
|
||||
int candidate_smac_index;
|
||||
int candidate_smac_port;
|
||||
u16 vid;
|
||||
int vlan_index;
|
||||
int vlan_port;
|
||||
u16 candidate_vid;
|
||||
int candidate_vlan_index;
|
||||
int candidate_vlan_port;
|
||||
int update_vid;
|
||||
};
|
||||
|
||||
struct mlx4_ib_qp {
|
||||
struct ib_qp ibqp;
|
||||
struct mlx4_qp mqp;
|
||||
@ -273,8 +289,9 @@ struct mlx4_ib_qp {
|
||||
struct list_head gid_list;
|
||||
struct list_head steering_rules;
|
||||
struct mlx4_ib_buf *sqp_proxy_rcv;
|
||||
struct mlx4_roce_smac_vlan_info pri;
|
||||
struct mlx4_roce_smac_vlan_info alt;
|
||||
u64 reg_id;
|
||||
|
||||
};
|
||||
|
||||
struct mlx4_ib_srq {
|
||||
@ -720,9 +737,12 @@ void mlx4_ib_tunnels_update_work(struct work_struct *work);
|
||||
int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
|
||||
enum ib_qp_type qpt, struct ib_wc *wc,
|
||||
struct ib_grh *grh, struct ib_mad *mad);
|
||||
|
||||
int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
|
||||
enum ib_qp_type dest_qpt, u16 pkey_index, u32 remote_qpn,
|
||||
u32 qkey, struct ib_ah_attr *attr, struct ib_mad *mad);
|
||||
u32 qkey, struct ib_ah_attr *attr, u8 *s_mac,
|
||||
struct ib_mad *mad);
|
||||
|
||||
__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx);
|
||||
|
||||
int mlx4_ib_demux_cm_handler(struct ib_device *ibdev, int port, int *slave,
|
||||
|
@ -662,10 +662,14 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
|
||||
if (!sqp)
|
||||
return -ENOMEM;
|
||||
qp = &sqp->qp;
|
||||
qp->pri.vid = 0xFFFF;
|
||||
qp->alt.vid = 0xFFFF;
|
||||
} else {
|
||||
qp = kzalloc(sizeof (struct mlx4_ib_qp), GFP_KERNEL);
|
||||
if (!qp)
|
||||
return -ENOMEM;
|
||||
qp->pri.vid = 0xFFFF;
|
||||
qp->alt.vid = 0xFFFF;
|
||||
}
|
||||
} else
|
||||
qp = *caller_qp;
|
||||
@ -940,11 +944,32 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
|
||||
{
|
||||
struct mlx4_ib_cq *send_cq, *recv_cq;
|
||||
|
||||
if (qp->state != IB_QPS_RESET)
|
||||
if (qp->state != IB_QPS_RESET) {
|
||||
if (mlx4_qp_modify(dev->dev, NULL, to_mlx4_state(qp->state),
|
||||
MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp))
|
||||
pr_warn("modify QP %06x to RESET failed.\n",
|
||||
qp->mqp.qpn);
|
||||
if (qp->pri.smac) {
|
||||
mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
|
||||
qp->pri.smac = 0;
|
||||
}
|
||||
if (qp->alt.smac) {
|
||||
mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac);
|
||||
qp->alt.smac = 0;
|
||||
}
|
||||
if (qp->pri.vid < 0x1000) {
|
||||
mlx4_unregister_vlan(dev->dev, qp->pri.vlan_port, qp->pri.vid);
|
||||
qp->pri.vid = 0xFFFF;
|
||||
qp->pri.candidate_vid = 0xFFFF;
|
||||
qp->pri.update_vid = 0;
|
||||
}
|
||||
if (qp->alt.vid < 0x1000) {
|
||||
mlx4_unregister_vlan(dev->dev, qp->alt.vlan_port, qp->alt.vid);
|
||||
qp->alt.vid = 0xFFFF;
|
||||
qp->alt.candidate_vid = 0xFFFF;
|
||||
qp->alt.update_vid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
get_cqs(qp, &send_cq, &recv_cq);
|
||||
|
||||
@ -1057,6 +1082,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
|
||||
qp = kzalloc(sizeof *qp, GFP_KERNEL);
|
||||
if (!qp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
qp->pri.vid = 0xFFFF;
|
||||
qp->alt.vid = 0xFFFF;
|
||||
/* fall through */
|
||||
case IB_QPT_UD:
|
||||
{
|
||||
@ -1188,12 +1215,13 @@ static void mlx4_set_sched(struct mlx4_qp_path *path, u8 port)
|
||||
|
||||
static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
|
||||
u64 smac, u16 vlan_tag, struct mlx4_qp_path *path,
|
||||
u8 port)
|
||||
struct mlx4_roce_smac_vlan_info *smac_info, u8 port)
|
||||
{
|
||||
int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port) ==
|
||||
IB_LINK_LAYER_ETHERNET;
|
||||
int vidx;
|
||||
int smac_index;
|
||||
int err;
|
||||
|
||||
|
||||
path->grh_mylmc = ah->src_path_bits & 0x7f;
|
||||
@ -1223,61 +1251,103 @@ static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
|
||||
}
|
||||
|
||||
if (is_eth) {
|
||||
path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
|
||||
((port - 1) << 6) | ((ah->sl & 7) << 3);
|
||||
|
||||
if (!(ah->ah_flags & IB_AH_GRH))
|
||||
return -1;
|
||||
|
||||
memcpy(path->dmac, ah->dmac, ETH_ALEN);
|
||||
path->ackto = MLX4_IB_LINK_TYPE_ETH;
|
||||
/* find the index into MAC table for IBoE */
|
||||
if (!is_zero_ether_addr((const u8 *)&smac)) {
|
||||
if (mlx4_find_cached_mac(dev->dev, port, smac,
|
||||
&smac_index))
|
||||
return -ENOENT;
|
||||
} else {
|
||||
smac_index = 0;
|
||||
}
|
||||
|
||||
path->grh_mylmc &= 0x80 | smac_index;
|
||||
path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
|
||||
((port - 1) << 6) | ((ah->sl & 7) << 3);
|
||||
|
||||
path->feup |= MLX4_FEUP_FORCE_ETH_UP;
|
||||
if (vlan_tag < 0x1000) {
|
||||
if (mlx4_find_cached_vlan(dev->dev, port, vlan_tag, &vidx))
|
||||
return -ENOENT;
|
||||
|
||||
path->vlan_index = vidx;
|
||||
path->fl = 1 << 6;
|
||||
if (smac_info->vid < 0x1000) {
|
||||
/* both valid vlan ids */
|
||||
if (smac_info->vid != vlan_tag) {
|
||||
/* different VIDs. unreg old and reg new */
|
||||
err = mlx4_register_vlan(dev->dev, port, vlan_tag, &vidx);
|
||||
if (err)
|
||||
return err;
|
||||
smac_info->candidate_vid = vlan_tag;
|
||||
smac_info->candidate_vlan_index = vidx;
|
||||
smac_info->candidate_vlan_port = port;
|
||||
smac_info->update_vid = 1;
|
||||
path->vlan_index = vidx;
|
||||
} else {
|
||||
path->vlan_index = smac_info->vlan_index;
|
||||
}
|
||||
} else {
|
||||
/* no current vlan tag in qp */
|
||||
err = mlx4_register_vlan(dev->dev, port, vlan_tag, &vidx);
|
||||
if (err)
|
||||
return err;
|
||||
smac_info->candidate_vid = vlan_tag;
|
||||
smac_info->candidate_vlan_index = vidx;
|
||||
smac_info->candidate_vlan_port = port;
|
||||
smac_info->update_vid = 1;
|
||||
path->vlan_index = vidx;
|
||||
}
|
||||
path->feup |= MLX4_FVL_FORCE_ETH_VLAN;
|
||||
path->fl = 1 << 6;
|
||||
} else {
|
||||
/* have current vlan tag. unregister it at modify-qp success */
|
||||
if (smac_info->vid < 0x1000) {
|
||||
smac_info->candidate_vid = 0xFFFF;
|
||||
smac_info->update_vid = 1;
|
||||
}
|
||||
}
|
||||
} else
|
||||
|
||||
/* get smac_index for RoCE use.
|
||||
* If no smac was yet assigned, register one.
|
||||
* If one was already assigned, but the new mac differs,
|
||||
* unregister the old one and register the new one.
|
||||
*/
|
||||
if (!smac_info->smac || smac_info->smac != smac) {
|
||||
/* register candidate now, unreg if needed, after success */
|
||||
smac_index = mlx4_register_mac(dev->dev, port, smac);
|
||||
if (smac_index >= 0) {
|
||||
smac_info->candidate_smac_index = smac_index;
|
||||
smac_info->candidate_smac = smac;
|
||||
smac_info->candidate_smac_port = port;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
smac_index = smac_info->smac_index;
|
||||
}
|
||||
|
||||
memcpy(path->dmac, ah->dmac, 6);
|
||||
path->ackto = MLX4_IB_LINK_TYPE_ETH;
|
||||
/* put MAC table smac index for IBoE */
|
||||
path->grh_mylmc = (u8) (smac_index) | 0x80;
|
||||
} else {
|
||||
path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
|
||||
((port - 1) << 6) | ((ah->sl & 0xf) << 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_qp_attr *qp,
|
||||
enum ib_qp_attr_mask qp_attr_mask,
|
||||
struct mlx4_ib_qp *mqp,
|
||||
struct mlx4_qp_path *path, u8 port)
|
||||
{
|
||||
return _mlx4_set_path(dev, &qp->ah_attr,
|
||||
mlx4_mac_to_u64((u8 *)qp->smac),
|
||||
(qp_attr_mask & IB_QP_VID) ? qp->vlan_id : 0xffff,
|
||||
path, port);
|
||||
path, &mqp->pri, port);
|
||||
}
|
||||
|
||||
static int mlx4_set_alt_path(struct mlx4_ib_dev *dev,
|
||||
const struct ib_qp_attr *qp,
|
||||
enum ib_qp_attr_mask qp_attr_mask,
|
||||
struct mlx4_ib_qp *mqp,
|
||||
struct mlx4_qp_path *path, u8 port)
|
||||
{
|
||||
return _mlx4_set_path(dev, &qp->alt_ah_attr,
|
||||
mlx4_mac_to_u64((u8 *)qp->alt_smac),
|
||||
(qp_attr_mask & IB_QP_ALT_VID) ?
|
||||
qp->alt_vlan_id : 0xffff,
|
||||
path, port);
|
||||
path, &mqp->alt, port);
|
||||
}
|
||||
|
||||
static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
|
||||
@ -1292,6 +1362,37 @@ static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, u8 *smac,
|
||||
struct mlx4_qp_context *context)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
u64 u64_mac;
|
||||
int smac_index;
|
||||
|
||||
|
||||
ndev = dev->iboe.netdevs[qp->port - 1];
|
||||
if (ndev) {
|
||||
smac = ndev->dev_addr;
|
||||
u64_mac = mlx4_mac_to_u64(smac);
|
||||
} else {
|
||||
u64_mac = dev->dev->caps.def_mac[qp->port];
|
||||
}
|
||||
|
||||
context->pri_path.sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | ((qp->port - 1) << 6);
|
||||
if (!qp->pri.smac) {
|
||||
smac_index = mlx4_register_mac(dev->dev, qp->port, u64_mac);
|
||||
if (smac_index >= 0) {
|
||||
qp->pri.candidate_smac_index = smac_index;
|
||||
qp->pri.candidate_smac = u64_mac;
|
||||
qp->pri.candidate_smac_port = qp->port;
|
||||
context->pri_path.grh_mylmc = 0x80 | (u8) smac_index;
|
||||
} else {
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
const struct ib_qp_attr *attr, int attr_mask,
|
||||
enum ib_qp_state cur_state, enum ib_qp_state new_state)
|
||||
@ -1403,7 +1504,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
}
|
||||
|
||||
if (attr_mask & IB_QP_AV) {
|
||||
if (mlx4_set_path(dev, attr, attr_mask, &context->pri_path,
|
||||
if (mlx4_set_path(dev, attr, attr_mask, qp, &context->pri_path,
|
||||
attr_mask & IB_QP_PORT ?
|
||||
attr->port_num : qp->port))
|
||||
goto out;
|
||||
@ -1426,7 +1527,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
dev->dev->caps.pkey_table_len[attr->alt_port_num])
|
||||
goto out;
|
||||
|
||||
if (mlx4_set_alt_path(dev, attr, attr_mask, &context->alt_path,
|
||||
if (mlx4_set_alt_path(dev, attr, attr_mask, qp,
|
||||
&context->alt_path,
|
||||
attr->alt_port_num))
|
||||
goto out;
|
||||
|
||||
@ -1532,6 +1634,20 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
context->pri_path.fl = 0x80;
|
||||
context->pri_path.sched_queue |= MLX4_IB_DEFAULT_SCHED_QUEUE;
|
||||
}
|
||||
if (rdma_port_get_link_layer(&dev->ib_dev, qp->port) ==
|
||||
IB_LINK_LAYER_ETHERNET) {
|
||||
if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_TUN_GSI ||
|
||||
qp->mlx4_ib_qp_type == MLX4_IB_QPT_GSI)
|
||||
context->pri_path.feup = 1 << 7; /* don't fsm */
|
||||
/* handle smac_index */
|
||||
if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_UD ||
|
||||
qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI ||
|
||||
qp->mlx4_ib_qp_type == MLX4_IB_QPT_TUN_GSI) {
|
||||
err = handle_eth_ud_smac_index(dev, qp, (u8 *)attr->smac, context);
|
||||
if (err)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET)
|
||||
@ -1619,28 +1735,113 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
||||
* If we moved a kernel QP to RESET, clean up all old CQ
|
||||
* entries and reinitialize the QP.
|
||||
*/
|
||||
if (new_state == IB_QPS_RESET && !ibqp->uobject) {
|
||||
mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
|
||||
ibqp->srq ? to_msrq(ibqp->srq): NULL);
|
||||
if (send_cq != recv_cq)
|
||||
mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
|
||||
if (new_state == IB_QPS_RESET) {
|
||||
if (!ibqp->uobject) {
|
||||
mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
|
||||
ibqp->srq ? to_msrq(ibqp->srq) : NULL);
|
||||
if (send_cq != recv_cq)
|
||||
mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
|
||||
|
||||
qp->rq.head = 0;
|
||||
qp->rq.tail = 0;
|
||||
qp->sq.head = 0;
|
||||
qp->sq.tail = 0;
|
||||
qp->sq_next_wqe = 0;
|
||||
if (qp->rq.wqe_cnt)
|
||||
*qp->db.db = 0;
|
||||
qp->rq.head = 0;
|
||||
qp->rq.tail = 0;
|
||||
qp->sq.head = 0;
|
||||
qp->sq.tail = 0;
|
||||
qp->sq_next_wqe = 0;
|
||||
if (qp->rq.wqe_cnt)
|
||||
*qp->db.db = 0;
|
||||
|
||||
if (qp->flags & MLX4_IB_QP_NETIF)
|
||||
mlx4_ib_steer_qp_reg(dev, qp, 0);
|
||||
if (qp->flags & MLX4_IB_QP_NETIF)
|
||||
mlx4_ib_steer_qp_reg(dev, qp, 0);
|
||||
}
|
||||
if (qp->pri.smac) {
|
||||
mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
|
||||
qp->pri.smac = 0;
|
||||
}
|
||||
if (qp->alt.smac) {
|
||||
mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac);
|
||||
qp->alt.smac = 0;
|
||||
}
|
||||
if (qp->pri.vid < 0x1000) {
|
||||
mlx4_unregister_vlan(dev->dev, qp->pri.vlan_port, qp->pri.vid);
|
||||
qp->pri.vid = 0xFFFF;
|
||||
qp->pri.candidate_vid = 0xFFFF;
|
||||
qp->pri.update_vid = 0;
|
||||
}
|
||||
|
||||
if (qp->alt.vid < 0x1000) {
|
||||
mlx4_unregister_vlan(dev->dev, qp->alt.vlan_port, qp->alt.vid);
|
||||
qp->alt.vid = 0xFFFF;
|
||||
qp->alt.candidate_vid = 0xFFFF;
|
||||
qp->alt.update_vid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (err && steer_qp)
|
||||
mlx4_ib_steer_qp_reg(dev, qp, 0);
|
||||
kfree(context);
|
||||
if (qp->pri.candidate_smac) {
|
||||
if (err) {
|
||||
mlx4_unregister_mac(dev->dev, qp->pri.candidate_smac_port, qp->pri.candidate_smac);
|
||||
} else {
|
||||
if (qp->pri.smac)
|
||||
mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac);
|
||||
qp->pri.smac = qp->pri.candidate_smac;
|
||||
qp->pri.smac_index = qp->pri.candidate_smac_index;
|
||||
qp->pri.smac_port = qp->pri.candidate_smac_port;
|
||||
}
|
||||
qp->pri.candidate_smac = 0;
|
||||
qp->pri.candidate_smac_index = 0;
|
||||
qp->pri.candidate_smac_port = 0;
|
||||
}
|
||||
if (qp->alt.candidate_smac) {
|
||||
if (err) {
|
||||
mlx4_unregister_mac(dev->dev, qp->alt.candidate_smac_port, qp->alt.candidate_smac);
|
||||
} else {
|
||||
if (qp->alt.smac)
|
||||
mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac);
|
||||
qp->alt.smac = qp->alt.candidate_smac;
|
||||
qp->alt.smac_index = qp->alt.candidate_smac_index;
|
||||
qp->alt.smac_port = qp->alt.candidate_smac_port;
|
||||
}
|
||||
qp->alt.candidate_smac = 0;
|
||||
qp->alt.candidate_smac_index = 0;
|
||||
qp->alt.candidate_smac_port = 0;
|
||||
}
|
||||
|
||||
if (qp->pri.update_vid) {
|
||||
if (err) {
|
||||
if (qp->pri.candidate_vid < 0x1000)
|
||||
mlx4_unregister_vlan(dev->dev, qp->pri.candidate_vlan_port,
|
||||
qp->pri.candidate_vid);
|
||||
} else {
|
||||
if (qp->pri.vid < 0x1000)
|
||||
mlx4_unregister_vlan(dev->dev, qp->pri.vlan_port,
|
||||
qp->pri.vid);
|
||||
qp->pri.vid = qp->pri.candidate_vid;
|
||||
qp->pri.vlan_port = qp->pri.candidate_vlan_port;
|
||||
qp->pri.vlan_index = qp->pri.candidate_vlan_index;
|
||||
}
|
||||
qp->pri.candidate_vid = 0xFFFF;
|
||||
qp->pri.update_vid = 0;
|
||||
}
|
||||
|
||||
if (qp->alt.update_vid) {
|
||||
if (err) {
|
||||
if (qp->alt.candidate_vid < 0x1000)
|
||||
mlx4_unregister_vlan(dev->dev, qp->alt.candidate_vlan_port,
|
||||
qp->alt.candidate_vid);
|
||||
} else {
|
||||
if (qp->alt.vid < 0x1000)
|
||||
mlx4_unregister_vlan(dev->dev, qp->alt.vlan_port,
|
||||
qp->alt.vid);
|
||||
qp->alt.vid = qp->alt.candidate_vid;
|
||||
qp->alt.vlan_port = qp->alt.candidate_vlan_port;
|
||||
qp->alt.vlan_index = qp->alt.candidate_vlan_index;
|
||||
}
|
||||
qp->alt.candidate_vid = 0xFFFF;
|
||||
qp->alt.update_vid = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1842,9 +2043,9 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
|
||||
{
|
||||
struct ib_device *ib_dev = sqp->qp.ibqp.device;
|
||||
struct mlx4_wqe_mlx_seg *mlx = wqe;
|
||||
struct mlx4_wqe_ctrl_seg *ctrl = wqe;
|
||||
struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
|
||||
struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
|
||||
struct net_device *ndev;
|
||||
union ib_gid sgid;
|
||||
u16 pkey;
|
||||
int send_size;
|
||||
@ -1868,12 +2069,11 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
|
||||
/* When multi-function is enabled, the ib_core gid
|
||||
* indexes don't necessarily match the hw ones, so
|
||||
* we must use our own cache */
|
||||
sgid.global.subnet_prefix =
|
||||
to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
|
||||
subnet_prefix;
|
||||
sgid.global.interface_id =
|
||||
to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
|
||||
guid_cache[ah->av.ib.gid_index];
|
||||
err = mlx4_get_roce_gid_from_slave(to_mdev(ib_dev)->dev,
|
||||
be32_to_cpu(ah->av.ib.port_pd) >> 24,
|
||||
ah->av.ib.gid_index, &sgid.raw[0]);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = ib_get_cached_gid(ib_dev,
|
||||
be32_to_cpu(ah->av.ib.port_pd) >> 24,
|
||||
@ -1902,6 +2102,9 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
|
||||
sqp->ud_header.grh.flow_label =
|
||||
ah->av.ib.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
|
||||
sqp->ud_header.grh.hop_limit = ah->av.ib.hop_limit;
|
||||
if (is_eth)
|
||||
memcpy(sqp->ud_header.grh.source_gid.raw, sgid.raw, 16);
|
||||
else {
|
||||
if (mlx4_is_mfunc(to_mdev(ib_dev)->dev)) {
|
||||
/* When multi-function is enabled, the ib_core gid
|
||||
* indexes don't necessarily match the hw ones, so
|
||||
@ -1917,6 +2120,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
|
||||
be32_to_cpu(ah->av.ib.port_pd) >> 24,
|
||||
ah->av.ib.gid_index,
|
||||
&sqp->ud_header.grh.source_gid);
|
||||
}
|
||||
memcpy(sqp->ud_header.grh.destination_gid.raw,
|
||||
ah->av.ib.dgid, 16);
|
||||
}
|
||||
@ -1949,16 +2153,23 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
|
||||
|
||||
if (is_eth) {
|
||||
u8 *smac;
|
||||
struct in6_addr in6;
|
||||
|
||||
u16 pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13;
|
||||
|
||||
mlx->sched_prio = cpu_to_be16(pcp);
|
||||
|
||||
memcpy(sqp->ud_header.eth.dmac_h, ah->av.eth.mac, 6);
|
||||
/* FIXME: cache smac value? */
|
||||
ndev = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1];
|
||||
if (!ndev)
|
||||
return -ENODEV;
|
||||
smac = ndev->dev_addr;
|
||||
memcpy(&ctrl->srcrb_flags16[0], ah->av.eth.mac, 2);
|
||||
memcpy(&ctrl->imm, ah->av.eth.mac + 2, 4);
|
||||
memcpy(&in6, sgid.raw, sizeof(in6));
|
||||
|
||||
if (!mlx4_is_mfunc(to_mdev(ib_dev)->dev))
|
||||
smac = to_mdev(sqp->qp.ibqp.device)->
|
||||
iboe.netdevs[sqp->qp.port - 1]->dev_addr;
|
||||
else /* use the src mac of the tunnel */
|
||||
smac = ah->av.eth.s_mac;
|
||||
memcpy(sqp->ud_header.eth.smac_h, smac, 6);
|
||||
if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6))
|
||||
mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK);
|
||||
@ -2190,6 +2401,8 @@ static void build_tunnel_header(struct ib_send_wr *wr, void *wqe, unsigned *mlx_
|
||||
hdr.remote_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
|
||||
hdr.pkey_index = cpu_to_be16(wr->wr.ud.pkey_index);
|
||||
hdr.qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
|
||||
memcpy(hdr.mac, ah->av.eth.mac, 6);
|
||||
hdr.vlan = ah->av.eth.vlan;
|
||||
|
||||
spc = MLX4_INLINE_ALIGN -
|
||||
((unsigned long) (inl + 1) & (MLX4_INLINE_ALIGN - 1));
|
||||
|
@ -627,6 +627,7 @@ static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)
|
||||
int port;
|
||||
struct kobject *p, *t;
|
||||
struct mlx4_port *mport;
|
||||
struct mlx4_active_ports actv_ports;
|
||||
|
||||
get_name(dev, name, slave, sizeof name);
|
||||
|
||||
@ -649,7 +650,11 @@ static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)
|
||||
goto err_ports;
|
||||
}
|
||||
|
||||
actv_ports = mlx4_get_active_ports(dev->dev, slave);
|
||||
|
||||
for (port = 1; port <= dev->dev->caps.num_ports; ++port) {
|
||||
if (!test_bit(port - 1, actv_ports.ports))
|
||||
continue;
|
||||
err = add_port(dev, port, slave);
|
||||
if (err)
|
||||
goto err_add;
|
||||
|
@ -796,7 +796,7 @@ static void __exit act2000_exit(void)
|
||||
act2000_card *last;
|
||||
while (card) {
|
||||
unregister_card(card);
|
||||
del_timer(&card->ptimer);
|
||||
del_timer_sync(&card->ptimer);
|
||||
card = card->next;
|
||||
}
|
||||
card = cards;
|
||||
|
@ -86,12 +86,13 @@ isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t *off)
|
||||
struct divert_info *inf;
|
||||
int len;
|
||||
|
||||
if (!*((struct divert_info **) file->private_data)) {
|
||||
if (!(inf = *((struct divert_info **) file->private_data))) {
|
||||
if (file->f_flags & O_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
interruptible_sleep_on(&(rd_queue));
|
||||
wait_event_interruptible(rd_queue, (inf =
|
||||
*((struct divert_info **) file->private_data)));
|
||||
}
|
||||
if (!(inf = *((struct divert_info **) file->private_data)))
|
||||
if (!inf)
|
||||
return (0);
|
||||
|
||||
inf->usage_cnt--; /* new usage count */
|
||||
|
@ -509,7 +509,8 @@ static void
|
||||
set_arcofi(struct IsdnCardState *cs, int bc) {
|
||||
cs->dc.isac.arcofi_bc = bc;
|
||||
arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5);
|
||||
interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
|
||||
wait_event_interruptible(cs->dc.isac.arcofi_wait,
|
||||
cs->dc.isac.arcofi_state == ARCOFI_NOP);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -528,7 +529,8 @@ check_arcofi(struct IsdnCardState *cs)
|
||||
}
|
||||
cs->dc.isac.arcofi_bc = 0;
|
||||
arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);
|
||||
interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
|
||||
wait_event_interruptible(cs->dc.isac.arcofi_wait,
|
||||
cs->dc.isac.arcofi_state == ARCOFI_NOP);
|
||||
if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {
|
||||
debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);
|
||||
p = cs->dc.isac.mon_rx;
|
||||
@ -595,7 +597,8 @@ check_arcofi(struct IsdnCardState *cs)
|
||||
Elsa_Types[cs->subtyp],
|
||||
cs->hw.elsa.base + 8);
|
||||
arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
|
||||
interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
|
||||
wait_event_interruptible(cs->dc.isac.arcofi_wait,
|
||||
cs->dc.isac.arcofi_state == ARCOFI_NOP);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
|
@ -573,7 +573,8 @@ modem_l2l1(struct PStack *st, int pr, void *arg)
|
||||
test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
|
||||
bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
|
||||
arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
|
||||
interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait);
|
||||
wait_event_interruptible(bcs->cs->dc.isac.arcofi_wait,
|
||||
bcs->cs->dc.isac.arcofi_state == ARCOFI_NOP);
|
||||
bcs->cs->hw.elsa.MFlag = 1;
|
||||
} else {
|
||||
printk(KERN_WARNING "ElsaSer: unknown pr %x\n", pr);
|
||||
|
@ -175,14 +175,15 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t *off)
|
||||
int len;
|
||||
hysdn_card *card = PDE_DATA(file_inode(file));
|
||||
|
||||
if (!*((struct log_data **) file->private_data)) {
|
||||
if (!(inf = *((struct log_data **) file->private_data))) {
|
||||
struct procdata *pd = card->proclog;
|
||||
if (file->f_flags & O_NONBLOCK)
|
||||
return (-EAGAIN);
|
||||
|
||||
interruptible_sleep_on(&(pd->rd_queue));
|
||||
wait_event_interruptible(pd->rd_queue, (inf =
|
||||
*((struct log_data **) file->private_data)));
|
||||
}
|
||||
if (!(inf = *((struct log_data **) file->private_data)))
|
||||
if (!inf)
|
||||
return (0);
|
||||
|
||||
inf->usage_cnt--; /* new usage count */
|
||||
|
@ -777,7 +777,8 @@ isdn_readbchan(int di, int channel, u_char *buf, u_char *fp, int len, wait_queue
|
||||
return 0;
|
||||
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
|
||||
if (sleep)
|
||||
interruptible_sleep_on(sleep);
|
||||
wait_event_interruptible(*sleep,
|
||||
!skb_queue_empty(&dev->drv[di]->rpqueue[channel]));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -1072,7 +1073,8 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t *off)
|
||||
retval = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
interruptible_sleep_on(&(dev->info_waitq));
|
||||
wait_event_interruptible(dev->info_waitq,
|
||||
file->private_data);
|
||||
}
|
||||
p = isdn_statstr();
|
||||
file->private_data = NULL;
|
||||
@ -1128,7 +1130,8 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t *off)
|
||||
retval = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
|
||||
wait_event_interruptible(dev->drv[drvidx]->st_waitq,
|
||||
dev->drv[drvidx]->stavail);
|
||||
}
|
||||
if (dev->drv[drvidx]->interface->readstat) {
|
||||
if (count > dev->drv[drvidx]->stavail)
|
||||
@ -1188,8 +1191,8 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
|
||||
goto out;
|
||||
}
|
||||
chidx = isdn_minor2chan(minor);
|
||||
while ((retval = isdn_writebuf_stub(drvidx, chidx, buf, count)) == 0)
|
||||
interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
|
||||
wait_event_interruptible(dev->drv[drvidx]->snd_waitq[chidx],
|
||||
(retval = isdn_writebuf_stub(drvidx, chidx, buf, count)));
|
||||
goto out;
|
||||
}
|
||||
if (minor <= ISDN_MINOR_CTRLMAX) {
|
||||
@ -2378,7 +2381,7 @@ static void __exit isdn_exit(void)
|
||||
}
|
||||
isdn_tty_exit();
|
||||
unregister_chrdev(ISDN_MAJOR, "isdn");
|
||||
del_timer(&dev->timer);
|
||||
del_timer_sync(&dev->timer);
|
||||
/* call vfree with interrupts enabled, else it will hang */
|
||||
vfree(dev);
|
||||
printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
|
||||
|
@ -378,10 +378,15 @@ isdn_ppp_release(int min, struct file *file)
|
||||
is->slcomp = NULL;
|
||||
#endif
|
||||
#ifdef CONFIG_IPPP_FILTER
|
||||
kfree(is->pass_filter);
|
||||
is->pass_filter = NULL;
|
||||
kfree(is->active_filter);
|
||||
is->active_filter = NULL;
|
||||
if (is->pass_filter) {
|
||||
sk_unattached_filter_destroy(is->pass_filter);
|
||||
is->pass_filter = NULL;
|
||||
}
|
||||
|
||||
if (is->active_filter) {
|
||||
sk_unattached_filter_destroy(is->active_filter);
|
||||
is->active_filter = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO: if this was the previous master: link the stuff to the new master */
|
||||
@ -629,25 +634,41 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
|
||||
#ifdef CONFIG_IPPP_FILTER
|
||||
case PPPIOCSPASS:
|
||||
{
|
||||
struct sock_fprog fprog;
|
||||
struct sock_filter *code;
|
||||
int len = get_filter(argp, &code);
|
||||
int err, len = get_filter(argp, &code);
|
||||
|
||||
if (len < 0)
|
||||
return len;
|
||||
kfree(is->pass_filter);
|
||||
is->pass_filter = code;
|
||||
is->pass_len = len;
|
||||
break;
|
||||
|
||||
fprog.len = len;
|
||||
fprog.filter = code;
|
||||
|
||||
if (is->pass_filter)
|
||||
sk_unattached_filter_destroy(is->pass_filter);
|
||||
err = sk_unattached_filter_create(&is->pass_filter, &fprog);
|
||||
kfree(code);
|
||||
|
||||
return err;
|
||||
}
|
||||
case PPPIOCSACTIVE:
|
||||
{
|
||||
struct sock_fprog fprog;
|
||||
struct sock_filter *code;
|
||||
int len = get_filter(argp, &code);
|
||||
int err, len = get_filter(argp, &code);
|
||||
|
||||
if (len < 0)
|
||||
return len;
|
||||
kfree(is->active_filter);
|
||||
is->active_filter = code;
|
||||
is->active_len = len;
|
||||
break;
|
||||
|
||||
fprog.len = len;
|
||||
fprog.filter = code;
|
||||
|
||||
if (is->active_filter)
|
||||
sk_unattached_filter_destroy(is->active_filter);
|
||||
err = sk_unattached_filter_create(&is->active_filter, &fprog);
|
||||
kfree(code);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_IPPP_FILTER */
|
||||
default:
|
||||
@ -1147,14 +1168,14 @@ isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *
|
||||
}
|
||||
|
||||
if (is->pass_filter
|
||||
&& sk_run_filter(skb, is->pass_filter) == 0) {
|
||||
&& SK_RUN_FILTER(is->pass_filter, skb) == 0) {
|
||||
if (is->debug & 0x2)
|
||||
printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
if (!(is->active_filter
|
||||
&& sk_run_filter(skb, is->active_filter) == 0)) {
|
||||
&& SK_RUN_FILTER(is->active_filter, skb) == 0)) {
|
||||
if (is->debug & 0x2)
|
||||
printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
|
||||
lp->huptimer = 0;
|
||||
@ -1293,14 +1314,14 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
}
|
||||
|
||||
if (ipt->pass_filter
|
||||
&& sk_run_filter(skb, ipt->pass_filter) == 0) {
|
||||
&& SK_RUN_FILTER(ipt->pass_filter, skb) == 0) {
|
||||
if (ipt->debug & 0x4)
|
||||
printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
|
||||
kfree_skb(skb);
|
||||
goto unlock;
|
||||
}
|
||||
if (!(ipt->active_filter
|
||||
&& sk_run_filter(skb, ipt->active_filter) == 0)) {
|
||||
&& SK_RUN_FILTER(ipt->active_filter, skb) == 0)) {
|
||||
if (ipt->debug & 0x4)
|
||||
printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
|
||||
lp->huptimer = 0;
|
||||
@ -1490,9 +1511,9 @@ int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
|
||||
}
|
||||
|
||||
drop |= is->pass_filter
|
||||
&& sk_run_filter(skb, is->pass_filter) == 0;
|
||||
&& SK_RUN_FILTER(is->pass_filter, skb) == 0;
|
||||
drop |= is->active_filter
|
||||
&& sk_run_filter(skb, is->active_filter) == 0;
|
||||
&& SK_RUN_FILTER(is->active_filter, skb) == 0;
|
||||
|
||||
skb_push(skb, IPPP_MAX_HEADER - 4);
|
||||
return drop;
|
||||
|
@ -796,6 +796,7 @@ static void set_running_timeout(unsigned long ptr)
|
||||
#endif
|
||||
dev = (struct pcbit_dev *) ptr;
|
||||
|
||||
dev->l2_state = L2_DOWN;
|
||||
wake_up_interruptible(&dev->set_running_wq);
|
||||
}
|
||||
|
||||
@ -818,7 +819,8 @@ static int set_protocol_running(struct pcbit_dev *dev)
|
||||
|
||||
add_timer(&dev->set_running_timer);
|
||||
|
||||
interruptible_sleep_on(&dev->set_running_wq);
|
||||
wait_event(dev->set_running_wq, dev->l2_state == L2_RUNNING ||
|
||||
dev->l2_state == L2_DOWN);
|
||||
|
||||
del_timer(&dev->set_running_timer);
|
||||
|
||||
@ -842,8 +844,6 @@ static int set_protocol_running(struct pcbit_dev *dev)
|
||||
printk(KERN_DEBUG "pcbit: initialization failed\n");
|
||||
printk(KERN_DEBUG "pcbit: firmware not loaded\n");
|
||||
|
||||
dev->l2_state = L2_DOWN;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "Bank3 = %02x\n",
|
||||
readb(dev->sh_mem + BANK3));
|
||||
|
@ -390,8 +390,8 @@ static void __exit sc_exit(void)
|
||||
/*
|
||||
* kill the timers
|
||||
*/
|
||||
del_timer(&(sc_adapter[i]->reset_timer));
|
||||
del_timer(&(sc_adapter[i]->stat_timer));
|
||||
del_timer_sync(&(sc_adapter[i]->reset_timer));
|
||||
del_timer_sync(&(sc_adapter[i]->stat_timer));
|
||||
|
||||
/*
|
||||
* Tell I4L we're toast
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user