summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-01 15:56:08 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-01 15:56:08 -0800
commit34229b277480f46c1e9a19f027f30b074512e68b (patch)
tree90d8b43ebceb850b0e7852d75283aebbd2abbc00
parent2c923414d3963b959f65a8a6031972402e6a34a5 (diff)
parent53729eb174c1589f9185340ffe8c10b3f39f3ef3 (diff)
downloadop-kernel-dev-34229b277480f46c1e9a19f027f30b074512e68b.zip
op-kernel-dev-34229b277480f46c1e9a19f027f30b074512e68b.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "This looks like a lot but it's a mixture of regression fixes as well as fixes for longer standing issues. 1) Fix on-channel cancellation in mac80211, from Johannes Berg. 2) Handle CHECKSUM_COMPLETE properly in xt_TCPMSS netfilter xtables module, from Eric Dumazet. 3) Avoid infinite loop in UDP SO_REUSEPORT logic, also from Eric Dumazet. 4) Avoid a NULL deref if we try to set SO_REUSEPORT after a socket is bound, from Craig Gallek. 5) GRO key comparisons don't take lightweight tunnels into account, from Jesse Gross. 6) Fix struct pid leak via SCM credentials in AF_UNIX, from Eric Dumazet. 7) We need to set the rtnl_link_ops of ipv6 SIT tunnels before we register them, otherwise the NEWLINK netlink message is missing the proper attributes. From Thadeu Lima de Souza Cascardo. 8) Several Spectrum chip bug fixes for mlxsw switch driver, from Ido Schimmel 9) Handle fragments properly in ipv4 easly socket demux, from Eric Dumazet. 10) Don't ignore the ifindex key specifier on ipv6 output route lookups, from Paolo Abeni" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (128 commits) tcp: avoid cwnd undo after receiving ECN irda: fix a potential use-after-free in ircomm_param_request net: tg3: avoid uninitialized variable warning net: nb8800: avoid uninitialized variable warning net: vxge: avoid unused function warnings net: bgmac: clarify CONFIG_BCMA dependency net: hp100: remove unnecessary #ifdefs net: davinci_cpdma: use dma_addr_t for DMA address ipv6/udp: use sticky pktinfo egress ifindex on connect() ipv6: enforce flowi6_oif usage in ip6_dst_lookup_tail() netlink: not trim skb for mmaped socket when dump vxlan: fix a out of bounds access in __vxlan_find_mac net: dsa: mv88e6xxx: fix port VLAN maps fib_trie: Fix shift by 32 in fib_table_lookup net: moxart: use correct accessors for DMA memory ipv4: ipconfig: avoid unused ic_proto_used symbol bnxt_en: Fix crash in bnxt_free_tx_skbs() during tx timeout. bnxt_en: Exclude rx_drop_pkts hw counter from the stack's rx_dropped counter. bnxt_en: Ring free response from close path should use completion ring net_sched: drr: check for NULL pointer in drr_dequeue ...
-rw-r--r--Documentation/devicetree/bindings/net/brcm,bcmgenet.txt4
-rw-r--r--Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt5
-rw-r--r--Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt7
-rw-r--r--Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt7
-rw-r--r--Documentation/devicetree/bindings/net/mdio-mux-gpio.txt8
-rw-r--r--Documentation/devicetree/bindings/net/mdio-mux.txt8
-rw-r--r--Documentation/devicetree/bindings/net/phy.txt6
-rw-r--r--Documentation/networking/ip-sysctl.txt2
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi19
-rw-r--r--drivers/net/dsa/mv88e6xxx.c5
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c12
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h1
-rw-r--r--drivers/net/ethernet/aurora/nb8800.c4
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig5
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c9
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c2
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c2
-rw-r--r--drivers/net/ethernet/cadence/macb.c2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c4
-rw-r--r--drivers/net/ethernet/ezchip/Kconfig1
-rw-r--r--drivers/net/ethernet/freescale/Makefile3
-rw-r--r--drivers/net/ethernet/freescale/fec.h44
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c133
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fcc.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hnae.c17
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hnae.h7
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c10
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h1
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c15
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.h2
-rw-r--r--drivers/net/ethernet/hp/hp100.c18
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c15
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c4
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c4
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c47
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h94
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c161
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c85
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.c46
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.h4
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c31
-rw-r--r--drivers/net/ethernet/rocker/rocker.c2
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c16
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c12
-rw-r--r--drivers/net/fddi/defxx.c8
-rw-r--r--drivers/net/geneve.c4
-rw-r--r--drivers/net/hyperv/hyperv_net.h1
-rw-r--r--drivers/net/hyperv/netvsc.c33
-rw-r--r--drivers/net/hyperv/netvsc_drv.c67
-rw-r--r--drivers/net/irda/bfin_sir.h3
-rw-r--r--drivers/net/macvlan.c2
-rw-r--r--drivers/net/phy/Kconfig1
-rw-r--r--drivers/net/phy/dp83640.c17
-rw-r--r--drivers/net/phy/phy.c46
-rw-r--r--drivers/net/phy/smsc.c54
-rw-r--r--drivers/net/ppp/pptp.c34
-rw-r--r--drivers/net/usb/lan78xx.c132
-rw-r--r--drivers/net/vxlan.c25
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c12
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c40
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-7000.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c74
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c4
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2400pci.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500pci.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500usb.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c3
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00config.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00mac.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt61pci.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt73usb.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/regd.c2
-rw-r--r--drivers/net/xen-netfront.c15
-rw-r--r--drivers/of/of_mdio.c37
-rw-r--r--drivers/ptp/ptp_ixp46x.c7
-rw-r--r--drivers/ssb/main.c7
-rw-r--r--fs/compat_ioctl.c3
-rw-r--r--include/linux/netdevice.h11
-rw-r--r--include/net/bluetooth/l2cap.h6
-rw-r--r--include/net/dst_metadata.h18
-rw-r--r--include/net/ip6_route.h12
-rw-r--r--include/net/netfilter/nf_conntrack_core.h8
-rw-r--r--include/net/sctp/structs.h5
-rw-r--r--include/net/sock.h12
-rw-r--r--include/net/sock_reuseport.h2
-rw-r--r--include/net/tcp.h2
-rw-r--r--net/bluetooth/6lowpan.c7
-rw-r--r--net/bluetooth/hci_request.c28
-rw-r--r--net/bluetooth/l2cap_core.c14
-rw-r--r--net/bluetooth/l2cap_sock.c12
-rw-r--r--net/bluetooth/smp.c16
-rw-r--r--net/bridge/br.c3
-rw-r--r--net/core/dev.c7
-rw-r--r--net/core/sock_reuseport.c9
-rw-r--r--net/ipv4/Kconfig1
-rw-r--r--net/ipv4/fib_trie.c7
-rw-r--r--net/ipv4/inet_diag.c21
-rw-r--r--net/ipv4/ip_fragment.c1
-rw-r--r--net/ipv4/ip_input.c5
-rw-r--r--net/ipv4/ipconfig.c4
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c2
-rw-r--r--net/ipv4/tcp.c12
-rw-r--r--net/ipv4/tcp_input.c12
-rw-r--r--net/ipv4/tcp_ipv4.c13
-rw-r--r--net/ipv4/udp.c32
-rw-r--r--net/ipv6/Kconfig1
-rw-r--r--net/ipv6/datagram.c3
-rw-r--r--net/ipv6/ip6_output.c6
-rw-r--r--net/ipv6/route.c7
-rw-r--r--net/ipv6/sit.c4
-rw-r--r--net/ipv6/udp.c32
-rw-r--r--net/irda/ircomm/ircomm_param.c3
-rw-r--r--net/iucv/af_iucv.c3
-rw-r--r--net/mac80211/ibss.c1
-rw-r--r--net/mac80211/main.c6
-rw-r--r--net/mac80211/mesh.c11
-rw-r--r--net/mac80211/mesh.h4
-rw-r--r--net/mac80211/mlme.c2
-rw-r--r--net/mac80211/offchannel.c16
-rw-r--r--net/mac80211/scan.c20
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/status.c5
-rw-r--r--net/mac80211/util.c16
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c38
-rw-r--r--net/netfilter/nf_conntrack_helper.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c2
-rw-r--r--net/netfilter/nf_tables_netdev.c8
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c4
-rw-r--r--net/netfilter/nft_byteorder.c6
-rw-r--r--net/netfilter/nft_ct.c2
-rw-r--r--net/netfilter/xt_TCPMSS.c9
-rw-r--r--net/netlink/af_netlink.c3
-rw-r--r--net/rfkill/core.c16
-rw-r--r--net/sched/sch_drr.c2
-rw-r--r--net/sctp/input.c17
-rw-r--r--net/sctp/proc.c12
-rw-r--r--net/sctp/sm_sideeffect.c12
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/sctp/transport.c8
-rw-r--r--net/switchdev/switchdev.c15
-rw-r--r--net/tipc/subscr.c11
-rw-r--r--net/unix/af_unix.c1
-rw-r--r--net/wireless/reg.c45
154 files changed, 1402 insertions, 843 deletions
diff --git a/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt
index 451fef2..10587bd 100644
--- a/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt
+++ b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt
@@ -68,7 +68,7 @@ ethernet@f0b60000 {
phy1: ethernet-phy@1 {
max-speed = <1000>;
reg = <0x1>;
- compatible = "brcm,28nm-gphy", "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-ieee802.3-c22";
};
};
};
@@ -115,7 +115,7 @@ ethernet@f0ba0000 {
phy0: ethernet-phy@0 {
max-speed = <1000>;
reg = <0x0>;
- compatible = "brcm,bcm53125", "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-ieee802.3-c22";
};
};
};
diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
index 80411b2..ecacfa4 100644
--- a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
+++ b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
@@ -4,8 +4,6 @@ Required properties:
- compatible: should be "hisilicon,hns-dsaf-v1" or "hisilicon,hns-dsaf-v2".
"hisilicon,hns-dsaf-v1" is for hip05.
"hisilicon,hns-dsaf-v2" is for Hi1610 and Hi1612.
-- dsa-name: dsa fabric name who provide this interface.
- should be "dsafX", X is the dsaf id.
- mode: dsa fabric mode string. only support one of dsaf modes like these:
"2port-64vf",
"6port-16rss",
@@ -26,9 +24,8 @@ Required properties:
Example:
-dsa: dsa@c7000000 {
+dsaf0: dsa@c7000000 {
compatible = "hisilicon,hns-dsaf-v1";
- dsa_name = "dsaf0";
mode = "6port-16rss";
interrupt-parent = <&mbigen_dsa>;
reg = <0x0 0xC0000000 0x0 0x420000
diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt
index 41d19be..e6a9d1c 100644
--- a/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt
+++ b/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt
@@ -4,8 +4,9 @@ Required properties:
- compatible: "hisilicon,hns-nic-v1" or "hisilicon,hns-nic-v2".
"hisilicon,hns-nic-v1" is for hip05.
"hisilicon,hns-nic-v2" is for Hi1610 and Hi1612.
-- ae-name: accelerator name who provides this interface,
- is simply a name referring to the name of name in the accelerator node.
+- ae-handle: accelerator engine handle for hns,
+ specifies a reference to the associating hardware driver node.
+ see Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
- port-id: is the index of port provided by DSAF (the accelerator). DSAF can
connect to 8 PHYs. Port 0 to 1 are both used for adminstration purpose. They
are called debug ports.
@@ -41,7 +42,7 @@ Example:
ethernet@0{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <0>;
local-mac-address = [a2 14 e4 4b 56 76];
};
diff --git a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
index aeea50c..d0cb869 100644
--- a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
+++ b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
@@ -6,12 +6,17 @@ Required properties:
- interrupts: interrupt for the device
- 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.
+- clocks: List of clocks for this device. At least one clock is
+ mandatory for the core clock. If several clocks are given, then the
+ clock-names property must be used to identify them.
Optional properties:
- tx-csum-limit: maximum mtu supported by port that allow TX checksum.
Value is presented in bytes. If not used, by default 1600B is set for
"marvell,armada-370-neta" and 9800B for others.
+- clock-names: List of names corresponding to clocks property; shall be
+ "core" for core clock and "bus" for the optional bus clock.
+
Example:
diff --git a/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
index 7938411..694987d 100644
--- a/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
+++ b/Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
@@ -38,7 +38,6 @@ Example :
phy11: ethernet-phy@1 {
reg = <1>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -48,7 +47,6 @@ Example :
};
phy12: ethernet-phy@2 {
reg = <2>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -58,7 +56,6 @@ Example :
};
phy13: ethernet-phy@3 {
reg = <3>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -68,7 +65,6 @@ Example :
};
phy14: ethernet-phy@4 {
reg = <4>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -85,7 +81,6 @@ Example :
phy21: ethernet-phy@1 {
reg = <1>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -95,7 +90,6 @@ Example :
};
phy22: ethernet-phy@2 {
reg = <2>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -105,7 +99,6 @@ Example :
};
phy23: ethernet-phy@3 {
reg = <3>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -115,7 +108,6 @@ Example :
};
phy24: ethernet-phy@4 {
reg = <4>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt b/Documentation/devicetree/bindings/net/mdio-mux.txt
index f65606f..491f5bd 100644
--- a/Documentation/devicetree/bindings/net/mdio-mux.txt
+++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
@@ -47,7 +47,6 @@ Example :
phy11: ethernet-phy@1 {
reg = <1>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -57,7 +56,6 @@ Example :
};
phy12: ethernet-phy@2 {
reg = <2>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -67,7 +65,6 @@ Example :
};
phy13: ethernet-phy@3 {
reg = <3>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -77,7 +74,6 @@ Example :
};
phy14: ethernet-phy@4 {
reg = <4>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -94,7 +90,6 @@ Example :
phy21: ethernet-phy@1 {
reg = <1>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -104,7 +99,6 @@ Example :
};
phy22: ethernet-phy@2 {
reg = <2>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -114,7 +108,6 @@ Example :
};
phy23: ethernet-phy@3 {
reg = <3>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
@@ -124,7 +117,6 @@ Example :
};
phy24: ethernet-phy@4 {
reg = <4>;
- compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
index 525e165..bc1c3c8 100644
--- a/Documentation/devicetree/bindings/net/phy.txt
+++ b/Documentation/devicetree/bindings/net/phy.txt
@@ -17,8 +17,7 @@ Optional Properties:
"ethernet-phy-ieee802.3-c22" or "ethernet-phy-ieee802.3-c45" for
PHYs that implement IEEE802.3 clause 22 or IEEE802.3 clause 45
specifications. If neither of these are specified, the default is to
- assume clause 22. The compatible list may also contain other
- elements.
+ assume clause 22.
If the phy's identifier is known then the list may contain an entry
of the form: "ethernet-phy-idAAAA.BBBB" where
@@ -28,6 +27,9 @@ Optional Properties:
4 hex digits. This is the chip vendor OUI bits 19:24,
followed by 10 bits of a vendor specific ID.
+ The compatible list should not contain other values than those
+ listed here.
+
- max-speed: Maximum PHY supported speed (10, 100, 1000...)
- broken-turn-around: If set, indicates the PHY device does not correctly
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ceb44a0..73b36d7 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -594,7 +594,7 @@ tcp_fastopen - INTEGER
tcp_syn_retries - INTEGER
Number of times initial SYNs for an active TCP connection attempt
- will be retransmitted. Should not be higher than 255. Default value
+ will be retransmitted. Should not be higher than 127. Default value
is 6, which corresponds to 63seconds till the last retransmission
with the current initial RTO of 1second. With this the final timeout
for an active TCP connection attempt will happen after 127seconds.
diff --git a/MAINTAINERS b/MAINTAINERS
index 30aca4a..f678c37 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10173,7 +10173,7 @@ F: drivers/net/ethernet/natsemi/sonic.*
SONICS SILICON BACKPLANE DRIVER (SSB)
M: Michael Buesch <m@bues.ch>
-L: netdev@vger.kernel.org
+L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/ssb/
F: include/linux/ssb/
diff --git a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi
index da7b6e6..933cba3 100644
--- a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi
@@ -23,9 +23,8 @@ soc0: soc@000000000 {
};
};
- dsa: dsa@c7000000 {
+ dsaf0: dsa@c7000000 {
compatible = "hisilicon,hns-dsaf-v1";
- dsa_name = "dsaf0";
mode = "6port-16rss";
interrupt-parent = <&mbigen_dsa>;
@@ -127,7 +126,7 @@ soc0: soc@000000000 {
eth0: ethernet@0{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <0>;
local-mac-address = [00 00 00 01 00 58];
status = "disabled";
@@ -135,14 +134,14 @@ soc0: soc@000000000 {
};
eth1: ethernet@1{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <1>;
status = "disabled";
dma-coherent;
};
eth2: ethernet@2{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <2>;
local-mac-address = [00 00 00 01 00 5a];
status = "disabled";
@@ -150,7 +149,7 @@ soc0: soc@000000000 {
};
eth3: ethernet@3{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <3>;
local-mac-address = [00 00 00 01 00 5b];
status = "disabled";
@@ -158,7 +157,7 @@ soc0: soc@000000000 {
};
eth4: ethernet@4{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <4>;
local-mac-address = [00 00 00 01 00 5c];
status = "disabled";
@@ -166,7 +165,7 @@ soc0: soc@000000000 {
};
eth5: ethernet@5{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <5>;
local-mac-address = [00 00 00 01 00 5d];
status = "disabled";
@@ -174,7 +173,7 @@ soc0: soc@000000000 {
};
eth6: ethernet@6{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <6>;
local-mac-address = [00 00 00 01 00 5e];
status = "disabled";
@@ -182,7 +181,7 @@ soc0: soc@000000000 {
};
eth7: ethernet@7{
compatible = "hisilicon,hns-nic-v1";
- ae-name = "dsaf0";
+ ae-handle = <&dsaf0>;
port-id = <7>;
local-mac-address = [00 00 00 01 00 5f];
status = "disabled";
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 9fe33fc..cf34681 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1532,7 +1532,7 @@ int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
/* no PVID with ranges, otherwise it's a bug */
if (pvid)
- err = _mv88e6xxx_port_pvid_set(ds, port, vid);
+ err = _mv88e6xxx_port_pvid_set(ds, port, vlan->vid_end);
unlock:
mutex_unlock(&ps->smi_mutex);
@@ -2163,7 +2163,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
* database, and allow every port to egress frames on all other ports.
*/
reg = BIT(ps->num_ports) - 1; /* all ports */
- ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg & ~port);
+ reg &= ~BIT(port); /* except itself */
+ ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg);
if (ret)
goto abort;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index a4799c1..5eb9b20 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -628,6 +628,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
int ret;
ring = pdata->rx_ring;
+ irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
IRQF_SHARED, ring->irq_name, ring);
if (ret)
@@ -635,6 +636,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
if (pdata->cq_cnt) {
ring = pdata->tx_ring->cp_ring;
+ irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
IRQF_SHARED, ring->irq_name, ring);
if (ret) {
@@ -649,15 +651,19 @@ static int xgene_enet_register_irq(struct net_device *ndev)
static void xgene_enet_free_irq(struct net_device *ndev)
{
struct xgene_enet_pdata *pdata;
+ struct xgene_enet_desc_ring *ring;
struct device *dev;
pdata = netdev_priv(ndev);
dev = ndev_to_dev(ndev);
- devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring);
+ ring = pdata->rx_ring;
+ irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+ devm_free_irq(dev, ring->irq, ring);
if (pdata->cq_cnt) {
- devm_free_irq(dev, pdata->tx_ring->cp_ring->irq,
- pdata->tx_ring->cp_ring);
+ ring = pdata->tx_ring->cp_ring;
+ irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+ devm_free_irq(dev, ring->irq, ring);
}
}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 70d5b62..248dfc4 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -25,6 +25,7 @@
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/efi.h>
+#include <linux/irq.h>
#include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/of_net.h>
diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c
index ecc4a33..f71ab26 100644
--- a/drivers/net/ethernet/aurora/nb8800.c
+++ b/drivers/net/ethernet/aurora/nb8800.c
@@ -302,7 +302,7 @@ static int nb8800_poll(struct napi_struct *napi, int budget)
nb8800_tx_done(dev);
again:
- while (work < budget) {
+ do {
struct nb8800_rx_buf *rxb;
unsigned int len;
@@ -330,7 +330,7 @@ again:
rxd->report = 0;
last = next;
work++;
- }
+ } while (work < budget);
if (work) {
priv->rx_descs[last].desc.config |= DESC_EOC;
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 8550df1..19f7cd0 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -151,8 +151,11 @@ config BNX2X_VXLAN
config BGMAC
tristate "BCMA bus GBit core support"
- depends on BCMA_HOST_SOC && HAS_DMA && (BCM47XX || ARCH_BCM_5301X)
+ depends on BCMA && BCMA_HOST_SOC
+ depends on HAS_DMA
+ depends on BCM47XX || ARCH_BCM_5301X || COMPILE_TEST
select PHYLIB
+ select FIXED_PHY
---help---
This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus.
They can be found on BCM47xx SoCs and provide gigabit ethernet.
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index df835f5..5dc89e5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1490,10 +1490,11 @@ static void bnxt_free_tx_skbs(struct bnxt *bp)
last = tx_buf->nr_frags;
j += 2;
- for (k = 0; k < last; k++, j = NEXT_TX(j)) {
+ for (k = 0; k < last; k++, j++) {
+ int ring_idx = j & bp->tx_ring_mask;
skb_frag_t *frag = &skb_shinfo(skb)->frags[k];
- tx_buf = &txr->tx_buf_ring[j];
+ tx_buf = &txr->tx_buf_ring[ring_idx];
dma_unmap_page(
&pdev->dev,
dma_unmap_addr(tx_buf, mapping),
@@ -3406,7 +3407,7 @@ static int hwrm_ring_free_send_msg(struct bnxt *bp,
struct hwrm_ring_free_output *resp = bp->hwrm_cmd_resp_addr;
u16 error_code;
- bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, -1, -1);
+ bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, cmpl_ring_id, -1);
req.ring_type = ring_type;
req.ring_id = cpu_to_le16(ring->fw_ring_id);
@@ -4819,8 +4820,6 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
stats->multicast += le64_to_cpu(hw_stats->rx_mcast_pkts);
- stats->rx_dropped += le64_to_cpu(hw_stats->rx_drop_pkts);
-
stats->tx_dropped += le64_to_cpu(hw_stats->tx_drop_pkts);
}
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 0d77596..457c3bc 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -401,7 +401,7 @@ int bcmgenet_mii_probe(struct net_device *dev)
* Ethernet MAC ISRs
*/
if (priv->internal_phy)
- priv->mii_bus->irq[phydev->mdio.addr] = PHY_IGNORE_INTERRUPT;
+ priv->phydev->irq = PHY_IGNORE_INTERRUPT;
return 0;
}
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 9293675..49eea89 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12016,7 +12016,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
int ret;
u32 offset, len, b_offset, odd_len;
u8 *buf;
- __be32 start, end;
+ __be32 start = 0, end;
if (tg3_flag(tp, NO_NVRAM) ||
eeprom->magic != TG3_EEPROM_MAGIC)
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 9d9984a..50c9410 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -2823,7 +2823,7 @@ static int macb_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct device_node *phy_node;
const struct macb_config *macb_config = NULL;
- struct clk *pclk, *hclk, *tx_clk;
+ struct clk *pclk, *hclk = NULL, *tx_clk = NULL;
unsigned int queue_mask, num_queues;
struct macb_platform_data *pdata;
bool native_io;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index b895044..8727655 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -1526,7 +1526,6 @@ static int liquidio_ptp_gettime(struct ptp_clock_info *ptp,
struct timespec64 *ts)
{
u64 ns;
- u32 remainder;
unsigned long flags;
struct lio *lio = container_of(ptp, struct lio, ptp_info);
struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
@@ -1536,8 +1535,7 @@ static int liquidio_ptp_gettime(struct ptp_clock_info *ptp,
ns += lio->ptp_adjust;
spin_unlock_irqrestore(&lio->ptp_lock, flags);
- ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
- ts->tv_nsec = remainder;
+ *ts = ns_to_timespec64(ns);
return 0;
}
diff --git a/drivers/net/ethernet/ezchip/Kconfig b/drivers/net/ethernet/ezchip/Kconfig
index 48ecbc8..b423ad3 100644
--- a/drivers/net/ethernet/ezchip/Kconfig
+++ b/drivers/net/ethernet/ezchip/Kconfig
@@ -18,6 +18,7 @@ if NET_VENDOR_EZCHIP
config EZCHIP_NPS_MANAGEMENT_ENET
tristate "EZchip NPS management enet support"
depends on OF_IRQ && OF_NET
+ depends on HAS_IOMEM
---help---
Simple LAN device for debug or management purposes.
Device supports interrupts for RX and TX(completion).
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 4097c58..cbe21dc 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -4,6 +4,9 @@
obj-$(CONFIG_FEC) += fec.o
fec-objs :=fec_main.o fec_ptp.o
+CFLAGS_fec_main.o := -D__CHECK_ENDIAN__
+CFLAGS_fec_ptp.o := -D__CHECK_ENDIAN__
+
obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 99d33e2..2106d72 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -19,8 +19,7 @@
#include <linux/timecounter.h>
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
- defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
/*
* Just figures, Motorola would have to change the offsets for
* registers in the same peripheral device on different models
@@ -190,28 +189,45 @@
/*
* Define the buffer descriptor structure.
+ *
+ * Evidently, ARM SoCs have the FEC block generated in a
+ * little endian mode so adjust endianness accordingly.
*/
-#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+#if defined(CONFIG_ARM)
+#define fec32_to_cpu le32_to_cpu
+#define fec16_to_cpu le16_to_cpu
+#define cpu_to_fec32 cpu_to_le32
+#define cpu_to_fec16 cpu_to_le16
+#define __fec32 __le32
+#define __fec16 __le16
+
struct bufdesc {
- unsigned short cbd_datlen; /* Data length */
- unsigned short cbd_sc; /* Control and status info */
- unsigned long cbd_bufaddr; /* Buffer address */
+ __fec16 cbd_datlen; /* Data length */
+ __fec16 cbd_sc; /* Control and status info */
+ __fec32 cbd_bufaddr; /* Buffer address */
};
#else
+#define fec32_to_cpu be32_to_cpu
+#define fec16_to_cpu be16_to_cpu
+#define cpu_to_fec32 cpu_to_be32
+#define cpu_to_fec16 cpu_to_be16
+#define __fec32 __be32
+#define __fec16 __be16
+
struct bufdesc {
- unsigned short cbd_sc; /* Control and status info */
- unsigned short cbd_datlen; /* Data length */
- unsigned long cbd_bufaddr; /* Buffer address */
+ __fec16 cbd_sc; /* Control and status info */
+ __fec16 cbd_datlen; /* Data length */
+ __fec32 cbd_bufaddr; /* Buffer address */
};
#endif
struct bufdesc_ex {
struct bufdesc desc;
- unsigned long cbd_esc;
- unsigned long cbd_prot;
- unsigned long cbd_bdu;
- unsigned long ts;
- unsigned short res0[4];
+ __fec32 cbd_esc;
+ __fec32 cbd_prot;
+ __fec32 cbd_bdu;
+ __fec32 ts;
+ __fec16 res0[4];
};
/*
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 502da6f..41c81f6 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -332,11 +332,13 @@ static void fec_dump(struct net_device *ndev)
bdp = txq->tx_bd_base;
do {
- pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
+ pr_info("%3u %c%c 0x%04x 0x%08x %4u %p\n",
index,
bdp == txq->cur_tx ? 'S' : ' ',
bdp == txq->dirty_tx ? 'H' : ' ',
- bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
+ fec16_to_cpu(bdp->cbd_sc),
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
txq->tx_skbuff[index]);
bdp = fec_enet_get_nextdesc(bdp, fep, 0);
index++;
@@ -389,7 +391,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
bdp = fec_enet_get_nextdesc(bdp, fep, queue);
ebdp = (struct bufdesc_ex *)bdp;
- status = bdp->cbd_sc;
+ status = fec16_to_cpu(bdp->cbd_sc);
status &= ~BD_ENET_TX_STATS;
status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
frag_len = skb_shinfo(skb)->frags[frag].size;
@@ -411,7 +413,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
if (skb->ip_summed == CHECKSUM_PARTIAL)
estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
ebdp->cbd_bdu = 0;
- ebdp->cbd_esc = estatus;
+ ebdp->cbd_esc = cpu_to_fec32(estatus);
}
bufaddr = page_address(this_frag->page.p) + this_frag->page_offset;
@@ -435,9 +437,9 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
goto dma_mapping_error;
}
- bdp->cbd_bufaddr = addr;
- bdp->cbd_datlen = frag_len;
- bdp->cbd_sc = status;
+ bdp->cbd_bufaddr = cpu_to_fec32(addr);
+ bdp->cbd_datlen = cpu_to_fec16(frag_len);
+ bdp->cbd_sc = cpu_to_fec16(status);
}
return bdp;
@@ -445,8 +447,8 @@ dma_mapping_error:
bdp = txq->cur_tx;
for (i = 0; i < frag; i++) {
bdp = fec_enet_get_nextdesc(bdp, fep, queue);
- dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
- bdp->cbd_datlen, DMA_TO_DEVICE);
+ dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE);
}
return ERR_PTR(-ENOMEM);
}
@@ -483,7 +485,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
/* Fill in a Tx ring entry */
bdp = txq->cur_tx;
last_bdp = bdp;
- status = bdp->cbd_sc;
+ status = fec16_to_cpu(bdp->cbd_sc);
status &= ~BD_ENET_TX_STATS;
/* Set buffer length and buffer pointer */
@@ -539,21 +541,21 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
ebdp->cbd_bdu = 0;
- ebdp->cbd_esc = estatus;
+ ebdp->cbd_esc = cpu_to_fec32(estatus);
}
index = fec_enet_get_bd_index(txq->tx_bd_base, last_bdp, fep);
/* Save skb pointer */
txq->tx_skbuff[index] = skb;
- bdp->cbd_datlen = buflen;
- bdp->cbd_bufaddr = addr;
+ bdp->cbd_datlen = cpu_to_fec16(buflen);
+ bdp->cbd_bufaddr = cpu_to_fec32(addr);
/* Send it on its way. Tell FEC it's ready, interrupt when done,
* it's the last BD of the frame, and to put the CRC on the end.
*/
status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
- bdp->cbd_sc = status;
+ bdp->cbd_sc = cpu_to_fec16(status);
/* If this was the last BD in the ring, start at the beginning again. */
bdp = fec_enet_get_nextdesc(last_bdp, fep, queue);
@@ -585,7 +587,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
unsigned int estatus = 0;
dma_addr_t addr;
- status = bdp->cbd_sc;
+ status = fec16_to_cpu(bdp->cbd_sc);
status &= ~BD_ENET_TX_STATS;
status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
@@ -607,8 +609,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- bdp->cbd_datlen = size;
- bdp->cbd_bufaddr = addr;
+ bdp->cbd_datlen = cpu_to_fec16(size);
+ bdp->cbd_bufaddr = cpu_to_fec32(addr);
if (fep->bufdesc_ex) {
if (fep->quirks & FEC_QUIRK_HAS_AVB)
@@ -616,7 +618,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
if (skb->ip_summed == CHECKSUM_PARTIAL)
estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
ebdp->cbd_bdu = 0;
- ebdp->cbd_esc = estatus;
+ ebdp->cbd_esc = cpu_to_fec32(estatus);
}
/* Handle the last BD specially */
@@ -625,10 +627,10 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
if (is_last) {
status |= BD_ENET_TX_INTR;
if (fep->bufdesc_ex)
- ebdp->cbd_esc |= BD_ENET_TX_INT;
+ ebdp->cbd_esc |= cpu_to_fec32(BD_ENET_TX_INT);
}
- bdp->cbd_sc = status;
+ bdp->cbd_sc = cpu_to_fec16(status);
return 0;
}
@@ -647,7 +649,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
unsigned short status;
unsigned int estatus = 0;
- status = bdp->cbd_sc;
+ status = fec16_to_cpu(bdp->cbd_sc);
status &= ~BD_ENET_TX_STATS;
status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
@@ -671,8 +673,8 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
}
}
- bdp->cbd_bufaddr = dmabuf;
- bdp->cbd_datlen = hdr_len;
+ bdp->cbd_bufaddr = cpu_to_fec32(dmabuf);
+ bdp->cbd_datlen = cpu_to_fec16(hdr_len);
if (fep->bufdesc_ex) {
if (fep->quirks & FEC_QUIRK_HAS_AVB)
@@ -680,10 +682,10 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
if (skb->ip_summed == CHECKSUM_PARTIAL)
estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
ebdp->cbd_bdu = 0;
- ebdp->cbd_esc = estatus;
+ ebdp->cbd_esc = cpu_to_fec32(estatus);
}
- bdp->cbd_sc = status;
+ bdp->cbd_sc = cpu_to_fec16(status);
return 0;
}
@@ -823,15 +825,15 @@ static void fec_enet_bd_init(struct net_device *dev)
/* Initialize the BD for every fragment in the page. */
if (bdp->cbd_bufaddr)
- bdp->cbd_sc = BD_ENET_RX_EMPTY;
+ bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY);
else
- bdp->cbd_sc = 0;
+ bdp->cbd_sc = cpu_to_fec16(0);
bdp = fec_enet_get_nextdesc(bdp, fep, q);
}
/* Set the last buffer to wrap */
bdp = fec_enet_get_prevdesc(bdp, fep, q);
- bdp->cbd_sc |= BD_SC_WRAP;
+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP);
rxq->cur_rx = rxq->rx_bd_base;
}
@@ -844,18 +846,18 @@ static void fec_enet_bd_init(struct net_device *dev)
for (i = 0; i < txq->tx_ring_size; i++) {
/* Initialize the BD for every fragment in the page. */
- bdp->cbd_sc = 0;
+ bdp->cbd_sc = cpu_to_fec16(0);
if (txq->tx_skbuff[i]) {
dev_kfree_skb_any(txq->tx_skbuff[i]);
txq->tx_skbuff[i] = NULL;
}
- bdp->cbd_bufaddr = 0;
+ bdp->cbd_bufaddr = cpu_to_fec32(0);
bdp = fec_enet_get_nextdesc(bdp, fep, q);
}
/* Set the last buffer to wrap */
bdp = fec_enet_get_prevdesc(bdp, fep, q);
- bdp->cbd_sc |= BD_SC_WRAP;
+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP);
txq->dirty_tx = bdp;
}
}
@@ -947,8 +949,10 @@ fec_restart(struct net_device *ndev)
*/
if (fep->quirks & FEC_QUIRK_ENET_MAC) {
memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
- writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
- writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
+ writel((__force u32)cpu_to_be32(temp_mac[0]),
+ fep->hwp + FEC_ADDR_LOW);
+ writel((__force u32)cpu_to_be32(temp_mac[1]),
+ fep->hwp + FEC_ADDR_HIGH);
}
/* Clear any outstanding interrupt. */
@@ -1222,7 +1226,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
while (bdp != READ_ONCE(txq->cur_tx)) {
/* Order the load of cur_tx and cbd_sc */
rmb();
- status = READ_ONCE(bdp->cbd_sc);
+ status = fec16_to_cpu(READ_ONCE(bdp->cbd_sc));
if (status & BD_ENET_TX_READY)
break;
@@ -1230,10 +1234,12 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
skb = txq->tx_skbuff[index];
txq->tx_skbuff[index] = NULL;
- if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
- dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
- bdp->cbd_datlen, DMA_TO_DEVICE);
- bdp->cbd_bufaddr = 0;
+ if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ bdp->cbd_bufaddr = cpu_to_fec32(0);
if (!skb) {
bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
continue;
@@ -1264,7 +1270,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
struct skb_shared_hwtstamps shhwtstamps;
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- fec_enet_hwtstamp(fep, ebdp->ts, &shhwtstamps);
+ fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps);
skb_tstamp_tx(skb, &shhwtstamps);
}
@@ -1324,10 +1330,8 @@ fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff
if (off)
skb_reserve(skb, fep->rx_align + 1 - off);
- bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
- FEC_ENET_RX_FRSIZE - fep->rx_align,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+ bdp->cbd_bufaddr = cpu_to_fec32(dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE));
+ if (dma_mapping_error(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr))) {
if (net_ratelimit())
netdev_err(ndev, "Rx DMA memory map failed\n");
return -ENOMEM;
@@ -1349,7 +1353,8 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
if (!new_skb)
return false;
- dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
+ dma_sync_single_for_cpu(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
FEC_ENET_RX_FRSIZE - fep->rx_align,
DMA_FROM_DEVICE);
if (!swap)
@@ -1396,7 +1401,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
*/
bdp = rxq->cur_rx;
- while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
+ while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) {
if (pkt_received >= budget)
break;
@@ -1438,7 +1443,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
/* Process the incoming frame. */
ndev->stats.rx_packets++;
- pkt_len = bdp->cbd_datlen;
+ pkt_len = fec16_to_cpu(bdp->cbd_datlen);
ndev->stats.rx_bytes += pkt_len;
index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep);
@@ -1456,7 +1461,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
ndev->stats.rx_dropped++;
goto rx_processing_done;
}
- dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
FEC_ENET_RX_FRSIZE - fep->rx_align,
DMA_FROM_DEVICE);
}
@@ -1475,7 +1481,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
/* If this is a VLAN packet remove the VLAN Tag */
vlan_packet_rcvd = false;
if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
- fep->bufdesc_ex && (ebdp->cbd_esc & BD_ENET_RX_VLAN)) {
+ fep->bufdesc_ex &&
+ (ebdp->cbd_esc & cpu_to_fec32(BD_ENET_RX_VLAN))) {
/* Push and remove the vlan tag */
struct vlan_hdr *vlan_header =
(struct vlan_hdr *) (data + ETH_HLEN);
@@ -1491,12 +1498,12 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
/* Get receive timestamp from the skb */
if (fep->hwts_rx_en && fep->bufdesc_ex)
- fec_enet_hwtstamp(fep, ebdp->ts,
+ fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts),
skb_hwtstamps(skb));
if (fep->bufdesc_ex &&
(fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
- if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) {
+ if (!(ebdp->cbd_esc & cpu_to_fec32(FLAG_RX_CSUM_ERROR))) {
/* don't check it */
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
@@ -1513,7 +1520,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
napi_gro_receive(&fep->napi, skb);
if (is_copybreak) {
- dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr,
+ dma_sync_single_for_device(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
FEC_ENET_RX_FRSIZE - fep->rx_align,
DMA_FROM_DEVICE);
} else {
@@ -1527,12 +1535,12 @@ rx_processing_done:
/* Mark the buffer empty */
status |= BD_ENET_RX_EMPTY;
- bdp->cbd_sc = status;
+ bdp->cbd_sc = cpu_to_fec16(status);
if (fep->bufdesc_ex) {
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- ebdp->cbd_esc = BD_ENET_RX_INT;
+ ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT);
ebdp->cbd_prot = 0;
ebdp->cbd_bdu = 0;
}
@@ -2145,8 +2153,7 @@ static int fec_enet_get_regs_len(struct net_device *ndev)
/* List of registers that can be safety be read to dump them with ethtool */
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
- defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
static u32 fec_enet_register_offset[] = {
FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0,
FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL,
@@ -2662,7 +2669,7 @@ static void fec_enet_free_buffers(struct net_device *ndev)
rxq->rx_skbuff[i] = NULL;
if (skb) {
dma_unmap_single(&fep->pdev->dev,
- bdp->cbd_bufaddr,
+ fec32_to_cpu(bdp->cbd_bufaddr),
FEC_ENET_RX_FRSIZE - fep->rx_align,
DMA_FROM_DEVICE);
dev_kfree_skb(skb);
@@ -2777,11 +2784,11 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
}
rxq->rx_skbuff[i] = skb;
- bdp->cbd_sc = BD_ENET_RX_EMPTY;
+ bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY);
if (fep->bufdesc_ex) {
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- ebdp->cbd_esc = BD_ENET_RX_INT;
+ ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT);
}
bdp = fec_enet_get_nextdesc(bdp, fep, queue);
@@ -2789,7 +2796,7 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
/* Set the last buffer to wrap. */
bdp = fec_enet_get_prevdesc(bdp, fep, queue);
- bdp->cbd_sc |= BD_SC_WRAP;
+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP);
return 0;
err_alloc:
@@ -2812,12 +2819,12 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
if (!txq->tx_bounce[i])
goto err_alloc;
- bdp->cbd_sc = 0;
- bdp->cbd_bufaddr = 0;
+ bdp->cbd_sc = cpu_to_fec16(0);
+ bdp->cbd_bufaddr = cpu_to_fec32(0);
if (fep->bufdesc_ex) {
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- ebdp->cbd_esc = BD_ENET_TX_INT;
+ ebdp->cbd_esc = cpu_to_fec32(BD_ENET_TX_INT);
}
bdp = fec_enet_get_nextdesc(bdp, fep, queue);
@@ -2825,7 +2832,7 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
/* Set the last buffer to wrap. */
bdp = fec_enet_get_prevdesc(bdp, fep, queue);
- bdp->cbd_sc |= BD_SC_WRAP;
+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP);
return 0;
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
index 52e0091..1ba359f 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
@@ -552,7 +552,7 @@ static void tx_restart(struct net_device *dev)
cbd_t __iomem *prev_bd;
cbd_t __iomem *last_tx_bd;
- last_tx_bd = fep->tx_bd_base + ((fpi->tx_ring - 1) * sizeof(cbd_t));
+ last_tx_bd = fep->tx_bd_base + (fpi->tx_ring - 1);
/* get the current bd held in TBPTR and scan back from this point */
recheck_bd = curr_tbptr = (cbd_t __iomem *)
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c
index b364529..3bfe36f 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.c
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.c
@@ -95,21 +95,17 @@ static struct hnae_buf_ops hnae_bops = {
static int __ae_match(struct device *dev, const void *data)
{
struct hnae_ae_dev *hdev = cls_to_ae_dev(dev);
- const char *ae_id = data;
- if (!strncmp(ae_id, hdev->name, AE_NAME_SIZE))
- return 1;
-
- return 0;
+ return hdev->dev->of_node == data;
}
-static struct hnae_ae_dev *find_ae(const char *ae_id)
+static struct hnae_ae_dev *find_ae(const struct device_node *ae_node)
{
struct device *dev;
- WARN_ON(!ae_id);
+ WARN_ON(!ae_node);
- dev = class_find_device(hnae_class, NULL, ae_id, __ae_match);
+ dev = class_find_device(hnae_class, NULL, ae_node, __ae_match);
return dev ? cls_to_ae_dev(dev) : NULL;
}
@@ -316,7 +312,8 @@ EXPORT_SYMBOL(hnae_reinit_handle);
* return handle ptr or ERR_PTR
*/
struct hnae_handle *hnae_get_handle(struct device *owner_dev,
- const char *ae_id, u32 port_id,
+ const struct device_node *ae_node,
+ u32 port_id,
struct hnae_buf_ops *bops)
{
struct hnae_ae_dev *dev;
@@ -324,7 +321,7 @@ struct hnae_handle *hnae_get_handle(struct device *owner_dev,
int i, j;
int ret;
- dev = find_ae(ae_id);
+ dev = find_ae(ae_node);
if (!dev)
return ERR_PTR(-ENODEV);
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h
index 6ca94dc..1cbcb9f 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -524,8 +524,11 @@ struct hnae_handle {
#define ring_to_dev(ring) ((ring)->q->dev->dev)
-struct hnae_handle *hnae_get_handle(struct device *owner_dev, const char *ae_id,
- u32 port_id, struct hnae_buf_ops *bops);
+struct hnae_handle *hnae_get_handle(struct device *owner_dev,
+ const struct device_node *ae_node,
+ u32 port_id,
+ struct hnae_buf_ops *bops);
+
void hnae_put_handle(struct hnae_handle *handle);
int hnae_ae_register(struct hnae_ae_dev *dev, struct module *owner);
void hnae_ae_unregister(struct hnae_ae_dev *dev);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index 522b264..a0070d0 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -847,6 +847,7 @@ static struct hnae_ae_ops hns_dsaf_ops = {
int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev)
{
struct hnae_ae_dev *ae_dev = &dsaf_dev->ae_dev;
+ static atomic_t id = ATOMIC_INIT(-1);
switch (dsaf_dev->dsaf_ver) {
case AE_VERSION_1:
@@ -858,6 +859,9 @@ int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev)
default:
break;
}
+
+ snprintf(ae_dev->name, AE_NAME_SIZE, "%s%d", DSAF_DEVICE_NAME,
+ (int)atomic_inc_return(&id));
ae_dev->ops = &hns_dsaf_ops;
ae_dev->dev = dsaf_dev->dev;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 1c33bd0..9439f04 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -35,7 +35,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev)
int ret, i;
u32 desc_num;
u32 buf_size;
- const char *name, *mode_str;
+ const char *mode_str;
struct device_node *np = dsaf_dev->dev->of_node;
if (of_device_is_compatible(np, "hisilicon,hns-dsaf-v1"))
@@ -43,14 +43,6 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev)
else
dsaf_dev->dsaf_ver = AE_VERSION_2;
- ret = of_property_read_string(np, "dsa_name", &name);
- if (ret) {
- dev_err(dsaf_dev->dev, "get dsaf name fail, ret=%d!\n", ret);
- return ret;
- }
- strncpy(dsaf_dev->ae_dev.name, name, AE_NAME_SIZE);
- dsaf_dev->ae_dev.name[AE_NAME_SIZE - 1] = '\0';
-
ret = of_property_read_string(np, "mode", &mode_str);
if (ret) {
dev_err(dsaf_dev->dev, "get dsaf mode fail, ret=%d!\n", ret);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
index 31c312f..40205b9 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -18,6 +18,7 @@ struct hns_mac_cb;
#define DSAF_DRV_NAME "hns_dsaf"
#define DSAF_MOD_VERSION "v1.0"
+#define DSAF_DEVICE_NAME "dsaf"
#define HNS_DSAF_DEBUG_NW_REG_OFFSET 0x100000
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 0e30846..3f77ff7 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1802,7 +1802,7 @@ static int hns_nic_try_get_ae(struct net_device *ndev)
int ret;
h = hnae_get_handle(&priv->netdev->dev,
- priv->ae_name, priv->port_id, NULL);
+ priv->ae_node, priv->port_id, NULL);
if (IS_ERR_OR_NULL(h)) {
ret = PTR_ERR(h);
dev_dbg(priv->dev, "has not handle, register notifier!\n");
@@ -1880,13 +1880,16 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
else
priv->enet_ver = AE_VERSION_2;
- ret = of_property_read_string(node, "ae-name", &priv->ae_name);
- if (ret)
- goto out_read_string_fail;
+ priv->ae_node = (void *)of_parse_phandle(node, "ae-handle", 0);
+ if (IS_ERR_OR_NULL(priv->ae_node)) {
+ ret = PTR_ERR(priv->ae_node);
+ dev_err(dev, "not find ae-handle\n");
+ goto out_read_prop_fail;
+ }
ret = of_property_read_u32(node, "port-id", &priv->port_id);
if (ret)
- goto out_read_string_fail;
+ goto out_read_prop_fail;
hns_init_mac_addr(ndev);
@@ -1945,7 +1948,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
out_notify_fail:
(void)cancel_work_sync(&priv->service_task);
-out_read_string_fail:
+out_read_prop_fail:
free_netdev(ndev);
return ret;
}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h
index 4b75270..c68ab3d 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h
@@ -51,7 +51,7 @@ struct hns_nic_ops {
};
struct hns_nic_priv {
- const char *ae_name;
+ const struct device_node *ae_node;
u32 enet_ver;
u32 port_id;
int phy_mode;
diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c
index 1d5c3e1..3daf2d4 100644
--- a/drivers/net/ethernet/hp/hp100.c
+++ b/drivers/net/ethernet/hp/hp100.c
@@ -194,7 +194,6 @@ static const char *hp100_isa_tbl[] = {
};
#endif
-#ifdef CONFIG_EISA
static struct eisa_device_id hp100_eisa_tbl[] = {
{ "HWPF180" }, /* HP J2577 rev A */
{ "HWP1920" }, /* HP 27248B */
@@ -205,9 +204,7 @@ static struct eisa_device_id hp100_eisa_tbl[] = {
{ "" } /* Mandatory final entry ! */
};
MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl);
-#endif
-#ifdef CONFIG_PCI
static const struct pci_device_id hp100_pci_tbl[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,},
@@ -219,7 +216,6 @@ static const struct pci_device_id hp100_pci_tbl[] = {
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, hp100_pci_tbl);
-#endif
static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;
static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;
@@ -2842,7 +2838,6 @@ static void cleanup_dev(struct net_device *d)
free_netdev(d);
}
-#ifdef CONFIG_EISA
static int hp100_eisa_probe(struct device *gendev)
{
struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));
@@ -2884,9 +2879,7 @@ static struct eisa_driver hp100_eisa_driver = {
.remove = hp100_eisa_remove,
}
};
-#endif
-#ifdef CONFIG_PCI
static int hp100_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -2955,7 +2948,6 @@ static struct pci_driver hp100_pci_driver = {
.probe = hp100_pci_probe,
.remove = hp100_pci_remove,
};
-#endif
/*
* module section
@@ -3032,23 +3024,17 @@ static int __init hp100_module_init(void)
err = hp100_isa_init();
if (err && err != -ENODEV)
goto out;
-#ifdef CONFIG_EISA
err = eisa_driver_register(&hp100_eisa_driver);
if (err && err != -ENODEV)
goto out2;
-#endif
-#ifdef CONFIG_PCI
err = pci_register_driver(&hp100_pci_driver);
if (err && err != -ENODEV)
goto out3;
-#endif
out:
return err;
out3:
-#ifdef CONFIG_EISA
eisa_driver_unregister (&hp100_eisa_driver);
out2:
-#endif
hp100_isa_cleanup();
goto out;
}
@@ -3057,12 +3043,8 @@ static int __init hp100_module_init(void)
static void __exit hp100_module_exit(void)
{
hp100_isa_cleanup();
-#ifdef CONFIG_EISA
eisa_driver_unregister (&hp100_eisa_driver);
-#endif
-#ifdef CONFIG_PCI
pci_unregister_driver (&hp100_pci_driver);
-#endif
}
module_init(hp100_module_init)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index bb4612c..8f3b53e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -7117,9 +7117,7 @@ static void i40e_service_task(struct work_struct *work)
i40e_watchdog_subtask(pf);
i40e_fdir_reinit_subtask(pf);
i40e_sync_filters_subtask(pf);
-#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE)
i40e_sync_udp_filters_subtask(pf);
-#endif
i40e_clean_adminq_subtask(pf);
i40e_service_event_complete(pf);
@@ -8515,6 +8513,8 @@ static u8 i40e_get_udp_port_idx(struct i40e_pf *pf, __be16 port)
}
#endif
+
+#if IS_ENABLED(CONFIG_VXLAN)
/**
* i40e_add_vxlan_port - Get notifications about VXLAN ports that come up
* @netdev: This physical port's netdev
@@ -8524,7 +8524,6 @@ static u8 i40e_get_udp_port_idx(struct i40e_pf *pf, __be16 port)
static void i40e_add_vxlan_port(struct net_device *netdev,
sa_family_t sa_family, __be16 port)
{
-#if IS_ENABLED(CONFIG_VXLAN)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
@@ -8557,7 +8556,6 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_VXLAN;
pf->pending_udp_bitmap |= BIT_ULL(next_idx);
pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
-#endif
}
/**
@@ -8569,7 +8567,6 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
static void i40e_del_vxlan_port(struct net_device *netdev,
sa_family_t sa_family, __be16 port)
{
-#if IS_ENABLED(CONFIG_VXLAN)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
@@ -8592,9 +8589,10 @@ static void i40e_del_vxlan_port(struct net_device *netdev,
netdev_warn(netdev, "vxlan port %d was not found, not deleting\n",
ntohs(port));
}
-#endif
}
+#endif
+#if IS_ENABLED(CONFIG_GENEVE)
/**
* i40e_add_geneve_port - Get notifications about GENEVE ports that come up
* @netdev: This physical port's netdev
@@ -8604,7 +8602,6 @@ static void i40e_del_vxlan_port(struct net_device *netdev,
static void i40e_add_geneve_port(struct net_device *netdev,
sa_family_t sa_family, __be16 port)
{
-#if IS_ENABLED(CONFIG_GENEVE)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
@@ -8639,7 +8636,6 @@ static void i40e_add_geneve_port(struct net_device *netdev,
pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
dev_info(&pf->pdev->dev, "adding geneve port %d\n", ntohs(port));
-#endif
}
/**
@@ -8651,7 +8647,6 @@ static void i40e_add_geneve_port(struct net_device *netdev,
static void i40e_del_geneve_port(struct net_device *netdev,
sa_family_t sa_family, __be16 port)
{
-#if IS_ENABLED(CONFIG_GENEVE)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
@@ -8677,8 +8672,8 @@ static void i40e_del_geneve_port(struct net_device *netdev,
netdev_warn(netdev, "geneve port %d was not found, not deleting\n",
ntohs(port));
}
-#endif
}
+#endif
static int i40e_get_phys_port_id(struct net_device *netdev,
struct netdev_phys_item_id *ppid)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 720516b0..47bd8b3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2313,8 +2313,8 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
struct iphdr *this_ip_hdr;
u32 network_hdr_len;
u8 l4_hdr = 0;
- struct udphdr *oudph;
- struct iphdr *oiph;
+ struct udphdr *oudph = NULL;
+ struct iphdr *oiph = NULL;
u32 l4_tunnel = 0;
if (skb->encapsulation) {
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index a0c0383..5583118 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -762,10 +762,10 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
if (length <= 8 && (uintptr_t)data & 0x7) {
/* Copy unaligned small data fragment to TSO header data area */
- memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE,
+ memcpy(txq->tso_hdrs + tx_index * TSO_HEADER_SIZE,
data, length);
desc->buf_ptr = txq->tso_hdrs_dma
- + txq->tx_curr_desc * TSO_HEADER_SIZE;
+ + tx_index * TSO_HEADER_SIZE;
} else {
/* Alignment is okay, map buffer and hand off to hardware */
txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index fabc8df..662c2ee 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -11,28 +11,28 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
#include <linux/etherdevice.h>
-#include <linux/platform_device.h>
-#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
#include <linux/inetdevice.h>
-#include <linux/mbus.h>
-#include <linux/module.h>
#include <linux/interrupt.h>
-#include <linux/if_vlan.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
#include <linux/io.h>
-#include <net/tso.h>
+#include <linux/kernel.h>
+#include <linux/mbus.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
-#include <linux/of_address.h>
#include <linux/phy.h>
-#include <linux/clk.h>
-#include <linux/cpu.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/tso.h>
/* Registers */
#define MVNETA_RXQ_CONFIG_REG(q) (0x1400 + ((q) << 2))
@@ -373,6 +373,8 @@ struct mvneta_port {
/* Core clock */
struct clk *clk;
+ /* AXI clock */
+ struct clk *clk_bus;
u8 mcast_count[256];
u16 tx_ring_size;
u16 rx_ring_size;
@@ -3242,26 +3244,25 @@ static void mvneta_ethtool_update_stats(struct mvneta_port *pp)
const struct mvneta_statistic *s;
void __iomem *base = pp->base;
u32 high, low, val;
+ u64 val64;
int i;
for (i = 0, s = mvneta_statistics;
s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics);
s++, i++) {
- val = 0;
-
switch (s->type) {
case T_REG_32:
val = readl_relaxed(base + s->offset);
+ pp->ethtool_stats[i] += val;
break;
case T_REG_64:
/* Docs say to read low 32-bit then high */
low = readl_relaxed(base + s->offset);
high = readl_relaxed(base + s->offset + 4);
- val = (u64)high << 32 | low;
+ val64 = (u64)high << 32 | low;
+ pp->ethtool_stats[i] += val64;
break;
}
-
- pp->ethtool_stats[i] += val;
}
}
@@ -3605,7 +3606,9 @@ static int mvneta_probe(struct platform_device *pdev)
pp->indir[0] = rxq_def;
- pp->clk = devm_clk_get(&pdev->dev, NULL);
+ pp->clk = devm_clk_get(&pdev->dev, "core");
+ if (IS_ERR(pp->clk))
+ pp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pp->clk)) {
err = PTR_ERR(pp->clk);
goto err_put_phy_node;
@@ -3613,6 +3616,10 @@ static int mvneta_probe(struct platform_device *pdev)
clk_prepare_enable(pp->clk);
+ pp->clk_bus = devm_clk_get(&pdev->dev, "bus");
+ if (!IS_ERR(pp->clk_bus))
+ clk_prepare_enable(pp->clk_bus);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pp->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pp->base)) {
@@ -3724,6 +3731,7 @@ err_free_stats:
err_free_ports:
free_percpu(pp->ports);
err_clk:
+ clk_disable_unprepare(pp->clk_bus);
clk_disable_unprepare(pp->clk);
err_put_phy_node:
of_node_put(phy_node);
@@ -3741,6 +3749,7 @@ static int mvneta_remove(struct platform_device *pdev)
struct mvneta_port *pp = netdev_priv(dev);
unregister_netdev(dev);
+ clk_disable_unprepare(pp->clk_bus);
clk_disable_unprepare(pp->clk);
free_percpu(pp->ports);
free_percpu(pp->stats);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 0c52372..bb77e22 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -1044,6 +1044,92 @@ static inline void mlxsw_reg_sftr_pack(char *payload,
mlxsw_reg_sftr_port_mask_set(payload, port, 1);
}
+/* SFDF - Switch Filtering DB Flush
+ * --------------------------------
+ * The switch filtering DB flush register is used to flush the FDB.
+ * Note that FDB notifications are flushed as well.
+ */
+#define MLXSW_REG_SFDF_ID 0x2013
+#define MLXSW_REG_SFDF_LEN 0x14
+
+static const struct mlxsw_reg_info mlxsw_reg_sfdf = {
+ .id = MLXSW_REG_SFDF_ID,
+ .len = MLXSW_REG_SFDF_LEN,
+};
+
+/* reg_sfdf_swid
+ * Switch partition ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, sfdf, swid, 0x00, 24, 8);
+
+enum mlxsw_reg_sfdf_flush_type {
+ MLXSW_REG_SFDF_FLUSH_PER_SWID,
+ MLXSW_REG_SFDF_FLUSH_PER_FID,
+ MLXSW_REG_SFDF_FLUSH_PER_PORT,
+ MLXSW_REG_SFDF_FLUSH_PER_PORT_AND_FID,
+ MLXSW_REG_SFDF_FLUSH_PER_LAG,
+ MLXSW_REG_SFDF_FLUSH_PER_LAG_AND_FID,
+};
+
+/* reg_sfdf_flush_type
+ * Flush type.
+ * 0 - All SWID dynamic entries are flushed.
+ * 1 - All FID dynamic entries are flushed.
+ * 2 - All dynamic entries pointing to port are flushed.
+ * 3 - All FID dynamic entries pointing to port are flushed.
+ * 4 - All dynamic entries pointing to LAG are flushed.
+ * 5 - All FID dynamic entries pointing to LAG are flushed.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdf, flush_type, 0x04, 28, 4);
+
+/* reg_sfdf_flush_static
+ * Static.
+ * 0 - Flush only dynamic entries.
+ * 1 - Flush both dynamic and static entries.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdf, flush_static, 0x04, 24, 1);
+
+static inline void mlxsw_reg_sfdf_pack(char *payload,
+ enum mlxsw_reg_sfdf_flush_type type)
+{
+ MLXSW_REG_ZERO(sfdf, payload);
+ mlxsw_reg_sfdf_flush_type_set(payload, type);
+ mlxsw_reg_sfdf_flush_static_set(payload, true);
+}
+
+/* reg_sfdf_fid
+ * FID to flush.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdf, fid, 0x0C, 0, 16);
+
+/* reg_sfdf_system_port
+ * Port to flush.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdf, system_port, 0x0C, 0, 16);
+
+/* reg_sfdf_port_fid_system_port
+ * Port to flush, pointed to by FID.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdf, port_fid_system_port, 0x08, 0, 16);
+
+/* reg_sfdf_lag_id
+ * LAG ID to flush.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdf, lag_id, 0x0C, 0, 10);
+
+/* reg_sfdf_lag_fid_lag_id
+ * LAG ID to flush, pointed to by FID.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, sfdf, lag_fid_lag_id, 0x08, 0, 10);
+
/* SLDR - Switch LAG Descriptor Register
* -----------------------------------------
* The switch LAG descriptor register is populated by LAG descriptors.
@@ -1701,20 +1787,20 @@ MLXSW_ITEM32(reg, pmlp, width, 0x00, 0, 8);
* Module number.
* Access: RW
*/
-MLXSW_ITEM32_INDEXED(reg, pmlp, module, 0x04, 0, 8, 0x04, 0, false);
+MLXSW_ITEM32_INDEXED(reg, pmlp, module, 0x04, 0, 8, 0x04, 0x00, false);
/* reg_pmlp_tx_lane
* Tx Lane. When rxtx field is cleared, this field is used for Rx as well.
* Access: RW
*/
-MLXSW_ITEM32_INDEXED(reg, pmlp, tx_lane, 0x04, 16, 2, 0x04, 16, false);
+MLXSW_ITEM32_INDEXED(reg, pmlp, tx_lane, 0x04, 16, 2, 0x04, 0x00, false);
/* reg_pmlp_rx_lane
* Rx Lane. When rxtx field is cleared, this field is ignored and Rx lane is
* equal to Tx lane.
* Access: RW
*/
-MLXSW_ITEM32_INDEXED(reg, pmlp, rx_lane, 0x04, 24, 2, 0x04, 24, false);
+MLXSW_ITEM32_INDEXED(reg, pmlp, rx_lane, 0x04, 24, 2, 0x04, 0x00, false);
static inline void mlxsw_reg_pmlp_pack(char *payload, u8 local_port)
{
@@ -3121,6 +3207,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id)
return "SFGC";
case MLXSW_REG_SFTR_ID:
return "SFTR";
+ case MLXSW_REG_SFDF_ID:
+ return "SFDF";
case MLXSW_REG_SLDR_ID:
return "SLDR";
case MLXSW_REG_SLCR_ID:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index ce6845d..217856b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1979,6 +1979,115 @@ static struct mlxsw_driver mlxsw_sp_driver = {
.profile = &mlxsw_sp_config_profile,
};
+static int
+mlxsw_sp_port_fdb_flush_by_port(const struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char sfdf_pl[MLXSW_REG_SFDF_LEN];
+
+ mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_PORT);
+ mlxsw_reg_sfdf_system_port_set(sfdf_pl, mlxsw_sp_port->local_port);
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
+}
+
+static int
+mlxsw_sp_port_fdb_flush_by_port_fid(const struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 fid)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char sfdf_pl[MLXSW_REG_SFDF_LEN];
+
+ mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_PORT_AND_FID);
+ mlxsw_reg_sfdf_fid_set(sfdf_pl, fid);
+ mlxsw_reg_sfdf_port_fid_system_port_set(sfdf_pl,
+ mlxsw_sp_port->local_port);
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
+}
+
+static int
+mlxsw_sp_port_fdb_flush_by_lag_id(const struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char sfdf_pl[MLXSW_REG_SFDF_LEN];
+
+ mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_LAG);
+ mlxsw_reg_sfdf_lag_id_set(sfdf_pl, mlxsw_sp_port->lag_id);
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
+}
+
+static int
+mlxsw_sp_port_fdb_flush_by_lag_id_fid(const struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 fid)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ char sfdf_pl[MLXSW_REG_SFDF_LEN];
+
+ mlxsw_reg_sfdf_pack(sfdf_pl, MLXSW_REG_SFDF_FLUSH_PER_LAG_AND_FID);
+ mlxsw_reg_sfdf_fid_set(sfdf_pl, fid);
+ mlxsw_reg_sfdf_lag_fid_lag_id_set(sfdf_pl, mlxsw_sp_port->lag_id);
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
+}
+
+static int
+__mlxsw_sp_port_fdb_flush(const struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ int err, last_err = 0;
+ u16 vid;
+
+ for (vid = 1; vid < VLAN_N_VID - 1; vid++) {
+ err = mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_port, vid);
+ if (err)
+ last_err = err;
+ }
+
+ return last_err;
+}
+
+static int
+__mlxsw_sp_port_fdb_flush_lagged(const struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ int err, last_err = 0;
+ u16 vid;
+
+ for (vid = 1; vid < VLAN_N_VID - 1; vid++) {
+ err = mlxsw_sp_port_fdb_flush_by_lag_id_fid(mlxsw_sp_port, vid);
+ if (err)
+ last_err = err;
+ }
+
+ return last_err;
+}
+
+static int mlxsw_sp_port_fdb_flush(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ if (!list_empty(&mlxsw_sp_port->vports_list))
+ if (mlxsw_sp_port->lagged)
+ return __mlxsw_sp_port_fdb_flush_lagged(mlxsw_sp_port);
+ else
+ return __mlxsw_sp_port_fdb_flush(mlxsw_sp_port);
+ else
+ if (mlxsw_sp_port->lagged)
+ return mlxsw_sp_port_fdb_flush_by_lag_id(mlxsw_sp_port);
+ else
+ return mlxsw_sp_port_fdb_flush_by_port(mlxsw_sp_port);
+}
+
+static int mlxsw_sp_vport_fdb_flush(struct mlxsw_sp_port *mlxsw_sp_vport)
+{
+ u16 vfid = mlxsw_sp_vport_vfid_get(mlxsw_sp_vport);
+ u16 fid = mlxsw_sp_vfid_to_fid(vfid);
+
+ if (mlxsw_sp_vport->lagged)
+ return mlxsw_sp_port_fdb_flush_by_lag_id_fid(mlxsw_sp_vport,
+ fid);
+ else
+ return mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_vport, fid);
+}
+
static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
{
return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
@@ -2006,10 +2115,14 @@ static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port)
return 0;
}
-static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port)
+static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool flush_fdb)
{
struct net_device *dev = mlxsw_sp_port->dev;
+ if (flush_fdb && mlxsw_sp_port_fdb_flush(mlxsw_sp_port))
+ netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n");
+
mlxsw_sp_port->learning = 0;
mlxsw_sp_port->learning_sync = 0;
mlxsw_sp_port->uc_flood = 0;
@@ -2200,10 +2313,15 @@ err_col_port_enable:
return err;
}
+static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
+ struct net_device *br_dev,
+ bool flush_fdb);
+
static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *lag_dev)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_port *mlxsw_sp_vport;
struct mlxsw_sp_upper *lag;
u16 lag_id = mlxsw_sp_port->lag_id;
int err;
@@ -2220,7 +2338,32 @@ static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
if (err)
return err;
+ /* In case we leave a LAG device that has bridges built on top,
+ * then their teardown sequence is never issued and we need to
+ * invoke the necessary cleanup routines ourselves.
+ */
+ list_for_each_entry(mlxsw_sp_vport, &mlxsw_sp_port->vports_list,
+ vport.list) {
+ struct net_device *br_dev;
+
+ if (!mlxsw_sp_vport->bridged)
+ continue;
+
+ br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport);
+ mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev, false);
+ }
+
+ if (mlxsw_sp_port->bridged) {
+ mlxsw_sp_port_active_vlans_del(mlxsw_sp_port);
+ mlxsw_sp_port_bridge_leave(mlxsw_sp_port, false);
+
+ if (lag->ref_count == 1)
+ mlxsw_sp_master_bridge_dec(mlxsw_sp, NULL);
+ }
+
if (lag->ref_count == 1) {
+ if (mlxsw_sp_port_fdb_flush_by_lag_id(mlxsw_sp_port))
+ netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n");
err = mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
if (err)
return err;
@@ -2272,9 +2415,6 @@ static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port,
return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled);
}
-static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
- struct net_device *br_dev);
-
static int mlxsw_sp_port_vlan_link(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *vlan_dev)
{
@@ -2312,7 +2452,7 @@ static int mlxsw_sp_port_vlan_unlink(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *br_dev;
br_dev = mlxsw_sp_vport_br_get(mlxsw_sp_vport);
- mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev);
+ mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport, br_dev, true);
}
mlxsw_sp_vport->dev = mlxsw_sp_port->dev;
@@ -2374,7 +2514,8 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
}
mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev);
} else {
- err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port);
+ err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port,
+ true);
mlxsw_sp_master_bridge_dec(mlxsw_sp, upper_dev);
if (err) {
netdev_err(dev, "Failed to leave bridge\n");
@@ -2541,7 +2682,8 @@ static void mlxsw_sp_br_vfid_destroy(struct mlxsw_sp *mlxsw_sp,
}
static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
- struct net_device *br_dev)
+ struct net_device *br_dev,
+ bool flush_fdb)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_vport->mlxsw_sp;
u16 vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
@@ -2604,6 +2746,9 @@ static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
goto err_vport_flood_set;
}
+ if (flush_fdb && mlxsw_sp_vport_fdb_flush(mlxsw_sp_vport))
+ netdev_err(dev, "Failed to flush FDB\n");
+
/* Switch between the vFIDs and destroy the old one if needed. */
new_vfid->nr_vports++;
mlxsw_sp_vport->vport.vfid = new_vfid;
@@ -2777,7 +2922,7 @@ static int mlxsw_sp_netdevice_vport_event(struct net_device *dev,
if (!mlxsw_sp_vport)
return NOTIFY_DONE;
err = mlxsw_sp_vport_bridge_leave(mlxsw_sp_vport,
- upper_dev);
+ upper_dev, true);
if (err) {
netdev_err(dev, "Failed to leave bridge\n");
return NOTIFY_BAD;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index a23dc61..7f42eb1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -120,7 +120,6 @@ struct mlxsw_sp {
} fdb_notify;
#define MLXSW_SP_DEFAULT_AGEING_TIME 300
u32 ageing_time;
- struct mutex fdb_lock; /* Make sure FDB sessions are atomic. */
struct mlxsw_sp_upper master_bridge;
struct mlxsw_sp_upper lags[MLXSW_SP_LAG_MAX];
};
@@ -254,5 +253,6 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev,
__be16 __always_unused proto, u16 vid);
int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
bool set, bool only_uc);
+void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);
#endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 45479ef..e492ca2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -45,6 +45,7 @@
#include <linux/if_bridge.h>
#include <linux/workqueue.h>
#include <linux/jiffies.h>
+#include <linux/rtnetlink.h>
#include <net/switchdev.h>
#include "spectrum.h"
@@ -124,14 +125,14 @@ static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
int err;
switch (state) {
- case BR_STATE_DISABLED: /* fall-through */
case BR_STATE_FORWARDING:
spms_state = MLXSW_REG_SPMS_STATE_FORWARDING;
break;
- case BR_STATE_LISTENING: /* fall-through */
case BR_STATE_LEARNING:
spms_state = MLXSW_REG_SPMS_STATE_LEARNING;
break;
+ case BR_STATE_LISTENING: /* fall-through */
+ case BR_STATE_DISABLED: /* fall-through */
case BR_STATE_BLOCKING:
spms_state = MLXSW_REG_SPMS_STATE_DISCARDING;
break;
@@ -936,6 +937,14 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
vlan->vid_begin, vlan->vid_end, false);
}
+void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ u16 vid;
+
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
+ __mlxsw_sp_port_vlans_del(mlxsw_sp_port, vid, vid, false);
+}
+
static int
mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port,
const struct switchdev_obj_port_fdb *fdb)
@@ -1040,10 +1049,12 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
struct switchdev_obj_port_fdb *fdb,
- switchdev_obj_dump_cb_t *cb)
+ switchdev_obj_dump_cb_t *cb,
+ struct net_device *orig_dev)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- u16 vport_vid = 0, vport_fid = 0;
+ struct mlxsw_sp_port *tmp;
+ u16 vport_fid = 0;
char *sfd_pl;
char mac[ETH_ALEN];
u16 fid;
@@ -1058,13 +1069,11 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
if (!sfd_pl)
return -ENOMEM;
- mutex_lock(&mlxsw_sp_port->mlxsw_sp->fdb_lock);
if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
u16 tmp;
tmp = mlxsw_sp_vport_vfid_get(mlxsw_sp_port);
vport_fid = mlxsw_sp_vfid_to_fid(tmp);
- vport_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
}
mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0);
@@ -1088,12 +1097,13 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac, &fid,
&local_port);
if (local_port == mlxsw_sp_port->local_port) {
- if (vport_fid && vport_fid != fid)
- continue;
- else if (vport_fid)
- fdb->vid = vport_vid;
- else
+ if (vport_fid && vport_fid == fid)
+ fdb->vid = 0;
+ else if (!vport_fid &&
+ !mlxsw_sp_fid_is_vfid(fid))
fdb->vid = fid;
+ else
+ continue;
ether_addr_copy(fdb->addr, mac);
fdb->ndm_state = NUD_REACHABLE;
err = cb(&fdb->obj);
@@ -1104,14 +1114,22 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
case MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG:
mlxsw_reg_sfd_uc_lag_unpack(sfd_pl, i,
mac, &fid, &lag_id);
- if (mlxsw_sp_port ==
- mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id)) {
- if (vport_fid && vport_fid != fid)
+ tmp = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id);
+ if (tmp && tmp->local_port ==
+ mlxsw_sp_port->local_port) {
+ /* LAG records can only point to LAG
+ * devices or VLAN devices on top.
+ */
+ if (!netif_is_lag_master(orig_dev) &&
+ !is_vlan_dev(orig_dev))
continue;
- else if (vport_fid)
- fdb->vid = vport_vid;
- else
+ if (vport_fid && vport_fid == fid)
+ fdb->vid = 0;
+ else if (!vport_fid &&
+ !mlxsw_sp_fid_is_vfid(fid))
fdb->vid = fid;
+ else
+ continue;
ether_addr_copy(fdb->addr, mac);
fdb->ndm_state = NUD_REACHABLE;
err = cb(&fdb->obj);
@@ -1124,7 +1142,6 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
} while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT);
out:
- mutex_unlock(&mlxsw_sp_port->mlxsw_sp->fdb_lock);
kfree(sfd_pl);
return stored_err ? stored_err : err;
}
@@ -1176,7 +1193,8 @@ static int mlxsw_sp_port_obj_dump(struct net_device *dev,
break;
case SWITCHDEV_OBJ_ID_PORT_FDB:
err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port,
- SWITCHDEV_OBJ_PORT_FDB(obj), cb);
+ SWITCHDEV_OBJ_PORT_FDB(obj), cb,
+ obj->orig_dev);
break;
default:
err = -EOPNOTSUPP;
@@ -1194,14 +1212,14 @@ static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
.switchdev_port_obj_dump = mlxsw_sp_port_obj_dump,
};
-static void mlxsw_sp_fdb_call_notifiers(bool learning, bool learning_sync,
- bool adding, char *mac, u16 vid,
+static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
+ char *mac, u16 vid,
struct net_device *dev)
{
struct switchdev_notifier_fdb_info info;
unsigned long notifier_type;
- if (learning && learning_sync) {
+ if (learning_sync) {
info.addr = mac;
info.vid = vid;
notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
@@ -1237,7 +1255,7 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n");
goto just_remove;
}
- vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
+ vid = 0;
/* Override the physical port with the vPort. */
mlxsw_sp_port = mlxsw_sp_vport;
} else {
@@ -1257,8 +1275,7 @@ do_fdb_op:
if (!do_notification)
return;
- mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning,
- mlxsw_sp_port->learning_sync,
+ mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning_sync,
adding, mac, vid, mlxsw_sp_port->dev);
return;
@@ -1273,6 +1290,7 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
bool adding)
{
struct mlxsw_sp_port *mlxsw_sp_port;
+ struct net_device *dev;
char mac[ETH_ALEN];
u16 lag_vid = 0;
u16 lag_id;
@@ -1298,11 +1316,13 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
goto just_remove;
}
- vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
- lag_vid = vid;
+ lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
+ dev = mlxsw_sp_vport->dev;
+ vid = 0;
/* Override the physical port with the vPort. */
mlxsw_sp_port = mlxsw_sp_vport;
} else {
+ dev = mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev;
vid = fid;
}
@@ -1319,10 +1339,8 @@ do_fdb_op:
if (!do_notification)
return;
- mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning,
- mlxsw_sp_port->learning_sync,
- adding, mac, vid,
- mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev);
+ mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning_sync, adding, mac,
+ vid, dev);
return;
just_remove:
@@ -1374,7 +1392,7 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
- mutex_lock(&mlxsw_sp->fdb_lock);
+ rtnl_lock();
do {
mlxsw_reg_sfn_pack(sfn_pl);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
@@ -1387,7 +1405,7 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
} while (num_rec);
- mutex_unlock(&mlxsw_sp->fdb_lock);
+ rtnl_unlock();
kfree(sfn_pl);
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
@@ -1402,7 +1420,6 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
return err;
}
- mutex_init(&mlxsw_sp->fdb_lock);
INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index a10c928..00cfd95 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -28,6 +28,16 @@
#include "moxart_ether.h"
+static inline void moxart_desc_write(u32 data, u32 *desc)
+{
+ *desc = cpu_to_le32(data);
+}
+
+static inline u32 moxart_desc_read(u32 *desc)
+{
+ return le32_to_cpu(*desc);
+}
+
static inline void moxart_emac_write(struct net_device *ndev,
unsigned int reg, unsigned long value)
{
@@ -112,7 +122,7 @@ static void moxart_mac_enable(struct net_device *ndev)
static void moxart_mac_setup_desc_ring(struct net_device *ndev)
{
struct moxart_mac_priv_t *priv = netdev_priv(ndev);
- void __iomem *desc;
+ void *desc;
int i;
for (i = 0; i < TX_DESC_NUM; i++) {
@@ -121,7 +131,7 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev)
priv->tx_buf[i] = priv->tx_buf_base + priv->tx_buf_size * i;
}
- writel(TX_DESC1_END, desc + TX_REG_OFFSET_DESC1);
+ moxart_desc_write(TX_DESC1_END, desc + TX_REG_OFFSET_DESC1);
priv->tx_head = 0;
priv->tx_tail = 0;
@@ -129,8 +139,8 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev)
for (i = 0; i < RX_DESC_NUM; i++) {
desc = priv->rx_desc_base + i * RX_REG_DESC_SIZE;
memset(desc, 0, RX_REG_DESC_SIZE);
- writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0);
- writel(RX_BUF_SIZE & RX_DESC1_BUF_SIZE_MASK,
+ moxart_desc_write(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0);
+ moxart_desc_write(RX_BUF_SIZE & RX_DESC1_BUF_SIZE_MASK,
desc + RX_REG_OFFSET_DESC1);
priv->rx_buf[i] = priv->rx_buf_base + priv->rx_buf_size * i;
@@ -141,12 +151,12 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev)
if (dma_mapping_error(&ndev->dev, priv->rx_mapping[i]))
netdev_err(ndev, "DMA mapping error\n");
- writel(priv->rx_mapping[i],
+ moxart_desc_write(priv->rx_mapping[i],
desc + RX_REG_OFFSET_DESC2 + RX_DESC2_ADDRESS_PHYS);
- writel(priv->rx_buf[i],
+ moxart_desc_write((uintptr_t)priv->rx_buf[i],
desc + RX_REG_OFFSET_DESC2 + RX_DESC2_ADDRESS_VIRT);
}
- writel(RX_DESC1_END, desc + RX_REG_OFFSET_DESC1);
+ moxart_desc_write(RX_DESC1_END, desc + RX_REG_OFFSET_DESC1);
priv->rx_head = 0;
@@ -201,14 +211,15 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget)
napi);
struct net_device *ndev = priv->ndev;
struct sk_buff *skb;
- void __iomem *desc;
+ void *desc;
unsigned int desc0, len;
int rx_head = priv->rx_head;
int rx = 0;
while (rx < budget) {
desc = priv->rx_desc_base + (RX_REG_DESC_SIZE * rx_head);
- desc0 = readl(desc + RX_REG_OFFSET_DESC0);
+ desc0 = moxart_desc_read(desc + RX_REG_OFFSET_DESC0);
+ rmb(); /* ensure desc0 is up to date */
if (desc0 & RX_DESC0_DMA_OWN)
break;
@@ -250,7 +261,8 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget)
priv->stats.multicast++;
rx_next:
- writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0);
+ wmb(); /* prevent setting ownership back too early */
+ moxart_desc_write(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0);
rx_head = RX_NEXT(rx_head);
priv->rx_head = rx_head;
@@ -310,7 +322,7 @@ static irqreturn_t moxart_mac_interrupt(int irq, void *dev_id)
static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct moxart_mac_priv_t *priv = netdev_priv(ndev);
- void __iomem *desc;
+ void *desc;
unsigned int len;
unsigned int tx_head = priv->tx_head;
u32 txdes1;
@@ -319,11 +331,12 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
desc = priv->tx_desc_base + (TX_REG_DESC_SIZE * tx_head);
spin_lock_irq(&priv->txlock);
- if (readl(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) {
+ if (moxart_desc_read(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) {
net_dbg_ratelimited("no TX space for packet\n");
priv->stats.tx_dropped++;
goto out_unlock;
}
+ rmb(); /* ensure data is only read that had TX_DESC0_DMA_OWN cleared */
len = skb->len > TX_BUF_SIZE ? TX_BUF_SIZE : skb->len;
@@ -337,9 +350,9 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
priv->tx_len[tx_head] = len;
priv->tx_skb[tx_head] = skb;
- writel(priv->tx_mapping[tx_head],
+ moxart_desc_write(priv->tx_mapping[tx_head],
desc + TX_REG_OFFSET_DESC2 + TX_DESC2_ADDRESS_PHYS);
- writel(skb->data,
+ moxart_desc_write((uintptr_t)skb->data,
desc + TX_REG_OFFSET_DESC2 + TX_DESC2_ADDRESS_VIRT);
if (skb->len < ETH_ZLEN) {
@@ -354,8 +367,9 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
txdes1 = TX_DESC1_LTS | TX_DESC1_FTS | (len & TX_DESC1_BUF_SIZE_MASK);
if (tx_head == TX_DESC_NUM_MASK)
txdes1 |= TX_DESC1_END;
- writel(txdes1, desc + TX_REG_OFFSET_DESC1);
- writel(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0);
+ moxart_desc_write(txdes1, desc + TX_REG_OFFSET_DESC1);
+ wmb(); /* flush descriptor before transferring ownership */
+ moxart_desc_write(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0);
/* start to send packet */
writel(0xffffffff, priv->base + REG_TX_POLL_DEMAND);
diff --git a/drivers/net/ethernet/moxa/moxart_ether.h b/drivers/net/ethernet/moxa/moxart_ether.h
index 2be9280..93a9563 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.h
+++ b/drivers/net/ethernet/moxa/moxart_ether.h
@@ -300,7 +300,7 @@ struct moxart_mac_priv_t {
dma_addr_t rx_base;
dma_addr_t rx_mapping[RX_DESC_NUM];
- void __iomem *rx_desc_base;
+ void *rx_desc_base;
unsigned char *rx_buf_base;
unsigned char *rx_buf[RX_DESC_NUM];
unsigned int rx_head;
@@ -308,7 +308,7 @@ struct moxart_mac_priv_t {
dma_addr_t tx_base;
dma_addr_t tx_mapping[TX_DESC_NUM];
- void __iomem *tx_desc_base;
+ void *tx_desc_base;
unsigned char *tx_buf_base;
unsigned char *tx_buf[RX_DESC_NUM];
unsigned int tx_head;
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index 50d5604..e0993eb 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -2223,8 +2223,6 @@ static irqreturn_t vxge_isr_napi(int irq, void *dev_id)
return IRQ_NONE;
}
-#ifdef CONFIG_PCI_MSI
-
static irqreturn_t vxge_tx_msix_handle(int irq, void *dev_id)
{
struct vxge_fifo *fifo = (struct vxge_fifo *)dev_id;
@@ -2442,16 +2440,13 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev)
if (vdev->config.intr_type == MSI_X)
pci_disable_msix(vdev->pdev);
}
-#endif
static void vxge_rem_isr(struct vxgedev *vdev)
{
-#ifdef CONFIG_PCI_MSI
- if (vdev->config.intr_type == MSI_X) {
+ if (IS_ENABLED(CONFIG_PCI_MSI) &&
+ vdev->config.intr_type == MSI_X) {
vxge_rem_msix_isr(vdev);
- } else
-#endif
- if (vdev->config.intr_type == INTA) {
+ } else if (vdev->config.intr_type == INTA) {
synchronize_irq(vdev->pdev->irq);
free_irq(vdev->pdev->irq, vdev);
}
@@ -2460,11 +2455,10 @@ static void vxge_rem_isr(struct vxgedev *vdev)
static int vxge_add_isr(struct vxgedev *vdev)
{
int ret = 0;
-#ifdef CONFIG_PCI_MSI
int vp_idx = 0, intr_idx = 0, intr_cnt = 0, msix_idx = 0, irq_req = 0;
int pci_fun = PCI_FUNC(vdev->pdev->devfn);
- if (vdev->config.intr_type == MSI_X)
+ if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X)
ret = vxge_enable_msix(vdev);
if (ret) {
@@ -2475,7 +2469,7 @@ static int vxge_add_isr(struct vxgedev *vdev)
vdev->config.intr_type = INTA;
}
- if (vdev->config.intr_type == MSI_X) {
+ if (IS_ENABLED(CONFIG_PCI_MSI) && vdev->config.intr_type == MSI_X) {
for (intr_idx = 0;
intr_idx < (vdev->no_of_vpath *
VXGE_HW_VPATH_MSIX_ACTIVE); intr_idx++) {
@@ -2576,9 +2570,8 @@ static int vxge_add_isr(struct vxgedev *vdev)
vdev->vxge_entries[intr_cnt].in_use = 1;
vdev->vxge_entries[intr_cnt].arg = &vdev->vpaths[0];
}
-INTA_MODE:
-#endif
+INTA_MODE:
if (vdev->config.intr_type == INTA) {
snprintf(vdev->desc[0], VXGE_INTR_STRLEN,
"%s:vxge:INTA", vdev->ndev->name);
@@ -3889,12 +3882,12 @@ static void vxge_device_config_init(struct vxge_hw_device_config *device_config,
if (max_mac_vpath > VXGE_MAX_MAC_ADDR_COUNT)
max_mac_vpath = VXGE_MAX_MAC_ADDR_COUNT;
-#ifndef CONFIG_PCI_MSI
- vxge_debug_init(VXGE_ERR,
- "%s: This Kernel does not support "
- "MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME);
- *intr_type = INTA;
-#endif
+ if (!IS_ENABLED(CONFIG_PCI_MSI)) {
+ vxge_debug_init(VXGE_ERR,
+ "%s: This Kernel does not support "
+ "MSI-X. Defaulting to INTA", VXGE_DRIVER_NAME);
+ *intr_type = INTA;
+ }
/* Configure whether MSI-X or IRQL. */
switch (*intr_type) {
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index a4ab71d..166a7fc 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -3531,12 +3531,14 @@ static void rocker_port_fdb_learn_work(struct work_struct *work)
info.addr = lw->addr;
info.vid = lw->vid;
+ rtnl_lock();
if (learned && removing)
call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
lw->rocker_port->dev, &info.info);
else if (learned && !removing)
call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
lw->rocker_port->dev, &info.info);
+ rtnl_unlock();
rocker_port_kfree(lw->trans, work);
}
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index cc106d8..23fa298 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -389,17 +389,27 @@ static int vnet_rx_one(struct vnet_port *port, struct vio_net_desc *desc)
if (vio_version_after_eq(&port->vio, 1, 8)) {
struct vio_net_dext *dext = vio_net_ext(desc);
+ skb_reset_network_header(skb);
+
if (dext->flags & VNET_PKT_HCK_IPV4_HDRCKSUM) {
if (skb->protocol == ETH_P_IP) {
- struct iphdr *iph = (struct iphdr *)skb->data;
+ struct iphdr *iph = ip_hdr(skb);
iph->check = 0;
ip_send_check(iph);
}
}
if ((dext->flags & VNET_PKT_HCK_FULLCKSUM) &&
- skb->ip_summed == CHECKSUM_NONE)
- vnet_fullcsum(skb);
+ skb->ip_summed == CHECKSUM_NONE) {
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+ int ihl = iph->ihl * 4;
+
+ skb_reset_transport_header(skb);
+ skb_set_transport_header(skb, ihl);
+ vnet_fullcsum(skb);
+ }
+ }
if (dext->flags & VNET_PKT_HCK_IPV4_HDRCKSUM_OK) {
skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum_level = 0;
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 657b65b..18bf3a8 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -82,7 +82,7 @@ struct cpdma_desc {
struct cpdma_desc_pool {
phys_addr_t phys;
- u32 hw_addr;
+ dma_addr_t hw_addr;
void __iomem *iomap; /* ioremap map */
void *cpumap; /* dma_alloc map */
int desc_size, mem_size;
@@ -152,7 +152,7 @@ struct cpdma_chan {
* abstract out these details
*/
static struct cpdma_desc_pool *
-cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
+cpdma_desc_pool_create(struct device *dev, u32 phys, dma_addr_t hw_addr,
int size, int align)
{
int bitmap_size;
@@ -176,13 +176,13 @@ cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
if (phys) {
pool->phys = phys;
- pool->iomap = ioremap(phys, size);
+ pool->iomap = ioremap(phys, size); /* should be memremap? */
pool->hw_addr = hw_addr;
} else {
- pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
+ pool->cpumap = dma_alloc_coherent(dev, size, &pool->hw_addr,
GFP_KERNEL);
- pool->iomap = pool->cpumap;
- pool->hw_addr = pool->phys;
+ pool->iomap = (void __iomem __force *)pool->cpumap;
+ pool->phys = pool->hw_addr; /* assumes no IOMMU, don't use this value */
}
if (pool->iomap)
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
index 7f975a2..b0de8ec 100644
--- a/drivers/net/fddi/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -533,8 +533,8 @@ static int dfx_register(struct device *bdev)
const char *print_name = dev_name(bdev);
struct net_device *dev;
DFX_board_t *bp; /* board pointer */
- resource_size_t bar_start[3]; /* pointers to ports */
- resource_size_t bar_len[3]; /* resource length */
+ resource_size_t bar_start[3] = {0}; /* pointers to ports */
+ resource_size_t bar_len[3] = {0}; /* resource length */
int alloc_size; /* total buffer size used */
struct resource *region;
int err = 0;
@@ -3697,8 +3697,8 @@ static void dfx_unregister(struct device *bdev)
int dfx_bus_pci = dev_is_pci(bdev);
int dfx_bus_tc = DFX_BUS_TC(bdev);
int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
- resource_size_t bar_start[3]; /* pointers to ports */
- resource_size_t bar_len[3]; /* resource lengths */
+ resource_size_t bar_start[3] = {0}; /* pointers to ports */
+ resource_size_t bar_len[3] = {0}; /* resource lengths */
int alloc_size; /* total buffer size used */
unregister_netdev(dev);
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 7456569..0b14ac3 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -980,9 +980,9 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
opts = ip_tunnel_info_opts(info);
if (key->tun_flags & TUNNEL_CSUM)
- flags |= GENEVE_F_UDP_CSUM;
+ flags &= ~GENEVE_F_UDP_ZERO_CSUM6_TX;
else
- flags &= ~GENEVE_F_UDP_CSUM;
+ flags |= GENEVE_F_UDP_ZERO_CSUM6_TX;
err = geneve6_build_skb(dst, skb, key->tun_flags, vni,
info->options_len, opts,
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index f4130af..fcb92c0 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -624,6 +624,7 @@ struct nvsp_message {
#define RNDIS_PKT_ALIGN_DEFAULT 8
struct multi_send_data {
+ struct sk_buff *skb; /* skb containing the pkt */
struct hv_netvsc_packet *pkt; /* netvsc pkt pending */
u32 count; /* counter of batched packets */
};
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 059fc52..ec313fc 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -841,6 +841,18 @@ static inline int netvsc_send_pkt(
return ret;
}
+/* Move packet out of multi send data (msd), and clear msd */
+static inline void move_pkt_msd(struct hv_netvsc_packet **msd_send,
+ struct sk_buff **msd_skb,
+ struct multi_send_data *msdp)
+{
+ *msd_skb = msdp->skb;
+ *msd_send = msdp->pkt;
+ msdp->skb = NULL;
+ msdp->pkt = NULL;
+ msdp->count = 0;
+}
+
int netvsc_send(struct hv_device *device,
struct hv_netvsc_packet *packet,
struct rndis_message *rndis_msg,
@@ -855,6 +867,7 @@ int netvsc_send(struct hv_device *device,
unsigned int section_index = NETVSC_INVALID_INDEX;
struct multi_send_data *msdp;
struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL;
+ struct sk_buff *msd_skb = NULL;
bool try_batch;
bool xmit_more = (skb != NULL) ? skb->xmit_more : false;
@@ -897,10 +910,8 @@ int netvsc_send(struct hv_device *device,
net_device->send_section_size) {
section_index = netvsc_get_next_send_section(net_device);
if (section_index != NETVSC_INVALID_INDEX) {
- msd_send = msdp->pkt;
- msdp->pkt = NULL;
- msdp->count = 0;
- msd_len = 0;
+ move_pkt_msd(&msd_send, &msd_skb, msdp);
+ msd_len = 0;
}
}
@@ -919,31 +930,31 @@ int netvsc_send(struct hv_device *device,
packet->total_data_buflen += msd_len;
}
- if (msdp->pkt)
- dev_kfree_skb_any(skb);
+ if (msdp->skb)
+ dev_kfree_skb_any(msdp->skb);
if (xmit_more && !packet->cp_partial) {
+ msdp->skb = skb;
msdp->pkt = packet;
msdp->count++;
} else {
cur_send = packet;
+ msdp->skb = NULL;
msdp->pkt = NULL;
msdp->count = 0;
}
} else {
- msd_send = msdp->pkt;
- msdp->pkt = NULL;
- msdp->count = 0;
+ move_pkt_msd(&msd_send, &msd_skb, msdp);
cur_send = packet;
}
if (msd_send) {
- m_ret = netvsc_send_pkt(msd_send, net_device, pb, skb);
+ m_ret = netvsc_send_pkt(msd_send, net_device, NULL, msd_skb);
if (m_ret != 0) {
netvsc_free_send_slot(net_device,
msd_send->send_buf_index);
- dev_kfree_skb_any(skb);
+ dev_kfree_skb_any(msd_skb);
}
}
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 1c8db9a..1d3a665 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -196,65 +196,6 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size,
return ppi;
}
-union sub_key {
- u64 k;
- struct {
- u8 pad[3];
- u8 kb;
- u32 ka;
- };
-};
-
-/* Toeplitz hash function
- * data: network byte order
- * return: host byte order
- */
-static u32 comp_hash(u8 *key, int klen, void *data, int dlen)
-{
- union sub_key subk;
- int k_next = 4;
- u8 dt;
- int i, j;
- u32 ret = 0;
-
- subk.k = 0;
- subk.ka = ntohl(*(u32 *)key);
-
- for (i = 0; i < dlen; i++) {
- subk.kb = key[k_next];
- k_next = (k_next + 1) % klen;
- dt = ((u8 *)data)[i];
- for (j = 0; j < 8; j++) {
- if (dt & 0x80)
- ret ^= subk.ka;
- dt <<= 1;
- subk.k <<= 1;
- }
- }
-
- return ret;
-}
-
-static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
-{
- struct flow_keys flow;
- int data_len;
-
- if (!skb_flow_dissect_flow_keys(skb, &flow, 0) ||
- !(flow.basic.n_proto == htons(ETH_P_IP) ||
- flow.basic.n_proto == htons(ETH_P_IPV6)))
- return false;
-
- if (flow.basic.ip_proto == IPPROTO_TCP)
- data_len = 12;
- else
- data_len = 8;
-
- *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len);
-
- return true;
-}
-
static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
void *accel_priv, select_queue_fallback_t fallback)
{
@@ -267,11 +208,9 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1)
return 0;
- if (netvsc_set_hash(&hash, skb)) {
- q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
- ndev->real_num_tx_queues;
- skb_set_hash(skb, hash, PKT_HASH_TYPE_L3);
- }
+ hash = skb_get_hash(skb);
+ q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
+ ndev->real_num_tx_queues;
if (!nvsc_dev->chn_table[q_idx])
q_idx = 0;
diff --git a/drivers/net/irda/bfin_sir.h b/drivers/net/irda/bfin_sir.h
index 29cbde8..d47cf14 100644
--- a/drivers/net/irda/bfin_sir.h
+++ b/drivers/net/irda/bfin_sir.h
@@ -82,9 +82,6 @@ struct bfin_sir_self {
#define DRIVER_NAME "bfin_sir"
-#define port_membase(port) (((struct bfin_sir_port *)(port))->membase)
-#define get_lsr_cache(port) (((struct bfin_sir_port *)(port))->lsr)
-#define put_lsr_cache(port, v) (((struct bfin_sir_port *)(port))->lsr = (v))
#include <asm/bfin_serial.h>
static const unsigned short per[][4] = {
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 6a57a00..94e6888 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1323,6 +1323,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
list_add_tail_rcu(&vlan->list, &port->vlans);
netif_stacked_transfer_operstate(lowerdev, dev);
+ linkwatch_fire_event(dev);
return 0;
@@ -1522,6 +1523,7 @@ static int macvlan_device_event(struct notifier_block *unused,
port = macvlan_port_get_rtnl(dev);
switch (event) {
+ case NETDEV_UP:
case NETDEV_CHANGE:
list_for_each_entry(vlan, &port->vlans, list)
netif_stacked_transfer_operstate(vlan->lowerdev,
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 60994a8..f0a77020 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -186,6 +186,7 @@ config MDIO_GPIO
config MDIO_OCTEON
tristate "Support for MDIO buses on Octeon and ThunderX SOCs"
depends on 64BIT
+ depends on HAS_IOMEM
help
This module provides a driver for the Octeon and ThunderX MDIO
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 180f699..7a240fc 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -846,6 +846,11 @@ static void decode_rxts(struct dp83640_private *dp83640,
struct skb_shared_hwtstamps *shhwtstamps = NULL;
struct sk_buff *skb;
unsigned long flags;
+ u8 overflow;
+
+ overflow = (phy_rxts->ns_hi >> 14) & 0x3;
+ if (overflow)
+ pr_debug("rx timestamp queue overflow, count %d\n", overflow);
spin_lock_irqsave(&dp83640->rx_lock, flags);
@@ -888,6 +893,7 @@ static void decode_txts(struct dp83640_private *dp83640,
struct skb_shared_hwtstamps shhwtstamps;
struct sk_buff *skb;
u64 ns;
+ u8 overflow;
/* We must already have the skb that triggered this. */
@@ -897,6 +903,17 @@ static void decode_txts(struct dp83640_private *dp83640,
pr_debug("have timestamp but tx_queue empty\n");
return;
}
+
+ overflow = (phy_txts->ns_hi >> 14) & 0x3;
+ if (overflow) {
+ pr_debug("tx timestamp queue overflow, count %d\n", overflow);
+ while (skb) {
+ skb_complete_tx_timestamp(skb, NULL);
+ skb = skb_dequeue(&dp83640->tx_queue);
+ }
+ return;
+ }
+
ns = phy2txts(phy_txts);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(ns);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 8763bb2..5590b9c 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -692,25 +692,29 @@ void phy_change(struct work_struct *work)
struct phy_device *phydev =
container_of(work, struct phy_device, phy_queue);
- if (phydev->drv->did_interrupt &&
- !phydev->drv->did_interrupt(phydev))
- goto ignore;
+ if (phy_interrupt_is_valid(phydev)) {
+ if (phydev->drv->did_interrupt &&
+ !phydev->drv->did_interrupt(phydev))
+ goto ignore;
- if (phy_disable_interrupts(phydev))
- goto phy_err;
+ if (phy_disable_interrupts(phydev))
+ goto phy_err;
+ }
mutex_lock(&phydev->lock);
if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
phydev->state = PHY_CHANGELINK;
mutex_unlock(&phydev->lock);
- atomic_dec(&phydev->irq_disable);
- enable_irq(phydev->irq);
+ if (phy_interrupt_is_valid(phydev)) {
+ atomic_dec(&phydev->irq_disable);
+ enable_irq(phydev->irq);
- /* Reenable interrupts */
- if (PHY_HALTED != phydev->state &&
- phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED))
- goto irq_enable_err;
+ /* Reenable interrupts */
+ if (PHY_HALTED != phydev->state &&
+ phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED))
+ goto irq_enable_err;
+ }
/* reschedule state queue work to run as soon as possible */
cancel_delayed_work_sync(&phydev->state_queue);
@@ -905,10 +909,10 @@ void phy_state_machine(struct work_struct *work)
phydev->adjust_link(phydev->attached_dev);
break;
case PHY_RUNNING:
- /* Only register a CHANGE if we are polling or ignoring
- * interrupts and link changed since latest checking.
+ /* Only register a CHANGE if we are polling and link changed
+ * since latest checking.
*/
- if (!phy_interrupt_is_valid(phydev)) {
+ if (phydev->irq == PHY_POLL) {
old_link = phydev->link;
err = phy_read_status(phydev);
if (err)
@@ -1000,15 +1004,21 @@ void phy_state_machine(struct work_struct *work)
phy_state_to_str(old_state),
phy_state_to_str(phydev->state));
- queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
- PHY_STATE_TIME * HZ);
+ /* Only re-schedule a PHY state machine change if we are polling the
+ * PHY, if PHY_IGNORE_INTERRUPT is set, then we will be moving
+ * between states from phy_mac_interrupt()
+ */
+ if (phydev->irq == PHY_POLL)
+ queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
+ PHY_STATE_TIME * HZ);
}
void phy_mac_interrupt(struct phy_device *phydev, int new_link)
{
- cancel_work_sync(&phydev->phy_queue);
phydev->link = new_link;
- schedule_work(&phydev->phy_queue);
+
+ /* Trigger a state machine change */
+ queue_work(system_power_efficient_wq, &phydev->phy_queue);
}
EXPORT_SYMBOL(phy_mac_interrupt);
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index e485f26..2e21e93 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -24,6 +24,10 @@
#include <linux/netdevice.h>
#include <linux/smscphy.h>
+struct smsc_phy_priv {
+ bool energy_enable;
+};
+
static int smsc_phy_config_intr(struct phy_device *phydev)
{
int rc = phy_write (phydev, MII_LAN83C185_IM,
@@ -43,19 +47,14 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
static int smsc_phy_config_init(struct phy_device *phydev)
{
- int __maybe_unused len;
- struct device *dev __maybe_unused = &phydev->mdio.dev;
- struct device_node *of_node __maybe_unused = dev->of_node;
+ struct smsc_phy_priv *priv = phydev->priv;
+
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
- int enable_energy = 1;
if (rc < 0)
return rc;
- if (of_find_property(of_node, "smsc,disable-energy-detect", &len))
- enable_energy = 0;
-
- if (enable_energy) {
+ if (priv->energy_enable) {
/* Enable energy detect mode for this SMSC Transceivers */
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
rc | MII_LAN83C185_EDPWRDOWN);
@@ -110,10 +109,13 @@ static int lan911x_config_init(struct phy_device *phydev)
*/
static int lan87xx_read_status(struct phy_device *phydev)
{
+ struct smsc_phy_priv *priv = phydev->priv;
+
int err = genphy_read_status(phydev);
- int i;
- if (!phydev->link) {
+ if (!phydev->link && priv->energy_enable) {
+ int i;
+
/* Disable EDPD to wake up PHY */
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0)
@@ -149,6 +151,26 @@ static int lan87xx_read_status(struct phy_device *phydev)
return err;
}
+static int smsc_phy_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct device_node *of_node = dev->of_node;
+ struct smsc_phy_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->energy_enable = true;
+
+ if (of_property_read_bool(of_node, "smsc,disable-energy-detect"))
+ priv->energy_enable = false;
+
+ phydev->priv = priv;
+
+ return 0;
+}
+
static struct phy_driver smsc_phy_driver[] = {
{
.phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
@@ -159,6 +181,8 @@ static struct phy_driver smsc_phy_driver[] = {
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+ .probe = smsc_phy_probe,
+
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
@@ -180,6 +204,8 @@ static struct phy_driver smsc_phy_driver[] = {
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+ .probe = smsc_phy_probe,
+
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
@@ -201,6 +227,8 @@ static struct phy_driver smsc_phy_driver[] = {
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+ .probe = smsc_phy_probe,
+
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = lan87xx_read_status,
@@ -222,6 +250,8 @@ static struct phy_driver smsc_phy_driver[] = {
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+ .probe = smsc_phy_probe,
+
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
@@ -242,6 +272,8 @@ static struct phy_driver smsc_phy_driver[] = {
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+ .probe = smsc_phy_probe,
+
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = lan87xx_read_status,
@@ -263,6 +295,8 @@ static struct phy_driver smsc_phy_driver[] = {
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+ .probe = smsc_phy_probe,
+
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = lan87xx_read_status,
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 90868ca..ae0905e 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -129,24 +129,27 @@ static int lookup_chan_dst(u16 call_id, __be32 d_addr)
return i < MAX_CALLID;
}
-static int add_chan(struct pppox_sock *sock)
+static int add_chan(struct pppox_sock *sock,
+ struct pptp_addr *sa)
{
static int call_id;
spin_lock(&chan_lock);
- if (!sock->proto.pptp.src_addr.call_id) {
+ if (!sa->call_id) {
call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
if (call_id == MAX_CALLID) {
call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
if (call_id == MAX_CALLID)
goto out_err;
}
- sock->proto.pptp.src_addr.call_id = call_id;
- } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
+ sa->call_id = call_id;
+ } else if (test_bit(sa->call_id, callid_bitmap)) {
goto out_err;
+ }
- set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
- rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
+ sock->proto.pptp.src_addr = *sa;
+ set_bit(sa->call_id, callid_bitmap);
+ rcu_assign_pointer(callid_sock[sa->call_id], sock);
spin_unlock(&chan_lock);
return 0;
@@ -416,7 +419,6 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
struct sock *sk = sock->sk;
struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
struct pppox_sock *po = pppox_sk(sk);
- struct pptp_opt *opt = &po->proto.pptp;
int error = 0;
if (sockaddr_len < sizeof(struct sockaddr_pppox))
@@ -424,10 +426,22 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
lock_sock(sk);
- opt->src_addr = sp->sa_addr.pptp;
- if (add_chan(po))
+ if (sk->sk_state & PPPOX_DEAD) {
+ error = -EALREADY;
+ goto out;
+ }
+
+ if (sk->sk_state & PPPOX_BOUND) {
error = -EBUSY;
+ goto out;
+ }
+
+ if (add_chan(po, &sp->sa_addr.pptp))
+ error = -EBUSY;
+ else
+ sk->sk_state |= PPPOX_BOUND;
+out:
release_sock(sk);
return error;
}
@@ -498,7 +512,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
}
opt->dst_addr = sp->sa_addr.pptp;
- sk->sk_state = PPPOX_CONNECTED;
+ sk->sk_state |= PPPOX_CONNECTED;
end:
release_sock(sk);
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 2ed5333..1c299b8 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -36,7 +36,7 @@
#define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>"
#define DRIVER_DESC "LAN78XX USB 3.0 Gigabit Ethernet Devices"
#define DRIVER_NAME "lan78xx"
-#define DRIVER_VERSION "1.0.1"
+#define DRIVER_VERSION "1.0.2"
#define TX_TIMEOUT_JIFFIES (5 * HZ)
#define THROTTLE_JIFFIES (HZ / 8)
@@ -462,32 +462,53 @@ static int lan78xx_read_raw_eeprom(struct lan78xx_net *dev, u32 offset,
u32 length, u8 *data)
{
u32 val;
+ u32 saved;
int i, ret;
+ int retval;
- ret = lan78xx_eeprom_confirm_not_busy(dev);
- if (ret)
- return ret;
+ /* depends on chip, some EEPROM pins are muxed with LED function.
+ * disable & restore LED function to access EEPROM.
+ */
+ ret = lan78xx_read_reg(dev, HW_CFG, &val);
+ saved = val;
+ if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000) {
+ val &= ~(HW_CFG_LED1_EN_ | HW_CFG_LED0_EN_);
+ ret = lan78xx_write_reg(dev, HW_CFG, val);
+ }
+
+ retval = lan78xx_eeprom_confirm_not_busy(dev);
+ if (retval)
+ return retval;
for (i = 0; i < length; i++) {
val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_;
val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
ret = lan78xx_write_reg(dev, E2P_CMD, val);
- if (unlikely(ret < 0))
- return -EIO;
+ if (unlikely(ret < 0)) {
+ retval = -EIO;
+ goto exit;
+ }
- ret = lan78xx_wait_eeprom(dev);
- if (ret < 0)
- return ret;
+ retval = lan78xx_wait_eeprom(dev);
+ if (retval < 0)
+ goto exit;
ret = lan78xx_read_reg(dev, E2P_DATA, &val);
- if (unlikely(ret < 0))
- return -EIO;
+ if (unlikely(ret < 0)) {
+ retval = -EIO;
+ goto exit;
+ }
data[i] = val & 0xFF;
offset++;
}
- return 0;
+ retval = 0;
+exit:
+ if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000)
+ ret = lan78xx_write_reg(dev, HW_CFG, saved);
+
+ return retval;
}
static int lan78xx_read_eeprom(struct lan78xx_net *dev, u32 offset,
@@ -509,44 +530,67 @@ static int lan78xx_write_raw_eeprom(struct lan78xx_net *dev, u32 offset,
u32 length, u8 *data)
{
u32 val;
+ u32 saved;
int i, ret;
+ int retval;
- ret = lan78xx_eeprom_confirm_not_busy(dev);
- if (ret)
- return ret;
+ /* depends on chip, some EEPROM pins are muxed with LED function.
+ * disable & restore LED function to access EEPROM.
+ */
+ ret = lan78xx_read_reg(dev, HW_CFG, &val);
+ saved = val;
+ if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000) {
+ val &= ~(HW_CFG_LED1_EN_ | HW_CFG_LED0_EN_);
+ ret = lan78xx_write_reg(dev, HW_CFG, val);
+ }
+
+ retval = lan78xx_eeprom_confirm_not_busy(dev);
+ if (retval)
+ goto exit;
/* Issue write/erase enable command */
val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_;
ret = lan78xx_write_reg(dev, E2P_CMD, val);
- if (unlikely(ret < 0))
- return -EIO;
+ if (unlikely(ret < 0)) {
+ retval = -EIO;
+ goto exit;
+ }
- ret = lan78xx_wait_eeprom(dev);
- if (ret < 0)
- return ret;
+ retval = lan78xx_wait_eeprom(dev);
+ if (retval < 0)
+ goto exit;
for (i = 0; i < length; i++) {
/* Fill data register */
val = data[i];
ret = lan78xx_write_reg(dev, E2P_DATA, val);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ retval = -EIO;
+ goto exit;
+ }
/* Send "write" command */
val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_;
val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
ret = lan78xx_write_reg(dev, E2P_CMD, val);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ retval = -EIO;
+ goto exit;
+ }
- ret = lan78xx_wait_eeprom(dev);
- if (ret < 0)
- return ret;
+ retval = lan78xx_wait_eeprom(dev);
+ if (retval < 0)
+ goto exit;
offset++;
}
- return 0;
+ retval = 0;
+exit:
+ if ((dev->devid & ID_REV_CHIP_ID_MASK_) == 0x78000000)
+ ret = lan78xx_write_reg(dev, HW_CFG, saved);
+
+ return retval;
}
static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset,
@@ -904,7 +948,6 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
if (!phydev->link && dev->link_on) {
dev->link_on = false;
- netif_carrier_off(dev->net);
/* reset MAC */
ret = lan78xx_read_reg(dev, MAC_CR, &buf);
@@ -914,6 +957,8 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
ret = lan78xx_write_reg(dev, MAC_CR, buf);
if (unlikely(ret < 0))
return -EIO;
+
+ phy_mac_interrupt(phydev, 0);
} else if (phydev->link && !dev->link_on) {
dev->link_on = true;
@@ -953,7 +998,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
ethtool_cmd_speed(&ecmd), ecmd.duplex, ladv, radv);
ret = lan78xx_update_flowcontrol(dev, ecmd.duplex, ladv, radv);
- netif_carrier_on(dev->net);
+ phy_mac_interrupt(phydev, 1);
}
return ret;
@@ -1495,7 +1540,6 @@ done:
static int lan78xx_mdio_init(struct lan78xx_net *dev)
{
int ret;
- int i;
dev->mdiobus = mdiobus_alloc();
if (!dev->mdiobus) {
@@ -1511,10 +1555,6 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev)
snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
dev->udev->bus->busnum, dev->udev->devnum);
- /* handle our own interrupt */
- for (i = 0; i < PHY_MAX_ADDR; i++)
- dev->mdiobus->irq[i] = PHY_IGNORE_INTERRUPT;
-
switch (dev->devid & ID_REV_CHIP_ID_MASK_) {
case 0x78000000:
case 0x78500000:
@@ -1558,6 +1598,16 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
return -EIO;
}
+ /* Enable PHY interrupts.
+ * We handle our own interrupt
+ */
+ ret = phy_read(phydev, LAN88XX_INT_STS);
+ ret = phy_write(phydev, LAN88XX_INT_MASK,
+ LAN88XX_INT_MASK_MDINTPIN_EN_ |
+ LAN88XX_INT_MASK_LINK_CHANGE_);
+
+ phydev->irq = PHY_IGNORE_INTERRUPT;
+
ret = phy_connect_direct(dev->net, phydev,
lan78xx_link_status_change,
PHY_INTERFACE_MODE_GMII);
@@ -1580,14 +1630,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
SUPPORTED_Pause | SUPPORTED_Asym_Pause);
genphy_config_aneg(phydev);
- /* Workaround to enable PHY interrupt.
- * phy_start_interrupts() is API for requesting and enabling
- * PHY interrupt. However, USB-to-Ethernet device can't use
- * request_irq() called in phy_start_interrupts().
- * Set PHY to PHY_HALTED and call phy_start()
- * to make a call to phy_enable_interrupts()
- */
- phy_stop(phydev);
phy_start(phydev);
netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
@@ -2221,7 +2263,9 @@ netdev_tx_t lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net)
if (skb2) {
skb_queue_tail(&dev->txq_pend, skb2);
- if (skb_queue_len(&dev->txq_pend) > 10)
+ /* throttle TX patch at slower than SUPER SPEED USB */
+ if ((dev->udev->speed < USB_SPEED_SUPER) &&
+ (skb_queue_len(&dev->txq_pend) > 10))
netif_stop_queue(net);
} else {
netif_dbg(dev, tx_err, dev->net,
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 2d88c79..6543918 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -73,7 +73,7 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
static int vxlan_net_id;
static struct rtnl_link_ops vxlan_link_ops;
-static const u8 all_zeros_mac[ETH_ALEN];
+static const u8 all_zeros_mac[ETH_ALEN + 2];
static int vxlan_sock_add(struct vxlan_dev *vxlan);
@@ -1985,11 +1985,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
vxlan->cfg.port_max, true);
if (info) {
- if (info->key.tun_flags & TUNNEL_CSUM)
- flags |= VXLAN_F_UDP_CSUM;
- else
- flags &= ~VXLAN_F_UDP_CSUM;
-
ttl = info->key.ttl;
tos = info->key.tos;
@@ -2004,8 +1999,15 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
goto drop;
sk = vxlan->vn4_sock->sock->sk;
- if (info && (info->key.tun_flags & TUNNEL_DONT_FRAGMENT))
- df = htons(IP_DF);
+ if (info) {
+ if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)
+ df = htons(IP_DF);
+
+ if (info->key.tun_flags & TUNNEL_CSUM)
+ flags |= VXLAN_F_UDP_CSUM;
+ else
+ flags &= ~VXLAN_F_UDP_CSUM;
+ }
memset(&fl4, 0, sizeof(fl4));
fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0;
@@ -2101,6 +2103,13 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
return;
}
+ if (info) {
+ if (info->key.tun_flags & TUNNEL_CSUM)
+ flags &= ~VXLAN_F_UDP_ZERO_CSUM6_TX;
+ else
+ flags |= VXLAN_F_UDP_ZERO_CSUM6_TX;
+ }
+
ttl = ttl ? : ip6_dst_hoplimit(ndst);
err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr,
0, ttl, src_port, dst_port, htonl(vni << 8), md,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index a7afdee..73fb423 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -150,18 +150,18 @@ int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
return -EIO;
}
- if (magic == AR5416_EEPROM_MAGIC) {
- *swap_needed = false;
- } else if (swab16(magic) == AR5416_EEPROM_MAGIC) {
+ *swap_needed = false;
+ if (swab16(magic) == AR5416_EEPROM_MAGIC) {
if (ah->ah_flags & AH_NO_EEP_SWAP) {
ath_info(common,
"Ignoring endianness difference in EEPROM magic bytes.\n");
-
- *swap_needed = false;
} else {
*swap_needed = true;
}
- } else {
+ } else if (magic != AR5416_EEPROM_MAGIC) {
+ if (ath9k_hw_use_flash(ah))
+ return 0;
+
ath_err(common,
"Invalid EEPROM Magic (0x%04x).\n", magic);
return -EINVAL;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 5363739..b98db8a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -879,11 +879,24 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
return 0;
}
-static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
+void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
{
+ struct sdio_func *func;
+ struct mmc_host *host;
+ uint max_blocks;
uint nents;
int err;
+ func = sdiodev->func[2];
+ host = func->card->host;
+ sdiodev->sg_support = host->max_segs > 1;
+ max_blocks = min_t(uint, host->max_blk_count, 511u);
+ sdiodev->max_request_size = min_t(uint, host->max_req_size,
+ max_blocks * func->cur_blksize);
+ sdiodev->max_segment_count = min_t(uint, host->max_segs,
+ SG_MAX_SINGLE_ALLOC);
+ sdiodev->max_segment_size = host->max_seg_size;
+
if (!sdiodev->sg_support)
return;
@@ -1021,9 +1034,6 @@ static void brcmf_sdiod_host_fixup(struct mmc_host *host)
static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
{
- struct sdio_func *func;
- struct mmc_host *host;
- uint max_blocks;
int ret = 0;
sdiodev->num_funcs = 2;
@@ -1054,26 +1064,6 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
goto out;
}
- /*
- * determine host related variables after brcmf_sdiod_probe()
- * as func->cur_blksize is properly set and F2 init has been
- * completed successfully.
- */
- func = sdiodev->func[2];
- host = func->card->host;
- sdiodev->sg_support = host->max_segs > 1;
- max_blocks = min_t(uint, host->max_blk_count, 511u);
- sdiodev->max_request_size = min_t(uint, host->max_req_size,
- max_blocks * func->cur_blksize);
- sdiodev->max_segment_count = min_t(uint, host->max_segs,
- SG_MAX_SINGLE_ALLOC);
- sdiodev->max_segment_size = host->max_seg_size;
-
- /* allocate scatter-gather table. sg support
- * will be disabled upon allocation failure.
- */
- brcmf_sdiod_sgtable_alloc(sdiodev);
-
ret = brcmf_sdiod_freezer_attach(sdiodev);
if (ret)
goto out;
@@ -1084,7 +1074,7 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
ret = -ENODEV;
goto out;
}
- brcmf_sdiod_host_fixup(host);
+ brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host);
out:
if (ret)
brcmf_sdiod_remove(sdiodev);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 4265b50..cfee477 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/netdevice.h>
+#include <linux/module.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "core.h"
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index dd66143..a14d9d9d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4114,6 +4114,11 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
goto fail;
}
+ /* allocate scatter-gather table. sg support
+ * will be disabled upon allocation failure.
+ */
+ brcmf_sdiod_sgtable_alloc(bus->sdiodev);
+
/* Query the F2 block size, set roundup accordingly */
bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
bus->roundup = min(max_roundup, bus->blocksize);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 5ec7a6d..23f2231 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -342,6 +342,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
/* Issue an abort to the specified function */
int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
+void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
enum brcmf_sdiod_state state);
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c
index e60cf14..fa41a5e 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c
@@ -74,16 +74,19 @@
#define IWL7260_UCODE_API_MAX 17
#define IWL7265_UCODE_API_MAX 17
#define IWL7265D_UCODE_API_MAX 20
+#define IWL3168_UCODE_API_MAX 20
/* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 13
#define IWL7265_UCODE_API_OK 13
#define IWL7265D_UCODE_API_OK 13
+#define IWL3168_UCODE_API_OK 20
/* Lowest firmware API version supported */
#define IWL7260_UCODE_API_MIN 13
#define IWL7265_UCODE_API_MIN 13
#define IWL7265D_UCODE_API_MIN 13
+#define IWL3168_UCODE_API_MIN 20
/* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d
@@ -92,6 +95,8 @@
#define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL3165_NVM_VERSION 0x709
#define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */
+#define IWL3168_NVM_VERSION 0xd01
+#define IWL3168_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7265_NVM_VERSION 0x0a1d
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7265D_NVM_VERSION 0x0c11
@@ -109,6 +114,9 @@
#define IWL3160_FW_PRE "iwlwifi-3160-"
#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
+#define IWL3168_FW_PRE "iwlwifi-3168-"
+#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode"
+
#define IWL7265_FW_PRE "iwlwifi-7265-"
#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
@@ -180,6 +188,12 @@ static const struct iwl_ht_params iwl7000_ht_params = {
.ucode_api_ok = IWL7265_UCODE_API_OK, \
.ucode_api_min = IWL7265_UCODE_API_MIN
+#define IWL_DEVICE_3008 \
+ IWL_DEVICE_7000_COMMON, \
+ .ucode_api_max = IWL3168_UCODE_API_MAX, \
+ .ucode_api_ok = IWL3168_UCODE_API_OK, \
+ .ucode_api_min = IWL3168_UCODE_API_MIN
+
#define IWL_DEVICE_7005D \
IWL_DEVICE_7000_COMMON, \
.ucode_api_max = IWL7265D_UCODE_API_MAX, \
@@ -299,11 +313,11 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
const struct iwl_cfg iwl3168_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3168",
- .fw_name_pre = IWL7265D_FW_PRE,
- IWL_DEVICE_7000,
+ .fw_name_pre = IWL3168_FW_PRE,
+ IWL_DEVICE_3008,
.ht_params = &iwl7000_ht_params,
- .nvm_ver = IWL3165_NVM_VERSION,
- .nvm_calib_ver = IWL3165_TX_POWER_VERSION,
+ .nvm_ver = IWL3168_NVM_VERSION,
+ .nvm_calib_ver = IWL3168_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
@@ -376,5 +390,6 @@ const struct iwl_cfg iwl7265d_n_cfg = {
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
+MODULE_FIRMWARE(IWL3168_MODULE_FIRMWARE(IWL3168_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
index 0036d18..ba3f0bb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
@@ -510,6 +510,9 @@ struct iwl_mvm_tx_resp {
* @scd_ssn: the index of the last contiguously sent packet
* @txed: number of Txed frames in this batch
* @txed_2_done: number of Acked frames in this batch
+ * @reduced_txp: power reduced according to TPC. This is the actual value and
+ * not a copy from the LQ command. Thus, if not the first rate was used
+ * for Tx-ing then this value will be set to 0 by FW.
*/
struct iwl_mvm_ba_notif {
__le32 sta_addr_lo32;
@@ -524,7 +527,8 @@ struct iwl_mvm_ba_notif {
__le16 scd_ssn;
u8 txed;
u8 txed_2_done;
- __le16 reserved1;
+ u8 reduced_txp;
+ u8 reserved1;
} __packed;
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 7bb6fd0..94caa88 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -2,6 +2,7 @@
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -724,14 +725,28 @@ static int _rs_collect_tx_data(struct iwl_mvm *mvm,
return 0;
}
-static int rs_collect_tx_data(struct iwl_mvm *mvm,
- struct iwl_lq_sta *lq_sta,
- struct iwl_scale_tbl_info *tbl,
- int scale_index, int attempts, int successes,
- u8 reduced_txp)
+static int rs_collect_tpc_data(struct iwl_mvm *mvm,
+ struct iwl_lq_sta *lq_sta,
+ struct iwl_scale_tbl_info *tbl,
+ int scale_index, int attempts, int successes,
+ u8 reduced_txp)
+{
+ struct iwl_rate_scale_data *window = NULL;
+
+ if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION))
+ return -EINVAL;
+
+ window = &tbl->tpc_win[reduced_txp];
+ return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
+ window);
+}
+
+static int rs_collect_tlc_data(struct iwl_mvm *mvm,
+ struct iwl_lq_sta *lq_sta,
+ struct iwl_scale_tbl_info *tbl,
+ int scale_index, int attempts, int successes)
{
struct iwl_rate_scale_data *window = NULL;
- int ret;
if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
return -EINVAL;
@@ -745,16 +760,6 @@ static int rs_collect_tx_data(struct iwl_mvm *mvm,
/* Select window for current tx bit rate */
window = &(tbl->win[scale_index]);
-
- ret = _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
- window);
- if (ret)
- return ret;
-
- if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION))
- return -EINVAL;
-
- window = &tbl->tpc_win[reduced_txp];
return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
window);
}
@@ -1301,17 +1306,30 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
* first index into rate scale table.
*/
if (info->flags & IEEE80211_TX_STAT_AMPDU) {
- /* ampdu_ack_len = 0 marks no BA was received. In this case
- * treat it as a single frame loss as we don't want the success
- * ratio to dip too quickly because a BA wasn't received
+ rs_collect_tpc_data(mvm, lq_sta, curr_tbl, lq_rate.index,
+ info->status.ampdu_len,
+ info->status.ampdu_ack_len,
+ reduced_txp);
+
+ /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
+ * it as a single frame loss as we don't want the success ratio
+ * to dip too quickly because a BA wasn't received.
+ * For TPC, there's no need for this optimisation since we want
+ * to recover very quickly from a bad power reduction and,
+ * therefore we'd like the success ratio to get an immediate hit
+ * when failing to get a BA, so we'd switch back to a lower or
+ * zero power reduction. When FW transmits agg with a rate
+ * different from the initial rate, it will not use reduced txp
+ * and will send BA notification twice (one empty with reduced
+ * txp equal to the value from LQ and one with reduced txp 0).
+ * We need to update counters for each txp level accordingly.
*/
if (info->status.ampdu_ack_len == 0)
info->status.ampdu_len = 1;
- rs_collect_tx_data(mvm, lq_sta, curr_tbl, lq_rate.index,
- info->status.ampdu_len,
- info->status.ampdu_ack_len,
- reduced_txp);
+ rs_collect_tlc_data(mvm, lq_sta, curr_tbl, lq_rate.index,
+ info->status.ampdu_len,
+ info->status.ampdu_ack_len);
/* Update success/fail counts if not searching for new mode */
if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
@@ -1344,9 +1362,13 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
else
continue;
- rs_collect_tx_data(mvm, lq_sta, tmp_tbl, lq_rate.index,
- 1, i < retries ? 0 : legacy_success,
- reduced_txp);
+ rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
+ lq_rate.index, 1,
+ i < retries ? 0 : legacy_success,
+ reduced_txp);
+ rs_collect_tlc_data(mvm, lq_sta, tmp_tbl,
+ lq_rate.index, 1,
+ i < retries ? 0 : legacy_success);
}
/* Update success/fail counts if not searching for new mode */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 8bf48a7..0914ec2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1029,7 +1029,6 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
mvmsta->tid_data[tid].rate_n_flags =
le32_to_cpu(tx_resp->initial_rate);
- mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc;
mvmsta->tid_data[tid].tx_time =
le16_to_cpu(tx_resp->wireless_media_time);
}
@@ -1060,7 +1059,7 @@ static void iwl_mvm_tx_info_from_ba_notif(struct ieee80211_tx_info *info,
/* TODO: not accounted if the whole A-MPDU failed */
info->status.tx_time = tid_data->tx_time;
info->status.status_driver_data[0] =
- (void *)(uintptr_t)tid_data->reduced_tpc;
+ (void *)(uintptr_t)ba_notif->reduced_txp;
info->status.status_driver_data[1] =
(void *)(uintptr_t)tid_data->rate_n_flags;
}
@@ -1133,6 +1132,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
scd_flow, ba_resp_scd_ssn, ba_notif->txed,
ba_notif->txed_2_done);
+ IWL_DEBUG_TX_REPLY(mvm, "reduced txp from ba notif %d\n",
+ ba_notif->reduced_txp);
tid_data->next_reclaimed = ba_resp_scd_ssn;
iwl_mvm_check_ratid_empty(mvm, sta, tid);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 6261a68..00335ea 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -378,7 +378,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)},
/* 3168 Series */
+ {IWL_PCI_DEVICE(0x24FB, 0x2010, iwl3168_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FB, 0x2110, iwl3168_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x24FB, 0x2050, iwl3168_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x24FB, 0x2150, iwl3168_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FB, 0x0000, iwl3168_2ac_cfg)},
/* 7265 Series */
@@ -475,6 +478,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)},
{IWL_PCI_DEVICE(0x24FD, 0x8010, iwl8265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x24FD, 0x0810, iwl8265_2ac_cfg)},
/* 9000 Series */
{IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl5165_2ac_cfg)},
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c32889a..a28414c 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -991,7 +991,8 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
goto nla_put_failure;
}
- if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, ETH_ALEN, hdr->addr2))
+ if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
+ ETH_ALEN, data->addresses[1].addr))
goto nla_put_failure;
/* We get the skb->data */
@@ -2736,7 +2737,7 @@ static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr)
spin_lock_bh(&hwsim_radio_lock);
list_for_each_entry(data, &hwsim_radios, list) {
- if (mac80211_hwsim_addr_match(data, addr)) {
+ if (memcmp(data->addresses[1].addr, addr, ETH_ALEN) == 0) {
_found = true;
break;
}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
index 9a3966c..155f343 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
@@ -273,8 +273,10 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
!(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
index 1a6740b..2553cdd 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
@@ -274,8 +274,10 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
!(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
index d26018f..2d64611 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
@@ -437,8 +437,10 @@ static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
!(filter_flags & FIF_CONTROL));
- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 9733b31..a26afca 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1490,7 +1490,8 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
!(filter_flags & FIF_PLCPFAIL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 3282ddb..2642714 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -669,6 +669,7 @@ enum rt2x00_state_flags {
CONFIG_POWERSAVING,
CONFIG_HT_DISABLED,
CONFIG_QOS_DISABLED,
+ CONFIG_MONITORING,
/*
* Mark we currently are sequentially reading TX_STA_FIFO register
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
index 7e8bb11..6a1f508 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
@@ -277,6 +277,11 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
else
clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+ if (conf->flags & IEEE80211_CONF_MONITOR)
+ set_bit(CONFIG_MONITORING, &rt2x00dev->flags);
+ else
+ clear_bit(CONFIG_MONITORING, &rt2x00dev->flags);
+
rt2x00dev->curr_band = conf->chandef.chan->band;
rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
rt2x00dev->tx_power = conf->power_level;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
index 3c26ee6..13da95a 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
@@ -385,11 +385,6 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
*total_flags |= FIF_PSPOLL;
}
- /*
- * Check if there is any work left for us.
- */
- if (rt2x00dev->packet_filter == *total_flags)
- return;
rt2x00dev->packet_filter = *total_flags;
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
index c0e730e..24a3436 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
@@ -530,8 +530,10 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
index 7081e13..7bbc869 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
@@ -480,8 +480,10 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
!(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
+ !test_bit(CONFIG_MONITORING, &rt2x00dev->flags) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c
index a62bf0a..5be3411 100644
--- a/drivers/net/wireless/realtek/rtlwifi/regd.c
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
@@ -351,7 +351,6 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select(
case COUNTRY_CODE_SPAIN:
case COUNTRY_CODE_FRANCE:
case COUNTRY_CODE_ISRAEL:
- case COUNTRY_CODE_WORLD_WIDE_13:
return &rtl_regdom_12_13;
case COUNTRY_CODE_MKK:
case COUNTRY_CODE_MKK1:
@@ -360,6 +359,7 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select(
return &rtl_regdom_14_60_64;
case COUNTRY_CODE_GLOBAL_DOMAIN:
return &rtl_regdom_14;
+ case COUNTRY_CODE_WORLD_WIDE_13:
case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
return &rtl_regdom_12_13_5g_all;
default:
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d6abf19..96ccd4e 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -364,6 +364,7 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue)
RING_IDX cons, prod;
unsigned short id;
struct sk_buff *skb;
+ bool more_to_do;
BUG_ON(!netif_carrier_ok(queue->info->netdev));
@@ -398,18 +399,8 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue)
queue->tx.rsp_cons = prod;
- /*
- * Set a new event, then check for race with update of tx_cons.
- * Note that it is essential to schedule a callback, no matter
- * how few buffers are pending. Even if there is space in the
- * transmit ring, higher layers may be blocked because too much
- * data is outstanding: in such cases notification from Xen is
- * likely to be the only kick that we'll get.
- */
- queue->tx.sring->rsp_event =
- prod + ((queue->tx.sring->req_prod - prod) >> 1) + 1;
- mb(); /* update shared area */
- } while ((cons == prod) && (prod != queue->tx.sring->rsp_prod));
+ RING_FINAL_CHECK_FOR_RESPONSES(&queue->tx, more_to_do);
+ } while (more_to_do);
xennet_maybe_wake_tx(queue);
}
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 86829f8..5648317 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -143,11 +143,31 @@ int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
}
EXPORT_SYMBOL(of_mdio_parse_addr);
+/* The following is a list of PHY compatible strings which appear in
+ * some DTBs. The compatible string is never matched against a PHY
+ * driver, so is pointless. We only expect devices which are not PHYs
+ * to have a compatible string, so they can be matched to an MDIO
+ * driver. Encourage users to upgrade their DT blobs to remove these.
+ */
+static const struct of_device_id whitelist_phys[] = {
+ { .compatible = "brcm,40nm-ephy" },
+ { .compatible = "marvell,88E1111", },
+ { .compatible = "marvell,88e1116", },
+ { .compatible = "marvell,88e1118", },
+ { .compatible = "marvell,88e1149r", },
+ { .compatible = "marvell,88e1310", },
+ { .compatible = "marvell,88E1510", },
+ { .compatible = "marvell,88E1514", },
+ { .compatible = "moxa,moxart-rtl8201cp", },
+ {}
+};
+
/*
* Return true if the child node is for a phy. It must either:
* o Compatible string of "ethernet-phy-idX.X"
* o Compatible string of "ethernet-phy-ieee802.3-c45"
* o Compatible string of "ethernet-phy-ieee802.3-c22"
+ * o In the white list above (and issue a warning)
* o No compatibility string
*
* A device which is not a phy is expected to have a compatible string
@@ -166,6 +186,13 @@ static bool of_mdiobus_child_is_phy(struct device_node *child)
if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c22"))
return true;
+ if (of_match_node(whitelist_phys, child)) {
+ pr_warn(FW_WARN
+ "%s: Whitelisted compatible string. Please remove\n",
+ child->full_name);
+ return true;
+ }
+
if (!of_find_property(child, "compatible", NULL))
return true;
@@ -256,11 +283,19 @@ static int of_phy_match(struct device *dev, void *phy_np)
struct phy_device *of_phy_find_device(struct device_node *phy_np)
{
struct device *d;
+ struct mdio_device *mdiodev;
+
if (!phy_np)
return NULL;
d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match);
- return d ? to_phy_device(d) : NULL;
+ if (d) {
+ mdiodev = to_mdio_device(d);
+ if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
+ return to_phy_device(d);
+ }
+
+ return NULL;
}
EXPORT_SYMBOL(of_phy_find_device);
diff --git a/drivers/ptp/ptp_ixp46x.c b/drivers/ptp/ptp_ixp46x.c
index 934c139..ee4f183 100644
--- a/drivers/ptp/ptp_ixp46x.c
+++ b/drivers/ptp/ptp_ixp46x.c
@@ -178,7 +178,6 @@ static int ptp_ixp_adjtime(struct ptp_clock_info *ptp, s64 delta)
static int ptp_ixp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
u64 ns;
- u32 remainder;
unsigned long flags;
struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
struct ixp46x_ts_regs *regs = ixp_clock->regs;
@@ -189,8 +188,7 @@ static int ptp_ixp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
spin_unlock_irqrestore(&register_lock, flags);
- ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
- ts->tv_nsec = remainder;
+ *ts = ns_to_timespec64(ns);
return 0;
}
@@ -202,8 +200,7 @@ static int ptp_ixp_settime(struct ptp_clock_info *ptp,
struct ixp_clock *ixp_clock = container_of(ptp, struct ixp_clock, caps);
struct ixp46x_ts_regs *regs = ixp_clock->regs;
- ns = ts->tv_sec * 1000000000ULL;
- ns += ts->tv_nsec;
+ ns = timespec64_to_ns(ts);
spin_lock_irqsave(&register_lock, flags);
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index cde5ff7..d1a7507 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -613,9 +613,10 @@ out:
return err;
}
-static int ssb_bus_register(struct ssb_bus *bus,
- ssb_invariants_func_t get_invariants,
- unsigned long baseaddr)
+static int __maybe_unused
+ssb_bus_register(struct ssb_bus *bus,
+ ssb_invariants_func_t get_invariants,
+ unsigned long baseaddr)
{
int err;
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index a5b8eb6..6402eaf 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1261,6 +1261,9 @@ COMPATIBLE_IOCTL(HCIUNBLOCKADDR)
COMPATIBLE_IOCTL(HCIINQUIRY)
COMPATIBLE_IOCTL(HCIUARTSETPROTO)
COMPATIBLE_IOCTL(HCIUARTGETPROTO)
+COMPATIBLE_IOCTL(HCIUARTGETDEVICE)
+COMPATIBLE_IOCTL(HCIUARTSETFLAGS)
+COMPATIBLE_IOCTL(HCIUARTGETFLAGS)
COMPATIBLE_IOCTL(RFCOMMCREATEDEV)
COMPATIBLE_IOCTL(RFCOMMRELEASEDEV)
COMPATIBLE_IOCTL(RFCOMMGETDEVLIST)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5ac140d..289c231 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -512,7 +512,6 @@ static inline void napi_enable(struct napi_struct *n)
clear_bit(NAPI_STATE_NPSVC, &n->state);
}
-#ifdef CONFIG_SMP
/**
* napi_synchronize - wait until NAPI is not running
* @n: napi context
@@ -523,12 +522,12 @@ static inline void napi_enable(struct napi_struct *n)
*/
static inline void napi_synchronize(const struct napi_struct *n)
{
- while (test_bit(NAPI_STATE_SCHED, &n->state))
- msleep(1);
+ if (IS_ENABLED(CONFIG_SMP))
+ while (test_bit(NAPI_STATE_SCHED, &n->state))
+ msleep(1);
+ else
+ barrier();
}
-#else
-# define napi_synchronize(n) barrier()
-#endif
enum netdev_queue_state_t {
__QUEUE_STATE_DRV_XOFF,
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 5289929..5ee3c68 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -252,6 +252,12 @@ struct l2cap_conn_rsp {
#define L2CAP_PSM_3DSP 0x0021
#define L2CAP_PSM_IPSP 0x0023 /* 6LoWPAN */
+#define L2CAP_PSM_DYN_START 0x1001
+#define L2CAP_PSM_DYN_END 0xffff
+#define L2CAP_PSM_AUTO_END 0x10ff
+#define L2CAP_PSM_LE_DYN_START 0x0080
+#define L2CAP_PSM_LE_DYN_END 0x00ff
+
/* channel identifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h
index 6816f0f..30a56ab 100644
--- a/include/net/dst_metadata.h
+++ b/include/net/dst_metadata.h
@@ -44,6 +44,24 @@ static inline bool skb_valid_dst(const struct sk_buff *skb)
return dst && !(dst->flags & DST_METADATA);
}
+static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
+ const struct sk_buff *skb_b)
+{
+ const struct metadata_dst *a, *b;
+
+ if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
+ return 0;
+
+ a = (const struct metadata_dst *) skb_dst(skb_a);
+ b = (const struct metadata_dst *) skb_dst(skb_b);
+
+ if (!a != !b || a->u.tun_info.options_len != b->u.tun_info.options_len)
+ return 1;
+
+ return memcmp(&a->u.tun_info, &b->u.tun_info,
+ sizeof(a->u.tun_info) + a->u.tun_info.options_len);
+}
+
struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags);
struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 877f682..295d291 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -64,8 +64,16 @@ static inline bool rt6_need_strict(const struct in6_addr *daddr)
void ip6_route_input(struct sk_buff *skb);
-struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
- struct flowi6 *fl6);
+struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
+ struct flowi6 *fl6, int flags);
+
+static inline struct dst_entry *ip6_route_output(struct net *net,
+ const struct sock *sk,
+ struct flowi6 *fl6)
+{
+ return ip6_route_output_flags(net, sk, fl6, 0);
+}
+
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
int flags);
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 788ef58..62e17d1 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -79,12 +79,10 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *proto);
-#ifdef CONFIG_LOCKDEP
-# define CONNTRACK_LOCKS 8
-#else
-# define CONNTRACK_LOCKS 1024
-#endif
+#define CONNTRACK_LOCKS 1024
+
extern spinlock_t nf_conntrack_locks[CONNTRACK_LOCKS];
+void nf_conntrack_lock(spinlock_t *lock);
extern spinlock_t nf_conntrack_expect_lock;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 20e7212..205630b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -756,7 +756,6 @@ struct sctp_transport {
/* Reference counting. */
atomic_t refcnt;
- __u32 dead:1,
/* RTO-Pending : A flag used to track if one of the DATA
* chunks sent to this address is currently being
* used to compute a RTT. If this flag is 0,
@@ -766,7 +765,7 @@ struct sctp_transport {
* calculation completes (i.e. the DATA chunk
* is SACK'd) clear this flag.
*/
- rto_pending:1,
+ __u32 rto_pending:1,
/*
* hb_sent : a flag that signals that we have a pending
@@ -955,7 +954,7 @@ void sctp_transport_route(struct sctp_transport *, union sctp_addr *,
void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk);
void sctp_transport_free(struct sctp_transport *);
void sctp_transport_reset_timers(struct sctp_transport *);
-void sctp_transport_hold(struct sctp_transport *);
+int sctp_transport_hold(struct sctp_transport *);
void sctp_transport_put(struct sctp_transport *);
void sctp_transport_update_rto(struct sctp_transport *, __u32);
void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
diff --git a/include/net/sock.h b/include/net/sock.h
index b9e7b3d..f5ea148 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1036,18 +1036,6 @@ struct proto {
#ifdef SOCK_REFCNT_DEBUG
atomic_t socks;
#endif
-#ifdef CONFIG_MEMCG_KMEM
- /*
- * cgroup specific init/deinit functions. Called once for all
- * protocols that implement it, from cgroups populate function.
- * This function has to setup any files the protocol want to
- * appear in the kmem cgroup filesystem.
- */
- int (*init_cgroup)(struct mem_cgroup *memcg,
- struct cgroup_subsys *ss);
- void (*destroy_cgroup)(struct mem_cgroup *memcg);
- struct cg_proto *(*proto_cgroup)(struct mem_cgroup *memcg);
-#endif
int (*diag_destroy)(struct sock *sk, int err);
};
diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h
index 7dda3d7..aecd303 100644
--- a/include/net/sock_reuseport.h
+++ b/include/net/sock_reuseport.h
@@ -16,7 +16,7 @@ struct sock_reuseport {
};
extern int reuseport_alloc(struct sock *sk);
-extern int reuseport_add_sock(struct sock *sk, const struct sock *sk2);
+extern int reuseport_add_sock(struct sock *sk, struct sock *sk2);
extern void reuseport_detach_sock(struct sock *sk);
extern struct sock *reuseport_select_sock(struct sock *sk,
u32 hash,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 8ea1997..f6f8f03 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -216,7 +216,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
/* TCP thin-stream limits */
#define TCP_THIN_LINEAR_RETRIES 6 /* After 6 linear retries, do exp. backoff */
-/* TCP initial congestion window as per draft-hkchu-tcpm-initcwnd-01 */
+/* TCP initial congestion window as per rfc6928 */
#define TCP_INIT_CWND 10
/* Bit Flags for sysctl_tcp_fastopen */
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index d040365..8a4cc2f 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -307,6 +307,9 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
/* check that it's our buffer */
if (lowpan_is_ipv6(*skb_network_header(skb))) {
+ /* Pull off the 1-byte of 6lowpan header. */
+ skb_pull(skb, 1);
+
/* Copy the packet so that the IPv6 header is
* properly aligned.
*/
@@ -317,6 +320,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
local_skb->protocol = htons(ETH_P_IPV6);
local_skb->pkt_type = PACKET_HOST;
+ local_skb->dev = dev;
skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
@@ -335,6 +339,8 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
if (!local_skb)
goto drop;
+ local_skb->dev = dev;
+
ret = iphc_decompress(local_skb, dev, chan);
if (ret < 0) {
kfree_skb(local_skb);
@@ -343,7 +349,6 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
local_skb->protocol = htons(ETH_P_IPV6);
local_skb->pkt_type = PACKET_HOST;
- local_skb->dev = dev;
if (give_skb_to_upper(local_skb, dev)
!= NET_RX_SUCCESS) {
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 41b5f38..c78ee2d 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -688,21 +688,29 @@ static u8 update_white_list(struct hci_request *req)
* command to remove it from the controller.
*/
list_for_each_entry(b, &hdev->le_white_list, list) {
- struct hci_cp_le_del_from_white_list cp;
+ /* If the device is neither in pend_le_conns nor
+ * pend_le_reports then remove it from the whitelist.
+ */
+ if (!hci_pend_le_action_lookup(&hdev->pend_le_conns,
+ &b->bdaddr, b->bdaddr_type) &&
+ !hci_pend_le_action_lookup(&hdev->pend_le_reports,
+ &b->bdaddr, b->bdaddr_type)) {
+ struct hci_cp_le_del_from_white_list cp;
+
+ cp.bdaddr_type = b->bdaddr_type;
+ bacpy(&cp.bdaddr, &b->bdaddr);
- if (hci_pend_le_action_lookup(&hdev->pend_le_conns,
- &b->bdaddr, b->bdaddr_type) ||
- hci_pend_le_action_lookup(&hdev->pend_le_reports,
- &b->bdaddr, b->bdaddr_type)) {
- white_list_entries++;
+ hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST,
+ sizeof(cp), &cp);
continue;
}
- cp.bdaddr_type = b->bdaddr_type;
- bacpy(&cp.bdaddr, &b->bdaddr);
+ if (hci_find_irk_by_addr(hdev, &b->bdaddr, b->bdaddr_type)) {
+ /* White list can not be used with RPAs */
+ return 0x00;
+ }
- hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST,
- sizeof(cp), &cp);
+ white_list_entries++;
}
/* Since all no longer valid white list entries have been
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 39a5149..eb4f5f2 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -197,10 +197,20 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
chan->sport = psm;
err = 0;
} else {
- u16 p;
+ u16 p, start, end, incr;
+
+ if (chan->src_type == BDADDR_BREDR) {
+ start = L2CAP_PSM_DYN_START;
+ end = L2CAP_PSM_AUTO_END;
+ incr = 2;
+ } else {
+ start = L2CAP_PSM_LE_DYN_START;
+ end = L2CAP_PSM_LE_DYN_END;
+ incr = 1;
+ }
err = -EINVAL;
- for (p = 0x1001; p < 0x1100; p += 2)
+ for (p = start; p <= end; p += incr)
if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
chan->psm = cpu_to_le16(p);
chan->sport = cpu_to_le16(p);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 1bb5515..e4cae72 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -58,7 +58,7 @@ static int l2cap_validate_bredr_psm(u16 psm)
return -EINVAL;
/* Restrict usage of well-known PSMs */
- if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE))
+ if (psm < L2CAP_PSM_DYN_START && !capable(CAP_NET_BIND_SERVICE))
return -EACCES;
return 0;
@@ -67,11 +67,11 @@ static int l2cap_validate_bredr_psm(u16 psm)
static int l2cap_validate_le_psm(u16 psm)
{
/* Valid LE_PSM ranges are defined only until 0x00ff */
- if (psm > 0x00ff)
+ if (psm > L2CAP_PSM_LE_DYN_END)
return -EINVAL;
/* Restrict fixed, SIG assigned PSM values to CAP_NET_BIND_SERVICE */
- if (psm <= 0x007f && !capable(CAP_NET_BIND_SERVICE))
+ if (psm < L2CAP_PSM_LE_DYN_START && !capable(CAP_NET_BIND_SERVICE))
return -EACCES;
return 0;
@@ -125,6 +125,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
goto done;
}
+ bacpy(&chan->src, &la.l2_bdaddr);
+ chan->src_type = la.l2_bdaddr_type;
+
if (la.l2_cid)
err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid));
else
@@ -156,9 +159,6 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
break;
}
- bacpy(&chan->src, &la.l2_bdaddr);
- chan->src_type = la.l2_bdaddr_type;
-
if (chan->psm && bdaddr_type_is_le(chan->src_type))
chan->mode = L2CAP_MODE_LE_FLOWCTL;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index ffed8a1..4b175df 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1072,22 +1072,6 @@ static void smp_notify_keys(struct l2cap_conn *conn)
hcon->dst_type = smp->remote_irk->addr_type;
queue_work(hdev->workqueue, &conn->id_addr_update_work);
}
-
- /* When receiving an indentity resolving key for
- * a remote device that does not use a resolvable
- * private address, just remove the key so that
- * it is possible to use the controller white
- * list for scanning.
- *
- * Userspace will have been told to not store
- * this key at this point. So it is safe to
- * just remove it.
- */
- if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) {
- list_del_rcu(&smp->remote_irk->list);
- kfree_rcu(smp->remote_irk, rcu);
- smp->remote_irk = NULL;
- }
}
if (smp->csrk) {
diff --git a/net/bridge/br.c b/net/bridge/br.c
index a1abe49..3addc05 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -121,6 +121,7 @@ static struct notifier_block br_device_notifier = {
.notifier_call = br_device_event
};
+/* called with RTNL */
static int br_switchdev_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -130,7 +131,6 @@ static int br_switchdev_event(struct notifier_block *unused,
struct switchdev_notifier_fdb_info *fdb_info;
int err = NOTIFY_DONE;
- rtnl_lock();
p = br_port_get_rtnl(dev);
if (!p)
goto out;
@@ -155,7 +155,6 @@ static int br_switchdev_event(struct notifier_block *unused,
}
out:
- rtnl_unlock();
return err;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index cc9e365..8cba3d8 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4351,6 +4351,7 @@ static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb)
diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
diffs |= p->vlan_tci ^ skb->vlan_tci;
+ diffs |= skb_metadata_dst_cmp(p, skb);
if (maclen == ETH_HLEN)
diffs |= compare_ether_header(skb_mac_header(p),
skb_mac_header(skb));
@@ -4548,10 +4549,12 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
break;
case GRO_MERGED_FREE:
- if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
+ if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
+ skb_dst_drop(skb);
kmem_cache_free(skbuff_head_cache, skb);
- else
+ } else {
__kfree_skb(skb);
+ }
break;
case GRO_HELD:
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
index 1df98c5..e92b759 100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -93,10 +93,17 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse)
* @sk2: Socket belonging to the existing reuseport group.
* May return ENOMEM and not add socket to group under memory pressure.
*/
-int reuseport_add_sock(struct sock *sk, const struct sock *sk2)
+int reuseport_add_sock(struct sock *sk, struct sock *sk2)
{
struct sock_reuseport *reuse;
+ if (!rcu_access_pointer(sk2->sk_reuseport_cb)) {
+ int err = reuseport_alloc(sk2);
+
+ if (err)
+ return err;
+ }
+
spin_lock_bh(&reuseport_lock);
reuse = rcu_dereference_protected(sk2->sk_reuseport_cb,
lockdep_is_held(&reuseport_lock)),
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index c229205..7758247 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -353,6 +353,7 @@ config INET_ESP
select CRYPTO_CBC
select CRYPTO_SHA1
select CRYPTO_DES
+ select CRYPTO_ECHAINIV
---help---
Support for IPsec ESP.
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 7aea0cc..d07fc07 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1394,9 +1394,10 @@ found:
struct fib_info *fi = fa->fa_info;
int nhsel, err;
- if ((index >= (1ul << fa->fa_slen)) &&
- ((BITS_PER_LONG > KEYLENGTH) || (fa->fa_slen != KEYLENGTH)))
- continue;
+ if ((BITS_PER_LONG > KEYLENGTH) || (fa->fa_slen < KEYLENGTH)) {
+ if (index >= (1ul << fa->fa_slen))
+ continue;
+ }
if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
continue;
if (fi->fib_dead)
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 8bb8e7a..6029157 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -361,13 +361,20 @@ struct sock *inet_diag_find_one_icsk(struct net *net,
req->id.idiag_dport, req->id.idiag_src[0],
req->id.idiag_sport, req->id.idiag_if);
#if IS_ENABLED(CONFIG_IPV6)
- else if (req->sdiag_family == AF_INET6)
- sk = inet6_lookup(net, hashinfo,
- (struct in6_addr *)req->id.idiag_dst,
- req->id.idiag_dport,
- (struct in6_addr *)req->id.idiag_src,
- req->id.idiag_sport,
- req->id.idiag_if);
+ else if (req->sdiag_family == AF_INET6) {
+ if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) &&
+ ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src))
+ sk = inet_lookup(net, hashinfo, req->id.idiag_dst[3],
+ req->id.idiag_dport, req->id.idiag_src[3],
+ req->id.idiag_sport, req->id.idiag_if);
+ else
+ sk = inet6_lookup(net, hashinfo,
+ (struct in6_addr *)req->id.idiag_dst,
+ req->id.idiag_dport,
+ (struct in6_addr *)req->id.idiag_src,
+ req->id.idiag_sport,
+ req->id.idiag_if);
+ }
#endif
else
return ERR_PTR(-EINVAL);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 3f00810..187c6fc 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -661,6 +661,7 @@ int ip_defrag(struct net *net, struct sk_buff *skb, u32 user)
struct ipq *qp;
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
+ skb_orphan(skb);
/* Lookup (or create) queue header */
qp = ip_find(net, ip_hdr(skb), user, vif);
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index b1209b6..d77eb0c 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -316,7 +316,10 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
const struct iphdr *iph = ip_hdr(skb);
struct rtable *rt;
- if (sysctl_ip_early_demux && !skb_dst(skb) && !skb->sk) {
+ if (sysctl_ip_early_demux &&
+ !skb_dst(skb) &&
+ !skb->sk &&
+ !ip_is_fragment(iph)) {
const struct net_protocol *ipprot;
int protocol = iph->protocol;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 67f7c9d..2ed9dd2 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -143,7 +143,11 @@ static char dhcp_client_identifier[253] __initdata;
/* Persistent data: */
+#ifdef IPCONFIG_DYNAMIC
static int ic_proto_used; /* Protocol used, if any */
+#else
+#define ic_proto_used 0
+#endif
static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */
static u8 ic_domain[64]; /* DNS (not NIS) domain name */
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index 6fb869f6..a04dee5 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -27,8 +27,6 @@ static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb,
{
int err;
- skb_orphan(skb);
-
local_bh_disable();
err = ip_defrag(net, skb, user);
local_bh_enable();
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index fd17eec..19746b3 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -279,6 +279,7 @@
#include <asm/uaccess.h>
#include <asm/ioctls.h>
+#include <asm/unaligned.h>
#include <net/busy_poll.h>
int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT;
@@ -2638,6 +2639,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
const struct inet_connection_sock *icsk = inet_csk(sk);
u32 now = tcp_time_stamp;
unsigned int start;
+ u64 rate64;
u32 rate;
memset(info, 0, sizeof(*info));
@@ -2703,15 +2705,17 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_total_retrans = tp->total_retrans;
rate = READ_ONCE(sk->sk_pacing_rate);
- info->tcpi_pacing_rate = rate != ~0U ? rate : ~0ULL;
+ rate64 = rate != ~0U ? rate : ~0ULL;
+ put_unaligned(rate64, &info->tcpi_pacing_rate);
rate = READ_ONCE(sk->sk_max_pacing_rate);
- info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL;
+ rate64 = rate != ~0U ? rate : ~0ULL;
+ put_unaligned(rate64, &info->tcpi_max_pacing_rate);
do {
start = u64_stats_fetch_begin_irq(&tp->syncp);
- info->tcpi_bytes_acked = tp->bytes_acked;
- info->tcpi_bytes_received = tp->bytes_received;
+ put_unaligned(tp->bytes_acked, &info->tcpi_bytes_acked);
+ put_unaligned(tp->bytes_received, &info->tcpi_bytes_received);
} while (u64_stats_fetch_retry_irq(&tp->syncp, start));
info->tcpi_segs_out = tp->segs_out;
info->tcpi_segs_in = tp->segs_in;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 0003d40..1c2a734 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2164,8 +2164,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
- int cnt, oldcnt;
- int err;
+ int cnt, oldcnt, lost;
unsigned int mss;
/* Use SACK to deduce losses of new sequences sent during recovery */
const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq;
@@ -2205,9 +2204,10 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
break;
mss = tcp_skb_mss(skb);
- err = tcp_fragment(sk, skb, (packets - oldcnt) * mss,
- mss, GFP_ATOMIC);
- if (err < 0)
+ /* If needed, chop off the prefix to mark as lost. */
+ lost = (packets - oldcnt) * mss;
+ if (lost < skb->len &&
+ tcp_fragment(sk, skb, lost, mss, GFP_ATOMIC) < 0)
break;
cnt = packets;
}
@@ -2366,8 +2366,6 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss)
tp->snd_ssthresh = tp->prior_ssthresh;
tcp_ecn_withdraw_cwr(tp);
}
- } else {
- tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh);
}
tp->snd_cwnd_stamp = tcp_time_stamp;
tp->undo_marker = 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5ced3e4..a4d5237 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -707,7 +707,8 @@ release_sk1:
outside socket context is ugly, certainly. What can I do?
*/
-static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
+static void tcp_v4_send_ack(struct net *net,
+ struct sk_buff *skb, u32 seq, u32 ack,
u32 win, u32 tsval, u32 tsecr, int oif,
struct tcp_md5sig_key *key,
int reply_flags, u8 tos)
@@ -722,7 +723,6 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
];
} rep;
struct ip_reply_arg arg;
- struct net *net = dev_net(skb_dst(skb)->dev);
memset(&rep.th, 0, sizeof(struct tcphdr));
memset(&arg, 0, sizeof(arg));
@@ -784,7 +784,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
struct inet_timewait_sock *tw = inet_twsk(sk);
struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
- tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+ tcp_v4_send_ack(sock_net(sk), skb,
+ tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
tcp_time_stamp + tcptw->tw_ts_offset,
tcptw->tw_ts_recent,
@@ -803,8 +804,10 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
* sk->sk_state == TCP_SYN_RECV -> for Fast Open.
*/
- tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ?
- tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
+ u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 :
+ tcp_sk(sk)->snd_nxt;
+
+ tcp_v4_send_ack(sock_net(sk), skb, seq,
tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd,
tcp_time_stamp,
req->ts_recent,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index dc45b53..be0b218 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -499,6 +499,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
struct sock *sk, *result;
struct hlist_nulls_node *node;
int score, badness, matches = 0, reuseport = 0;
+ bool select_ok = true;
u32 hash = 0;
begin:
@@ -512,14 +513,18 @@ begin:
badness = score;
reuseport = sk->sk_reuseport;
if (reuseport) {
- struct sock *sk2;
hash = udp_ehashfn(net, daddr, hnum,
saddr, sport);
- sk2 = reuseport_select_sock(sk, hash, skb,
- sizeof(struct udphdr));
- if (sk2) {
- result = sk2;
- goto found;
+ if (select_ok) {
+ struct sock *sk2;
+
+ sk2 = reuseport_select_sock(sk, hash, skb,
+ sizeof(struct udphdr));
+ if (sk2) {
+ result = sk2;
+ select_ok = false;
+ goto found;
+ }
}
matches = 1;
}
@@ -563,6 +568,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask);
struct udp_hslot *hslot2, *hslot = &udptable->hash[slot];
int score, badness, matches = 0, reuseport = 0;
+ bool select_ok = true;
u32 hash = 0;
rcu_read_lock();
@@ -601,14 +607,18 @@ begin:
badness = score;
reuseport = sk->sk_reuseport;
if (reuseport) {
- struct sock *sk2;
hash = udp_ehashfn(net, daddr, hnum,
saddr, sport);
- sk2 = reuseport_select_sock(sk, hash, skb,
+ if (select_ok) {
+ struct sock *sk2;
+
+ sk2 = reuseport_select_sock(sk, hash, skb,
sizeof(struct udphdr));
- if (sk2) {
- result = sk2;
- goto found;
+ if (sk2) {
+ result = sk2;
+ select_ok = false;
+ goto found;
+ }
}
matches = 1;
}
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index bb7dabe..40c8975 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -69,6 +69,7 @@ config INET6_ESP
select CRYPTO_CBC
select CRYPTO_SHA1
select CRYPTO_DES
+ select CRYPTO_ECHAINIV
---help---
Support for IPsec ESP.
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 517c55b..4281621 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -162,6 +162,9 @@ ipv4_connected:
fl6.fl6_dport = inet->inet_dport;
fl6.fl6_sport = inet->inet_sport;
+ if (!fl6.flowi6_oif)
+ fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
+
if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))
fl6.flowi6_oif = np->mcast_oif;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 23de98f..a163102 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -909,6 +909,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
struct rt6_info *rt;
#endif
int err;
+ int flags = 0;
/* The correct way to handle this would be to do
* ip6_route_get_saddr, and then ip6_route_output; however,
@@ -940,10 +941,13 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
dst_release(*dst);
*dst = NULL;
}
+
+ if (fl6->flowi6_oif)
+ flags |= RT6_LOOKUP_F_IFACE;
}
if (!*dst)
- *dst = ip6_route_output(net, sk, fl6);
+ *dst = ip6_route_output_flags(net, sk, fl6, flags);
err = (*dst)->error;
if (err)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 3c8834b..ed44663 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1183,11 +1183,10 @@ static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table
return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
}
-struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
- struct flowi6 *fl6)
+struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
+ struct flowi6 *fl6, int flags)
{
struct dst_entry *dst;
- int flags = 0;
bool any_src;
dst = l3mdev_rt6_dst_by_oif(net, fl6);
@@ -1208,7 +1207,7 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
}
-EXPORT_SYMBOL(ip6_route_output);
+EXPORT_SYMBOL_GPL(ip6_route_output_flags);
struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
{
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index e794ef6..2066d1c 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -201,14 +201,14 @@ static int ipip6_tunnel_create(struct net_device *dev)
if ((__force u16)t->parms.i_flags & SIT_ISATAP)
dev->priv_flags |= IFF_ISATAP;
+ dev->rtnl_link_ops = &sit_link_ops;
+
err = register_netdevice(dev);
if (err < 0)
goto out;
ipip6_tunnel_clone_6rd(dev, sitn);
- dev->rtnl_link_ops = &sit_link_ops;
-
dev_hold(dev);
ipip6_tunnel_link(sitn, t);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5d2c2af..22e28a4 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -257,6 +257,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
struct sock *sk, *result;
struct hlist_nulls_node *node;
int score, badness, matches = 0, reuseport = 0;
+ bool select_ok = true;
u32 hash = 0;
begin:
@@ -270,14 +271,18 @@ begin:
badness = score;
reuseport = sk->sk_reuseport;
if (reuseport) {
- struct sock *sk2;
hash = udp6_ehashfn(net, daddr, hnum,
saddr, sport);
- sk2 = reuseport_select_sock(sk, hash, skb,
- sizeof(struct udphdr));
- if (sk2) {
- result = sk2;
- goto found;
+ if (select_ok) {
+ struct sock *sk2;
+
+ sk2 = reuseport_select_sock(sk, hash, skb,
+ sizeof(struct udphdr));
+ if (sk2) {
+ result = sk2;
+ select_ok = false;
+ goto found;
+ }
}
matches = 1;
}
@@ -321,6 +326,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask);
struct udp_hslot *hslot2, *hslot = &udptable->hash[slot];
int score, badness, matches = 0, reuseport = 0;
+ bool select_ok = true;
u32 hash = 0;
rcu_read_lock();
@@ -358,14 +364,18 @@ begin:
badness = score;
reuseport = sk->sk_reuseport;
if (reuseport) {
- struct sock *sk2;
hash = udp6_ehashfn(net, daddr, hnum,
saddr, sport);
- sk2 = reuseport_select_sock(sk, hash, skb,
+ if (select_ok) {
+ struct sock *sk2;
+
+ sk2 = reuseport_select_sock(sk, hash, skb,
sizeof(struct udphdr));
- if (sk2) {
- result = sk2;
- goto found;
+ if (sk2) {
+ result = sk2;
+ select_ok = false;
+ goto found;
+ }
}
matches = 1;
}
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
index 3c4caa6..5728e76 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -134,11 +134,10 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
return -1;
}
skb_put(skb, count);
+ pr_debug("%s(), skb->len=%d\n", __func__, skb->len);
spin_unlock_irqrestore(&self->spinlock, flags);
- pr_debug("%s(), skb->len=%d\n", __func__ , skb->len);
-
if (flush) {
/* ircomm_tty_do_softint will take care of the rest */
schedule_work(&self->tqueue);
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index ef50a94..fc3598a 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -708,6 +708,9 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
if (!addr || addr->sa_family != AF_IUCV)
return -EINVAL;
+ if (addr_len < sizeof(struct sockaddr_iucv))
+ return -EINVAL;
+
lock_sock(sk);
if (sk->sk_state != IUCV_OPEN) {
err = -EBADFD;
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index f7fc0e0..978d3bc 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1733,7 +1733,6 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
continue;
sdata->u.ibss.last_scan_completed = jiffies;
- ieee80211_queue_work(&local->hw, &sdata->work);
}
mutex_unlock(&local->iflist_mtx);
}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6bcf0fa..8190bf2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -248,6 +248,7 @@ static void ieee80211_restart_work(struct work_struct *work)
/* wait for scan work complete */
flush_workqueue(local->workqueue);
+ flush_work(&local->sched_scan_stopped_work);
WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
"%s called with hardware scan in progress\n", __func__);
@@ -256,6 +257,11 @@ static void ieee80211_restart_work(struct work_struct *work)
list_for_each_entry(sdata, &local->interfaces, list)
flush_delayed_work(&sdata->dec_tailroom_needed_wk);
ieee80211_scan_cancel(local);
+
+ /* make sure any new ROC will consider local->in_reconfig */
+ flush_delayed_work(&local->roc_work);
+ flush_work(&local->hw_roc_done);
+
ieee80211_reconfig(local);
rtnl_unlock();
}
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index fa28500..6f85b6a 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1370,17 +1370,6 @@ out:
sdata_unlock(sdata);
}
-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
-{
- struct ieee80211_sub_if_data *sdata;
-
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list)
- if (ieee80211_vif_is_mesh(&sdata->vif) &&
- ieee80211_sdata_running(sdata))
- ieee80211_queue_work(&local->hw, &sdata->work);
- rcu_read_unlock();
-}
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index a159634..4a8019f 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -362,14 +362,10 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP;
}
-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
-
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
void ieee80211s_stop(void);
#else
-static inline void
-ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
{ return false; }
static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1c342e2..bfbb1ac 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4005,8 +4005,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
ieee80211_queue_work(&sdata->local->hw,
&sdata->u.mgd.monitor_work);
- /* and do all the other regular work too */
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
}
}
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 8b2f4ea..55a9c5b 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -252,14 +252,11 @@ static bool ieee80211_recalc_sw_work(struct ieee80211_local *local,
static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc,
unsigned long start_time)
{
- struct ieee80211_local *local = roc->sdata->local;
-
if (WARN_ON(roc->notified))
return;
roc->start_time = start_time;
roc->started = true;
- roc->hw_begun = true;
if (roc->mgmt_tx_cookie) {
if (!WARN_ON(!roc->frame)) {
@@ -274,9 +271,6 @@ static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc,
}
roc->notified = true;
-
- if (!local->ops->remain_on_channel)
- ieee80211_recalc_sw_work(local, start_time);
}
static void ieee80211_hw_roc_start(struct work_struct *work)
@@ -291,6 +285,7 @@ static void ieee80211_hw_roc_start(struct work_struct *work)
if (!roc->started)
break;
+ roc->hw_begun = true;
ieee80211_handle_roc_started(roc, local->hw_roc_start_time);
}
@@ -413,6 +408,10 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
return;
}
+ /* defer roc if driver is not started (i.e. during reconfig) */
+ if (local->in_reconfig)
+ return;
+
roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
list);
@@ -534,8 +533,10 @@ ieee80211_coalesce_hw_started_roc(struct ieee80211_local *local,
* begin, otherwise they'll both be marked properly by the work
* struct that runs once the driver notifies us of the beginning
*/
- if (cur_roc->hw_begun)
+ if (cur_roc->hw_begun) {
+ new_roc->hw_begun = true;
ieee80211_handle_roc_started(new_roc, now);
+ }
return true;
}
@@ -658,6 +659,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
queued = true;
roc->on_channel = tmp->on_channel;
ieee80211_handle_roc_started(roc, now);
+ ieee80211_recalc_sw_work(local, now);
break;
}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index a413e52..ae980ce 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -314,6 +314,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
bool was_scanning = local->scanning;
struct cfg80211_scan_request *scan_req;
struct ieee80211_sub_if_data *scan_sdata;
+ struct ieee80211_sub_if_data *sdata;
lockdep_assert_held(&local->mtx);
@@ -373,7 +374,16 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
ieee80211_mlme_notify_scan_completed(local);
ieee80211_ibss_notify_scan_completed(local);
- ieee80211_mesh_notify_scan_completed(local);
+
+ /* Requeue all the work that might have been ignored while
+ * the scan was in progress; if there was none this will
+ * just be a no-op for the particular interface.
+ */
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (ieee80211_sdata_running(sdata))
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ }
+
if (was_scanning)
ieee80211_start_next_roc(local);
}
@@ -1213,6 +1223,14 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
trace_api_sched_scan_stopped(local);
+ /*
+ * this shouldn't really happen, so for simplicity
+ * simply ignore it, and let mac80211 reconfigure
+ * the sched scan later on.
+ */
+ if (local->in_reconfig)
+ return;
+
schedule_work(&local->sched_scan_stopped_work);
}
EXPORT_SYMBOL(ieee80211_sched_scan_stopped);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 4402ad5..a4a4f89 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1453,7 +1453,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
more_data = ieee80211_sta_ps_more_data(sta, ignored_acs, reason, driver_release_tids);
- if (reason == IEEE80211_FRAME_RELEASE_PSPOLL)
+ if (driver_release_tids && reason == IEEE80211_FRAME_RELEASE_PSPOLL)
driver_release_tids =
BIT(find_highest_prio_tid(driver_release_tids));
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 5bad05e..6101deb 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -51,6 +51,11 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
struct ieee80211_hdr *hdr = (void *)skb->data;
int ac;
+ if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) {
+ ieee80211_free_txskb(&local->hw, skb);
+ return;
+ }
+
/*
* This skb 'survived' a round-trip through the driver, and
* hopefully the driver didn't mangle it too badly. However,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 3943d4b..58f58bd 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2043,16 +2043,26 @@ int ieee80211_reconfig(struct ieee80211_local *local)
*/
if (sched_scan_req->n_scan_plans > 1 ||
__ieee80211_request_sched_scan_start(sched_scan_sdata,
- sched_scan_req))
+ sched_scan_req)) {
+ RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
+ RCU_INIT_POINTER(local->sched_scan_req, NULL);
sched_scan_stopped = true;
+ }
mutex_unlock(&local->mtx);
if (sched_scan_stopped)
cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);
wake_up:
- local->in_reconfig = false;
- barrier();
+ if (local->in_reconfig) {
+ local->in_reconfig = false;
+ barrier();
+
+ /* Restart deferred ROCs */
+ mutex_lock(&local->mtx);
+ ieee80211_start_next_roc(local);
+ mutex_unlock(&local->mtx);
+ }
if (local->monitors == local->open_count && local->monitors > 0)
ieee80211_add_virtual_monitor(local);
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 43d8c98..f0f688d 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -164,8 +164,6 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
};
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
- if (e.cidr == 0)
- return -EINVAL;
if (adt == IPSET_TEST)
e.cidr = HOST_MASK;
@@ -377,8 +375,6 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
};
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
- if (e.cidr == 0)
- return -EINVAL;
if (adt == IPSET_TEST)
e.cidr = HOST_MASK;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3cb3cb8..58882de 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -66,6 +66,21 @@ EXPORT_SYMBOL_GPL(nf_conntrack_locks);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(nf_conntrack_expect_lock);
EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock);
+static __read_mostly spinlock_t nf_conntrack_locks_all_lock;
+static __read_mostly bool nf_conntrack_locks_all;
+
+void nf_conntrack_lock(spinlock_t *lock) __acquires(lock)
+{
+ spin_lock(lock);
+ while (unlikely(nf_conntrack_locks_all)) {
+ spin_unlock(lock);
+ spin_lock(&nf_conntrack_locks_all_lock);
+ spin_unlock(&nf_conntrack_locks_all_lock);
+ spin_lock(lock);
+ }
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_lock);
+
static void nf_conntrack_double_unlock(unsigned int h1, unsigned int h2)
{
h1 %= CONNTRACK_LOCKS;
@@ -82,12 +97,12 @@ static bool nf_conntrack_double_lock(struct net *net, unsigned int h1,
h1 %= CONNTRACK_LOCKS;
h2 %= CONNTRACK_LOCKS;
if (h1 <= h2) {
- spin_lock(&nf_conntrack_locks[h1]);
+ nf_conntrack_lock(&nf_conntrack_locks[h1]);
if (h1 != h2)
spin_lock_nested(&nf_conntrack_locks[h2],
SINGLE_DEPTH_NESTING);
} else {
- spin_lock(&nf_conntrack_locks[h2]);
+ nf_conntrack_lock(&nf_conntrack_locks[h2]);
spin_lock_nested(&nf_conntrack_locks[h1],
SINGLE_DEPTH_NESTING);
}
@@ -102,16 +117,19 @@ static void nf_conntrack_all_lock(void)
{
int i;
- for (i = 0; i < CONNTRACK_LOCKS; i++)
- spin_lock_nested(&nf_conntrack_locks[i], i);
+ spin_lock(&nf_conntrack_locks_all_lock);
+ nf_conntrack_locks_all = true;
+
+ for (i = 0; i < CONNTRACK_LOCKS; i++) {
+ spin_lock(&nf_conntrack_locks[i]);
+ spin_unlock(&nf_conntrack_locks[i]);
+ }
}
static void nf_conntrack_all_unlock(void)
{
- int i;
-
- for (i = 0; i < CONNTRACK_LOCKS; i++)
- spin_unlock(&nf_conntrack_locks[i]);
+ nf_conntrack_locks_all = false;
+ spin_unlock(&nf_conntrack_locks_all_lock);
}
unsigned int nf_conntrack_htable_size __read_mostly;
@@ -757,7 +775,7 @@ restart:
hash = hash_bucket(_hash, net);
for (; i < net->ct.htable_size; i++) {
lockp = &nf_conntrack_locks[hash % CONNTRACK_LOCKS];
- spin_lock(lockp);
+ nf_conntrack_lock(lockp);
if (read_seqcount_retry(&net->ct.generation, sequence)) {
spin_unlock(lockp);
goto restart;
@@ -1382,7 +1400,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
for (; *bucket < net->ct.htable_size; (*bucket)++) {
lockp = &nf_conntrack_locks[*bucket % CONNTRACK_LOCKS];
local_bh_disable();
- spin_lock(lockp);
+ nf_conntrack_lock(lockp);
if (*bucket < net->ct.htable_size) {
hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) {
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index bd9d315..3b40ec5 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -425,7 +425,7 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me,
}
local_bh_disable();
for (i = 0; i < net->ct.htable_size; i++) {
- spin_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
+ nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
if (i < net->ct.htable_size) {
hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode)
unhelp(h, me);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index dbb1bb3..355e855 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -840,7 +840,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) {
restart:
lockp = &nf_conntrack_locks[cb->args[0] % CONNTRACK_LOCKS];
- spin_lock(lockp);
+ nf_conntrack_lock(lockp);
if (cb->args[0] >= net->ct.htable_size) {
spin_unlock(lockp);
goto out;
diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c
index b6605e0..5eefe4a 100644
--- a/net/netfilter/nf_tables_netdev.c
+++ b/net/netfilter/nf_tables_netdev.c
@@ -224,12 +224,12 @@ static int __init nf_tables_netdev_init(void)
nft_register_chain_type(&nft_filter_chain_netdev);
ret = register_pernet_subsys(&nf_tables_netdev_net_ops);
- if (ret < 0)
+ if (ret < 0) {
nft_unregister_chain_type(&nft_filter_chain_netdev);
-
+ return ret;
+ }
register_netdevice_notifier(&nf_tables_netdev_notifier);
-
- return ret;
+ return 0;
}
static void __exit nf_tables_netdev_exit(void)
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 5d010f2..94837d2 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -307,12 +307,12 @@ static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout)
local_bh_disable();
for (i = 0; i < net->ct.htable_size; i++) {
- spin_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
+ nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
if (i < net->ct.htable_size) {
hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode)
untimeout(h, timeout);
}
- spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
+ nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
}
local_bh_enable();
}
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
index 383c171..b78c28b 100644
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -46,16 +46,14 @@ static void nft_byteorder_eval(const struct nft_expr *expr,
switch (priv->op) {
case NFT_BYTEORDER_NTOH:
for (i = 0; i < priv->len / 8; i++) {
- src64 = get_unaligned_be64(&src[i]);
- src64 = be64_to_cpu((__force __be64)src64);
+ src64 = get_unaligned((u64 *)&src[i]);
put_unaligned_be64(src64, &dst[i]);
}
break;
case NFT_BYTEORDER_HTON:
for (i = 0; i < priv->len / 8; i++) {
src64 = get_unaligned_be64(&src[i]);
- src64 = (__force u64)cpu_to_be64(src64);
- put_unaligned_be64(src64, &dst[i]);
+ put_unaligned(src64, (u64 *)&dst[i]);
}
break;
}
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index a0eb216..d4a4619 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -127,6 +127,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
NF_CT_LABELS_MAX_SIZE - size);
return;
}
+#endif
case NFT_CT_BYTES: /* fallthrough */
case NFT_CT_PKTS: {
const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
@@ -138,7 +139,6 @@ static void nft_ct_get_eval(const struct nft_expr *expr,
memcpy(dest, &count, sizeof(count));
return;
}
-#endif
default:
break;
}
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index b7c43de..e118397 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -228,7 +228,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
u8 nexthdr;
- __be16 frag_off;
+ __be16 frag_off, oldlen, newlen;
int tcphoff;
int ret;
@@ -244,7 +244,12 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
return NF_DROP;
if (ret > 0) {
ipv6h = ipv6_hdr(skb);
- ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret);
+ oldlen = ipv6h->payload_len;
+ newlen = htons(ntohs(oldlen) + ret);
+ if (skb->ip_summed == CHECKSUM_COMPLETE)
+ skb->csum = csum_add(csum_sub(skb->csum, oldlen),
+ newlen);
+ ipv6h->payload_len = newlen;
}
return XT_CONTINUE;
}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 81dc1bb..f1ffb34 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2831,7 +2831,8 @@ static int netlink_dump(struct sock *sk)
* reasonable static buffer based on the expected largest dump of a
* single netdev. The outcome is MSG_TRUNC error.
*/
- skb_reserve(skb, skb_tailroom(skb) - alloc_size);
+ if (!netlink_rx_is_mmaped(sk))
+ skb_reserve(skb, skb_tailroom(skb) - alloc_size);
netlink_skb_set_owner_r(skb, sk);
len = cb->dump(skb, cb);
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index f53bf3b6..cf5b69a 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -1095,17 +1095,6 @@ static unsigned int rfkill_fop_poll(struct file *file, poll_table *wait)
return res;
}
-static bool rfkill_readable(struct rfkill_data *data)
-{
- bool r;
-
- mutex_lock(&data->mtx);
- r = !list_empty(&data->events);
- mutex_unlock(&data->mtx);
-
- return r;
-}
-
static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
@@ -1122,8 +1111,11 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
goto out;
}
mutex_unlock(&data->mtx);
+ /* since we re-check and it just compares pointers,
+ * using !list_empty() without locking isn't a problem
+ */
ret = wait_event_interruptible(data->read_wait,
- rfkill_readable(data));
+ !list_empty(&data->events));
mutex_lock(&data->mtx);
if (ret)
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index f26bdea..a1cd778 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -403,6 +403,8 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
if (len <= cl->deficit) {
cl->deficit -= len;
skb = qdisc_dequeue_peeked(cl->qdisc);
+ if (unlikely(skb == NULL))
+ goto out;
if (cl->qdisc->q.qlen == 0)
list_del(&cl->alist);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index bf61dfb..49d2cc7 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -935,15 +935,22 @@ static struct sctp_association *__sctp_lookup_association(
struct sctp_transport **pt)
{
struct sctp_transport *t;
+ struct sctp_association *asoc = NULL;
+ rcu_read_lock();
t = sctp_addrs_lookup_transport(net, local, peer);
- if (!t || t->dead)
- return NULL;
+ if (!t || !sctp_transport_hold(t))
+ goto out;
- sctp_association_hold(t->asoc);
+ asoc = t->asoc;
+ sctp_association_hold(asoc);
*pt = t;
- return t->asoc;
+ sctp_transport_put(t);
+
+out:
+ rcu_read_unlock();
+ return asoc;
}
/* Look up an association. protected by RCU read lock */
@@ -955,9 +962,7 @@ struct sctp_association *sctp_lookup_association(struct net *net,
{
struct sctp_association *asoc;
- rcu_read_lock();
asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
- rcu_read_unlock();
return asoc;
}
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 684c5b3..ded7d93 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -165,8 +165,6 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
transports) {
addr = &transport->ipaddr;
- if (transport->dead)
- continue;
af = sctp_get_af_specific(addr->sa.sa_family);
if (af->cmp_addr(addr, primary)) {
@@ -380,6 +378,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
}
transport = (struct sctp_transport *)v;
+ if (!sctp_transport_hold(transport))
+ return 0;
assoc = transport->asoc;
epb = &assoc->base;
sk = epb->sk;
@@ -412,6 +412,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
sk->sk_rcvbuf);
seq_printf(seq, "\n");
+ sctp_transport_put(transport);
+
return 0;
}
@@ -489,12 +491,12 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
}
tsp = (struct sctp_transport *)v;
+ if (!sctp_transport_hold(tsp))
+ return 0;
assoc = tsp->asoc;
list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
transports) {
- if (tsp->dead)
- continue;
/*
* The remote address (ADDR)
*/
@@ -544,6 +546,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "\n");
}
+ sctp_transport_put(tsp);
+
return 0;
}
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 2e21384..b5327bb 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -259,12 +259,6 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
goto out_unlock;
}
- /* Is this transport really dead and just waiting around for
- * the timer to let go of the reference?
- */
- if (transport->dead)
- goto out_unlock;
-
/* Run through the state machine. */
error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT,
SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_T3_RTX),
@@ -380,12 +374,6 @@ void sctp_generate_heartbeat_event(unsigned long data)
goto out_unlock;
}
- /* Is this structure just waiting around for us to actually
- * get destroyed?
- */
- if (transport->dead)
- goto out_unlock;
-
error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT,
SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_HEARTBEAT),
asoc->state, asoc->ep, asoc,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9bb80ec..5ca2ebf 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6636,6 +6636,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
if (cmsgs->srinfo->sinfo_flags &
~(SCTP_UNORDERED | SCTP_ADDR_OVER |
+ SCTP_SACK_IMMEDIATELY |
SCTP_ABORT | SCTP_EOF))
return -EINVAL;
break;
@@ -6659,6 +6660,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
if (cmsgs->sinfo->snd_flags &
~(SCTP_UNORDERED | SCTP_ADDR_OVER |
+ SCTP_SACK_IMMEDIATELY |
SCTP_ABORT | SCTP_EOF))
return -EINVAL;
break;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index aab9e3f..a431c14 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -132,8 +132,6 @@ fail:
*/
void sctp_transport_free(struct sctp_transport *transport)
{
- transport->dead = 1;
-
/* Try to delete the heartbeat timer. */
if (del_timer(&transport->hb_timer))
sctp_transport_put(transport);
@@ -169,7 +167,7 @@ static void sctp_transport_destroy_rcu(struct rcu_head *head)
*/
static void sctp_transport_destroy(struct sctp_transport *transport)
{
- if (unlikely(!transport->dead)) {
+ if (unlikely(atomic_read(&transport->refcnt))) {
WARN(1, "Attempt to destroy undead transport %p!\n", transport);
return;
}
@@ -296,9 +294,9 @@ void sctp_transport_route(struct sctp_transport *transport,
}
/* Hold a reference to a transport. */
-void sctp_transport_hold(struct sctp_transport *transport)
+int sctp_transport_hold(struct sctp_transport *transport)
{
- atomic_inc(&transport->refcnt);
+ return atomic_add_unless(&transport->refcnt, 1, 0);
}
/* Release a reference to a transport and clean up
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index ebc661d..47f7da5 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -20,6 +20,7 @@
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/if_vlan.h>
+#include <linux/rtnetlink.h>
#include <net/ip_fib.h>
#include <net/switchdev.h>
@@ -567,7 +568,6 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj,
}
EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
-static DEFINE_MUTEX(switchdev_mutex);
static RAW_NOTIFIER_HEAD(switchdev_notif_chain);
/**
@@ -582,9 +582,9 @@ int register_switchdev_notifier(struct notifier_block *nb)
{
int err;
- mutex_lock(&switchdev_mutex);
+ rtnl_lock();
err = raw_notifier_chain_register(&switchdev_notif_chain, nb);
- mutex_unlock(&switchdev_mutex);
+ rtnl_unlock();
return err;
}
EXPORT_SYMBOL_GPL(register_switchdev_notifier);
@@ -600,9 +600,9 @@ int unregister_switchdev_notifier(struct notifier_block *nb)
{
int err;
- mutex_lock(&switchdev_mutex);
+ rtnl_lock();
err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb);
- mutex_unlock(&switchdev_mutex);
+ rtnl_unlock();
return err;
}
EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
@@ -616,16 +616,17 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
* Call all network notifier blocks. This should be called by driver
* when it needs to propagate hardware event.
* Return values are same as for atomic_notifier_call_chain().
+ * rtnl_lock must be held.
*/
int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
struct switchdev_notifier_info *info)
{
int err;
+ ASSERT_RTNL();
+
info->dev = dev;
- mutex_lock(&switchdev_mutex);
err = raw_notifier_call_chain(&switchdev_notif_chain, val, info);
- mutex_unlock(&switchdev_mutex);
return err;
}
EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 350cca3..69ee2ee 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -289,15 +289,14 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid,
struct sockaddr_tipc *addr, void *usr_data,
void *buf, size_t len)
{
- struct tipc_subscriber *subscriber = usr_data;
+ struct tipc_subscriber *subscrb = usr_data;
struct tipc_subscription *sub = NULL;
struct tipc_net *tn = net_generic(net, tipc_net_id);
- tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscriber, &sub);
- if (sub)
- tipc_nametbl_subscribe(sub);
- else
- tipc_conn_terminate(tn->topsrv, subscriber->conid);
+ if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub))
+ return tipc_conn_terminate(tn->topsrv, subscrb->conid);
+
+ tipc_nametbl_subscribe(sub);
}
/* Handle one request to establish a new subscriber */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index c5bf5ef..49d5093 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2339,6 +2339,7 @@ again:
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
+ scm_destroy(&scm);
goto out;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 3b0ce1c..547ceec 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -231,20 +231,22 @@ static const struct ieee80211_regdomain world_regdom = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
/* IEEE 802.11b/g, channels 12..13. */
- REG_RULE(2467-10, 2472+10, 40, 6, 20,
- NL80211_RRF_NO_IR),
+ REG_RULE(2467-10, 2472+10, 20, 6, 20,
+ NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW),
/* IEEE 802.11 channel 14 - Only JP enables
* this and for 802.11b only */
REG_RULE(2484-10, 2484+10, 20, 6, 20,
NL80211_RRF_NO_IR |
NL80211_RRF_NO_OFDM),
/* IEEE 802.11a, channel 36..48 */
- REG_RULE(5180-10, 5240+10, 160, 6, 20,
- NL80211_RRF_NO_IR),
+ REG_RULE(5180-10, 5240+10, 80, 6, 20,
+ NL80211_RRF_NO_IR |
+ NL80211_RRF_AUTO_BW),
/* IEEE 802.11a, channel 52..64 - DFS required */
- REG_RULE(5260-10, 5320+10, 160, 6, 20,
+ REG_RULE(5260-10, 5320+10, 80, 6, 20,
NL80211_RRF_NO_IR |
+ NL80211_RRF_AUTO_BW |
NL80211_RRF_DFS),
/* IEEE 802.11a, channel 100..144 - DFS required */
@@ -2745,7 +2747,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
const struct ieee80211_power_rule *power_rule = NULL;
char bw[32], cac_time[32];
- pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
+ pr_debug(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
for (i = 0; i < rd->n_reg_rules; i++) {
reg_rule = &rd->reg_rules[i];
@@ -2772,7 +2774,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
* in certain regions
*/
if (power_rule->max_antenna_gain)
- pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
+ pr_debug(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
freq_range->start_freq_khz,
freq_range->end_freq_khz,
bw,
@@ -2780,7 +2782,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
power_rule->max_eirp,
cac_time);
else
- pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
+ pr_debug(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
freq_range->start_freq_khz,
freq_range->end_freq_khz,
bw,
@@ -2813,35 +2815,35 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
struct cfg80211_registered_device *rdev;
rdev = cfg80211_rdev_by_wiphy_idx(lr->wiphy_idx);
if (rdev) {
- pr_info("Current regulatory domain updated by AP to: %c%c\n",
+ pr_debug("Current regulatory domain updated by AP to: %c%c\n",
rdev->country_ie_alpha2[0],
rdev->country_ie_alpha2[1]);
} else
- pr_info("Current regulatory domain intersected:\n");
+ pr_debug("Current regulatory domain intersected:\n");
} else
- pr_info("Current regulatory domain intersected:\n");
+ pr_debug("Current regulatory domain intersected:\n");
} else if (is_world_regdom(rd->alpha2)) {
- pr_info("World regulatory domain updated:\n");
+ pr_debug("World regulatory domain updated:\n");
} else {
if (is_unknown_alpha2(rd->alpha2))
- pr_info("Regulatory domain changed to driver built-in settings (unknown country)\n");
+ pr_debug("Regulatory domain changed to driver built-in settings (unknown country)\n");
else {
if (reg_request_cell_base(lr))
- pr_info("Regulatory domain changed to country: %c%c by Cell Station\n",
+ pr_debug("Regulatory domain changed to country: %c%c by Cell Station\n",
rd->alpha2[0], rd->alpha2[1]);
else
- pr_info("Regulatory domain changed to country: %c%c\n",
+ pr_debug("Regulatory domain changed to country: %c%c\n",
rd->alpha2[0], rd->alpha2[1]);
}
}
- pr_info(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region));
+ pr_debug(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region));
print_rd_rules(rd);
}
static void print_regdomain_info(const struct ieee80211_regdomain *rd)
{
- pr_info("Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]);
+ pr_debug("Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]);
print_rd_rules(rd);
}
@@ -2862,7 +2864,8 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
return -EALREADY;
if (!is_valid_rd(rd)) {
- pr_err("Invalid regulatory domain detected:\n");
+ pr_err("Invalid regulatory domain detected: %c%c\n",
+ rd->alpha2[0], rd->alpha2[1]);
print_regdomain_info(rd);
return -EINVAL;
}
@@ -2898,7 +2901,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
return -EALREADY;
if (!is_valid_rd(rd)) {
- pr_err("Invalid regulatory domain detected:\n");
+ pr_err("Invalid regulatory domain detected: %c%c\n",
+ rd->alpha2[0], rd->alpha2[1]);
print_regdomain_info(rd);
return -EINVAL;
}
@@ -2956,7 +2960,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
*/
if (!is_valid_rd(rd)) {
- pr_err("Invalid regulatory domain detected:\n");
+ pr_err("Invalid regulatory domain detected: %c%c\n",
+ rd->alpha2[0], rd->alpha2[1]);
print_regdomain_info(rd);
return -EINVAL;
}
OpenPOWER on IntegriCloud