* [PATCH/RFC net-next] ravb: RX checksum offload
From: Simon Horman @ 2017-09-12 13:04 UTC (permalink / raw)
To: David Miller, Sergei Shtylyov
Cc: Magnus Damm, netdev, linux-renesas-soc, Simon Horman
Add support for RX checksum offload. This is enabled by default and
may be disabled and re-enabled using ethtool:
# ethtool -K eth0 rx off
# ethtool -K eth0 rx on
The RAVB provides a simple checksumming scheme which appears to be
completely compatible with CHECKSUM_COMPLETE: a 1's complement sum of
all packet data after the L2 header is appended to packet data; this may
be trivially read by the driver and used to update the skb accordingly.
In terms of performance throughput is close to gigabit line-rate both with
and without RX checksum offload enabled. Perf output, however, appears to
indicate that significantly less time is spent in do_csum(). This is as
expected.
Test results with RX checksum offload enabled:
# /usr/bin/perf_3.16 record -o /run/perf.data -a netperf -t TCP_MAERTS -H 10.4.3.162
MIGRATED TCP MAERTS TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.4.3.162 () port 0 AF_INET : demo
enable_enobufs failed: getprotobyname
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.00 938.78
[ perf record: Woken up 14 times to write data ]
[ perf record: Captured and wrote 3.524 MB /run/perf.data (~153957 samples) ]
Summary of output of perf report:
19.49% ksoftirqd/0 [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore
9.88% ksoftirqd/0 [kernel.kallsyms] [k] __pi_memcpy
7.33% ksoftirqd/0 [kernel.kallsyms] [k] skb_put
7.00% ksoftirqd/0 [kernel.kallsyms] [k] ravb_poll
3.89% ksoftirqd/0 [kernel.kallsyms] [k] dev_gro_receive
3.65% netperf [kernel.kallsyms] [k] __arch_copy_to_user
3.43% swapper [kernel.kallsyms] [k] arch_cpu_idle
2.77% swapper [kernel.kallsyms] [k] tick_nohz_idle_enter
1.85% ksoftirqd/0 [kernel.kallsyms] [k] __netdev_alloc_skb
1.80% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irq
1.64% ksoftirqd/0 [kernel.kallsyms] [k] __slab_alloc.isra.79
1.62% ksoftirqd/0 [kernel.kallsyms] [k] __pi___inval_cache_range
Test results without RX checksum offload enabled:
# /usr/bin/perf_3.16 record -o /run/perf.data -a netperf -t TCP_MAERTS -H 10.4.3.162
MIGRATED TCP MAERTS TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.4.3.162 () port 0 AF_INET : demo
enable_enobufs failed: getprotobyname
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.00 941.09
[ perf record: Woken up 14 times to write data ]
[ perf record: Captured and wrote 3.411 MB /run/perf.data (~149040 samples) ]
Summary of output of perf report:
17.50% ksoftirqd/0 [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore
10.60% ksoftirqd/0 [kernel.kallsyms] [k] __pi_memcpy
7.91% ksoftirqd/0 [kernel.kallsyms] [k] skb_put
6.95% ksoftirqd/0 [kernel.kallsyms] [k] do_csum
6.22% ksoftirqd/0 [kernel.kallsyms] [k] ravb_poll
3.84% ksoftirqd/0 [kernel.kallsyms] [k] dev_gro_receive
2.53% netperf [kernel.kallsyms] [k] __arch_copy_to_user
2.53% swapper [kernel.kallsyms] [k] arch_cpu_idle
2.27% swapper [kernel.kallsyms] [k] tick_nohz_idle_enter
1.90% ksoftirqd/0 [kernel.kallsyms] [k] __pi___inval_cache_range
1.90% ksoftirqd/0 [kernel.kallsyms] [k] __netdev_alloc_skb
1.52% ksoftirqd/0 [kernel.kallsyms] [k] __slab_alloc.isra.79
Above results collected on an R-Car Gen 3 Salvator-X/r8a7796 ES1.0.
Also tested on a R-Car Gen 3 Salvator-X/r8a7795 ES1.0.
By inspection this also appears to be compatible with the ravb found
on R-Car Gen 2 SoCs, however, this patch is currently untested on such
hardware.
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/net/ethernet/renesas/ravb_main.c | 58 +++++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index fdf30bfa403b..7c6438cd7de7 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -403,8 +403,9 @@ static void ravb_emac_init(struct net_device *ndev)
/* Receive frame limit set register */
ravb_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR);
- /* PAUSE prohibition */
+ /* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */
ravb_write(ndev, ECMR_ZPF | (priv->duplex ? ECMR_DM : 0) |
+ (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) |
ECMR_TE | ECMR_RE, ECMR);
ravb_set_rate(ndev);
@@ -520,6 +521,19 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
}
}
+static void ravb_rx_csum(struct sk_buff *skb)
+{
+ u8 *hw_csum;
+
+ /* The hardware checksum is 2 bytes appended to packet data */
+ if (unlikely(skb->len < 2))
+ return;
+ hw_csum = skb_tail_pointer(skb) - 2;
+ skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb_trim(skb, skb->len - 2);
+}
+
/* Packet receive function for Ethernet AVB */
static bool ravb_rx(struct net_device *ndev, int *quota, int q)
{
@@ -587,8 +601,11 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q)
ts.tv_nsec = le32_to_cpu(desc->ts_n);
shhwtstamps->hwtstamp = timespec64_to_ktime(ts);
}
+
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
+ if (ndev->features & NETIF_F_RXCSUM)
+ ravb_rx_csum(skb);
napi_gro_receive(&priv->napi[q], skb);
stats->rx_packets++;
stats->rx_bytes += pkt_len;
@@ -1842,6 +1859,41 @@ static int ravb_do_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
return phy_mii_ioctl(phydev, req, cmd);
}
+static void ravb_set_rx_csum(struct net_device *ndev, bool enable)
+{
+ struct ravb_private *priv = netdev_priv(ndev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* Disable TX and RX */
+ ravb_rcv_snd_disable(ndev);
+
+ /* Modify RX Checksum setting */
+ if (enable)
+ ravb_modify(ndev, ECMR, 0, ECMR_RCSC);
+ else
+ ravb_modify(ndev, ECMR, ECMR_RCSC, 0);
+
+ /* Enable TX and RX */
+ ravb_rcv_snd_enable(ndev);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int ravb_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+ netdev_features_t changed = ndev->features ^ features;
+
+ if (changed & NETIF_F_RXCSUM)
+ ravb_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
+
+ ndev->features = features;
+
+ return 0;
+}
+
static const struct net_device_ops ravb_netdev_ops = {
.ndo_open = ravb_open,
.ndo_stop = ravb_close,
@@ -1853,6 +1905,7 @@ static const struct net_device_ops ravb_netdev_ops = {
.ndo_do_ioctl = ravb_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_features = ravb_set_features,
};
/* MDIO bus init function */
@@ -2004,6 +2057,9 @@ static int ravb_probe(struct platform_device *pdev)
if (!ndev)
return -ENOMEM;
+ ndev->features |= NETIF_F_RXCSUM;
+ ndev->hw_features |= ndev->features;
+
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
--
2.1.4
^ permalink raw reply related
* RE: [PATCH v2 net 1/3] lan78xx: Fix for eeprom read/write when device auto suspend
From: Nisar.Sayed @ 2017-09-12 13:01 UTC (permalink / raw)
To: andrew; +Cc: davem, UNGLinuxDriver, netdev
In-Reply-To: <20170911202428.GB5983@lunn.ch>
> > From: Nisar Sayed <Nisar.Sayed@microchip.com>
> >
> > Fix for eeprom read/write when device auto suspend
> >
> > Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to
> > 10/100/1000 Ethernet device driver")
> > Signed-off-by: Nisar Sayed <Nisar.Sayed@microchip.com>
> > ---
> > drivers/net/usb/lan78xx.c | 22 ++++++++++++++++++----
> > 1 file changed, 18 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
> > index b99a7fb..baf91c7 100644
> > --- a/drivers/net/usb/lan78xx.c
> > +++ b/drivers/net/usb/lan78xx.c
> > @@ -1265,30 +1265,44 @@ static int lan78xx_ethtool_get_eeprom(struct
> net_device *netdev,
> > struct ethtool_eeprom *ee, u8 *data) {
> > struct lan78xx_net *dev = netdev_priv(netdev);
> > + int ret = -EINVAL;
> > +
> > + if (usb_autopm_get_interface(dev->intf) < 0)
> > + return ret;
>
> Hi Nisar
>
> It is better to do
>
> ret = usb_autopm_get_interface(dev->intf;
> if (ret)
> return ret;
>
> i.e. use the error code usb_autopm_get_interface() gives you.
>
> > ee->magic = LAN78XX_EEPROM_MAGIC;
> >
> > - return lan78xx_read_raw_eeprom(dev, ee->offset, ee->len, data);
> > + ret = lan78xx_read_raw_eeprom(dev, ee->offset, ee->len, data);
> > +
> > + usb_autopm_put_interface(dev->intf);
> > +
> > + return ret;
> > }
> >
> > static int lan78xx_ethtool_set_eeprom(struct net_device *netdev,
> > struct ethtool_eeprom *ee, u8 *data) {
> > struct lan78xx_net *dev = netdev_priv(netdev);
> > + int ret = -EINVAL;
> > +
> > + if (usb_autopm_get_interface(dev->intf) < 0)
> > + return ret;
>
> Same here.
>
> Andrew
Thanks Andrew, will update it.
- Nisar
^ permalink raw reply
* Re: [PATCH net-next v2 1/2] net: phy: realtek: rename RTL8211F_PAGE_SELECT to RTL821x_PAGE_SELECT
From: Andrew Lunn @ 2017-09-12 12:57 UTC (permalink / raw)
To: Kunihiko Hayashi; +Cc: Florian Fainelli, netdev, Jassi Brar
In-Reply-To: <1505210076-32311-1-git-send-email-hayashi.kunihiko@socionext.com>
On Tue, Sep 12, 2017 at 06:54:35PM +0900, Kunihiko Hayashi wrote:
> This renames the definition of page select register from
> RTL8211F_PAGE_SELECT to RTL821x_PAGE_SELECT to use it across models.
>
> Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* [PATCH] w90p910_ether: include linux/interrupt.h
From: Arnd Bergmann @ 2017-09-12 12:31 UTC (permalink / raw)
To: Wan ZongShun
Cc: linux-arm-kernel, netdev, David S. Miller, Arnd Bergmann,
linux-kernel
A randconfig build caused a compile failure:
drivers/net/ethernet/nuvoton/w90p910_ether.c: In function 'w90p910_ether_close':
drivers/net/ethernet/nuvoton/w90p910_ether.c:580:2: error: implicit declaration of function 'free_irq'; did you mean 'free_uid'? [-Werror=implicit-function-declaration]
Adding the correct include fixes the problem.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ethernet/nuvoton/w90p910_ether.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index 89ab786da25f..4a67c55aa9f1 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
--
2.9.0
^ permalink raw reply related
* [PATCH net] net: bonding: fix tlb_dynamic_lb default value
From: Nikolay Aleksandrov @ 2017-09-12 12:10 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, maheshb, Nikolay Aleksandrov
Commit 8b426dc54cf4 ("bonding: remove hardcoded value") changed the
default value for tlb_dynamic_lb which lead to either broken ALB mode
(since tlb_dynamic_lb can be changed only in TLB) or setting TLB mode
with tlb_dynamic_lb equal to 0.
The first issue was recently fixed by setting tlb_dynamic_lb to 1 always
when switching to ALB mode, but the default value is still wrong and
we'll enter TLB mode with tlb_dynamic_lb equal to 0 if the mode is
changed via netlink or sysfs. In order to restore the previous behaviour
and default value simply remove the mode check around the default param
initialization for tlb_dynamic_lb which will always set it to 1 as
before.
Fixes: 8b426dc54cf4 ("bonding: remove hardcoded value")
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
drivers/net/bonding/bond_main.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index fc63992ab0e0..c99dc59d729b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4289,7 +4289,7 @@ static int bond_check_params(struct bond_params *params)
int bond_mode = BOND_MODE_ROUNDROBIN;
int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
int lacp_fast = 0;
- int tlb_dynamic_lb = 0;
+ int tlb_dynamic_lb;
/* Convert string parameters. */
if (mode) {
@@ -4601,16 +4601,13 @@ static int bond_check_params(struct bond_params *params)
}
ad_user_port_key = valptr->value;
- if ((bond_mode == BOND_MODE_TLB) || (bond_mode == BOND_MODE_ALB)) {
- bond_opt_initstr(&newval, "default");
- valptr = bond_opt_parse(bond_opt_get(BOND_OPT_TLB_DYNAMIC_LB),
- &newval);
- if (!valptr) {
- pr_err("Error: No tlb_dynamic_lb default value");
- return -EINVAL;
- }
- tlb_dynamic_lb = valptr->value;
+ bond_opt_initstr(&newval, "default");
+ valptr = bond_opt_parse(bond_opt_get(BOND_OPT_TLB_DYNAMIC_LB), &newval);
+ if (!valptr) {
+ pr_err("Error: No tlb_dynamic_lb default value");
+ return -EINVAL;
}
+ tlb_dynamic_lb = valptr->value;
if (lp_interval == 0) {
pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n",
--
2.1.4
^ permalink raw reply related
* Re: ipset losing entries on its own
From: Akshat Kakkar @ 2017-09-12 11:54 UTC (permalink / raw)
To: Denys Fedoryshchenko; +Cc: netdev, netdev-owner
In-Reply-To: <CAA5aLPgM9=VU4Cysy-LtN-uXPqvG00X2v8MP9EM5RtPVB6tGvw@mail.gmail.com>
can somebody throw more light on this? How it is possible (without a
bug) that for exactly same set of IPs, at time IPSET HASHSIZE remains
at 1024 and at times it increases to 2048?
As a workaround I am running the show setting HASHSIZE as 16384 at
times of IPSET creation itself, and till now (its more than 4 days)
the issue has not repeated.
But this need to be addressed, right?
^ permalink raw reply
* Re: Subject: [PATCH] vxlan: only reduce known arp boardcast request to support, virtual IP
From: Jiri Benc @ 2017-09-12 11:51 UTC (permalink / raw)
To: oc; +Cc: davem, Linux Kernel Network Developers
In-Reply-To: <2c1bfd7d-5fe7-d492-2396-71deaeb14244@yunify.com>
On Tue, 12 Sep 2017 11:26:49 +0800, oc wrote:
> The purpose of vxlan arp reduce feature is to reply the boardcast
> arp request in vtep instead of sending it out to save traffic.
> The current implemention drops arp packet, if the ip cannot be
> found in neigh table. In the case of virtual IP address, user
> defines IP address without management from SDN controller. The IP
> address does not exist in neigh table, so the arp boardcast request
> from a client can not be sent to the server who owns the virtual IP
> address.
>
> This patch allow the arp request to be sent out if:
> 1. not arp boardcast request
> 2. cannot be found in neigh table
> 3. arp record status is not NUD_CONNECTED
>
> The user defined of virtual IP address works while arp reduce still
> suppress the arp boardcast for IP address managed by SDN controller
> with this patch.
Your patch is whitespace damaged, does not conform to the kernel coding
style and the email does not have your full name in the From header.
As for the patch itself, you're changing existing functionality that
people may depend on and thus a new config option is needed to enable
the behavior.
Jiri
^ permalink raw reply
* [PATCH] vti: fix NULL dereference in xfrm_input()
From: Alexey Kodanev @ 2017-09-12 11:53 UTC (permalink / raw)
To: netdev; +Cc: Steffen Klassert, Herbert Xu, David Miller, Alexey Kodanev
Can be reproduced with LTP tests:
# icmp-uni-vti.sh -p ah -a sha256 -m tunnel -S fffffffe -k 1 -s 10
IPv4:
RIP: 0010:xfrm_input+0x7f9/0x870
...
Call Trace:
<IRQ>
vti_input+0xaa/0x110 [ip_vti]
? skb_free_head+0x21/0x40
vti_rcv+0x33/0x40 [ip_vti]
xfrm4_ah_rcv+0x33/0x60
ip_local_deliver_finish+0x94/0x1e0
ip_local_deliver+0x6f/0xe0
? ip_route_input_noref+0x28/0x50
...
# icmp-uni-vti.sh -6 -p ah -a sha256 -m tunnel -S fffffffe -k 1 -s 10
IPv6:
RIP: 0010:xfrm_input+0x7f9/0x870
...
Call Trace:
<IRQ>
xfrm6_rcv_tnl+0x3c/0x40
vti6_rcv+0xd5/0xe0 [ip6_vti]
xfrm6_ah_rcv+0x33/0x60
ip6_input_finish+0xee/0x460
ip6_input+0x3f/0xb0
ip6_rcv_finish+0x45/0xa0
ipv6_rcv+0x34b/0x540
xfrm_input() invokes xfrm_rcv_cb() -> vti_rcv_cb(), the last callback
might call skb_scrub_packet(), which in turn can reset secpath.
Fix it by adding a check that skb->sp is not NULL.
Fixes: 7e9e9202bccc ("xfrm: Clear RX SKB secpath xfrm_offload")
Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
net/xfrm/xfrm_input.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 2515cd2..8ac9d32 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -429,7 +429,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
nf_reset(skb);
if (decaps) {
- skb->sp->olen = 0;
+ if (skb->sp)
+ skb->sp->olen = 0;
skb_dst_drop(skb);
gro_cells_receive(&gro_cells, skb);
return 0;
@@ -440,7 +441,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async);
if (xfrm_gro) {
- skb->sp->olen = 0;
+ if (skb->sp)
+ skb->sp->olen = 0;
skb_dst_drop(skb);
gro_cells_receive(&gro_cells, skb);
return err;
--
1.7.1
^ permalink raw reply related
* [PATCH] qed: remove unnecessary call to memset
From: Himanshu Jha @ 2017-09-12 11:19 UTC (permalink / raw)
To: Yuval.Mintz
Cc: Ariel.Elior, everest-linux-l2, netdev, linux-kernel, Himanshu Jha
call to memset to assign 0 value immediately after allocating
memory with kzalloc is unnecesaary as kzalloc allocates the memory
filled with 0 value.
Semantic patch used to resolve this issue:
@@
expression e,e2; constant c;
statement S;
@@
e = kzalloc(e2, c);
if(e == NULL) S
- memset(e, 0, e2);
Signed-off-by: Himanshu Jha <himanshujha199640@gmail.com>
---
drivers/net/ethernet/qlogic/qed/qed_dcbx.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
index eaca457..8f6ccc0 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
@@ -1244,7 +1244,6 @@ int qed_dcbx_get_config_params(struct qed_hwfn *p_hwfn,
if (!dcbx_info)
return -ENOMEM;
- memset(dcbx_info, 0, sizeof(*dcbx_info));
rc = qed_dcbx_query_params(p_hwfn, dcbx_info, QED_DCBX_OPERATIONAL_MIB);
if (rc) {
kfree(dcbx_info);
--
2.7.4
^ permalink raw reply related
* Re: broken vlan support on Realtek RTL8111/8168/8411 rev 9
From: Benoit Panizzon @ 2017-09-12 11:07 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev
In-Reply-To: <20170911222325.GA23162@electric-eye.fr.zoreil.com>
Hi Francois
> ethtool -K eth0 rxvlan off
Thank you, that did the trick, vlan tags are not correctly passed on
and not set to vlan 0 with rxvlan turned off.
> For my reward, please send a complete dmesg where the messages from
> the vanilla r8169 module appear for the rev 09 card (r81..f ?). I
> won't dig it right now.
Yes, the 'f' variant:
[ 1.035203] r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
[ 1.035262] r8169 0000:03:00.0: setting latency timer to 64
[ 1.035348] r8169 0000:03:00.0: irq 41 for MSI/MSI-X
[ 1.035634] r8169 0000:03:00.0: eth0: RTL8168f/8111f at 0xffffc90000c28000, c8:60:00:dd:f8:6c, XID 08000800 IRQ 41
[ 1.035637] r8169 0000:03:00.0: eth0: jumbo features [frames: 9200 bytes, tx checksumming: ko]
[ 10.403921] r8169 0000:03:00.0: firmware: agent loaded rtl_nic/rtl8168f-1.fw into memory
Linux pulsar 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) x86_64 GNU/Linux
624831688e25aa47fa84c30c045fcae3 /lib/firmware/rtl_nic/rtl8168f-1.fw
Firmware Bug or Hardware Problem?
-Benoît Panizzon-
--
I m p r o W a r e A G - Leiter Commerce Kunden
______________________________________________________
Zurlindenstrasse 29 Tel +41 61 826 93 00
CH-4133 Pratteln Fax +41 61 826 93 01
Schweiz Web http://www.imp.ch
______________________________________________________
^ permalink raw reply
* Re: [Patch net v3 3/3] net_sched: carefully handle tcf_block_put()
From: Jiri Pirko @ 2017-09-12 10:43 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, jiri, jakub.kicinski, jhs
In-Reply-To: <20170911233332.7594-4-xiyou.wangcong@gmail.com>
Tue, Sep 12, 2017 at 01:33:32AM CEST, xiyou.wangcong@gmail.com wrote:
>As pointed out by Jiri, there is still a race condition between
>tcf_block_put() and tcf_chain_destroy() in a RCU callback. There
>is no way to make it correct without proper locking or synchronization,
>because both operate on a shared list.
>
>Locking is hard, because the only lock we can pick here is a spinlock,
>however, in tc_dump_tfilter() we iterate this list with a sleeping
>function called (tcf_chain_dump()), which makes using a lock to protect
>chain_list almost impossible.
>
>Jiri suggested the idea of holding a refcnt before flushing, this works
>because it guarantees us there would be no parallel tcf_chain_destroy()
>during the loop, therefore the race condition is gone. But we have to
>be very careful with proper synchronization with RCU callbacks.
>
>Suggested-by: Jiri Pirko <jiri@mellanox.com>
>Cc: Jamal Hadi Salim <jhs@mojatatu.com>
>Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Thanks!
^ permalink raw reply
* Re: [Patch net v3 2/3] net_sched: fix reference counting of tc filter chain
From: Jiri Pirko @ 2017-09-12 10:43 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, jiri, jakub.kicinski, jhs
In-Reply-To: <20170911233332.7594-3-xiyou.wangcong@gmail.com>
Tue, Sep 12, 2017 at 01:33:31AM CEST, xiyou.wangcong@gmail.com wrote:
>This patch fixes the following ugliness of tc filter chain refcnt:
>
>a) tp proto should hold a refcnt to the chain too. This significantly
> simplifies the logic.
>
>b) Chain 0 is no longer special, it is created with refcnt=1 like any
> other chains. All the ugliness in tcf_chain_put() can be gone!
>
>c) No need to handle the flushing oddly, because block still holds
> chain 0, it can not be released, this guarantees block is the last
> user.
>
>d) The race condition with RCU callbacks is easier to handle with just
> a rcu_barrier(). Much easier to understand, nothing to hide. Thanks
> to the previous patch. Please see also the comments in code.
>
>e) Make the code understandable by humans, much less error-prone.
>
>Fixes: 744a4cf63e52 ("net: sched: fix use after free when tcf_chain_destroy is called multiple times")
>Fixes: 5bc1701881e3 ("net: sched: introduce multichain support for filters")
>Cc: Jiri Pirko <jiri@mellanox.com>
>Cc: Jamal Hadi Salim <jhs@mojatatu.com>
>Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Looking good to me. Thanks!
Acked-by: Jiri Pirko <jiri@mellanox.com>
^ permalink raw reply
* Re: [Patch net v3 1/3] net_sched: get rid of tcfa_rcu
From: Jiri Pirko @ 2017-09-12 10:40 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, jiri, jakub.kicinski, jhs, Eric Dumazet
In-Reply-To: <20170912094215.GB2036@nanopsycho>
Tue, Sep 12, 2017 at 11:42:15AM CEST, jiri@resnulli.us wrote:
>Tue, Sep 12, 2017 at 01:33:30AM CEST, xiyou.wangcong@gmail.com wrote:
>>gen estimator has been rewritten in commit 1c0d32fde5bd
>>("net_sched: gen_estimator: complete rewrite of rate estimators"),
>>the caller is no longer needed to wait for a grace period.
>>So this patch gets rid of it.
>>
>>This also completely closes a race condition between action free
>>path and filter chain add/remove path for the following patch.
>>Because otherwise the nested RCU callback can't be caught by
>>rcu_barrier().
>>
>>Please see also the comments in code.
>
>Looks like this is causing a null pointer dereference bug for me, 100%
>of the time. Just add and remove any rule with action and you get:
>
[...]
>
>Looks like you need to save owner of the module before you call
>__tcf_idr_release so you can later on use it for module_put
This patch helps:
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index fcd7dc7..de73e71 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -514,13 +514,15 @@ EXPORT_SYMBOL(tcf_action_exec);
int tcf_action_destroy(struct list_head *actions, int bind)
{
+ const struct tc_action_ops *ops;
struct tc_action *a, *tmp;
int ret = 0;
list_for_each_entry_safe(a, tmp, actions, list) {
+ ops = a->ops;
ret = __tcf_idr_release(a, bind, true);
if (ret == ACT_P_DELETED)
- module_put(a->ops->owner);
+ module_put(ops->owner);
else if (ret < 0)
return ret;
}
^ permalink raw reply related
* [PATCH] ipv4: Namespaceify tcp_fastopen knob
From: Haishuang Yan @ 2017-09-12 10:30 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, Eric Dumazet
Cc: netdev, linux-kernel, Haishuang Yan
Different namespace application might require enable TCP Fast Open
feature independently of the host.
Reported-by: Luca BRUNO <lucab@debian.org>
Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
---
include/net/netns/ipv4.h | 2 ++
include/net/tcp.h | 1 -
net/ipv4/af_inet.c | 7 ++++---
net/ipv4/sysctl_net_ipv4.c | 42 +++++++++++++++++++++---------------------
net/ipv4/tcp.c | 4 ++--
net/ipv4/tcp_fastopen.c | 13 ++++++-------
net/ipv4/tcp_ipv4.c | 2 ++
samples/bpf/test_ipip.sh | 2 ++
8 files changed, 39 insertions(+), 34 deletions(-)
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 305e031..ea0953b 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -128,6 +128,8 @@ struct netns_ipv4 {
struct inet_timewait_death_row tcp_death_row;
int sysctl_max_syn_backlog;
int sysctl_tcp_max_orphans;
+ int sysctl_tcp_fastopen;
+ unsigned int sysctl_tcp_fastopen_blackhole_timeout;
#ifdef CONFIG_NET_L3_MASTER_DEV
int sysctl_udp_l3mdev_accept;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index ac2d998..e4cc0dd 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -240,7 +240,6 @@
/* sysctl variables for tcp */
-extern int sysctl_tcp_fastopen;
extern int sysctl_tcp_retrans_collapse;
extern int sysctl_tcp_stdurg;
extern int sysctl_tcp_rfc1337;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index e31108e..309b849 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -195,7 +195,7 @@ int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
unsigned char old_state;
- int err;
+ int err, tcp_fastopen;
lock_sock(sk);
@@ -217,8 +217,9 @@ int inet_listen(struct socket *sock, int backlog)
* because the socket was in TCP_LISTEN state previously but
* was shutdown() rather than close().
*/
- if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) &&
- (sysctl_tcp_fastopen & TFO_SERVER_ENABLE) &&
+ tcp_fastopen = sock_net(sk)->ipv4.sysctl_tcp_fastopen;
+ if ((tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) &&
+ (tcp_fastopen & TFO_SERVER_ENABLE) &&
!inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) {
fastopen_queue_tune(sk, backlog);
tcp_fastopen_init_key_once(true);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 4f26c8d3..30ebeb9 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -394,27 +394,6 @@ static int proc_tcp_available_ulp(struct ctl_table *ctl,
.proc_handler = proc_dointvec
},
{
- .procname = "tcp_fastopen",
- .data = &sysctl_tcp_fastopen,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "tcp_fastopen_key",
- .mode = 0600,
- .maxlen = ((TCP_FASTOPEN_KEY_LENGTH * 2) + 10),
- .proc_handler = proc_tcp_fastopen_key,
- },
- {
- .procname = "tcp_fastopen_blackhole_timeout_sec",
- .data = &sysctl_tcp_fastopen_blackhole_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_tfo_blackhole_detect_timeout,
- .extra1 = &zero,
- },
- {
.procname = "tcp_abort_on_overflow",
.data = &sysctl_tcp_abort_on_overflow,
.maxlen = sizeof(int),
@@ -1085,6 +1064,27 @@ static int proc_tcp_available_ulp(struct ctl_table *ctl,
.mode = 0644,
.proc_handler = proc_dointvec
},
+ {
+ .procname = "tcp_fastopen",
+ .data = &init_net.ipv4.sysctl_tcp_fastopen,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "tcp_fastopen_key",
+ .mode = 0600,
+ .maxlen = ((TCP_FASTOPEN_KEY_LENGTH * 2) + 10),
+ .proc_handler = proc_tcp_fastopen_key,
+ },
+ {
+ .procname = "tcp_fastopen_blackhole_timeout_sec",
+ .data = &init_net.ipv4.sysctl_tcp_fastopen_blackhole_timeout,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_tfo_blackhole_detect_timeout,
+ .extra1 = &zero,
+ },
#ifdef CONFIG_IP_ROUTE_MULTIPATH
{
.procname = "fib_multipath_use_neigh",
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 39187ac..b3a2ffc 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1126,7 +1126,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
struct sockaddr *uaddr = msg->msg_name;
int err, flags;
- if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) ||
+ if (!(sock_net(sk)->ipv4.sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) ||
(uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) &&
uaddr->sa_family == AF_UNSPEC))
return -EOPNOTSUPP;
@@ -2759,7 +2759,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
case TCP_FASTOPEN_CONNECT:
if (val > 1 || val < 0) {
err = -EINVAL;
- } else if (sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) {
+ } else if (net->ipv4.sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) {
if (sk->sk_state == TCP_CLOSE)
tp->fastopen_connect = val;
else
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
index e3c3322..1bf57e8 100644
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -9,8 +9,6 @@
#include <net/inetpeer.h>
#include <net/tcp.h>
-int sysctl_tcp_fastopen __read_mostly = TFO_CLIENT_ENABLE;
-
struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock);
@@ -282,18 +280,19 @@ struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
struct tcp_fastopen_cookie valid_foc = { .len = -1 };
bool syn_data = TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1;
struct sock *child;
+ int tcp_fastopen = sock_net(sk)->ipv4.sysctl_tcp_fastopen;
if (foc->len == 0) /* Client requests a cookie */
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENCOOKIEREQD);
- if (!((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) &&
+ if (!((tcp_fastopen & TFO_SERVER_ENABLE) &&
(syn_data || foc->len >= 0) &&
tcp_fastopen_queue_check(sk))) {
foc->len = -1;
return NULL;
}
- if (syn_data && (sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_REQD))
+ if (syn_data && (tcp_fastopen & TFO_SERVER_COOKIE_NOT_REQD))
goto fastopen;
if (foc->len >= 0 && /* Client presents or requests a cookie */
@@ -347,7 +346,7 @@ bool tcp_fastopen_cookie_check(struct sock *sk, u16 *mss,
return false;
}
- if (sysctl_tcp_fastopen & TFO_CLIENT_NO_COOKIE) {
+ if (sock_net(sk)->ipv4.sysctl_tcp_fastopen & TFO_CLIENT_NO_COOKIE) {
cookie->len = -1;
return true;
}
@@ -402,7 +401,6 @@ bool tcp_fastopen_defer_connect(struct sock *sk, int *err)
*/
/* Default to 1hr */
-unsigned int sysctl_tcp_fastopen_blackhole_timeout __read_mostly = 60 * 60;
static atomic_t tfo_active_disable_times __read_mostly = ATOMIC_INIT(0);
static unsigned long tfo_active_disable_stamp __read_mostly;
@@ -431,13 +429,14 @@ bool tcp_fastopen_active_should_disable(struct sock *sk)
int tfo_da_times = atomic_read(&tfo_active_disable_times);
int multiplier;
unsigned long timeout;
+ unsigned int tfo_bh_timeout = sock_net(sk)->ipv4.sysctl_tcp_fastopen_blackhole_timeout;
if (!tfo_da_times)
return false;
/* Limit timout to max: 2^6 * initial timeout */
multiplier = 1 << min(tfo_da_times - 1, 6);
- timeout = multiplier * sysctl_tcp_fastopen_blackhole_timeout * HZ;
+ timeout = multiplier * tfo_bh_timeout * HZ;
if (time_before(jiffies, tfo_active_disable_stamp + timeout))
return true;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 4b17a91..38d30ea 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2473,6 +2473,8 @@ static int __net_init tcp_sk_init(struct net *net)
net->ipv4.sysctl_tcp_window_scaling = 1;
net->ipv4.sysctl_tcp_timestamps = 1;
+ net->ipv4.sysctl_tcp_fastopen = TFO_CLIENT_ENABLE;
+ net->ipv4.sysctl_tcp_fastopen_blackhole_timeout = 60 * 60;
return 0;
fail:
tcp_sk_exit(net);
diff --git a/samples/bpf/test_ipip.sh b/samples/bpf/test_ipip.sh
index 1969254..7bbc521 100755
--- a/samples/bpf/test_ipip.sh
+++ b/samples/bpf/test_ipip.sh
@@ -173,6 +173,8 @@ function cleanup {
cleanup
echo "Testing IP tunnels..."
test_ipip
+sleep 1
test_ipip6
+sleep 1
test_ip6ip6
echo "*** PASS ***"
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH] ieee802154: fix gcc-4.9 warnings
From: Stefan Schmidt @ 2017-09-12 10:24 UTC (permalink / raw)
To: Arnd Bergmann, Harry Morris, linuxdev, Alexander Aring
Cc: Marcel Holtmann, David S. Miller, Markus Elfring,
Gustavo A. R. Silva, Florian Westphal, Johannes Berg,
Christophe JAILLET, Colin Ian King, linux-wpan, netdev,
linux-kernel
In-Reply-To: <20170912101636.3811626-1-arnd@arndb.de>
Hello.
On 09/12/2017 12:16 PM, Arnd Bergmann wrote:
> All older compiler versions up to gcc-4.9 produce these
> harmless warnings:
>
> drivers/net/ieee802154/ca8210.c: In function 'ca8210_skb_tx':
> drivers/net/ieee802154/ca8210.c:1947:9: warning: missing braces around initializer [-Wmissing-braces]
>
> This changes the syntax to something that works on all versions
> without warnings.
>
> Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/net/ieee802154/ca8210.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
> index 24a1eabbbc9d..e6b8ce81a6c3 100644
> --- a/drivers/net/ieee802154/ca8210.c
> +++ b/drivers/net/ieee802154/ca8210.c
> @@ -1944,7 +1944,7 @@ static int ca8210_skb_tx(
> )
> {
> int status;
> - struct ieee802154_hdr header = { 0 };
> + struct ieee802154_hdr header = { };
> struct secspec secspec;
> unsigned int mac_len;
>
Acked-by: Stefan Schmidt <stefan@osg.samsung.com>
regards
Stefan Schmidt
^ permalink raw reply
* [PATCH] ieee802154: fix gcc-4.9 warnings
From: Arnd Bergmann @ 2017-09-12 10:16 UTC (permalink / raw)
To: Harry Morris, linuxdev, Alexander Aring, Stefan Schmidt
Cc: Arnd Bergmann, Marcel Holtmann, David S. Miller, Markus Elfring,
Gustavo A. R. Silva, Florian Westphal, Johannes Berg,
Christophe JAILLET, Colin Ian King, linux-wpan, netdev,
linux-kernel
All older compiler versions up to gcc-4.9 produce these
harmless warnings:
drivers/net/ieee802154/ca8210.c: In function 'ca8210_skb_tx':
drivers/net/ieee802154/ca8210.c:1947:9: warning: missing braces around initializer [-Wmissing-braces]
This changes the syntax to something that works on all versions
without warnings.
Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ieee802154/ca8210.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 24a1eabbbc9d..e6b8ce81a6c3 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -1944,7 +1944,7 @@ static int ca8210_skb_tx(
)
{
int status;
- struct ieee802154_hdr header = { 0 };
+ struct ieee802154_hdr header = { };
struct secspec secspec;
unsigned int mac_len;
--
2.9.0
^ permalink raw reply related
* [PATCH net-next v2 2/2] net: phy: realtek: add RTL8201F phy-id and functions
From: Kunihiko Hayashi @ 2017-09-12 9:54 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli, netdev
Cc: Jassi Brar, Jongsung Kim, Kunihiko Hayashi
In-Reply-To: <1505210076-32311-1-git-send-email-hayashi.kunihiko@socionext.com>
From: Jassi Brar <jaswinder.singh@linaro.org>
Add RTL8201F phy-id and the related functions to the driver.
The original patch is as follows:
https://patchwork.kernel.org/patch/2538341/
Signed-off-by: Jongsung Kim <neidhard.kim@lge.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
Changes since v1:
- use RTL821x_PAGE_SELECT instead of defining RTL8201F_PAGE_SELECT
---
drivers/net/phy/realtek.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 99c3297..d4670ec 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -29,10 +29,22 @@
#define RTL8211F_INSR 0x1d
#define RTL8211F_TX_DELAY 0x100
+#define RTL8201F_ISR 0x1e
+#define RTL8201F_IER 0x13
+
MODULE_DESCRIPTION("Realtek PHY driver");
MODULE_AUTHOR("Johnson Leung");
MODULE_LICENSE("GPL");
+static int rtl8201_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, RTL8201F_ISR);
+
+ return (err < 0) ? err : 0;
+}
+
static int rtl821x_ack_interrupt(struct phy_device *phydev)
{
int err;
@@ -54,6 +66,25 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev)
return (err < 0) ? err : 0;
}
+static int rtl8201_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ /* switch to page 7 */
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0x7);
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, RTL8201F_IER,
+ BIT(13) | BIT(12) | BIT(11));
+ else
+ err = phy_write(phydev, RTL8201F_IER, 0);
+
+ /* restore to default page 0 */
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
+
+ return err;
+}
+
static int rtl8211b_config_intr(struct phy_device *phydev)
{
int err;
@@ -129,6 +160,18 @@ static struct phy_driver realtek_drvs[] = {
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
}, {
+ .phy_id = 0x001cc816,
+ .name = "RTL8201F 10/100Mbps Ethernet",
+ .phy_id_mask = 0x001fffff,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &rtl8201_ack_interrupt,
+ .config_intr = &rtl8201_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ }, {
.phy_id = 0x001cc912,
.name = "RTL8211B Gigabit Ethernet",
.phy_id_mask = 0x001fffff,
@@ -181,6 +224,7 @@ static struct phy_driver realtek_drvs[] = {
module_phy_driver(realtek_drvs);
static struct mdio_device_id __maybe_unused realtek_tbl[] = {
+ { 0x001cc816, 0x001fffff },
{ 0x001cc912, 0x001fffff },
{ 0x001cc914, 0x001fffff },
{ 0x001cc915, 0x001fffff },
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v2 1/2] net: phy: realtek: rename RTL8211F_PAGE_SELECT to RTL821x_PAGE_SELECT
From: Kunihiko Hayashi @ 2017-09-12 9:54 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli, netdev; +Cc: Jassi Brar, Kunihiko Hayashi
This renames the definition of page select register from
RTL8211F_PAGE_SELECT to RTL821x_PAGE_SELECT to use it across models.
Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
---
Changes since v1:
- new patch in this series
---
drivers/net/phy/realtek.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 9cbe645..99c3297 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -22,11 +22,11 @@
#define RTL821x_INER 0x12
#define RTL821x_INER_INIT 0x6400
#define RTL821x_INSR 0x13
+#define RTL821x_PAGE_SELECT 0x1f
#define RTL8211E_INER_LINK_STATUS 0x400
#define RTL8211F_INER_LINK_STATUS 0x0010
#define RTL8211F_INSR 0x1d
-#define RTL8211F_PAGE_SELECT 0x1f
#define RTL8211F_TX_DELAY 0x100
MODULE_DESCRIPTION("Realtek PHY driver");
@@ -46,10 +46,10 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev)
{
int err;
- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xa43);
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa43);
err = phy_read(phydev, RTL8211F_INSR);
/* restore to default page 0 */
- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0);
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
return (err < 0) ? err : 0;
}
@@ -102,7 +102,7 @@ static int rtl8211f_config_init(struct phy_device *phydev)
if (ret < 0)
return ret;
- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08);
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd08);
reg = phy_read(phydev, 0x11);
/* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */
@@ -114,7 +114,7 @@ static int rtl8211f_config_init(struct phy_device *phydev)
phy_write(phydev, 0x11, reg);
/* restore to default page 0 */
- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0);
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH v4 2/2] ip6_tunnel: fix ip6 tunnel lookup in collect_md mode
From: Haishuang Yan @ 2017-09-12 9:47 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI
Cc: netdev, linux-kernel, Haishuang Yan, Alexei Starovoitov
In-Reply-To: <1505209677-12728-1-git-send-email-yanhaishuang@cmss.chinamobile.com>
In collect_md mode, if the tun dev is down, it still can call
__ip6_tnl_rcv to receive on packets, and the rx statistics increase
improperly.
When the md tunnel is down, it's not neccessary to increase RX drops
for the tunnel device, packets would be recieved on fallback tunnel,
and the RX drops on fallback device will be increased as expected.
Fixes: 8d79266bc48c ("ip6_tunnel: add collect_md mode to IPv6 tunnels")
Cc: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
---
Change since v4:
* Make the commit message more clearer
* Fix wrong recipient address
---
net/ipv6/ip6_tunnel.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 10a693a..ae73164 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -171,7 +171,7 @@ static struct net_device_stats *ip6_get_stats(struct net_device *dev)
}
t = rcu_dereference(ip6n->collect_md_tun);
- if (t)
+ if (t && t->dev->flags & IFF_UP)
return t;
t = rcu_dereference(ip6n->tnls_wc[0]);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v4 1/2] ip_tunnel: fix ip tunnel lookup in collect_md mode
From: Haishuang Yan @ 2017-09-12 9:47 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI
Cc: netdev, linux-kernel, Haishuang Yan, Pravin B Shelar
In collect_md mode, if the tun dev is down, it still can call
ip_tunnel_rcv to receive on packets, and the rx statistics increase
improperly.
When the md tunnel is down, it's not neccessary to increase RX drops
for the tunnel device, packets would be recieved on fallback tunnel,
and the RX drops on fallback device will be increased as expected.
Fixes: 2e15ea390e6f ("ip_gre: Add support to collect tunnel metadata.")
Cc: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
---
Change since v4:
* Make the commit message more clearer.
* Fix wrong recipient addresss
---
net/ipv4/ip_tunnel.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index e1856bf..e9805ad 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -176,7 +176,7 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
return cand;
t = rcu_dereference(itn->collect_md_tun);
- if (t)
+ if (t && t->dev->flags & IFF_UP)
return t;
if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP)
--
1.8.3.1
^ permalink raw reply related
* Re: [Patch net v3 1/3] net_sched: get rid of tcfa_rcu
From: Jiri Pirko @ 2017-09-12 9:42 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, jiri, jakub.kicinski, jhs, Eric Dumazet
In-Reply-To: <20170911233332.7594-2-xiyou.wangcong@gmail.com>
Tue, Sep 12, 2017 at 01:33:30AM CEST, xiyou.wangcong@gmail.com wrote:
>gen estimator has been rewritten in commit 1c0d32fde5bd
>("net_sched: gen_estimator: complete rewrite of rate estimators"),
>the caller is no longer needed to wait for a grace period.
>So this patch gets rid of it.
>
>This also completely closes a race condition between action free
>path and filter chain add/remove path for the following patch.
>Because otherwise the nested RCU callback can't be caught by
>rcu_barrier().
>
>Please see also the comments in code.
Looks like this is causing a null pointer dereference bug for me, 100%
of the time. Just add and remove any rule with action and you get:
[ 598.599825] BUG: unable to handle kernel NULL pointer dereference at 0000000000000030
[ 598.607782] IP: tcf_action_destroy+0xc0/0x140
[ 598.612231] PGD 0 P4D 0
[ 598.614797] Oops: 0000 [#1] SMP KASAN
[ 598.618525] Modules linked in: act_gact cls_flower sch_ingress rpcsec_gss_krb5 auth_rpcgss nfsv4 dns_resolver nfs lockd grace fscache intel_rapl x86_pkg_temp_thermal coretemp mlxsw_spectrum kvm_intel mlxfw kvm parman bridge sunrpc irqbypass iTCO_wdt iTCO_vendor_support stp crct10dif_pclmul llc crc32_pclmul crc32c_intel mlxsw_pci ghash_clmulni_intel mlxsw_core i2c_i801 e1000e pcspkr ptp tpm_tis mei_me pps_core mei tpm_tis_core lpc_ich tpm shpchp video
[ 598.659010] CPU: 1 PID: 758 Comm: bash Tainted: G B 4.13.0jiri+ #70
[ 598.666509] Hardware name: Mellanox Technologies Ltd. Mellanox switch/Mellanox x86 mezzanine board, BIOS 4.6.5 08/02/2016
[ 598.677630] task: ffff880371624bc0 task.stack: ffff880387808000
[ 598.683648] RIP: 0010:tcf_action_destroy+0xc0/0x140
[ 598.688617] RSP: 0018:ffff88038d107cb8 EFLAGS: 00010282
[ 598.693922] RAX: 0000000000000000 RBX: ffff88038d107d28 RCX: ffffffff820b80e0
[ 598.701184] RDX: 0000000000000000 RSI: 0000000000000008 RDI: 0000000000000030
[ 598.708405] RBP: ffff88038d107ce8 R08: 0000000000000001 R09: 0000000000000001
[ 598.715607] R10: ffff88038d107b27 R11: fffffbfff0bcf36c R12: 0000000000000000
[ 598.722816] R13: ffff88038d107d38 R14: ffff88036bf75650 R15: 0000000000000001
[ 598.730047] FS: 00007f398050b700(0000) GS:ffff88038d100000(0000) knlGS:0000000000000000
[ 598.738253] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 598.744086] CR2: 0000000000000030 CR3: 0000000371ac4001 CR4: 00000000001606e0
[ 598.751328] Call Trace:
[ 598.753809] <IRQ>
[ 598.755871] tcf_exts_destroy+0x17f/0x260
[ 598.775969] fl_destroy_filter+0x1d/0x30 [cls_flower]
[ 598.781069] rcu_process_callbacks+0x6b2/0xe00
Kasan says:
[ 597.503005] BUG: KASAN: use-after-free in tcf_action_destroy+0xad/0x140
[ 597.509751] Read of size 8 at addr ffff88036bf75640 by task bash/758
[ 597.516222]
[ 597.517761] CPU: 1 PID: 758 Comm: bash Not tainted 4.13.0jiri+ #70
[ 597.524075] Hardware name: Mellanox Technologies Ltd. Mellanox switch/Mellanox x86 mezzanine board, BIOS 4.6.5 08/02/2016
[ 597.535132] Call Trace:
[ 597.537630] <IRQ>
[ 597.539718] dump_stack+0xd5/0x150
[ 597.554853] print_address_description+0x86/0x410
[ 597.559667] kasan_report+0x181/0x4c0
[ 597.583360] tcf_action_destroy+0xad/0x140
[ 597.587551] tcf_exts_destroy+0x17f/0x260
Ubsan says:
[ 598.184033] UBSAN: Undefined behaviour in net/sched/act_api.c:523:4
[ 598.190409] member access within null pointer of type 'const struct tc_action_ops'
[ 598.198076] CPU: 1 PID: 758 Comm: bash Tainted: G B 4.13.0jiri+ #70
[ 598.205570] Hardware name: Mellanox Technologies Ltd. Mellanox switch/Mellanox x86 mezzanine board, BIOS 4.6.5 08/02/2016
[ 598.216669] Call Trace:
[ 598.219157] <IRQ>
[ 598.221245] dump_stack+0xd5/0x150
[ 598.228703] ubsan_epilogue+0xd/0x4e
[ 598.232333] __ubsan_handle_type_mismatch+0xf2/0x293
[ 598.252880] tcf_action_destroy+0x115/0x140
[ 598.257151] tcf_exts_destroy+0x17f/0x260
[ 598.277336] fl_destroy_filter+0x1d/0x30 [cls_flower]
[ 598.282472] rcu_process_callbacks+0x6b2/0xe00
Looks like you need to save owner of the module before you call
__tcf_idr_release so you can later on use it for module_put
^ permalink raw reply
* RE: [PATCH] tipc: Use bsearch library function
From: David Laight @ 2017-09-12 9:24 UTC (permalink / raw)
To: 'David Miller', thomas@m3y3r.de
Cc: jon.maloy@ericsson.com, ying.xue@windriver.com,
netdev@vger.kernel.org, tipc-discussion@lists.sourceforge.net,
linux-kernel@vger.kernel.org
In-Reply-To: <20170911.143025.555018840006192902.davem@davemloft.net>
From: David Miller
> Sent: 11 September 2017 22:30
> From: Thomas Meyer <thomas@m3y3r.de>
> Date: Sat, 9 Sep 2017 05:18:19 +0200
>
> > @@ -168,6 +169,18 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head
> *seq_hea
> > return nseq;
> > }
> >
> > +static int nameseq_find_subseq_cmp(const void *key, const void *elt)
> > +{
> > + u32 instance = *(u32 *)key;
> > + struct sub_seq *sseq = (struct sub_seq *)elt;
>
> Please order local variables from longest to shortest (ie. reverse
> christmas tree).
You probably just need to remove the unnecessary cast of 'void *'.
Although adding the 'const' qualifier will make it wrong again.
You probably ought to make the 'key' a structure - even if it only
contains a single u32.
Casting pointers to numeric types is often wrong.
David
^ permalink raw reply
* Re: [PATCH net-next 2/3] net: ethernet: socionext: add AVE ethernet driver
From: Kunihiko Hayashi @ 2017-09-12 9:24 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, David S. Miller, Florian Fainelli, Rob Herring,
Mark Rutland, linux-arm-kernel, linux-kernel, devicetree,
Masahiro Yamada, Masami Hiramatsu, Jassi Brar
In-Reply-To: <20170911120009.GA24174@lunn.ch>
Hi Andrew,
On Mon, 11 Sep 2017 14:00:09 +0200 Andrew Lunn <andrew@lunn.ch> wrote:
> > > > +static irqreturn_t ave_interrupt(int irq, void *netdev)
> > > > +{
> > > > + struct net_device *ndev = (struct net_device *)netdev;
> > > > + struct ave_private *priv = netdev_priv(ndev);
> > > > + u32 gimr_val, gisr_val;
> > > > +
> > > > + gimr_val = ave_irq_disable_all(ndev);
> > > > +
> > > > + /* get interrupt status */
> > > > + gisr_val = ave_r32(ndev, AVE_GISR);
> > > > +
> > > > + /* PHY */
> > > > + if (gisr_val & AVE_GI_PHY) {
> > > > + ave_w32(ndev, AVE_GISR, AVE_GI_PHY);
> > > > + if (priv->internal_phy_interrupt)
> > > > + phy_mac_interrupt(ndev->phydev, ndev->phydev->link);
> > >
> > > Humm. I don't think this is correct. You are supposed to give it the
> > > new link state, not the old.
> > >
> > > What does a PHY interrupt mean here?
> >
> > In the general case, I think PHY events like changing link state are transmitted
> > to CPU as interrupt via interrupt controller, then PHY driver itself can handle
> > the interrupt.
> >
> > And in this case, PHY events are transmitted to MAC as one of its interrupt factor,
> > then I thought that MAC driver had to tell the events to PHY.
>
> Could this be in-band SGMI signalling from the PHY to the MAC? Does
> the documentation give examples of when this interrupt will happen?
>
> Andrew
Unfortunately this MAC doesn't support SGMII.
And there aren't any examples of when this interrupt will happen.
This interrupt happens after ave_open() is called and link is established.
However, I found that auto negotiation didn't start when this interrupt wasn't handled.
Although ave_init() calls phy_start_aneg(), it doesn't make sense
because phy driver doesn't start yet.
And according to Florian's comment in ave_init(),
> + phy_start_interrupts(phydev);
> +
> + phy_start_aneg(phydev);
>
> No, no, phy_start() would take care of all of that correctly for you,
> you don't have have to do it just there because ave_open() eventually
> calls phy_start() for you, so just drop these two calls.
When moving phy_start_aneg() to ave_open(), the handler doesn't need to call
phy_mac_interrupt() and I can remove it from the handler.
---
Best Regards,
Kunihiko Hayashi
^ permalink raw reply
* Re: [PATCH iproute2 1/2] lib/libnetlink: re malloc buff if size is not enough
From: Michal Kubecek @ 2017-09-12 9:09 UTC (permalink / raw)
To: Hangbin Liu; +Cc: Phil Sutter, netdev, Stephen Hemminger
In-Reply-To: <20170912084748.m4wz6kxfclc2mkxd@unicorn.suse.cz>
On Tue, Sep 12, 2017 at 10:47:48AM +0200, Michal Kubecek wrote:
> On Mon, Sep 11, 2017 at 03:19:55PM +0800, Hangbin Liu wrote:
> > On Fri, Sep 08, 2017 at 04:51:13PM +0200, Phil Sutter wrote:
> > > Regarding Michal's concern about reentrancy, maybe we should go into a
> > > different direction and make rtnl_recvmsg() return a newly allocated
> > > buffer which the caller has to free.
> >
> > Hmm... But we could not free the buf in __rtnl_talk(). Because in
> > __rtnl_talk() we assign the answer with the buf address and return to caller.
> >
> > for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
> > [...]
> > if (answer) {
> > *answer= h;
> > return 0;
> > }
> > }
> >
> > And the caller will keep use it in later code. Since there are plenty of
> > functions called rtnl_talk. I think it would be much more complex to free
> > the buffer every time.
> >
> >
> > Hi Michal,
> >
> > Would you like to tell me more about your concern with reentrancy? It's looks
> > arpd doesn't call rtnl_talk() or rtnl_dump_filter_l().
>
> I checked again and arpd indeed isn't a problem. It doesn't seem to call
> any of the two functions (directly or indirectly) and while it's linked
> with "-lpthread", it's not really multithreaded.
>
> But my concern was rather about other potential users of libnetlink
> (i.e. those which are not part of iproute2). I must admit, though, that
> I'm not sure if libnetlink code is reentrant as of now. (And people are
> discouraged from using it in its own manual page.)
>
> That being said, I still like Phil's idea for a different reason. While
> investigating the issue with "ip link show dev eth ..." which led me to
> commit 6599162b958e ("iplink: check for message truncation in
> iplink_get()"), I quickly peeked at some other callers of rtnl_talk()
> and I'm afraid there may be others which wouldn't handle truncated
> message correctly. I assume the maxlen argument was always chosen to be
> sufficient for any expected messages but as the example of iplink_get()
> shows, messages returned by kernel my grow over time.
>
> That's why I like the idea of __rtnl_talk() returning a pointer to newly
> allocated buffer (of sufficient size) rather than copying the response
> into a buffer provided by caller and potentially truncating it.
I'm sorry, I managed to forget that your patch 2 does already address
this problem. But the fact that any caller must keep in mind that he
must not call the same function again until the previous response is no
longer needed still feels like a trap. It's something you need to keep
in mind (where "you" in fact means any future contributor) and it's
easy to forget. That's why I prefer the reentrant functions like
strerror_r() or localtime_r() even in code which is not intended to be
multithreaded. Getting an object which is "mine" to do with whatever
I want until I no longer need it feels like a cleaner interface to me.
Michal Kubecek
^ permalink raw reply
* scheduling while atomic from vmci_transport_recv_stream_cb in 3.16 kernels
From: Michal Hocko @ 2017-09-12 9:08 UTC (permalink / raw)
To: Jorgen Hansen
Cc: Aditya Asarwade, Thomas Hellstrom, LKML, netdev, Masik Petr,
Ben Hutchings, Sasha Levin, Stable tree
Hi,
we are seeing the following splat with Debian 3.16 stable kernel
BUG: scheduling while atomic: MATLAB/26771/0x00000100
Modules linked in: veeamsnap(O) hmac cbc cts nfsv4 dns_resolver rpcsec_gss_krb5 nfsd auth_rpcgss oid_registry nfs_acl nfs lockd fscache sunrpc vmw_vso$
CPU: 0 PID: 26771 Comm: MATLAB Tainted: G O 3.16.0-4-amd64 #1 Debian 3.16.7-ckt20-1+deb8u3
Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 09/21/2015
ffff88315c1e4c20 ffffffff8150db3f ffff88193f803dc8 ffffffff8150acdf
ffffffff815103a2 0000000000012f00 ffff8819423dbfd8 0000000000012f00
ffff88315c1e4c20 ffff88193f803dc8 ffff88193f803d50 ffff88193f803dc0
Call Trace:
<IRQ> [<ffffffff8150db3f>] ? dump_stack+0x41/0x51
[<ffffffff8150acdf>] ? __schedule_bug+0x48/0x55
[<ffffffff815103a2>] ? __schedule+0x5d2/0x700
[<ffffffff8150f9b9>] ? schedule_timeout+0x229/0x2a0
[<ffffffff8109ba70>] ? select_task_rq_fair+0x390/0x700
[<ffffffff8109f780>] ? check_preempt_wakeup+0x120/0x1d0
[<ffffffff81510eb8>] ? wait_for_completion+0xa8/0x120
[<ffffffff81096de0>] ? wake_up_state+0x10/0x10
[<ffffffff810c3da0>] ? call_rcu_bh+0x20/0x20
[<ffffffff810c180b>] ? wait_rcu_gp+0x4b/0x60
[<ffffffff810c17b0>] ? ftrace_raw_output_rcu_utilization+0x40/0x40
[<ffffffffa02ca6f5>] ? vmci_event_unsubscribe+0x75/0xb0 [vmw_vmci]
[<ffffffffa031f5cd>] ? vmci_transport_destruct+0x1d/0xe0 [vmw_vsock_vmci_transport]
[<ffffffffa03167e3>] ? vsock_sk_destruct+0x13/0x60 [vsock]
[<ffffffff81409f7a>] ? __sk_free+0x1a/0x130
[<ffffffffa0320218>] ? vmci_transport_recv_stream_cb+0x1e8/0x2d0 [vmw_vsock_vmci_transport]
[<ffffffffa02c9cba>] ? vmci_datagram_invoke_guest_handler+0xaa/0xd0 [vmw_vmci]
[<ffffffffa02cab51>] ? vmci_dispatch_dgs+0xc1/0x200 [vmw_vmci]
[<ffffffff8106c294>] ? tasklet_action+0xf4/0x100
[<ffffffff8106c681>] ? __do_softirq+0xf1/0x290
[<ffffffff8106ca55>] ? irq_exit+0x95/0xa0
[<ffffffff81516b22>] ? do_IRQ+0x52/0xe0
[<ffffffff8151496d>] ? common_interrupt+0x6d/0x6d
AFAICS this has been fixed by 4ef7ea9195ea ("VSOCK: sock_put wasn't safe
to call in interrupt context") but this patch hasn't been backported to
stable trees. It applies cleanly on top of 3.16 stable tree but I am not
familiar with the code to send the backport to the stable maintainer
directly.
Could you double check that the patch below (just a blind cherry-pick)
is correct and it doesn't need additional patches on top?
Ben could you take this to your stable 3.16 branch if the patch is correct?
I am CCing Sasha for 4.1 stable tree as well. I haven't checked whether
pre 3.16 kernels are affected as well.
---
commit fac774c40b5c512113b6373cad498f35bee7a409
Author: Jorgen Hansen <jhansen@vmware.com>
Date: Wed Oct 21 04:53:56 2015 -0700
VSOCK: sock_put wasn't safe to call in interrupt context
commit 4ef7ea9195ea73262cd9730fb54e1eb726da157b upstream.
In the vsock vmci_transport driver, sock_put wasn't safe to call
in interrupt context, since that may call the vsock destructor
which in turn calls several functions that should only be called
from process context. This change defers the callling of these
functions to a worker thread. All these functions were
deallocation of resources related to the transport itself.
Furthermore, an unused callback was removed to simplify the
cleanup.
Multiple customers have been hitting this issue when using
VMware tools on vSphere 2015.
Also added a version to the vmci transport module (starting from
1.0.2.0-k since up until now it appears that this module was
sharing version with vsock that is currently at 1.0.1.0-k).
Reviewed-by: Aditya Asarwade <asarwade@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index 9bb63ffec4f2..aed136d27b01 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -40,13 +40,11 @@
static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg);
static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg);
-static void vmci_transport_peer_attach_cb(u32 sub_id,
- const struct vmci_event_data *ed,
- void *client_data);
static void vmci_transport_peer_detach_cb(u32 sub_id,
const struct vmci_event_data *ed,
void *client_data);
static void vmci_transport_recv_pkt_work(struct work_struct *work);
+static void vmci_transport_cleanup(struct work_struct *work);
static int vmci_transport_recv_listen(struct sock *sk,
struct vmci_transport_packet *pkt);
static int vmci_transport_recv_connecting_server(
@@ -75,6 +73,10 @@ struct vmci_transport_recv_pkt_info {
struct vmci_transport_packet pkt;
};
+static LIST_HEAD(vmci_transport_cleanup_list);
+static DEFINE_SPINLOCK(vmci_transport_cleanup_lock);
+static DECLARE_WORK(vmci_transport_cleanup_work, vmci_transport_cleanup);
+
static struct vmci_handle vmci_transport_stream_handle = { VMCI_INVALID_ID,
VMCI_INVALID_ID };
static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID;
@@ -791,44 +793,6 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
return err;
}
-static void vmci_transport_peer_attach_cb(u32 sub_id,
- const struct vmci_event_data *e_data,
- void *client_data)
-{
- struct sock *sk = client_data;
- const struct vmci_event_payload_qp *e_payload;
- struct vsock_sock *vsk;
-
- e_payload = vmci_event_data_const_payload(e_data);
-
- vsk = vsock_sk(sk);
-
- /* We don't ask for delayed CBs when we subscribe to this event (we
- * pass 0 as flags to vmci_event_subscribe()). VMCI makes no
- * guarantees in that case about what context we might be running in,
- * so it could be BH or process, blockable or non-blockable. So we
- * need to account for all possible contexts here.
- */
- local_bh_disable();
- bh_lock_sock(sk);
-
- /* XXX This is lame, we should provide a way to lookup sockets by
- * qp_handle.
- */
- if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
- e_payload->handle)) {
- /* XXX This doesn't do anything, but in the future we may want
- * to set a flag here to verify the attach really did occur and
- * we weren't just sent a datagram claiming it was.
- */
- goto out;
- }
-
-out:
- bh_unlock_sock(sk);
- local_bh_enable();
-}
-
static void vmci_transport_handle_detach(struct sock *sk)
{
struct vsock_sock *vsk;
@@ -871,28 +835,38 @@ static void vmci_transport_peer_detach_cb(u32 sub_id,
const struct vmci_event_data *e_data,
void *client_data)
{
- struct sock *sk = client_data;
+ struct vmci_transport *trans = client_data;
const struct vmci_event_payload_qp *e_payload;
- struct vsock_sock *vsk;
e_payload = vmci_event_data_const_payload(e_data);
- vsk = vsock_sk(sk);
- if (vmci_handle_is_invalid(e_payload->handle))
- return;
-
- /* Same rules for locking as for peer_attach_cb(). */
- local_bh_disable();
- bh_lock_sock(sk);
/* XXX This is lame, we should provide a way to lookup sockets by
* qp_handle.
*/
- if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
- e_payload->handle))
- vmci_transport_handle_detach(sk);
+ if (vmci_handle_is_invalid(e_payload->handle) ||
+ vmci_handle_is_equal(trans->qp_handle, e_payload->handle))
+ return;
- bh_unlock_sock(sk);
- local_bh_enable();
+ /* We don't ask for delayed CBs when we subscribe to this event (we
+ * pass 0 as flags to vmci_event_subscribe()). VMCI makes no
+ * guarantees in that case about what context we might be running in,
+ * so it could be BH or process, blockable or non-blockable. So we
+ * need to account for all possible contexts here.
+ */
+ spin_lock_bh(&trans->lock);
+ if (!trans->sk)
+ goto out;
+
+ /* Apart from here, trans->lock is only grabbed as part of sk destruct,
+ * where trans->sk isn't locked.
+ */
+ bh_lock_sock(trans->sk);
+
+ vmci_transport_handle_detach(trans->sk);
+
+ bh_unlock_sock(trans->sk);
+ out:
+ spin_unlock_bh(&trans->lock);
}
static void vmci_transport_qp_resumed_cb(u32 sub_id,
@@ -1181,7 +1155,7 @@ vmci_transport_recv_connecting_server(struct sock *listener,
*/
err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
vmci_transport_peer_detach_cb,
- pending, &detach_sub_id);
+ vmci_trans(vpending), &detach_sub_id);
if (err < VMCI_SUCCESS) {
vmci_transport_send_reset(pending, pkt);
err = vmci_transport_error_to_vsock_error(err);
@@ -1321,7 +1295,6 @@ vmci_transport_recv_connecting_client(struct sock *sk,
|| vmci_trans(vsk)->qpair
|| vmci_trans(vsk)->produce_size != 0
|| vmci_trans(vsk)->consume_size != 0
- || vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID
|| vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
skerr = EPROTO;
err = -EINVAL;
@@ -1389,7 +1362,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
struct vsock_sock *vsk;
struct vmci_handle handle;
struct vmci_qp *qpair;
- u32 attach_sub_id;
u32 detach_sub_id;
bool is_local;
u32 flags;
@@ -1399,7 +1371,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
vsk = vsock_sk(sk);
handle = VMCI_INVALID_HANDLE;
- attach_sub_id = VMCI_INVALID_ID;
detach_sub_id = VMCI_INVALID_ID;
/* If we have gotten here then we should be past the point where old
@@ -1444,23 +1415,15 @@ static int vmci_transport_recv_connecting_client_negotiate(
goto destroy;
}
- /* Subscribe to attach and detach events first.
+ /* Subscribe to detach events first.
*
* XXX We attach once for each queue pair created for now so it is easy
* to find the socket (it's provided), but later we should only
* subscribe once and add a way to lookup sockets by queue pair handle.
*/
- err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_ATTACH,
- vmci_transport_peer_attach_cb,
- sk, &attach_sub_id);
- if (err < VMCI_SUCCESS) {
- err = vmci_transport_error_to_vsock_error(err);
- goto destroy;
- }
-
err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
vmci_transport_peer_detach_cb,
- sk, &detach_sub_id);
+ vmci_trans(vsk), &detach_sub_id);
if (err < VMCI_SUCCESS) {
err = vmci_transport_error_to_vsock_error(err);
goto destroy;
@@ -1496,7 +1459,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size =
pkt->u.size;
- vmci_trans(vsk)->attach_sub_id = attach_sub_id;
vmci_trans(vsk)->detach_sub_id = detach_sub_id;
vmci_trans(vsk)->notify_ops->process_negotiate(sk);
@@ -1504,9 +1466,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
return 0;
destroy:
- if (attach_sub_id != VMCI_INVALID_ID)
- vmci_event_unsubscribe(attach_sub_id);
-
if (detach_sub_id != VMCI_INVALID_ID)
vmci_event_unsubscribe(detach_sub_id);
@@ -1607,9 +1566,11 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk,
vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
vmci_trans(vsk)->qpair = NULL;
vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = 0;
- vmci_trans(vsk)->attach_sub_id = vmci_trans(vsk)->detach_sub_id =
- VMCI_INVALID_ID;
+ vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
vmci_trans(vsk)->notify_ops = NULL;
+ INIT_LIST_HEAD(&vmci_trans(vsk)->elem);
+ vmci_trans(vsk)->sk = &vsk->sk;
+ vmci_trans(vsk)->lock = __SPIN_LOCK_UNLOCKED(vmci_trans(vsk)->lock);
if (psk) {
vmci_trans(vsk)->queue_pair_size =
vmci_trans(psk)->queue_pair_size;
@@ -1629,29 +1590,57 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk,
return 0;
}
-static void vmci_transport_destruct(struct vsock_sock *vsk)
+static void vmci_transport_free_resources(struct list_head *transport_list)
{
- if (vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID) {
- vmci_event_unsubscribe(vmci_trans(vsk)->attach_sub_id);
- vmci_trans(vsk)->attach_sub_id = VMCI_INVALID_ID;
- }
+ while (!list_empty(transport_list)) {
+ struct vmci_transport *transport =
+ list_first_entry(transport_list, struct vmci_transport,
+ elem);
+ list_del(&transport->elem);
- if (vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
- vmci_event_unsubscribe(vmci_trans(vsk)->detach_sub_id);
- vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
- }
+ if (transport->detach_sub_id != VMCI_INVALID_ID) {
+ vmci_event_unsubscribe(transport->detach_sub_id);
+ transport->detach_sub_id = VMCI_INVALID_ID;
+ }
- if (!vmci_handle_is_invalid(vmci_trans(vsk)->qp_handle)) {
- vmci_qpair_detach(&vmci_trans(vsk)->qpair);
- vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
- vmci_trans(vsk)->produce_size = 0;
- vmci_trans(vsk)->consume_size = 0;
+ if (!vmci_handle_is_invalid(transport->qp_handle)) {
+ vmci_qpair_detach(&transport->qpair);
+ transport->qp_handle = VMCI_INVALID_HANDLE;
+ transport->produce_size = 0;
+ transport->consume_size = 0;
+ }
+
+ kfree(transport);
}
+}
+
+static void vmci_transport_cleanup(struct work_struct *work)
+{
+ LIST_HEAD(pending);
+
+ spin_lock_bh(&vmci_transport_cleanup_lock);
+ list_replace_init(&vmci_transport_cleanup_list, &pending);
+ spin_unlock_bh(&vmci_transport_cleanup_lock);
+ vmci_transport_free_resources(&pending);
+}
+
+static void vmci_transport_destruct(struct vsock_sock *vsk)
+{
+ /* Ensure that the detach callback doesn't use the sk/vsk
+ * we are about to destruct.
+ */
+ spin_lock_bh(&vmci_trans(vsk)->lock);
+ vmci_trans(vsk)->sk = NULL;
+ spin_unlock_bh(&vmci_trans(vsk)->lock);
if (vmci_trans(vsk)->notify_ops)
vmci_trans(vsk)->notify_ops->socket_destruct(vsk);
- kfree(vsk->trans);
+ spin_lock_bh(&vmci_transport_cleanup_lock);
+ list_add(&vmci_trans(vsk)->elem, &vmci_transport_cleanup_list);
+ spin_unlock_bh(&vmci_transport_cleanup_lock);
+ schedule_work(&vmci_transport_cleanup_work);
+
vsk->trans = NULL;
}
@@ -2148,6 +2137,9 @@ module_init(vmci_transport_init);
static void __exit vmci_transport_exit(void)
{
+ cancel_work_sync(&vmci_transport_cleanup_work);
+ vmci_transport_free_resources(&vmci_transport_cleanup_list);
+
if (!vmci_handle_is_invalid(vmci_transport_stream_handle)) {
if (vmci_datagram_destroy_handle(
vmci_transport_stream_handle) != VMCI_SUCCESS)
@@ -2166,6 +2158,7 @@ module_exit(vmci_transport_exit);
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMCI transport for Virtual Sockets");
+MODULE_VERSION("1.0.2.0-k");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("vmware_vsock");
MODULE_ALIAS_NETPROTO(PF_VSOCK);
diff --git a/net/vmw_vsock/vmci_transport.h b/net/vmw_vsock/vmci_transport.h
index ce6c9623d5f0..2ad46f39649f 100644
--- a/net/vmw_vsock/vmci_transport.h
+++ b/net/vmw_vsock/vmci_transport.h
@@ -119,10 +119,12 @@ struct vmci_transport {
u64 queue_pair_size;
u64 queue_pair_min_size;
u64 queue_pair_max_size;
- u32 attach_sub_id;
u32 detach_sub_id;
union vmci_transport_notify notify;
struct vmci_transport_notify_ops *notify_ops;
+ struct list_head elem;
+ struct sock *sk;
+ spinlock_t lock; /* protects sk. */
};
int vmci_transport_register(void);
--
Michal Hocko
SUSE Labs
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox