* RE: bug in ixgbe_atr
From: Duyck, Alexander H @ 2016-10-14 16:09 UTC (permalink / raw)
To: Sowmini Varadhan; +Cc: netdev@vger.kernel.org
In-Reply-To: <20161014034831.GC14253@oracle.com>
> -----Original Message-----
> From: Sowmini Varadhan [mailto:sowmini.varadhan@oracle.com]
> Sent: Thursday, October 13, 2016 8:49 PM
> To: Duyck, Alexander H <alexander.h.duyck@intel.com>
> Cc: netdev@vger.kernel.org
> Subject: Re: bug in ixgbe_atr
>
> On (10/14/16 02:06), Duyck, Alexander H wrote:
> > > + case ETH_P_IP:
> > > + skb_header_pointer(skb, ETH_HLEN, sizeof (struct iphdr),
> > > + &ip_hdr);
> > > /* access ihl as u8 to avoid unaligned access on ia64 */
> > > - hlen = (hdr.network[0] & 0x0F) << 2;
> > > - l4_proto = hdr.ipv4->protocol;
> > > + hlen = ip_hdr.ipv4.ihl << 2;
> > > + l4_proto = ip_hdr.ipv4.protocol;
> > > break;
> :
> > The problem is this will break other stuff, for example I have seen
> > the ihl access actually cause problems with unaligned accesses as some
> > architectures decide to pull it as a u32 and then mask it.
>
> Yes, I noticed that u8 comment for ia64.. if that's the only issue here, we could
> just reset hdr.network to &ip_hdr..
>
> However, I suspect the above patch is probably not going to work for the vlan
> case (it was just a first-pass hack)
I kind of figured that. Ideally we only wat to pick out the pieces we need. I would prefer to avoid skb_header_pointer if possible since we only need a few parts of the header and don't really need to copy the whole thing.
> > My advice would be to keep this simple. Add a check to make sure we
> > have room for at least skb_headlen(skb) - 40 >= hrd.raw - skb->data.
>
> I don't parse that- the hdr union in ixgbe_atr doesnt have a ->raw field. Can you
> explain?
Sorry I was thinking of a different piece of code. In the case of the atr code it would be hdr.network, not hdr.raw. Basically the thought was to validate that there is enough data in skb_headlen() that we can verify that from where the network header should be we have at least 40 bytes of data as that would be the minimum needed for a TCP header and an IPv4 header, or just an IPv6 header. We would probably need a separate follow-up for the TCP header after we validate network header.
> > Messing with the protocol bits will break stuff since there is support
> > for tunneling also floating around in here now.
> >
> > I believe we are planning on dropping this code in favor of
> > ndo_rx_flow_steer in the future. If we do that then the whole problem
> > becomes moot.
>
> Dropping it is fine with me I guess - maybe just return, if the
> skb_headlen() doesnt have enough bytes for a network header, i.e., skb_headlen
> is at least ETH_HLEN + sizeof (struct iphdr) for ETH_P_IP, or ETH_HLEN + sizeof
> (struct ipv6hdr) for ETH_P_IPV6?
>
> --Sowmini
Right that is kind of what I was thinking. If we validate that we have at least 40 before inspecting the network header, and at least 20 before we validate the TCP header that would work for me.
- Alex
^ permalink raw reply
* Re: Need help with mdiobus_register and phy
From: Timur Tabi @ 2016-10-14 16:57 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev
In-Reply-To: <20161014131852.GM5822@lunn.ch>
Andrew Lunn wrote:
> That is a basic assumption of the code. If you cannot read the IDs how
> are you supposed to know what device it is, and what quirks you need
> to work around its broken features...
>
> Does the datasheet say anything about this?
>
> I would say for this device, suspend() is too aggressive.
This change in my driver makes the problem go away (I'm not sure if it's
a "fix"):
@@ -992,7 +992,7 @@ int emac_mac_up(struct emac_adapter *adpt)
emac_mac_rx_descs_refill(adpt, &adpt->rx_q);
ret = phy_connect_direct(netdev, adpt->phydev, emac_adjust_link,
- PHY_INTERFACE_MODE_SGMII);
+ PHY_INTERFACE_MODE_NA);
With the interface not set as SGMII, the following code in
at803x_suspend() is not executed:
/* also power-down SGMII interface */
ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN);
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
I don't see any other driver issue BMCR_PDOWN in their functions. I
added some printks for the PHYSID1 and PHYSID2 registers before and
after BMCR_PDOWN:
at803x_suspend:235 MII_PHYSID1=004d MII_PHYSID2=d074
at803x_suspend:242 MII_PHYSID1=ffff MII_PHYSID2=ffff
So after calling BMCR_PDOWN, the PHYSID1 and PHYSID2 registers are no
longer readable. Is that expected?
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc. Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* Re: Need help with mdiobus_register and phy
From: Andrew Lunn @ 2016-10-14 17:25 UTC (permalink / raw)
To: Timur Tabi; +Cc: netdev
In-Reply-To: <58010E79.2030607@codeaurora.org>
On Fri, Oct 14, 2016 at 11:57:29AM -0500, Timur Tabi wrote:
> Andrew Lunn wrote:
> >That is a basic assumption of the code. If you cannot read the IDs how
> >are you supposed to know what device it is, and what quirks you need
> >to work around its broken features...
> >
> >Does the datasheet say anything about this?
> >
> >I would say for this device, suspend() is too aggressive.
>
> This change in my driver makes the problem go away (I'm not sure if
> it's a "fix"):
>
> @@ -992,7 +992,7 @@ int emac_mac_up(struct emac_adapter *adpt)
> emac_mac_rx_descs_refill(adpt, &adpt->rx_q);
>
> ret = phy_connect_direct(netdev, adpt->phydev, emac_adjust_link,
> - PHY_INTERFACE_MODE_SGMII);
> + PHY_INTERFACE_MODE_NA);
It is normal to get the phy-mode from device tree. I've no idea what
ACPI is supposed to do. Setting it to PHY_INTERFACE_MODE_NA means you
assume the boot loader has correctly setup the hardware. You ACPI
firmware might of done this, but there is no guarantee a device tree
base bootloader has. So i would prefer not changing this.
> With the interface not set as SGMII, the following code in
> at803x_suspend() is not executed:
>
> /* also power-down SGMII interface */
> ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
> phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
> phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN);
> phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
>
> I don't see any other driver issue BMCR_PDOWN in their functions. I
> added some printks for the PHYSID1 and PHYSID2 registers before and
> after BMCR_PDOWN:
>
> at803x_suspend:235 MII_PHYSID1=004d MII_PHYSID2=d074
> at803x_suspend:242 MII_PHYSID1=ffff MII_PHYSID2=ffff
>
> So after calling BMCR_PDOWN, the PHYSID1 and PHYSID2 registers are
> no longer readable. Is that expected?
You are making two changes here. Is it the SGMII power down which is
causing the id registers to return 0xffff, or the BMCR_PDOWN.
The generic suspend code sets the PDOWN bit, so it is assuming the PHY
will respond afterwards.
Andrew
^ permalink raw reply
* [PATCH v2 net-next 1/2] lwtunnel: Add destroy state operation
From: Tom Herbert @ 2016-10-14 18:25 UTC (permalink / raw)
To: davem, netdev, roopa; +Cc: kernel-team
In-Reply-To: <20161014182537.1713757-1-tom@herbertland.com>
Users of lwt tunnels may set up some secondary state in build_state
function. Add a corresponding destroy_state function to allow users to
clean up state. This destroy state function is called from lwstate_free.
Also, we now free lwstate using kfree_rcu so user can assume structure
is not freed before rcu.
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/lwtunnel.h | 7 +++----
net/core/lwtunnel.c | 13 +++++++++++++
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
index ea3f80f..67d235f 100644
--- a/include/net/lwtunnel.h
+++ b/include/net/lwtunnel.h
@@ -29,6 +29,7 @@ struct lwtunnel_state {
int (*orig_input)(struct sk_buff *);
int len;
__u16 headroom;
+ struct rcu_head rcu;
__u8 data[0];
};
@@ -36,6 +37,7 @@ struct lwtunnel_encap_ops {
int (*build_state)(struct net_device *dev, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts);
+ void (*destroy_state)(struct lwtunnel_state *lws);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*input)(struct sk_buff *skb);
int (*fill_encap)(struct sk_buff *skb,
@@ -46,10 +48,7 @@ struct lwtunnel_encap_ops {
};
#ifdef CONFIG_LWTUNNEL
-static inline void lwtstate_free(struct lwtunnel_state *lws)
-{
- kfree(lws);
-}
+void lwtstate_free(struct lwtunnel_state *lws);
static inline struct lwtunnel_state *
lwtstate_get(struct lwtunnel_state *lws)
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index e5f84c2..88fd642 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -130,6 +130,19 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
}
EXPORT_SYMBOL(lwtunnel_build_state);
+void lwtstate_free(struct lwtunnel_state *lws)
+{
+ const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type];
+
+ if (ops->destroy_state) {
+ ops->destroy_state(lws);
+ kfree_rcu(lws, rcu);
+ } else {
+ kfree(lws);
+ }
+}
+EXPORT_SYMBOL(lwtstate_free);
+
int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate)
{
const struct lwtunnel_encap_ops *ops;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 net-next 0/2] ila: Cache a route in ILA lwt structure
From: Tom Herbert @ 2016-10-14 18:25 UTC (permalink / raw)
To: davem, netdev, roopa; +Cc: kernel-team
Add a dst_cache to ila_lwt structure. This holds a cached route for the
translated address. In ila_output we now perform a route lookup after
translation and if possible (destination in original route is full 128
bits) we set the dst_cache. Subsequent calls to ila_output can then use
the cache to avoid the route lookup.
This eliminates the need to set the gateway on ILA routes as previously
was being done. Now we can do somthing like:
./ip route add 3333::2000:0:0:2/128 encap ila 2222:0:0:2 \
csum-mode neutral-map dev eth0 ## No via needed!
Also, add destroy_state to lwt ops. We need this do destroy the
dst_cache.
- v2
- Fixed comparisons to fc_dst_len to make comparison against number
of bits in data structure not bytes.
- Move destroy_state under build_state (requested by Jiri)
- Other minor cleanup
Tested:
Running 200 TCP_RR streams:
Baseline, no ILA
1730716 tps
102/170/313 50/90/99% latencies
88.11 CPU utilization
Using ILA in both directions
1680428 tps
105/176/325 50/90/99% latencies
88.16 CPU utilization
Tom Herbert (2):
lwtunnel: Add destroy state operation
ila: Cache a route to translated address
include/net/lwtunnel.h | 7 ++---
net/core/lwtunnel.c | 13 ++++++++
net/ipv6/ila/ila_lwt.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 90 insertions(+), 10 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH v2 net-next 2/2] ila: Cache a route to translated address
From: Tom Herbert @ 2016-10-14 18:25 UTC (permalink / raw)
To: davem, netdev, roopa; +Cc: kernel-team
In-Reply-To: <20161014182537.1713757-1-tom@herbertland.com>
Add a dst_cache to ila_lwt structure. This holds a cached route for the
translated address. In ila_output we now perform a route lookup after
translation and if possible (destination in original route is full 128
bits) we set the dst_cache. Subsequent calls to ila_output can then use
the cache to avoid the route lookup.
This eliminates the need to set the gateway on ILA routes as previously
was being done. Now we can do something like:
./ip route add 3333::2000:0:0:2/128 encap ila 2222:0:0:2 \
csum-mode neutral-map dev eth0 ## No via needed!
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/ipv6/ila/ila_lwt.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 74 insertions(+), 6 deletions(-)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index e50c27a..d0a98d9 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -6,29 +6,80 @@
#include <linux/socket.h>
#include <linux/types.h>
#include <net/checksum.h>
+#include <net/dst_cache.h>
#include <net/ip.h>
#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
#include <net/lwtunnel.h>
#include <net/protocol.h>
#include <uapi/linux/ila.h>
#include "ila.h"
+struct ila_lwt {
+ struct ila_params p;
+ struct dst_cache dst_cache;
+ u32 connected : 1;
+};
+
+static inline struct ila_lwt *ila_lwt_lwtunnel(
+ struct lwtunnel_state *lwt)
+{
+ return (struct ila_lwt *)lwt->data;
+}
+
static inline struct ila_params *ila_params_lwtunnel(
- struct lwtunnel_state *lwstate)
+ struct lwtunnel_state *lwt)
{
- return (struct ila_params *)lwstate->data;
+ return &ila_lwt_lwtunnel(lwt)->p;
}
static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
- struct dst_entry *dst = skb_dst(skb);
+ struct dst_entry *orig_dst = skb_dst(skb);
+ struct ila_lwt *ilwt = ila_lwt_lwtunnel(orig_dst->lwtstate);
+ struct dst_entry *dst;
+ int err = -EINVAL;
if (skb->protocol != htons(ETH_P_IPV6))
goto drop;
- ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate), true);
+ ila_update_ipv6_locator(skb, ila_params_lwtunnel(orig_dst->lwtstate),
+ true);
+
+ dst = dst_cache_get(&ilwt->dst_cache);
+ if (unlikely(!dst)) {
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ struct flowi6 fl6;
+
+ /* Lookup a route for the new destination. Take into
+ * account that the base route may already have a gateway.
+ */
+
+ memset(&fl6, 0, sizeof(fl6));
+ fl6.flowi6_oif = orig_dst->dev->ifindex;
+ fl6.flowi6_iif = LOOPBACK_IFINDEX;
+ fl6.daddr = *rt6_nexthop((struct rt6_info *)orig_dst,
+ &ip6h->daddr);
+
+ dst = ip6_route_output(net, NULL, &fl6);
+ if (dst->error) {
+ err = -EHOSTUNREACH;
+ dst_release(dst);
+ goto drop;
+ }
+
+ dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+ if (IS_ERR(dst)) {
+ err = PTR_ERR(dst);
+ goto drop;
+ }
+
+ if (ilwt->connected)
+ dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr);
+ }
- return dst->lwtstate->orig_output(net, sk, skb);
+ skb_dst_set(skb, dst);
+ return dst_output(net, sk, skb);
drop:
kfree_skb(skb);
@@ -60,6 +111,7 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts)
{
+ struct ila_lwt *ilwt;
struct ila_params *p;
struct nlattr *tb[ILA_ATTR_MAX + 1];
size_t encap_len = sizeof(*p);
@@ -71,7 +123,7 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
if (family != AF_INET6)
return -EINVAL;
- if (cfg6->fc_dst_len < sizeof(struct ila_locator) + 1) {
+ if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
/* Need to have full locator and at least type field
* included in destination
*/
@@ -99,6 +151,13 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
if (!newts)
return -ENOMEM;
+ ilwt = ila_lwt_lwtunnel(newts);
+ ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
+ if (ret) {
+ kfree(newts);
+ return ret;
+ }
+
newts->len = encap_len;
p = ila_params_lwtunnel(newts);
@@ -120,11 +179,19 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
LWTUNNEL_STATE_INPUT_REDIRECT;
+ if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
+ ilwt->connected = 1;
+
*ts = newts;
return 0;
}
+static void ila_destroy_state(struct lwtunnel_state *lwt)
+{
+ dst_cache_destroy(&ila_lwt_lwtunnel(lwt)->dst_cache);
+}
+
static int ila_fill_encap_info(struct sk_buff *skb,
struct lwtunnel_state *lwtstate)
{
@@ -159,6 +226,7 @@ static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
static const struct lwtunnel_encap_ops ila_encap_ops = {
.build_state = ila_build_state,
+ .destroy_state = ila_destroy_state,
.output = ila_output,
.input = ila_input,
.fill_encap = ila_fill_encap_info,
--
2.9.3
^ permalink raw reply related
* Re: Need help with mdiobus_register and phy
From: Timur Tabi @ 2016-10-14 18:30 UTC (permalink / raw)
To: Andrew Lunn, zefir.kurtisi; +Cc: netdev
In-Reply-To: <20161014172514.GA23455@lunn.ch>
Andrew Lunn wrote:
> It is normal to get the phy-mode from device tree. I've no idea what
> ACPI is supposed to do. Setting it to PHY_INTERFACE_MODE_NA means you
> assume the boot loader has correctly setup the hardware. You ACPI
> firmware might of done this, but there is no guarantee a device tree
> base bootloader has. So i would prefer not changing this.
Fair enough. I don't think it's specified anywhere what firmware is
supposed to do.
What about specifying PHY_INTERFACE_MODE_NA on ACPI systems, but using
the phy-mode property on device tree systems? That doesn't sound like a
great idea.
>> >I don't see any other driver issue BMCR_PDOWN in their functions. I
>> >added some printks for the PHYSID1 and PHYSID2 registers before and
>> >after BMCR_PDOWN:
>> >
>> >at803x_suspend:235 MII_PHYSID1=004d MII_PHYSID2=d074
>> >at803x_suspend:242 MII_PHYSID1=ffff MII_PHYSID2=ffff
>> >
>> >So after calling BMCR_PDOWN, the PHYSID1 and PHYSID2 registers are
>> >no longer readable. Is that expected?
> You are making two changes here. Is it the SGMII power down which is
> causing the id registers to return 0xffff, or the BMCR_PDOWN.
>
> The generic suspend code sets the PDOWN bit, so it is assuming the PHY
> will respond afterwards.
Ok, it took me a while to figure this out. The driver does three writes:
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN);
phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
The first clears the AT803X_BT_BX_REG_SEL bit. According to the
datasheet, that changes the register set from copper to fiber mode.
BMCR_PDOWN in fiber mode shuts off the SerDes bus. That's not true in
copper mode.
Then after shutting down SerDes, it switches back to copper mode.
I also noticed the at803x_suspend already sends BMCR_PDOWN in copper
mode earlier in the function.
So the question remains: should drivers shut down the SerDes bus when
they suspend? In a sense, I'm wondering if we should revert
at803x: fix suspend/resume for SGMII link
However, the changelog for that patch makes it sound like it's a
necessary fix.
So I'm torn. With the SerDes connection disabled, the driver no longer
responds to ID register reads. That seems like something that would be
broken on device tree as well, but I don't understand why no one noticed
it before.
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc. Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* Re: [PATCH net-next v11 1/1] net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.
From: Allan W. Nielsen @ 2016-10-14 18:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev, andrew, f.fainelli, raju.lakkaraju
In-Reply-To: <20161014.110544.269842399219820528.davem@davemloft.net>
Hi David,
I'm really sorry if I messed up, or is not following the protocol...
But you have applied it already:
http://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/?id=4f58e6dceb0e44ca8f21568ed81e1df24e55964c
> commit 4f58e6dceb0e44ca8f21568ed81e1df24e55964c
> Author: Allan W. Nielsen <allan.nielsen@microsemi.com>
> AuthorDate: Wed Oct 12 15:47:51 2016 +0200
> Commit: David S. Miller <davem@davemloft.net>
> CommitDate: Fri Oct 14 10:06:13 2016 -0400
>
> net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.
>
> Edge-Rate cleanup include the following:
> - Updated device tree bindings documentation for edge-rate
> - The edge-rate is now specified as a "slowdown", meaning that it is now
> being specified as positive values instead of negative (both
> documentation and implementation wise).
> - Only explicitly documented values for "vsc8531,vddmac" and
> "vsc8531,edge-slowdown" are accepted by the device driver.
> - Deleted include/dt-bindings/net/mscc-phy-vsc8531.h as it was not needed.
> - Read/validate devicetree settings in probe instead of init
>
> Signed-off-by: Allan W. Nielsen <allan.nielsen@microsemi.com>
> Signed-off-by: Raju Lakkaraju <raju.lakkaraju@microsemi.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
Maybe the misunderstanding was caused by me posting the re-based version in
another thread.
Anyway, thanks a lot for the big effort you put into maintaining this
sub-system. I will be more care full next time to avoid such confusions.
Best regards
Allan W. Nielsen
On 14/10/16 11:05, David Miller wrote:
> EXTERNAL EMAIL
>
>
> From: "Allan W. Nielsen" <allan.nielsen@microsemi.com>
> Date: Thu, 13 Oct 2016 20:21:30 +0200
>
> > Edge-Rate cleanup include the following:
> > - Updated device tree bindings documentation for edge-rate
> > - The edge-rate is now specified as a "slowdown", meaning that it is now
> > being specified as positive values instead of negative (both
> > documentation and implementation wise).
> > - Only explicitly documented values for "vsc8531,vddmac" and
> > "vsc8531,edge-slowdown" are accepted by the device driver.
> > - Deleted include/dt-bindings/net/mscc-phy-vsc8531.h as it was not needed.
> > - Read/validate devicetree settings in probe instead of init
> >
> > Signed-off-by: Allan W. Nielsen <allan.nielsen@microsemi.com>
> > Signed-off-by: Raju Lakkaraju <raju.lakkaraju@microsemi.com>
>
> This patch does not apply to the net-next tree.
>
> Take my tree, put this email of your's into a file, and run this:
>
> bash$ git am file
>
> and you will get:
>
> [davem@dhcp-10-15-49-210 net-next]$ git am --signoff net-next-v11-1-1-net-phy-Cleanup-the-Edge-Rate-feature-in-Microsemi-PHYs..patch
> Applying: net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.
> error: patch failed: Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt:6
> error: Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt: patch does not apply
> error: patch failed: drivers/net/phy/mscc.c:12
> error: drivers/net/phy/mscc.c: patch does not apply
> error: include/dt-bindings/net/mscc-phy-vsc8531.h: does not exist in index
> Patch failed at 0001 net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.
> The copy of the patch that failed is found in:
> /home/davem/src/GIT/net-next/.git/rebase-apply/patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
>
> Please do not resubmit this patch until you can successfully email the
> patch to yourself and apply it cleanly to the net-next tree.
>
>
^ permalink raw reply
* [PATCH] net: qcom/emac: disable interrupts before calling phy_disconnect
From: Timur Tabi @ 2016-10-14 19:14 UTC (permalink / raw)
To: netdev
There is a race condition that can occur if EMAC interrupts are
enabled when phy_disconnect() is called. phy_disconnect() sets
adjust_link to NULL. When an interrupt occurs, the ISR might
call phy_mac_interrupt(), which wakes up the workqueue function
phy_state_machine(). This function might reference adjust_link,
thereby causing a null pointer exception.
Signed-off-by: Timur Tabi <timur@codeaurora.org>
---
drivers/net/ethernet/qualcomm/emac/emac-mac.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
index e97968e..6fb3bee 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -1021,14 +1021,18 @@ void emac_mac_down(struct emac_adapter *adpt)
napi_disable(&adpt->rx_q.napi);
phy_stop(adpt->phydev);
- phy_disconnect(adpt->phydev);
- /* disable mac irq */
+ /* Interrupts must be disabled before the PHY is disconnected, to
+ * avoid a race condition where adjust_link is null when we get
+ * an interrupt.
+ */
writel(DIS_INT, adpt->base + EMAC_INT_STATUS);
writel(0, adpt->base + EMAC_INT_MASK);
synchronize_irq(adpt->irq.irq);
free_irq(adpt->irq.irq, &adpt->irq);
+ phy_disconnect(adpt->phydev);
+
emac_mac_reset(adpt);
emac_tx_q_descs_free(adpt);
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc. Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [patch] stmmac: fix an error code in stmmac_ptp_register()
From: Dan Carpenter @ 2016-10-14 19:26 UTC (permalink / raw)
To: Giuseppe Cavallaro; +Cc: Alexandre Torgue, netdev, kernel-janitors
PTR_ERR(NULL) is success. We have to preserve the error code earlier.
Fixes: 7086605a6ab5 ("stmmac: fix error check when init ptp")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
Applies to net.git tree.
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index 289d527..5d61fb2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -185,8 +185,10 @@ int stmmac_ptp_register(struct stmmac_priv *priv)
priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
priv->device);
if (IS_ERR(priv->ptp_clock)) {
+ int ret = PTR_ERR(priv->ptp_clock);
+
priv->ptp_clock = NULL;
- return PTR_ERR(priv->ptp_clock);
+ return ret;
}
spin_lock_init(&priv->ptp_lock);
^ permalink raw reply related
* [PATCH v3] net: Require exact match for TCP socket lookups if dif is l3mdev
From: David Ahern @ 2016-10-14 19:29 UTC (permalink / raw)
To: netdev; +Cc: eric.dumazet, David Ahern
Currently, socket lookups for l3mdev (vrf) use cases can match a socket
that is bound to a port but not a device (ie., a global socket). If the
sysctl tcp_l3mdev_accept is not set this leads to ack packets going out
based on the main table even though the packet came in from an L3 domain.
The end result is that the connection does not establish creating
confusion for users since the service is running and a socket shows in
ss output. Fix by requiring an exact dif to sk_bound_dev_if match if the
skb came through an interface enslaved to an l3mdev device and the
tcp_l3mdev_accept is not set.
skb's through an l3mdev interface are marked by setting a flag in
inet{6}_skb_parm. The IPv6 variant is already set; this patch adds the
flag for IPv4. Using an skb flag avoids a device lookup on the dif. The
flag is set in the VRF driver using the IP{6}CB macros. For IPv4, the
inet_skb_parm struct is moved in the cb per commit 971f10eca186, so the
match function in the TCP stack needs to use TCP_SKB_CB. For IPv6, the
move is done after the socket lookup, so IP6CB is used.
The flags field in inet_skb_parm struct needs to be increased to add
another flag. There is currently a 1-byte hole following the flags,
so it can be expanded to u16 without increasing the size of the struct.
Fixes: 193125dbd8eb ("net: Introduce VRF device driver")
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
v3
- changed the match functions to pull the skb flag from TCP_SKB_CB
rather than IPCB for IPv4 per changes from 971f10eca186. match
function is moved to tcp.h as a consequence.
- made flags a u16 versus __u16 for consistency with frag_max_size
- updated commit message
v2
- reordered the checks in inet_exact_dif_match per Eric's comment
- changed the l3mdev determination from looking up the dif to using
a flag set on the skb which is much faster
drivers/net/vrf.c | 2 ++
include/linux/ipv6.h | 11 +++++++++++
include/net/ip.h | 8 +++++++-
include/net/tcp.h | 11 +++++++++++
net/ipv4/inet_hashtables.c | 8 +++++---
net/ipv6/inet6_hashtables.c | 7 ++++---
6 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 85c271c70d42..820de6a9ddde 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -956,6 +956,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
if (skb->pkt_type == PACKET_LOOPBACK) {
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
+ IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
skb->pkt_type = PACKET_HOST;
goto out;
}
@@ -996,6 +997,7 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
{
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
+ IPCB(skb)->flags |= IPSKB_L3SLAVE;
/* loopback traffic; do not push through packet taps again.
* Reset pkt_type for upper layers to process skb
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 7e9a789be5e0..c0644e5f603a 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -144,6 +144,17 @@ static inline int inet6_iif(const struct sk_buff *skb)
return l3_slave ? skb->skb_iif : IP6CB(skb)->iif;
}
+/* can not be used in TCP layer after tcp_v6_fill_cb */
+static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb)
+{
+#if defined(CONFIG_NET_L3_MASTER_DEV)
+ if (!net->ipv4.sysctl_tcp_l3mdev_accept &&
+ skb_l3mdev_slave(IP6CB(skb)->flags))
+ return true;
+#endif
+ return false;
+}
+
struct tcp6_request_sock {
struct tcp_request_sock tcp6rsk_tcp;
};
diff --git a/include/net/ip.h b/include/net/ip.h
index bc43c0fcae12..64d05d976b22 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -38,7 +38,7 @@ struct sock;
struct inet_skb_parm {
int iif;
struct ip_options opt; /* Compiled IP options */
- unsigned char flags;
+ u16 flags;
#define IPSKB_FORWARDED BIT(0)
#define IPSKB_XFRM_TUNNEL_SIZE BIT(1)
@@ -48,10 +48,16 @@ struct inet_skb_parm {
#define IPSKB_DOREDIRECT BIT(5)
#define IPSKB_FRAG_PMTU BIT(6)
#define IPSKB_FRAG_SEGS BIT(7)
+#define IPSKB_L3SLAVE BIT(8)
u16 frag_max_size;
};
+static inline bool skb_l3mdev_slave4(u16 flags)
+{
+ return !!(flags & IPSKB_L3SLAVE);
+}
+
static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
{
return ip_hdr(skb)->ihl * 4;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index f83b7f220a65..5c7bb59dc331 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -800,6 +800,17 @@ static inline int tcp_v6_iif(const struct sk_buff *skb)
}
#endif
+/* TCP_SKB_CB reference means this can not be used from early demux */
+static inline bool inet_exact_dif_match(struct net *net, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+ if (!net->ipv4.sysctl_tcp_l3mdev_accept &&
+ skb_l3mdev_slave4(TCP_SKB_CB(skb)->header.h4.flags))
+ return true;
+#endif
+ return false;
+}
+
/* Due to TSO, an SKB can be composed of multiple actual
* packets. To keep these tracked properly, we use this.
*/
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 77c20a489218..ca97835bfec4 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -25,6 +25,7 @@
#include <net/inet_hashtables.h>
#include <net/secure_seq.h>
#include <net/ip.h>
+#include <net/tcp.h>
#include <net/sock_reuseport.h>
static u32 inet_ehashfn(const struct net *net, const __be32 laddr,
@@ -172,7 +173,7 @@ EXPORT_SYMBOL_GPL(__inet_inherit_port);
static inline int compute_score(struct sock *sk, struct net *net,
const unsigned short hnum, const __be32 daddr,
- const int dif)
+ const int dif, bool exact_dif)
{
int score = -1;
struct inet_sock *inet = inet_sk(sk);
@@ -186,7 +187,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
return -1;
score += 4;
}
- if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if || exact_dif) {
if (sk->sk_bound_dev_if != dif)
return -1;
score += 4;
@@ -215,11 +216,12 @@ struct sock *__inet_lookup_listener(struct net *net,
unsigned int hash = inet_lhashfn(net, hnum);
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
int score, hiscore = 0, matches = 0, reuseport = 0;
+ bool exact_dif = inet_exact_dif_match(net, skb);
struct sock *sk, *result = NULL;
u32 phash = 0;
sk_for_each_rcu(sk, &ilb->head) {
- score = compute_score(sk, net, hnum, daddr, dif);
+ score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
if (score > hiscore) {
reuseport = sk->sk_reuseport;
if (reuseport) {
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 00cf28ad4565..2fd0374a35b1 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -96,7 +96,7 @@ EXPORT_SYMBOL(__inet6_lookup_established);
static inline int compute_score(struct sock *sk, struct net *net,
const unsigned short hnum,
const struct in6_addr *daddr,
- const int dif)
+ const int dif, bool exact_dif)
{
int score = -1;
@@ -109,7 +109,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
return -1;
score++;
}
- if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if || exact_dif) {
if (sk->sk_bound_dev_if != dif)
return -1;
score++;
@@ -131,11 +131,12 @@ struct sock *inet6_lookup_listener(struct net *net,
unsigned int hash = inet_lhashfn(net, hnum);
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
int score, hiscore = 0, matches = 0, reuseport = 0;
+ bool exact_dif = inet6_exact_dif_match(net, skb);
struct sock *sk, *result = NULL;
u32 phash = 0;
sk_for_each(sk, &ilb->head) {
- score = compute_score(sk, net, hnum, daddr, dif);
+ score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
if (score > hiscore) {
reuseport = sk->sk_reuseport;
if (reuseport) {
--
2.1.4
^ permalink raw reply related
* ethtool.h compile warning on c++
From: Ben Greear @ 2016-10-14 19:46 UTC (permalink / raw)
To: netdev
I am getting warnings about sign missmatch.
Maybe make SPEED_UNKNOWN be ((__u32)(0xFFFFFFFF)) ?
from ethtool.h:
#define SPEED_UNKNOWN -1
static inline int ethtool_validate_speed(__u32 speed)
{
return speed <= INT_MAX || speed == SPEED_UNKNOWN;
}
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: Kernel 4.6.7-rt13: Intel Ethernet driver igb causes huge latencies in cyclictest
From: Julia Cartwright @ 2016-10-14 19:55 UTC (permalink / raw)
To: Koehrer Mathias (ETAS/ESW5)
Cc: Williams, Mitch A, Kirsher, Jeffrey T,
linux-rt-users@vger.kernel.org, Sebastian Andrzej Siewior,
netdev@vger.kernel.org, intel-wired-lan@lists.osuosl.org, Greg
In-Reply-To: <f395ea6cd1274fac83d2744121da7441@FE-MBX1012.de.bosch.com>
On Fri, Oct 14, 2016 at 08:58:22AM +0000, Koehrer Mathias (ETAS/ESW5) wrote:
> Hi Julia,
>
> > Have you tested on a vanilla (non-RT) kernel? I doubt there is anything RT specific
> > about what you are seeing, but it might be nice to get confirmation. Also, bisection
> > would probably be easier if you confirm on a vanilla kernel.
> >
> > I find it unlikely that it's a kernel config option that changed which regressed you, but
> > instead was a code change to a driver. Which driver is now the question, and the
> > surface area is still big (processor mapping attributes for this region, PCI root
> > complex configuration, PCI brige configuration, igb driver itself, etc.).
> >
> > Big enough that I'd recommend a bisection. It looks like a bisection between 3.18
> > and 4.8 would take you about 18 tries to narrow down, assuming all goes well.
> >
>
> I have now repeated my tests using the vanilla kernel.
> There I got the very same issue.
> Using kernel 4.0 is fine, however starting with kernel 4.1, the issue appears.
Great, thanks for confirming! That helps narrow things down quite a
bit.
> Here is my exact (reproducible) test description:
> I applied the following patch to the kernel to get the igb trace.
> This patch instruments the igb_rd32() function to measure the call
> to readl() which is used to access registers of the igb NIC.
I took your test setup and ran it between 4.0 and 4.1 on the hardware on
my desk, which is an Atom-based board with dual I210s, however I didn't
see much difference.
However, it's a fairly simple board, with a much simpler PCI topology
than your workstation. I'll see if I can find some other hardware to
test on.
[..]
> This means, that I think that some other stuff in kernel 4.1 has changed,
> which has impact on the igb accesses.
>
> Any idea what component could cause this kind of issue?
Can you continue your bisection using 'git bisect'? You've already
narrowed it down between 4.0 and 4.1, so you're well on your way.
Another option might be to try to eliminate igb from the picture as
well, and try reading from another device from the same (or, perhaps
nearest) bus segment, and see if you see the same results.
Julia
^ permalink raw reply
* Re: [PATCH] net: asix: Avoid looping when the device does not respond
From: David Miller @ 2016-10-14 20:07 UTC (permalink / raw)
To: linux-0h96xk9xTtrk1uMJSBkQmQ
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1476402196-5920-1-git-send-email-linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
From: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
Date: Thu, 13 Oct 2016 16:43:16 -0700
> Check answers from USB stack and avoid re-sending the request
> multiple times if the device does not respond.
>
> This fixes the following problem, observed with a probably flaky adapter.
...
> Since the USB timeout is 5 seconds, and the operation is retried 30 times,
> this results in
...
> Signed-off-by: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
Applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: pull-request: wireless-drivers 2016-10-14
From: David Miller @ 2016-10-14 20:08 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <87oa2nbdpp.fsf@kamboji.qca.qualcomm.com>
From: Kalle Valo <kvalo@codeaurora.org>
Date: Fri, 14 Oct 2016 10:18:42 +0300
> first wireless-drivers pull request for 4.9 and this time we have
> unusually many fixes even before -rc1 is released. Most important here
> are the wlcore and rtlwifi commits which fix critical regressions,
> otherwise smaller impact fixes and one new sdio id for ath6kl.
>
> Please let me know if there are any problems.
Pulled, thanks Kalle.
^ permalink raw reply
* Re: [PATCH NET] ethtool: silence warning on bit loss
From: David Miller @ 2016-10-14 20:06 UTC (permalink / raw)
To: jesse.brandeburg; +Cc: netdev
In-Reply-To: <1476400435-18400-1-git-send-email-jesse.brandeburg@intel.com>
From: Jesse Brandeburg <jesse.brandeburg@intel.com>
Date: Thu, 13 Oct 2016 16:13:55 -0700
> Sparse was complaining when we went to prototype some code
> using ethtool_cmd_speed_set and SPEED_100000, which uses
> the upper 16 bits of __u32 speed for the first time.
>
> CHECK
> ...
> .../uapi/linux/ethtool.h:123:28: warning:
> cast truncates bits from constant value (186a0 becomes 86a0)
>
> The warning is actually bogus, as no bits are really lost, but
> we can get rid of the sparse warning with this one small change.
>
> Reported-by: Preethi Banala <preethi.banala@intel.com>
> Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Ok, I'll apply this.
There were alternative suggestions but I like this patch
because it makes it explicit what is going on.
Just removing the u16 cast requires the reader to implicitly
understand and know the types in the structure.
^ permalink raw reply
* Re: [PATCH v2] r8169: set coherent DMA mask as well as streaming DMA mask
From: Francois Romieu @ 2016-10-14 20:48 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: nic_swsd, netdev, linux-kernel, davem
In-Reply-To: <1476452433-20518-1-git-send-email-ard.biesheuvel@linaro.org>
Ard Biesheuvel <ard.biesheuvel@linaro.org> :
> PCI devices that are 64-bit DMA capable should set the coherent
> DMA mask as well as the streaming DMA mask. On some architectures,
> these are managed separately, and so the coherent DMA mask will be
> left at its default value of 32 if it is not set explicitly. This
> results in errors such as
>
> r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
> hwdev DMA mask = 0x00000000ffffffff, dev_addr = 0x00000080fbfff000
> swiotlb: coherent allocation failed for device 0000:02:00.0 size=4096
> CPU: 0 PID: 1062 Comm: systemd-udevd Not tainted 4.8.0+ #35
> Hardware name: AMD Seattle/Seattle, BIOS 10:53:24 Oct 13 2016
>
> on systems without memory that is 32-bit addressable by PCI devices.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Unless someone plans to plug an acenic, a 83820 (pci-e gem board, anyone ?)
on top of a pci <-> pci-e adapter on this kind of motherboard, no other
network driver that uses the pci_... dma api exhibits this mixed 32 / 64 bit
support bug. I haven't checked devices with 32 < mask < 64 nor plain DMA api
converted ones.
--
Ueimor
^ permalink raw reply
* [PATCH v2] vmxnet3: avoid assumption about invalid dma_pa in vmxnet3_set_mc()
From: Alexey Khoroshilov @ 2016-10-14 21:01 UTC (permalink / raw)
To: David Miller, Shrikrishna Khare
Cc: Alexey Khoroshilov, VMware, Inc., netdev, linux-kernel,
ldv-project
In-Reply-To: <20161013.094323.1769619439752576215.davem@davemloft.net>
vmxnet3_set_mc() checks new_table_pa returned by dma_map_single()
with dma_mapping_error(), but even there it assumes zero is invalid pa
(it assumes dma_mapping_error(...,0) returns true if new_table is NULL).
The patch adds an explicit variable to track status of new_table_pa.
Found by Linux Driver Verification project (linuxtesting.org).
v2: use "bool" and "true"/"false" for boolean variables.
Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
---
drivers/net/vmxnet3/vmxnet3_drv.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index b5554f2ebee4..ef83ae3b0a44 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2279,6 +2279,7 @@ vmxnet3_set_mc(struct net_device *netdev)
&adapter->shared->devRead.rxFilterConf;
u8 *new_table = NULL;
dma_addr_t new_table_pa = 0;
+ bool new_table_pa_valid = false;
u32 new_mode = VMXNET3_RXM_UCAST;
if (netdev->flags & IFF_PROMISC) {
@@ -2307,13 +2308,15 @@ vmxnet3_set_mc(struct net_device *netdev)
new_table,
sz,
PCI_DMA_TODEVICE);
+ if (!dma_mapping_error(&adapter->pdev->dev,
+ new_table_pa)) {
+ new_mode |= VMXNET3_RXM_MCAST;
+ new_table_pa_valid = true;
+ rxConf->mfTablePA = cpu_to_le64(
+ new_table_pa);
+ }
}
-
- if (!dma_mapping_error(&adapter->pdev->dev,
- new_table_pa)) {
- new_mode |= VMXNET3_RXM_MCAST;
- rxConf->mfTablePA = cpu_to_le64(new_table_pa);
- } else {
+ if (!new_table_pa_valid) {
netdev_info(netdev,
"failed to copy mcast list, setting ALL_MULTI\n");
new_mode |= VMXNET3_RXM_ALL_MULTI;
@@ -2338,7 +2341,7 @@ vmxnet3_set_mc(struct net_device *netdev)
VMXNET3_CMD_UPDATE_MAC_FILTERS);
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
- if (new_table_pa)
+ if (new_table_pa_valid)
dma_unmap_single(&adapter->pdev->dev, new_table_pa,
rxConf->mfTableLen, PCI_DMA_TODEVICE);
kfree(new_table);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] net: limit a number of namespaces which can be cleaned up concurrently
From: Andrei Vagin @ 2016-10-14 21:26 UTC (permalink / raw)
To: Eric W. Biederman
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
Andrei Vagin, David S. Miller
In-Reply-To: <87k2db39zf.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
On Thu, Oct 13, 2016 at 10:06:28PM -0500, Eric W. Biederman wrote:
> Andrei Vagin <avagin-5HdwGun5lf+gSpxsJD1C4w@public.gmane.org> writes:
>
> > On Thu, Oct 13, 2016 at 10:49:38AM -0500, Eric W. Biederman wrote:
> >> Andrei Vagin <avagin-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> writes:
> >>
> >> > From: Andrey Vagin <avagin-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
> >> >
> >> > The operation of destroying netns is heavy and it is executed under
> >> > net_mutex. If many namespaces are destroyed concurrently, net_mutex can
> >> > be locked for a long time. It is impossible to create a new netns during
> >> > this period of time.
> >>
> >> This may be the right approach or at least the right approach to bound
> >> net_mutex hold times but I have to take exception to calling network
> >> namespace cleanup heavy.
> >>
> >> The only particularly time consuming operation I have ever found are calls to
> >> synchronize_rcu/sycrhonize_sched/synchronize_net.
> >
> > I booted the kernel with maxcpus=1, in this case these functions work
> > very fast and the problem is there any way.
> >
> > Accoding to perf, we spend a lot of time in kobject_uevent:
> >
> > - 99.96% 0.00% kworker/u4:1 [kernel.kallsyms] [k] unregister_netdevice_many
> > - unregister_netdevice_many
> > - 99.95% rollback_registered_many
> > - 99.64% netdev_unregister_kobject
> > - 33.43% netdev_queue_update_kobjects
> > - 33.40% kobject_put
> > - kobject_release
> > + 33.37% kobject_uevent
> > + 0.03% kobject_del
> > + 0.03% sysfs_remove_group
> > - 33.13% net_rx_queue_update_kobjects
> > - kobject_put
> > - kobject_release
> > + 33.11% kobject_uevent
> > + 0.01% kobject_del
> > 0.00% rx_queue_release
> > - 33.08% device_del
> > + 32.75% kobject_uevent
> > + 0.17% device_remove_attrs
> > + 0.07% dpm_sysfs_remove
> > + 0.04% device_remove_class_symlinks
> > + 0.01% kobject_del
> > + 0.01% device_pm_remove
> > + 0.01% sysfs_remove_file_ns
> > + 0.00% klist_del
> > + 0.00% driver_deferred_probe_del
> > 0.00% cleanup_glue_dir.isra.14.part.15
> > 0.00% to_acpi_device_node
> > 0.00% sysfs_remove_group
> > 0.00% klist_del
> > 0.00% device_remove_attrs
> > + 0.26% call_netdevice_notifiers_info
> > + 0.04% rtmsg_ifinfo_build_skb
> > + 0.01% rtmsg_ifinfo_send
> > 0.00% dev_uc_flush
> > 0.00% netif_reset_xps_queues_gt
> >
> > Someone can listen these uevents, so we can't stop sending them without
> > breaking backward compatibility. We can try to optimize
> > kobject_uevent...
>
> Oh that is a surprise. We can definitely skip genenerating uevents for
> network namespaces that are exiting because by definition no one can see
> those network namespaces. If a socket existed that could see those
> uevents it would hold a reference to the network namespace and as such
> the network namespace could not exit.
>
> That sounds like it is worth investigating a little more deeply.
>
> I am surprised that allocation and freeing is so heavy we are spending
> lots of time doing that. On the other hand kobj_bcast_filter is very
> dumb and very late so I expect something can be moved earlier and make
> that code cheaper with the tiniest bit of work.
>
I'm sorry, I've collected this data for a kernel with debug options
(DEBUG_SPINLOCK, PROVE_LOCKING, DEBUG_LIST, etc). If a kernel is
compiled without debug options, kobject_uevent becomes less expensive,
but still expensive.
- 98.64% 0.00% kworker/u4:2 [kernel.kallsyms] [k] cleanup_net
- cleanup_net
- 98.54% ops_exit_list.isra.4
- 60.48% default_device_exit_batch
- 60.40% unregister_netdevice_many
- rollback_registered_many
- 59.82% netdev_unregister_kobject
- 20.10% device_del
+ 19.44% kobject_uevent
+ 0.40% device_remove_attrs
+ 0.17% dpm_sysfs_remove
+ 0.04% device_remove_class_symlinks
+ 0.04% kobject_del
+ 0.01% device_pm_remove
+ 0.01% sysfs_remove_file_ns
- 19.89% netdev_queue_update_kobjects
+ 19.81% kobject_put
+ 0.07% sysfs_remove_group
- 19.79% net_rx_queue_update_kobjects
kobject_put
- kobject_release
+ 19.77% kobject_uevent
+ 0.02% kobject_del
0.01% rx_queue_release
+ 0.02% kset_unregister
0.01% pm_runtime_set_memalloc_noio
0.01% bus_remove_device
+ 0.45% call_netdevice_notifiers_info
+ 0.07% rtmsg_ifinfo_build_skb
+ 0.04% rtmsg_ifinfo_send
0.01% kset_unregister
+ 0.07% rtnl_unlock
+ 19.27% rpcsec_gss_exit_net
+ 5.45% tcp_net_metrics_exit
+ 5.31% sunrpc_exit_net
+ 3.18% ip6addrlbl_net_exit
So after removing kobject_uevent, cleanup_net becomes more than two times faster:
1000 namespaces are cleaned up for 2.8 seconds with uevents, and 1.2 senconds
without uevents. I do this experiments with max_cpus=1 to exclude synchronize_rcu.
As a summary we can skip generating uevents, but it doesn't solve the original
problem. If we want to avoid the limit introduced in this patch, we have
to reduce the time for destroing net namespace in dozen times, don't we?
Here is a perf report after skipping generating uevents:
- 93.27% 0.00% kworker/u4:1 [kernel.kallsyms] [k] cleanup_net
- cleanup_net
- 92.97% ops_exit_list.isra.4
- 35.14% rpcsec_gss_exit_net
- gss_svc_shutdown_net
- 17.40% rsc_cache_destroy_net
+ 8.64% cache_unregister_net
+ 8.52% cache_purge
+ 0.22% cache_destroy_net
+ 9.00% cache_unregister_net
+ 8.49% cache_purge
+ 0.15% destroy_use_gss_proxy_proc_entry
+ 0.10% cache_destroy_net
- 14.35% tcp_net_metrics_exit
- 7.32% tcp_metrics_flush_all
+ 4.86% _raw_spin_unlock_bh
0.59% __local_bh_enable_ip
6.12% _raw_spin_lock_bh
0.90% _raw_spin_unlock_bh
- 13.08% sunrpc_exit_net
- 6.91% ip_map_cache_destroy
+ 3.90% cache_unregister_net
+ 2.86% cache_purge
+ 0.15% cache_destroy_net
+ 5.95% unix_gid_cache_destroy
+ 0.12% rpc_pipefs_exit_net
+ 0.10% rpc_proc_exit
- 7.35% ip6addrlbl_net_exit
+ call_rcu_sched
+ 3.34% xfrm_net_exit
+ 1.22% ipv6_frags_exit_net
+ 1.17% ipv4_frags_exit_net
+ 0.78% fib_net_exit
+ 0.76% inet6_net_exit
+ 0.76% devinet_exit_net
+ 0.68% addrconf_exit_net
+ 0.63% igmp6_net_exit
+ 0.59% ipv4_mib_exit_net
+ 0.59% uevent_net_exit
> Eric
^ permalink raw reply
* Re: Kernel 4.6.7-rt13: Intel Ethernet driver igb causes huge latencies in cyclictest
From: Richard Cochran @ 2016-10-14 22:06 UTC (permalink / raw)
To: Koehrer Mathias (ETAS/ESW5)
Cc: Julia Cartwright, Williams, Mitch A, Kirsher, Jeffrey T,
linux-rt-users@vger.kernel.org, Sebastian Andrzej Siewior,
netdev@vger.kernel.org, intel-wired-lan@lists.osuosl.org, Greg
In-Reply-To: <f395ea6cd1274fac83d2744121da7441@FE-MBX1012.de.bosch.com>
On Fri, Oct 14, 2016 at 08:58:22AM +0000, Koehrer Mathias (ETAS/ESW5) wrote:
> @@ -753,7 +756,9 @@ u32 igb_rd32(struct e1000_hw *hw, u32 re
> if (E1000_REMOVED(hw_addr))
> return ~value;
>
> + trace_igb(801);
> value = readl(&hw_addr[reg]);
> + trace_igb(802);
Nothing prevents this code from being preempted between the two trace
points, and so you can't be sure whether the time delta in the trace
is caused by the PCIe read stalling or not.
Thanks,
Richard
^ permalink raw reply
* Layer 2 over IPv6 GRE and path MTU discovery
From: Mike Walker @ 2016-10-14 22:31 UTC (permalink / raw)
To: netdev
When using a layer 2 GREv6 tunnel (ip6gretap), I am using a Linux
bridge to push Ethernet frames from an Ethernet port to the GREv6
device.
Here is an example of the topology:
PC -> eth0 -> grebridge -> gre6dev -> (internet) -> GRE endpoint -> Remote host
In this case, the PC connected to the Ethernet port is using IPv6 to
communicate with the remote host, so the source and destination IP of
the traffic being sent by the PC are both IPv6 addresses. So we have
an IPv6 header, Ethernet header, then GRE header once the
encapsulation is done.
Sometimes these packets are too large for the GRE tunnel's MTU. When
this happens, the router's kernel wants to send an ICMP "packet too
big" error message back to the PC.
However, the router has no routing information for the PC. The path
from the PC to the remote host is all supposed to be layer 2. The
router is not configured to route traffic to the PC or the remote
host, only to bridge the layer 2 frames.
What happens then is Linux tries to send an ICMP error, it can't find
the route, or else it sends it to its default route, none of which do
any good.
If the PC doesn't get this ICMP error, it will not know why the
packets were dropped, or it won't even know they were dropped. It's
an ICMP blackhole scenario right?
So, one solution I tried was hacking the kernel so that if it's trying
to send this ICMP "packet too big" error to a host, and we know it's a
layer 2 GRE tunnel, instead of the normal logic, force the ICMP error
message to be sent back out via the network interface the offending
packet was received on.
This mostly worked, the PC recieves the ICMP error and adjusts its
path MTU, so in the future it will know to fragment the packet if it's
too big.
Problem is, I don't know what source IP and mac address I should be
using when I send back this ICMP error to the PC. Normally this
network path doesn't have any layer 3 address, and even the mac
address normally is transparent / unknown to the PC. For my prototype
I simply set the source IP of the ICMP error to whatever was the
destination IP of the packet that was too big. I let the kernel use
the mac address of either the bridge or eth0.
I couldn't seem to find any RFC that says how this should be handled.
Any ideas?
^ permalink raw reply
* Re: bug in ixgbe_atr
From: Sowmini Varadhan @ 2016-10-14 23:00 UTC (permalink / raw)
To: Duyck, Alexander H; +Cc: netdev@vger.kernel.org
In-Reply-To: <B1C1DF2ACD01FD4881736AA51731BAB2A0E025@ORSMSX107.amr.corp.intel.com>
On (10/14/16 16:09), Duyck, Alexander H wrote:
> Sorry I was thinking of a different piece of code. In the case of the
> atr code it would be hdr.network, not hdr.raw. Basically the thought
> was to validate that there is enough data in skb_headlen() that we can
> verify that from where the network header should be we have at least
> 40 bytes of data as that would be the minimum needed for a TCP header
> and an IPv4 header, or just an IPv6 header. We would probably need a
> separate follow-up for the TCP header after we validate network header.
:
>> Dropping it is fine with me I guess - maybe just return, if the
>> skb_headlen() doesnt have enough bytes for a network header, i.e.,
>> skb_headlen
>> is at least ETH_HLEN + sizeof (struct iphdr) for ETH_P_IP, or ETH_HLEN +
>> sizeof (struct ipv6hdr) for ETH_P_IPV6?
> Right that is kind of what I was thinking. If we validate that we
> have at least 40 before inspecting the network header, and at least 20
> before we validate the TCP header that would work for me.
yes, I was on a plane through most of the day today but thought about
this. I think we can check if skb_network_offset() is between
skb->data and tail, and also make sure there are "enough" bytes for
trying to find the ip and transport header.
Let me try to put a RFC patch together for this tomorrow.
^ permalink raw reply
* [PATCH 0/2] net: Fix compiler warnings
From: Tushar Dave @ 2016-10-15 0:06 UTC (permalink / raw)
To: netdev; +Cc: chris.hyser, linux-kernel
Recently, ATU (iommu) changes are submitted to linux-sparc that
enables 64bit DMA on SPARC. However, this change also makes
'incompatible pointer type' compiler warnings inevitable on sunqe
and sunbmac driver.
The two patches in series fix compiler warnings.
Tushar Dave (2):
sunqe: Fix compiler warnings
sunbmac: Fix compiler warning
drivers/net/ethernet/sun/sunbmac.c | 5 +++--
drivers/net/ethernet/sun/sunbmac.h | 2 +-
drivers/net/ethernet/sun/sunqe.c | 11 ++++++-----
drivers/net/ethernet/sun/sunqe.h | 4 ++--
4 files changed, 12 insertions(+), 10 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 2/2] sunbmac: Fix compiler warning
From: Tushar Dave @ 2016-10-15 0:06 UTC (permalink / raw)
To: netdev; +Cc: chris.hyser, linux-kernel
In-Reply-To: <1476489966-9128-1-git-send-email-tushar.n.dave@oracle.com>
sunbmac uses '__u32' for dma handle while invoking kernel DMA APIs,
instead of using dma_addr_t. This hasn't caused any 'incompatible
pointer type' warning on SPARC because until now dma_addr_t is of
type u32. However, recent changes in SPARC ATU (iommu) enables 64bit
DMA and therefore dma_addr_t becomes of type u64. This makes
'incompatible pointer type' warnings inevitable.
e.g.
drivers/net/ethernet/sun/sunbmac.c: In function ‘bigmac_ether_init’:
drivers/net/ethernet/sun/sunbmac.c:1166: warning: passing argument 3 of ‘dma_alloc_coherent’ from incompatible pointer type
./include/linux/dma-mapping.h:445: note: expected ‘dma_addr_t *’ but argument is of type ‘__u32 *’
This patch resolves above compiler warning.
Signed-off-by: Tushar Dave <tushar.n.dave@oracle.com>
Reviewed-by: chris hyser <chris.hyser@oracle.com>
---
drivers/net/ethernet/sun/sunbmac.c | 5 +++--
drivers/net/ethernet/sun/sunbmac.h | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index aa4f9d2..02f4527 100644
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -623,6 +623,7 @@ static int bigmac_init_hw(struct bigmac *bp, int from_irq)
void __iomem *gregs = bp->gregs;
void __iomem *cregs = bp->creg;
void __iomem *bregs = bp->bregs;
+ __u32 bblk_dvma = (__u32)bp->bblock_dvma;
unsigned char *e = &bp->dev->dev_addr[0];
/* Latch current counters into statistics. */
@@ -671,9 +672,9 @@ static int bigmac_init_hw(struct bigmac *bp, int from_irq)
bregs + BMAC_XIFCFG);
/* Tell the QEC where the ring descriptors are. */
- sbus_writel(bp->bblock_dvma + bib_offset(be_rxd, 0),
+ sbus_writel(bblk_dvma + bib_offset(be_rxd, 0),
cregs + CREG_RXDS);
- sbus_writel(bp->bblock_dvma + bib_offset(be_txd, 0),
+ sbus_writel(bblk_dvma + bib_offset(be_txd, 0),
cregs + CREG_TXDS);
/* Setup the FIFO pointers into QEC local memory. */
diff --git a/drivers/net/ethernet/sun/sunbmac.h b/drivers/net/ethernet/sun/sunbmac.h
index 06dd217..532fc56 100644
--- a/drivers/net/ethernet/sun/sunbmac.h
+++ b/drivers/net/ethernet/sun/sunbmac.h
@@ -291,7 +291,7 @@ struct bigmac {
void __iomem *bregs; /* BigMAC Registers */
void __iomem *tregs; /* BigMAC Transceiver */
struct bmac_init_block *bmac_block; /* RX and TX descriptors */
- __u32 bblock_dvma; /* RX and TX descriptors */
+ dma_addr_t bblock_dvma; /* RX and TX descriptors */
spinlock_t lock;
--
1.9.1
^ permalink raw reply related
* [PATCH 1/2] sunqe: Fix compiler warnings
From: Tushar Dave @ 2016-10-15 0:06 UTC (permalink / raw)
To: netdev; +Cc: chris.hyser, linux-kernel
In-Reply-To: <1476489966-9128-1-git-send-email-tushar.n.dave@oracle.com>
sunqe uses '__u32' for dma handle while invoking kernel DMA APIs,
instead of using dma_addr_t. This hasn't caused any 'incompatible
pointer type' warning on SPARC because until now dma_addr_t is of
type u32. However, recent changes in SPARC ATU (iommu) enables 64bit
DMA and therefore dma_addr_t becomes of type u64. This makes
'incompatible pointer type' warnings inevitable.
e.g.
drivers/net/ethernet/sun/sunqe.c: In function ‘qec_ether_init’:
drivers/net/ethernet/sun/sunqe.c:883: warning: passing argument 3 of ‘dma_alloc_coherent’ from incompatible pointer type
./include/linux/dma-mapping.h:445: note: expected ‘dma_addr_t *’ but argument is of type ‘__u32 *’
drivers/net/ethernet/sun/sunqe.c:885: warning: passing argument 3 of ‘dma_alloc_coherent’ from incompatible pointer type
./include/linux/dma-mapping.h:445: note: expected ‘dma_addr_t *’ but argument is of type ‘__u32 *’
This patch resolves above compiler warnings.
Signed-off-by: Tushar Dave <tushar.n.dave@oracle.com>
Reviewed-by: chris hyser <chris.hyser@oracle.com>
---
drivers/net/ethernet/sun/sunqe.c | 11 ++++++-----
drivers/net/ethernet/sun/sunqe.h | 4 ++--
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
index 9b825780..9582948 100644
--- a/drivers/net/ethernet/sun/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@ -124,7 +124,7 @@ static void qe_init_rings(struct sunqe *qep)
{
struct qe_init_block *qb = qep->qe_block;
struct sunqe_buffers *qbufs = qep->buffers;
- __u32 qbufs_dvma = qep->buffers_dvma;
+ __u32 qbufs_dvma = (__u32)qep->buffers_dvma;
int i;
qep->rx_new = qep->rx_old = qep->tx_new = qep->tx_old = 0;
@@ -144,6 +144,7 @@ static int qe_init(struct sunqe *qep, int from_irq)
void __iomem *mregs = qep->mregs;
void __iomem *gregs = qecp->gregs;
unsigned char *e = &qep->dev->dev_addr[0];
+ __u32 qblk_dvma = (__u32)qep->qblock_dvma;
u32 tmp;
int i;
@@ -152,8 +153,8 @@ static int qe_init(struct sunqe *qep, int from_irq)
return -EAGAIN;
/* Setup initial rx/tx init block pointers. */
- sbus_writel(qep->qblock_dvma + qib_offset(qe_rxd, 0), cregs + CREG_RXDS);
- sbus_writel(qep->qblock_dvma + qib_offset(qe_txd, 0), cregs + CREG_TXDS);
+ sbus_writel(qblk_dvma + qib_offset(qe_rxd, 0), cregs + CREG_RXDS);
+ sbus_writel(qblk_dvma + qib_offset(qe_txd, 0), cregs + CREG_TXDS);
/* Enable/mask the various irq's. */
sbus_writel(0, cregs + CREG_RIMASK);
@@ -413,7 +414,7 @@ static void qe_rx(struct sunqe *qep)
struct net_device *dev = qep->dev;
struct qe_rxd *this;
struct sunqe_buffers *qbufs = qep->buffers;
- __u32 qbufs_dvma = qep->buffers_dvma;
+ __u32 qbufs_dvma = (__u32)qep->buffers_dvma;
int elem = qep->rx_new;
u32 flags;
@@ -572,7 +573,7 @@ static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct sunqe *qep = netdev_priv(dev);
struct sunqe_buffers *qbufs = qep->buffers;
- __u32 txbuf_dvma, qbufs_dvma = qep->buffers_dvma;
+ __u32 txbuf_dvma, qbufs_dvma = (__u32)qep->buffers_dvma;
unsigned char *txbuf;
int len, entry;
diff --git a/drivers/net/ethernet/sun/sunqe.h b/drivers/net/ethernet/sun/sunqe.h
index 581781b..ae190b7 100644
--- a/drivers/net/ethernet/sun/sunqe.h
+++ b/drivers/net/ethernet/sun/sunqe.h
@@ -334,12 +334,12 @@ struct sunqe {
void __iomem *qcregs; /* QEC per-channel Registers */
void __iomem *mregs; /* Per-channel MACE Registers */
struct qe_init_block *qe_block; /* RX and TX descriptors */
- __u32 qblock_dvma; /* RX and TX descriptors */
+ dma_addr_t qblock_dvma; /* RX and TX descriptors */
spinlock_t lock; /* Protects txfull state */
int rx_new, rx_old; /* RX ring extents */
int tx_new, tx_old; /* TX ring extents */
struct sunqe_buffers *buffers; /* CPU visible address. */
- __u32 buffers_dvma; /* DVMA visible address. */
+ dma_addr_t buffers_dvma; /* DVMA visible address. */
struct sunqec *parent;
u8 mconfig; /* Base MACE mconfig value */
struct platform_device *op; /* QE's OF device struct */
--
1.9.1
^ 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