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:
Linus Torvalds 2014-04-02 20:53:45 -07:00
commit cd6362befe
1387 changed files with 99888 additions and 30803 deletions

View File

@ -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.

View 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.

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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 {

View 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>;
};

View File

@ -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 {

View 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";
};
};
};

View File

@ -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

View File

@ -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 {

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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?

View 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.

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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 {

View File

@ -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:

View File

@ -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

View File

@ -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

View 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.

View 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";
};
};

View File

@ -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>;

View 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";
};

View 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 = <&ether_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";
};
};

View File

@ -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

View File

@ -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:

View File

@ -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:

View 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 */
};
};

View 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).

View File

@ -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.

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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
=========================

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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. */

View File

@ -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) {

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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 },

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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;
};

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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");

View File

@ -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;

View File

@ -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));

View File

@ -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