Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 5/5 v3] net: gemini: Indicate that we can handle jumboframes
From: Linus Walleij @ 2018-07-11 19:32 UTC (permalink / raw)
  To: netdev, David S . Miller
  Cc: Hans Ulli Kroll, Florian Fainelli, Michał Mirosław,
	Andrew Lunn, Linus Walleij
In-Reply-To: <20180711193245.21980-1-linus.walleij@linaro.org>

The hardware supposedly handles frames up to 10236 bytes and
implements .ndo_change_mtu() so accept 10236 minus the ethernet
header for a VLAN tagged frame on the netdevices. Use
ETH_MIN_MTU as minimum MTU.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- No changes, just resending with the rest.
ChangeLog v1->v2:
- Change the min MTU from 256 (vendor code) to ETH_MIN_MTU
  which makes more sense.
---
 drivers/net/ethernet/cortina/gemini.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 0f1d26441177..22f495b490d4 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -2476,6 +2476,11 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
 
 	netdev->hw_features = GMAC_OFFLOAD_FEATURES;
 	netdev->features |= GMAC_OFFLOAD_FEATURES | NETIF_F_GRO;
+	/* We can handle jumbo frames up to 10236 bytes so, let's accept
+	 * payloads of 10236 bytes minus VLAN and ethernet header
+	 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = 10236 - VLAN_ETH_HLEN;
 
 	port->freeq_refill = 0;
 	netif_napi_add(netdev, &port->napi, gmac_napi_poll,
-- 
2.17.1

^ permalink raw reply related

* [PATCH net-next 4/5 v3] net: gemini: Move main init to port
From: Linus Walleij @ 2018-07-11 19:32 UTC (permalink / raw)
  To: netdev, David S . Miller
  Cc: Hans Ulli Kroll, Florian Fainelli, Michał Mirosław,
	Andrew Lunn, Linus Walleij
In-Reply-To: <20180711193245.21980-1-linus.walleij@linaro.org>

The initialization sequence for the ethernet, setting up
interrupt routing and such things, need to be done after
both the ports are clocked and reset. Before this the
config will not "take". Move the initialization to the
port probe function and keep track of init status in
the state.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- No changes, just resending with the rest.
ChangeLog v1->v2:
- No changes, just resending with the rest.
---
 drivers/net/ethernet/cortina/gemini.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 2457a1239d69..0f1d26441177 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -151,6 +151,7 @@ struct gemini_ethernet {
 	void __iomem *base;
 	struct gemini_ethernet_port *port0;
 	struct gemini_ethernet_port *port1;
+	bool initialized;
 
 	spinlock_t	irq_lock; /* Locks IRQ-related registers */
 	unsigned int	freeq_order;
@@ -2303,6 +2304,14 @@ static void gemini_port_remove(struct gemini_ethernet_port *port)
 
 static void gemini_ethernet_init(struct gemini_ethernet *geth)
 {
+	/* Only do this once both ports are online */
+	if (geth->initialized)
+		return;
+	if (geth->port0 && geth->port1)
+		geth->initialized = true;
+	else
+		return;
+
 	writel(0, geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
 	writel(0, geth->base + GLOBAL_INTERRUPT_ENABLE_1_REG);
 	writel(0, geth->base + GLOBAL_INTERRUPT_ENABLE_2_REG);
@@ -2450,6 +2459,10 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
 		geth->port0 = port;
 	else
 		geth->port1 = port;
+
+	/* This will just be done once both ports are up and reset */
+	gemini_ethernet_init(geth);
+
 	platform_set_drvdata(pdev, port);
 
 	/* Set up and register the netdev */
@@ -2567,7 +2580,6 @@ static int gemini_ethernet_probe(struct platform_device *pdev)
 
 	spin_lock_init(&geth->irq_lock);
 	spin_lock_init(&geth->freeq_lock);
-	gemini_ethernet_init(geth);
 
 	/* The children will use this */
 	platform_set_drvdata(pdev, geth);
@@ -2580,8 +2592,8 @@ static int gemini_ethernet_remove(struct platform_device *pdev)
 {
 	struct gemini_ethernet *geth = platform_get_drvdata(pdev);
 
-	gemini_ethernet_init(geth);
 	geth_cleanup_freeq(geth);
+	geth->initialized = false;
 
 	return 0;
 }
-- 
2.17.1

^ permalink raw reply related

* [PATCH net-next 3/5 v3] net: gemini: Allow multiple ports to instantiate
From: Linus Walleij @ 2018-07-11 19:32 UTC (permalink / raw)
  To: netdev, David S . Miller
  Cc: Hans Ulli Kroll, Florian Fainelli, Michał Mirosław,
	Andrew Lunn, Linus Walleij
In-Reply-To: <20180711193245.21980-1-linus.walleij@linaro.org>

The code was not tested with two ports actually in use at
the same time. (I blame this on lack of actual hardware using
that feature.) Now after locating a system using both ports,
add necessary fix to make both ports come up.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- No changes, just resending with the rest.
ChangeLog v1->v2:
- No changes, just resending with the rest.
---
 drivers/net/ethernet/cortina/gemini.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index f0ab6426daca..2457a1239d69 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1789,7 +1789,10 @@ static int gmac_open(struct net_device *netdev)
 	phy_start(netdev->phydev);
 
 	err = geth_resize_freeq(port);
-	if (err) {
+	/* It's fine if it's just busy, the other port has set up
+	 * the freeq in that case.
+	 */
+	if (err && (err != -EBUSY)) {
 		netdev_err(netdev, "could not resize freeq\n");
 		goto err_stop_phy;
 	}
-- 
2.17.1

^ permalink raw reply related

* [PATCH net-next 2/5 v3] net: gemini: Improve connection prints
From: Linus Walleij @ 2018-07-11 19:32 UTC (permalink / raw)
  To: netdev, David S . Miller
  Cc: Hans Ulli Kroll, Florian Fainelli, Michał Mirosław,
	Andrew Lunn, Linus Walleij
In-Reply-To: <20180711193245.21980-1-linus.walleij@linaro.org>

Switch over to using a module parameter and debug prints
that can be controlled by this or ethtool like everyone
else. Depromote all other prints to debug messages.

The phy_print_status() was already in place, albeit never
really used because the debuglevel hiding it had to be
set up using ethtool.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Use phy_attached_info() live all other drivers.
- Put it in an if (netif_msg_link()) clause like the
  other message from phy_print_status().
- Explain more in the commit message.
ChangeLog v1->v2:
- Use a module parameter and the message levels like all
  other drivers and stop trying to be special.
---
 drivers/net/ethernet/cortina/gemini.c | 46 +++++++++++++++------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 8fc31723f700..f0ab6426daca 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -46,6 +46,11 @@
 #define DRV_NAME		"gmac-gemini"
 #define DRV_VERSION		"1.0"
 
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 #define HSIZE_8			0x00
 #define HSIZE_16		0x01
 #define HSIZE_32		0x02
@@ -300,23 +305,26 @@ static void gmac_speed_set(struct net_device *netdev)
 		status.bits.speed = GMAC_SPEED_1000;
 		if (phydev->interface == PHY_INTERFACE_MODE_RGMII)
 			status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
-		netdev_info(netdev, "connect to RGMII @ 1Gbit\n");
+		netdev_dbg(netdev, "connect %s to RGMII @ 1Gbit\n",
+			   phydev_name(phydev));
 		break;
 	case 100:
 		status.bits.speed = GMAC_SPEED_100;
 		if (phydev->interface == PHY_INTERFACE_MODE_RGMII)
 			status.bits.mii_rmii = GMAC_PHY_RGMII_100_10;
-		netdev_info(netdev, "connect to RGMII @ 100 Mbit\n");
+		netdev_dbg(netdev, "connect %s to RGMII @ 100 Mbit\n",
+			   phydev_name(phydev));
 		break;
 	case 10:
 		status.bits.speed = GMAC_SPEED_10;
 		if (phydev->interface == PHY_INTERFACE_MODE_RGMII)
 			status.bits.mii_rmii = GMAC_PHY_RGMII_100_10;
-		netdev_info(netdev, "connect to RGMII @ 10 Mbit\n");
+		netdev_dbg(netdev, "connect %s to RGMII @ 10 Mbit\n",
+			   phydev_name(phydev));
 		break;
 	default:
-		netdev_warn(netdev, "Not supported PHY speed (%d)\n",
-			    phydev->speed);
+		netdev_warn(netdev, "Unsupported PHY speed (%d) on %s\n",
+			    phydev->speed, phydev_name(phydev));
 	}
 
 	if (phydev->duplex == DUPLEX_FULL) {
@@ -363,12 +371,6 @@ static int gmac_setup_phy(struct net_device *netdev)
 		return -ENODEV;
 	netdev->phydev = phy;
 
-	netdev_info(netdev, "connected to PHY \"%s\"\n",
-		    phydev_name(phy));
-	phy_attached_print(phy, "phy_id=0x%.8lx, phy_mode=%s\n",
-			   (unsigned long)phy->phy_id,
-			   phy_modes(phy->interface));
-
 	phy->supported &= PHY_GBIT_FEATURES;
 	phy->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;
 	phy->advertising = phy->supported;
@@ -376,19 +378,19 @@ static int gmac_setup_phy(struct net_device *netdev)
 	/* set PHY interface type */
 	switch (phy->interface) {
 	case PHY_INTERFACE_MODE_MII:
-		netdev_info(netdev, "set GMAC0 to GMII mode, GMAC1 disabled\n");
+		netdev_dbg(netdev,
+			   "MII: set GMAC0 to GMII mode, GMAC1 disabled\n");
 		status.bits.mii_rmii = GMAC_PHY_MII;
-		netdev_info(netdev, "connect to MII\n");
 		break;
 	case PHY_INTERFACE_MODE_GMII:
-		netdev_info(netdev, "set GMAC0 to GMII mode, GMAC1 disabled\n");
+		netdev_dbg(netdev,
+			   "GMII: set GMAC0 to GMII mode, GMAC1 disabled\n");
 		status.bits.mii_rmii = GMAC_PHY_GMII;
-		netdev_info(netdev, "connect to GMII\n");
 		break;
 	case PHY_INTERFACE_MODE_RGMII:
-		dev_info(dev, "set GMAC0 and GMAC1 to MII/RGMII mode\n");
+		netdev_dbg(netdev,
+			   "RGMII: set GMAC0 and GMAC1 to MII/RGMII mode\n");
 		status.bits.mii_rmii = GMAC_PHY_RGMII_100_10;
-		netdev_info(netdev, "connect to RGMII\n");
 		break;
 	default:
 		netdev_err(netdev, "Unsupported MII interface\n");
@@ -398,6 +400,9 @@ static int gmac_setup_phy(struct net_device *netdev)
 	}
 	writel(status.bits32, port->gmac_base + GMAC_STATUS);
 
+	if (netif_msg_link(port))
+		phy_attached_info(phy);
+
 	return 0;
 }
 
@@ -1307,8 +1312,8 @@ static void gmac_enable_irq(struct net_device *netdev, int enable)
 	unsigned long flags;
 	u32 val, mask;
 
-	netdev_info(netdev, "%s device %d %s\n", __func__,
-		    netdev->dev_id, enable ? "enable" : "disable");
+	netdev_dbg(netdev, "%s device %d %s\n", __func__,
+		   netdev->dev_id, enable ? "enable" : "disable");
 	spin_lock_irqsave(&geth->irq_lock, flags);
 
 	mask = GMAC0_IRQ0_2 << (netdev->dev_id * 2);
@@ -1813,7 +1818,7 @@ static int gmac_open(struct net_device *netdev)
 		     HRTIMER_MODE_REL);
 	port->rx_coalesce_timer.function = &gmac_coalesce_delay_expired;
 
-	netdev_info(netdev, "opened\n");
+	netdev_dbg(netdev, "opened\n");
 
 	return 0;
 
@@ -2385,6 +2390,7 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
 	port->id = id;
 	port->geth = geth;
 	port->dev = dev;
+	port->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
 	/* DMA memory */
 	dmares = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
2.17.1

^ permalink raw reply related

* [PATCH net-next 1/5 v3] net: gemini: Look up L3 maxlen from table
From: Linus Walleij @ 2018-07-11 19:32 UTC (permalink / raw)
  To: netdev, David S . Miller
  Cc: Hans Ulli Kroll, Florian Fainelli, Michał Mirosław,
	Andrew Lunn, Linus Walleij

The code to calculate the hardware register enumerator
for the maximum L3 length isn't entirely simple to read.
Use the existing defines and rewrite the function into a
table look-up.

Acked-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Collected Michał's ACK.
ChangeLog v1->v2:
- No changes, just resending with the rest.
---
 drivers/net/ethernet/cortina/gemini.c | 61 ++++++++++++++++++++-------
 1 file changed, 46 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 6d7404f66f84..8fc31723f700 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -401,26 +401,57 @@ static int gmac_setup_phy(struct net_device *netdev)
 	return 0;
 }
 
-static int gmac_pick_rx_max_len(int max_l3_len)
-{
-	/* index = CONFIG_MAXLEN_XXX values */
-	static const int max_len[8] = {
-		1536, 1518, 1522, 1542,
-		9212, 10236, 1518, 1518
-	};
-	int i, n = 5;
+/* The maximum frame length is not logically enumerated in the
+ * hardware, so we do a table lookup to find the applicable max
+ * frame length.
+ */
+struct gmac_max_framelen {
+	unsigned int max_l3_len;
+	u8 val;
+};
 
-	max_l3_len += ETH_HLEN + VLAN_HLEN;
+static const struct gmac_max_framelen gmac_maxlens[] = {
+	{
+		.max_l3_len = 1518,
+		.val = CONFIG0_MAXLEN_1518,
+	},
+	{
+		.max_l3_len = 1522,
+		.val = CONFIG0_MAXLEN_1522,
+	},
+	{
+		.max_l3_len = 1536,
+		.val = CONFIG0_MAXLEN_1536,
+	},
+	{
+		.max_l3_len = 1542,
+		.val = CONFIG0_MAXLEN_1542,
+	},
+	{
+		.max_l3_len = 9212,
+		.val = CONFIG0_MAXLEN_9k,
+	},
+	{
+		.max_l3_len = 10236,
+		.val = CONFIG0_MAXLEN_10k,
+	},
+};
+
+static int gmac_pick_rx_max_len(unsigned int max_l3_len)
+{
+	const struct gmac_max_framelen *maxlen;
+	int maxtot;
+	int i;
 
-	if (max_l3_len > max_len[n])
-		return -1;
+	maxtot = max_l3_len + ETH_HLEN + VLAN_HLEN;
 
-	for (i = 0; i < 5; i++) {
-		if (max_len[i] >= max_l3_len && max_len[i] < max_len[n])
-			n = i;
+	for (i = 0; i < ARRAY_SIZE(gmac_maxlens); i++) {
+		maxlen = &gmac_maxlens[i];
+		if (maxtot <= maxlen->max_l3_len)
+			return maxlen->val;
 	}
 
-	return n;
+	return -1;
 }
 
 static int gmac_init(struct net_device *netdev)
-- 
2.17.1

^ permalink raw reply related

* Re: [PATCH v3 net-next] net/sched: add skbprio scheduler
From: Marcelo Ricardo Leitner @ 2018-07-11 19:33 UTC (permalink / raw)
  To: Cong Wang
  Cc: Michel Machado, Nishanth Devarajan, Jamal Hadi Salim, Jiri Pirko,
	David Miller, Linux Kernel Network Developers, Cody Doucette
In-Reply-To: <CAM_iQpW9pqSMZfJsfntZtva8wrfsw8UpQAg0ryumu5pPbgJ2UQ@mail.gmail.com>

On Tue, Jul 10, 2018 at 07:25:53PM -0700, Cong Wang wrote:
> On Mon, Jul 9, 2018 at 2:40 PM Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> >
> > On Mon, Jul 09, 2018 at 05:03:31PM -0400, Michel Machado wrote:
> > >    Changing TC_PRIO_MAX from 15 to 63 risks breaking backward compatibility
> > > with applications.
> >
> > If done, it needs to be done carefully, indeed. I don't know if it's
> > doable, neither I know how hard is your requirement for 64 different
> > priorities.
> 
> struct tc_prio_qopt {
>         int     bands;                  /* Number of bands */
>         __u8    priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
> };
> 
> How would you do it carefully?

quick shot, multiplex v1 and v2 formats based on bands and sizeof():

#define TCQ_PRIO_BANDS_V1	16
#define TCQ_PRIO_BANDS_V2	64
#define TC_PRIO_MAX_V2		64

struct tc_prio_qopt_v2 {
        int     bands;                  /* Number of bands */
        __u8    priomap[TC_PRIO_MAX_V2+1]; /* Map: logical priority -> PRIO band */
};

static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
                     struct netlink_ext_ack *extack)
{
        struct prio_sched_data *q = qdisc_priv(sch);
        struct Qdisc *queues[TCQ_PRIO_BANDS_V2];
        int oldbands = q->bands, i;
        struct tc_prio_qopt_v2 *qopt;

        if (nla_len(opt) < sizeof(int))
                return -EINVAL;
        qopt = nla_data(opt);

	if (qopt->bands <= TCQ_PRIO_BANDS_V1 &&
            nla_len(opt) < sizeof(struct tc_prio_qopt))
                return -EINVAL;

	if (qopt->bands <= TCQ_PRIO_BANDS_V2 &&
            nla_len(opt) < sizeof(*qopt))
                return -EINVAL;

	/* By here, if it has up to 3 bands, we can assume it is using the _v1
	 * layout, while if it has up to TCQ_PRIO_BANDS_V2 it is using the _v2
	 * format.
	 */

        if (qopt->bands > TCQ_PRIO_BANDS_V2 || qopt->bands < 2)
                return -EINVAL;
...

With something like this I think it can keep compatibility with old
software while also allowing the new usage.

> Also, it is not only used by prio but also pfifo_fast.

Yes. More is needed, indeed. prio2band would also need to be expanded,
etc. Yet, I still don't see any blocker.

^ permalink raw reply

* Re: [PATCH net v2] net/mlx5: fix uaccess beyond "count" in debugfs read/write handlers
From: Saeed Mahameed @ 2018-07-11 19:10 UTC (permalink / raw)
  To: jannh@google.com, davem@davemloft.net, leon@kernel.org
  Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-rdma@vger.kernel.org
In-Reply-To: <20180706201809.105152-1-jannh@google.com>

On Fri, 2018-07-06 at 22:18 +0200, Jann Horn wrote:
> In general, accessing userspace memory beyond the length of the
> supplied
> buffer in VFS read/write handlers can lead to both kernel memory
> corruption
> (via kernel_read()/kernel_write(), which can e.g. be triggered via
> sys_splice()) and privilege escalation inside userspace.
> 
> In this case, the affected files are in debugfs (and should therefore
> only
> be accessible to root) and check that *pos is zero (which prevents
> the
> sys_splice() trick). Therefore, this is not a security fix, but
> rather a
> small cleanup.
> 
> For the read handlers, fix it by using simple_read_from_buffer()
> instead of
> custom logic.
> For the write handler, add a check.
> 
> changed in v2:
>  - also fix dbg_write()
> 
> Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB
> adapters")
> Signed-off-by: Jann Horn <jannh@google.com>
> 

Applied to mlx5-next, Thanks!!

^ permalink raw reply

* Re: [PATCH net-next 5/5 v2] net: gemini: Indicate that we can handle jumboframes
From: Linus Walleij @ 2018-07-11 19:10 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: netdev, David S. Miller, Michal Miroslaw, Florian Fainelli,
	Paulius Zaleckas, Hans Ulli Kroll, Janos Laube, Linux ARM
In-Reply-To: <20180704203556.GC23469@lunn.ch>

On Wed, Jul 4, 2018 at 10:35 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Wed, Jul 04, 2018 at 08:33:24PM +0200, Linus Walleij wrote:
> > The hardware supposedly handles frames up to 10236 bytes and
> > implements .ndo_change_mtu() so accept 10236 minus the ethernet
> > header for a VLAN tagged frame on the netdevices. Use
> > ETH_MIN_MTU as minimum MTU.
> >
> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>
> Hi Linus
>
> Did you try with an MTU of 68? Maybe the vendor picked 256 because of
> a hardware limit?

Yeah works fine:

ping -s 68 169.254.1.2
PING 169.254.1.2 (169.254.1.2) 68(96) bytes of data.
76 bytes from 169.254.1.2: icmp_seq=1 ttl=64 time=0.359 ms
76 bytes from 169.254.1.2: icmp_seq=2 ttl=64 time=0.346 ms
76 bytes from 169.254.1.2: icmp_seq=3 ttl=64 time=0.351 ms

This also works fine:

ping -s 9000 169.254.1.2
PING 169.254.1.2 (169.254.1.2) 9000(9028) bytes of data.
9008 bytes from 169.254.1.2: icmp_seq=1 ttl=64 time=1.45 ms
9008 bytes from 169.254.1.2: icmp_seq=2 ttl=64 time=1.68 ms
9008 bytes from 169.254.1.2: icmp_seq=3 ttl=64 time=1.55 ms

I'll send new patches with all suggested changes soon :)

Thanks a lot for your help!

Yours,
Linus Walleij

^ permalink raw reply

* Re: [net-next PATCH] net: ipv4: fix listify ip_rcv_finish in case of forwarding
From: Saeed Mahameed @ 2018-07-11 19:05 UTC (permalink / raw)
  To: ecree@solarflare.com, netdev@vger.kernel.org, brouer@redhat.com
In-Reply-To: <153132125549.13161.16380200872856218805.stgit@firesoul>

On Wed, 2018-07-11 at 17:01 +0200, Jesper Dangaard Brouer wrote:
> Only driver sfc actually uses this, but I don't have this NIC, so I
> tested this on mlx5, with my own changes to make it use
> netif_receive_skb_list(),
> but I'm not ready to upstream the mlx5 driver change yet.


Thanks Jesper for sharing this, should we look forward to those patches
or do you want us to implement them ?

Thanks,
Saeed.

^ permalink raw reply

* Re: [PATCH bpf-next v4 2/3] bpf: btf: add btf print functionality
From: Jakub Kicinski @ 2018-07-11 19:10 UTC (permalink / raw)
  To: Okash Khawaja
  Cc: Daniel Borkmann, Martin KaFai Lau, Alexei Starovoitov,
	Yonghong Song, Quentin Monnet, David S. Miller, netdev,
	kernel-team, linux-kernel
In-Reply-To: <20180711032557.728015225@fb.com>

Thank you for all the changes made so far.

On Tue, 10 Jul 2018 20:21:10 -0700, Okash Khawaja wrote:
> --- /dev/null
> +++ b/tools/bpf/bpftool/btf_dumper.c
> @@ -0,0 +1,248 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2018 Facebook */
> +
> +#include <linux/btf.h>
> +#include <linux/err.h>
> +#include <stdio.h> /* for (FILE *) used by json_writer */
> +#include <linux/bitops.h>
> +#include <string.h>
> +#include <ctype.h>

Again, please sort the headers the way I suggested.  Otherwise as the
list of includes grows it's hard to know what's already there.

> +#include "btf.h"
> +#include "json_writer.h"
> +#include "main.h"
> +
> +#define BITS_PER_BYTE_MASK (BITS_PER_BYTE - 1)
> +#define BITS_PER_BYTE_MASKED(bits) ((bits) & BITS_PER_BYTE_MASK)
> +#define BITS_ROUNDDOWN_BYTES(bits) ((bits) >> 3)
> +#define BITS_ROUNDUP_BYTES(bits) \
> +	(BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits))
> +
> +static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
> +			      __u8 bit_offset, const void *data);
> +
> +static void btf_dumper_ptr(const void *data, json_writer_t *jw,
> +			   bool is_plain_text)
> +{
> +	if (is_plain_text)
> +		jsonw_printf(jw, "%p", *((unsigned long *)data));
> +	else
> +		jsonw_printf(jw, "%u", *((unsigned long *)data));

Again, please drop the extraneous parens. 

> +}
> +

> +static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
> +				const void *data, json_writer_t *jw,
> +				bool is_plain_text)
> +{
> +	int left_shift_bits, right_shift_bits;
> +	int nr_bits = BTF_INT_BITS(int_type);
> +	int total_bits_offset;
> +	int bytes_to_copy;
> +	int bits_to_copy;
> +	__u64 print_num;
> +
> +	total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
> +	data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
> +	bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
> +	bits_to_copy = bit_offset + nr_bits;
> +	bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
> +
> +	print_num = 0;
> +	memcpy(&print_num, data, bytes_to_copy);
> +#ifdef __BIG_ENDIAN_BITFIELD
> +	left_shift_bits = bit_offset;
> +#else
> +	left_shift_bits = 64 - bits_to_copy;
> +#endif
> +	right_shift_bits = 64 - nr_bits;

Please include <asm/byteorder.h> as I suggested to you previously.
This is dead code right now, look:

$ git diff
diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index c64465094b92..045add07b721 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -91,7 +91,8 @@ static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
 
        print_num = 0;
        memcpy(&print_num, data, bytes_to_copy);
-#ifdef __BIG_ENDIAN_BITFIELD
+#ifndef __LITTLE_ENDIAN_BITFIELD
+#error "abc"
        left_shift_bits = bit_offset;
 #else
        left_shift_bits = 64 - bits_to_copy;

$ make -C tools/bpf/bpftool/ CC=gcc-8
make: Entering directory '/home/jkicinski/devel/linux/tools/bpf/bpftool'
  CC       btf_dumper.o
btf_dumper.c: In function ‘btf_dumper_int_bits’:
btf_dumper.c:95:2: error: #error "abc"
 #error "abc"
  ^~~~~
Makefile:96: recipe for target 'btf_dumper.o' failed
make: *** [btf_dumper.o] Error 1
make: Leaving directory '/home/jkicinski/devel/linux/tools/bpf/bpftool'

^ permalink raw reply related

* Re: [PATCH net-next v2 04/11] devlink: Add support for region get command
From: Jakub Kicinski @ 2018-07-11 18:52 UTC (permalink / raw)
  To: Alex Vesker; +Cc: netdev, jiri, dsahern, andrew, rahul.lakkireddy
In-Reply-To: <1531305788-29420-5-git-send-email-valex@mellanox.com>

On Wed, 11 Jul 2018 13:43:01 +0300, Alex Vesker wrote:
> +	DEVLINK_ATTR_REGION_SIZE,               /* u32 */

> +	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
> +				region->size,
> +				DEVLINK_ATTR_PAD);

Size in the comment looks incorrect.

^ permalink raw reply

* Re: [PATCH net-next v2 00/11] devlink: Add support for region access
From: Jakub Kicinski @ 2018-07-11 18:48 UTC (permalink / raw)
  To: Alex Vesker
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, jiri-VPRAkNaXOzVWk0Htik3J/w,
	dsahern-Re5JQEeQqe8AvxtiuMwx3w, andrew-g2DYL2Zd6BY,
	rahul.lakkireddy-ut6Up61K2wZBDgjK7y7TUQ,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA, Johannes Berg
In-Reply-To: <1531305788-29420-1-git-send-email-valex-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

CC: linux-wireless, wifi chips used to have similar problem

On Wed, 11 Jul 2018 13:42:57 +0300, Alex Vesker wrote:
> This is a proposal which will allow access to driver defined address
> regions using devlink. Each device can create its supported address
> regions and register them. A device which exposes a region will allow
> access to it using devlink.
> 
> The suggested implementation will allow exposing regions to the user,
> reading and dumping snapshots taken from different regions. 
> A snapshot represents a memory image of a region taken by the driver.
> 
> If a device collects a snapshot of an address region it can be later
> exposed using devlink region read or dump commands.
> This functionality allows for future analyses on the snapshots to be
> done.
> 
> The major benefit of this support is not only to provide access to
> internal address regions which were inaccessible to the user but also
> to provide an additional way to debug complex error states using the
> region snapshots.
> 
> Implemented commands:
> $ devlink region help
> $ devlink region show [ DEV/REGION ]
> $ devlink region del DEV/REGION snapshot SNAPSHOT_ID
> $ devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]
> $ devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ]
> 	address ADDRESS length length

You got me excited with the read without snapshot but then you say below
that it's future work :)

> Show all of the exposed regions with region sizes:
> $ devlink region show
> pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2]
> pci/0000:00:05.0/fw-health: size 64 snapshot [1 2]
> 
> Delete a snapshot using:
> $ devlink region del pci/0000:00:05.0/cr-space snapshot 1
> 
> Dump a snapshot:
> $ devlink region dump pci/0000:00:05.0/fw-health snapshot 1
> 0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
> 0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8
> 0000000000000020 0016 0bb8 0016 1720 0000 0000 c00f 3ffc
> 0000000000000030 bada cce5 bada cce5 bada cce5 bada cce5
> 
> Read a specific part of a snapshot:
> $ devlink region read pci/0000:00:05.0/fw-health snapshot 1 address 0 
> 	length 16
> 0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
> 
> For more information you can check devlink-region.8 man page
> 
> Future:
> There is a plan to extend the support to include a write command
> as well as performing read and dump live region

Reading live region would be very interesting and alleviate the need
for complicated ethtool dump marshalling a number of drivers started
doing (incl. nfp).  Any plans on that?

Write support I'm less excited about :)

^ permalink raw reply

* Re: [PATCH v3 net-next] net/sched: add skbprio scheduler
From: Marcelo Ricardo Leitner @ 2018-07-11 18:37 UTC (permalink / raw)
  To: Cong Wang
  Cc: Michel Machado, Nishanth Devarajan, Jamal Hadi Salim, Jiri Pirko,
	David Miller, Linux Kernel Network Developers, Cody Doucette
In-Reply-To: <CAM_iQpUzkSdCzxCH5VxNEN=OyXNOXeiFUNGD-XwrbNptxyRkNA@mail.gmail.com>

On Tue, Jul 10, 2018 at 07:32:43PM -0700, Cong Wang wrote:
> On Mon, Jul 9, 2018 at 12:53 PM Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> >
> > On Mon, Jul 09, 2018 at 02:18:33PM -0400, Michel Machado wrote:
> > >
> > >    2. sch_prio.c does not have a global limit on the number of packets on
> > > all its queues, only a limit per queue.
> >
> > It can be useful to sch_prio.c as well, why not?
> > prio_enqueue()
> > {
> > ...
> > +       if (count > sch->global_limit)
> > +               prio_tail_drop(sch);   /* to be implemented */
> >         ret = qdisc_enqueue(skb, qdisc, to_free);
> >
> 
> Isn't the whole point of sch_prio offloading the queueing to
> each class? If you need a limit, there is one for each child
> qdisc if you use for example pfifo or bfifo (depending on you
> want to limit bytes or packets).

Yes, but Michel wants to drop from other lower priorities if needed,
and that's not possible if you handle the limit already in a child
qdisc as they don't know about their siblings. The idea in the example
above is to discard it from whatever lower priority is needed, then
queue it. (ok, the example missed to check the priority level)

As for the different units, sch_prio holds a count of how many packets
are queued on its children, and that's what would be used for the limit.

> 
> Also, what's your plan for backward compatibility here?

say:
  if (sch->global_limit && count > sch->global_limit)
as in, only do the limit check/enforcing if needed.

^ permalink raw reply

* Re: [PATCH] [v3] infiniband: i40iw, nes: don't use wall time for TCP sequence numbers
From: Jason Gunthorpe @ 2018-07-11 18:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Faisal Latif, Shiraz Saleem, Doug Ledford, David S. Miller,
	Geert Uytterhoeven, Yuval Shaia, Henry Orosco, Tatyana Nikolova,
	Mustafa Ismail, Jia-Ju Bai, Bart Van Assche, linux-rdma,
	linux-kernel, netdev
In-Reply-To: <20180709083523.448587-1-arnd@arndb.de>

On Mon, Jul 09, 2018 at 10:34:43AM +0200, Arnd Bergmann wrote:
> The nes infiniband driver uses current_kernel_time() to get a nanosecond
> granunarity timestamp to initialize its tcp sequence counters. This is
> one of only a few remaining users of that deprecated function, so we
> should try to get rid of it.
> 
> Aside from using a deprecated API, there are several problems I see here:
> 
> - Using a CLOCK_REALTIME based time source makes it predictable in
>   case the time base is synchronized.
> - Using a coarse timestamp means it only gets updated once per jiffie,
>   making it even more predictable in order to avoid having to access
>   the hardware clock source
> - The upper 2 bits are always zero because the nanoseconds are at most
>   999999999.
> 
> For the Linux TCP implementation, we use secure_tcp_seq(), which appears
> to be appropriate here as well, and solves all the above problems.
> 
> i40iw uses a variant of the same code, so I do that same thing there
> for ipv4. Unlike nes, i40e also supports ipv6, which needs to call
> secure_tcpv6_seq instead.
> 
> Acked-by: Shiraz Saleem <shiraz.saleem@intel.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> v2: use secure_tcpv6_seq for IPv6 support as suggested by Shiraz Saleem.
> v3: add a soft IPv6 dependency to prevent a link error with CONFIG_IPV6=m,
>     this now forces i40iw to be a module as well, add an IS_ENABLED()
>     check to avoid calling it when IPV6 is completely disabled.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/infiniband/hw/i40iw/Kconfig    |  1 +
>  drivers/infiniband/hw/i40iw/i40iw_cm.c | 26 +++++++++++++++++++++-----
>  drivers/infiniband/hw/nes/nes_cm.c     |  8 +++++---
>  net/core/secure_seq.c                  |  1 +
>  4 files changed, 28 insertions(+), 8 deletions(-)

Applied to for-next thanks

Jason

^ permalink raw reply

* [PATCH] of: mdio: Support fixed links in of_phy_get_and_connect()
From: Linus Walleij @ 2018-07-11 17:45 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, David S . Miller
  Cc: netdev, Laurent Pinchart, Linus Walleij

By a simple extension of of_phy_get_and_connect() drivers
that have a fixed link on e.g. RGMII can support also
fixed links, so in addition to:

ethernet-port {
	phy-mode = "rgmii";
	phy-handle = <&foo>;
};

This setup with a fixed-link node and no phy-handle will
now also work just fine:

ethernet-port {
	phy-mode = "rgmii";
	fixed-link {
		speed = <1000>;
		full-duplex;
		pause;
	};
};

This is very helpful for connecting random ethernet ports
to e.g. DSA switches that typically reside on fixed links.

The phy-mode is still there as the fixes link in this case
is still an RGMII link.

Tested on the Cortina Gemini driver with the Vitesse DSA
router chip on a fixed 1Gbit link.

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/of/of_mdio.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index d963baf8e53a..e92391d6d1bd 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -367,14 +367,23 @@ struct phy_device *of_phy_get_and_connect(struct net_device *dev,
 	phy_interface_t iface;
 	struct device_node *phy_np;
 	struct phy_device *phy;
+	int ret;
 
 	iface = of_get_phy_mode(np);
 	if (iface < 0)
 		return NULL;
-
-	phy_np = of_parse_phandle(np, "phy-handle", 0);
-	if (!phy_np)
-		return NULL;
+	if (of_phy_is_fixed_link(np)) {
+		ret = of_phy_register_fixed_link(np);
+		if (ret < 0) {
+			netdev_err(dev, "broken fixed-link specification\n");
+			return NULL;
+		}
+		phy_np = of_node_get(np);
+	} else {
+		phy_np = of_parse_phandle(np, "phy-handle", 0);
+		if (!phy_np)
+			return NULL;
+	}
 
 	phy = of_phy_connect(dev, phy_np, hndlr, 0, iface);
 
-- 
2.17.1

^ permalink raw reply related

* [PATCH net v2] KEYS: DNS: fix parsing multiple options
From: Eric Biggers @ 2018-07-11 17:46 UTC (permalink / raw)
  To: netdev, David S . Miller; +Cc: keyrings, David Howells, Wang Lei, Eric Biggers

From: Eric Biggers <ebiggers@google.com>

My recent fix for dns_resolver_preparse() printing very long strings was
incomplete, as shown by syzbot which still managed to hit the
WARN_ONCE() in set_precision() by adding a crafted "dns_resolver" key:

    precision 50001 too large
    WARNING: CPU: 7 PID: 864 at lib/vsprintf.c:2164 vsnprintf+0x48a/0x5a0

The bug this time isn't just a printing bug, but also a logical error
when multiple options ("#"-separated strings) are given in the key
payload.  Specifically, when separating an option string into name and
value, if there is no value then the name is incorrectly considered to
end at the end of the key payload, rather than the end of the current
option.  This bypasses validation of the option length, and also means
that specifying multiple options is broken -- which presumably has gone
unnoticed as there is currently only one valid option anyway.

A similar problem also applied to option values, as the kstrtoul() when
parsing the "dnserror" option will read past the end of the current
option and into the next option.

Fix these bugs by correctly computing the length of the option name and
by copying the option value, null-terminated, into a temporary buffer.

Reproducer for the WARN_ONCE() that syzbot hit:

    perl -e 'print "#A#", "\0" x 50000' | keyctl padd dns_resolver desc @s

Reproducer for "dnserror" option being parsed incorrectly (expected
behavior is to fail when seeing the unknown option "foo", actual
behavior was to read the dnserror value as "1#foo" and fail there):

    perl -e 'print "#dnserror=1#foo\0"' | keyctl padd dns_resolver desc @s

Reported-by: syzbot <syzkaller@googlegroups.com>
Fixes: 4a2d789267e0 ("DNS: If the DNS server returns an error, allow that to be cached [ver #2]")
Signed-off-by: Eric Biggers <ebiggers@google.com>
---

Changed since v1:
    - Also fix parsing the option values, not just option names.

 net/dns_resolver/dns_key.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index 40c851693f77..0c9478b91fa5 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -86,35 +86,39 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
 		opt++;
 		kdebug("options: '%s'", opt);
 		do {
+			int opt_len, opt_nlen;
 			const char *eq;
-			int opt_len, opt_nlen, opt_vlen, tmp;
+			char optval[128];
 
 			next_opt = memchr(opt, '#', end - opt) ?: end;
 			opt_len = next_opt - opt;
-			if (opt_len <= 0 || opt_len > 128) {
+			if (opt_len <= 0 || opt_len > sizeof(optval)) {
 				pr_warn_ratelimited("Invalid option length (%d) for dns_resolver key\n",
 						    opt_len);
 				return -EINVAL;
 			}
 
-			eq = memchr(opt, '=', opt_len) ?: end;
-			opt_nlen = eq - opt;
-			eq++;
-			opt_vlen = next_opt - eq; /* will be -1 if no value */
+			eq = memchr(opt, '=', opt_len);
+			if (eq) {
+				opt_nlen = eq - opt;
+				eq++;
+				memcpy(optval, eq, next_opt - eq);
+				optval[next_opt - eq] = '\0';
+			} else {
+				opt_nlen = opt_len;
+				optval[0] = '\0';
+			}
 
-			tmp = opt_vlen >= 0 ? opt_vlen : 0;
-			kdebug("option '%*.*s' val '%*.*s'",
-			       opt_nlen, opt_nlen, opt, tmp, tmp, eq);
+			kdebug("option '%*.*s' val '%s'",
+			       opt_nlen, opt_nlen, opt, optval);
 
 			/* see if it's an error number representing a DNS error
 			 * that's to be recorded as the result in this key */
 			if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 &&
 			    memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) {
 				kdebug("dns error number option");
-				if (opt_vlen <= 0)
-					goto bad_option_value;
 
-				ret = kstrtoul(eq, 10, &derrno);
+				ret = kstrtoul(optval, 10, &derrno);
 				if (ret < 0)
 					goto bad_option_value;
 
-- 
2.18.0.203.gfac676dfb9-goog

^ permalink raw reply related

* Re: [PATCH net-next 1/2] tcp: remove redundant rcv_nxt update
From: Eric Dumazet @ 2018-07-11 17:01 UTC (permalink / raw)
  To: Yafang Shao, davem, edumazet; +Cc: netdev, linux-kernel, shaoyafang
In-Reply-To: <1531315019-3553-1-git-send-email-laoar.shao@gmail.com>



On 07/11/2018 06:16 AM, Yafang Shao wrote:
> tcp_rcv_nxt_update() is already executed in tcp_data_queue().
> This line is redundant.
> 
> See bellow,
> 	tcp_queue_rcv
> 		tcp_rcv_nxt_update(tcp_sk(sk), TCP_SKB_CB(skb)->end_seq);
> 	tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq); <<<< redundant
> 
> Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> ---

This patch is fine (but not the following)

Signed-off-by: Eric Dumazet <edumazet@google.com>

Thanks.

^ permalink raw reply

* Re: [PATCH v2 0/5] can: enable multi-queue for SocketCAN devices
From: Jonas Mark (BT-FIR/ENG1) @ 2018-07-11 17:00 UTC (permalink / raw)
  To: Jonas Mark (BT-FIR/ENG1), Wolfgang Grandegger, Marc Kleine-Budde
  Cc: linux-can@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, hs@denx.de,
	ZHU Yi (BT-FIR/ENG1-Zhu), Petrovic Petar (CM-CI1/ENP1),
	Baetge Stephan (CM-CI1/ENP1), andy.shevchenko@gmail.com,
	socketcan@hartkopp.net, o.rempel@pengutronix.de,
	Jonas Mark (BT-FIR/ENG1)

Hi Marc,

> Betreff: [PATCH v2 0/5] can: enable multi-queue for SocketCAN devices

You have been interested in seeing the reason why we are proposing the
"can: enable multi-queue for SocketCAN devices" patch for the Linux
mainline. So far I have not heard from you. Do you now see a chance of
getting the patch accepted?

> 
> Changes in v2:
> - use GPIO descriptor API
> - make error handling pattern consistent
> - use more kernel helper macros and functions
> - fix coding style issues
> - remove superfluous subsystem name from filename
> 
> ---
> 
> Upon request by Marc Kleine-Budde this patch series does not only
> contain our patch to enable enable multi-queue for SocketCAN devices
> but also a driver (Companion driver suite) which makes active use of
> this feature.
> 
> The driver suite implements
>   - two CAN interfaces
>   - one generic command interfaces
> and offers a SocketCAN as well as a char device interface. The
> SocketCAN interface supports multi-queue.
> 
> The functionality bases on an external peripheral chip named Companion.
> It offers two CAN interfaces, each has 8 prioritized transmit FIFOs as
> well as one receive FIFO. Besides CAN, undisclosed additional functions
> can be accessed through the char device.
> 
> A standard SPI interface with two additional lines for flow control is
> used. The Companion chip is the SPI slave.
> 
> The driver suite consists of three separate drivers. The following
> diagram illustrates the dependencies in layers.
> 
>            /dev/companion       SocketCAN                User Space
> -------------------------------------------------------------------
>          +----------------+ +---------------+
>          | companion-char | | companion-can |
>          +----------------+ +---------------+
>          +----------------------------------+
>          |          companion-spi           |
>          +----------------------------------+
>          +----------------------------------+
>          |     standard SPI subsystem       |
>          +----------------------------------+          Linux Kernel
> -------------------------------------------------------------------
>                | | | |      | |                            Hardware
>             CS-+ | | |      | +-BUSY
>             CLK--+ | |      +---REQUEST
>             MOSI---+ |
>             MISO-----+
> 
> companion-spi
>    core.c: handles SPI, sysfs entry and interface to upper layer
>    protocol-manager.c: handles protocol with the SPI HW
>    queue-manager.c: handles buffering and packets scheduling
> 
> companion-can
>    makes use of multi-queue support and allows to use tc to configure
>    the queuing discipline (e.g. mqprio). Together with the SO_PRIORITY
>    socket option this allows to specify the FIFO a CAN frame shall be
>    sent to.
> 
> companion-char
>    handles messages to other undisclosed functionality beyond CAN.
> 
> Zhu Yi (5):
>   can: enable multi-queue for SocketCAN devices
>   spi: implement companion-spi driver
>   char: implement companion-char driver
>   can: implement companion-can driver
>   spi,can,char: add companion DT binding documentation
> 
>  .../devicetree/bindings/spi/bosch,companion.txt    |   82 ++
>  drivers/char/Kconfig                               |    7 +
>  drivers/char/Makefile                              |    3 +
>  drivers/char/companion.c                           |  360 ++++++
>  drivers/net/can/Kconfig                            |    8 +
>  drivers/net/can/Makefile                           |    2 +
>  drivers/net/can/companion.c                        |  693 ++++++++++++
>  drivers/net/can/dev.c                              |    8 +-
>  drivers/spi/Kconfig                                |    2 +
>  drivers/spi/Makefile                               |    2 +
>  drivers/spi/companion/Kconfig                      |    5 +
>  drivers/spi/companion/Makefile                     |    2 +
>  drivers/spi/companion/core.c                       | 1185 ++++++++++++++++++++
>  drivers/spi/companion/protocol-manager.c           | 1032 +++++++++++++++++
>  drivers/spi/companion/protocol-manager.h           |  341 ++++++
>  drivers/spi/companion/protocol.h                   |  273 +++++
>  drivers/spi/companion/queue-manager.c              |  144 +++
>  drivers/spi/companion/queue-manager.h              |  245 ++++
>  include/linux/can/dev.h                            |    7 +-
>  include/linux/companion.h                          |  259 +++++
>  20 files changed, 4656 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/spi/bosch,companion.txt
>  create mode 100644 drivers/char/companion.c
>  create mode 100644 drivers/net/can/companion.c
>  create mode 100644 drivers/spi/companion/Kconfig
>  create mode 100644 drivers/spi/companion/Makefile
>  create mode 100644 drivers/spi/companion/core.c
>  create mode 100644 drivers/spi/companion/protocol-manager.c
>  create mode 100644 drivers/spi/companion/protocol-manager.h
>  create mode 100644 drivers/spi/companion/protocol.h
>  create mode 100644 drivers/spi/companion/queue-manager.c
>  create mode 100644 drivers/spi/companion/queue-manager.h
>  create mode 100644 include/linux/companion.h
> 
> --
> 2.7.4

Greetings,
Mark

Building Technologies, Panel Software Fire (BT-FIR/ENG1) 
Bosch Sicherheitssysteme GmbH | Postfach 11 11 | 85626 Grasbrunn | GERMANY | www.boschsecurity.com

Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart HRB 23118 
Aufsichtsratsvorsitzender: Stefan Hartung; Geschäftsführung: Gert van Iperen, Andreas Bartz, Thomas Quante, Bernhard Schuster

^ permalink raw reply

* Re: general protection fault in in_aton
From: Dmitry Vyukov @ 2018-07-11 16:47 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: syzbot+2a831e062bb4aebd8755, Eric Van Hensbergen, Ron Minnich,
	Latchesar Ionkov, Jens Axboe, Bart Van Assche, David Miller,
	Linux Kernel Mailing List, Network Development, Sagi Grimberg,
	syzkaller-bugs, kasan-dev
In-Reply-To: <CA+55aFz1GVHUGiX1SE_5C-e9LdXdx3pBB10zwga1LOy6axk5Ww@mail.gmail.com>

On Tue, Jul 10, 2018 at 10:15 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Tue, Jul 10, 2018 at 12:57 PM Dmitry Vyukov <dvyukov@google.com> wrote:
>>
>> Is it really hard to get fault address? I know that userspace
>> generally receives fault address in siginfo.
>
> For an actual page fault it's trivial.
>
> However, for invalid addresses (aka "non-canonical"), you don't even
> get a page fault, you get a GP like in this case. And then the actual
> address is not available.


I see. Then I don't have any great ideas. Running without KASAN would
result in more, much more cryptic crashes.

FWIW for these "GPF could be caused by NULL-ptr deref" I first just
assume that it's in fact a NULL deref. And in this case it all pretty
quickly forms a consistent picture that it's indeed just a missing a
NULL pointer check. That dffffc0000000000 in a register also a good
hint.

^ permalink raw reply

* Re: KASAN: use-after-free Read in ipv6_gso_pull_exthdrs
From: Willem de Bruijn @ 2018-07-11 16:08 UTC (permalink / raw)
  To: Jiri Benc
  Cc: syzbot+7b9ed9872dab8c32305d, David Miller, Alexey Kuznetsov, LKML,
	Network Development, syzkaller-bugs, Hideaki YOSHIFUJI
In-Reply-To: <20180711120753.6940b66d@redhat.com>

On Wed, Jul 11, 2018 at 6:07 AM Jiri Benc <jbenc@redhat.com> wrote:
>
> Sorry for the delayed reply, I'm working through a pile of stuff after
> being off.
>
> On Sun, 8 Jul 2018 18:58:14 -0400, Willem de Bruijn wrote:
> > Setting skb->mac_len to 0, similar to mpls_gs_segment,
> > is sufficient if the encapsulated packet is not ETH_P_TEB.
> >
> > If the packet is encapsulated at L2, __skb_pull(skb, vlan_depth)
> > has to pull the inner mac header before passing to l3 handlers like
> > inet_gso_segment.
> >
> > If that header includes VLAN tags, skb_network_protocol will
> > parse then and update the mac length in vlan_depth. So
> > hardcoding to ETH_HLEN should be fine:
> >
> > @@ -104,7 +95,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
> >         __skb_pull(skb, nsh_len);
> >
> >         skb_reset_mac_header(skb);
> > -       skb_reset_mac_len(skb);
> > +       skb->mac_len = proto == ETH_P_TEB ? ETH_HLEN : 0;
> >         skb->protocol = proto;
> >
> >         features &= NETIF_F_SG;
>
> I agree. I think my original intention was to set mac_len to 0. Which
> is obviously not done by calling skb_reset_mac_len...
>
> Strangely, skb_network_protocol does not set *depth to ETH_HLEN if it
> is 0 and the type is ETH_P_TEB, which is something I would expect it to
> do. Thus we indeed have to differentiate between the two cases before
> calling skb_mac_gso_segment.
>
> Willem, will you send the patch formally (with the htons fix)? Thanks a
> lot for the analysis and the patch!

Thanks for verifying, Jiri.

Posted as http://patchwork.ozlabs.org/patch/942588/. I forgot to cc:
you directly in git send-email, sorry.

^ permalink raw reply

* [PATCH net] selftests: in udpgso_bench do not test udp zerocopy
From: Willem de Bruijn @ 2018-07-11 16:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, Willem de Bruijn
In-Reply-To: <20180711160046.198091-1-willemdebruijn.kernel@gmail.com>

From: Willem de Bruijn <willemb@google.com>

The udpgso benchmark compares various configurations of UDP and TCP.
Including one that is not upstream, udp zerocopy. This is a leftover
from the earlier RFC patchset.

The test is part of kselftests and run in continuous spinners. Remove
the failing case to make the test start passing.

Fixes: 3a687bef148d ("selftests: udp gso benchmark")
Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
 tools/testing/selftests/net/udpgso_bench.sh | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/tools/testing/selftests/net/udpgso_bench.sh b/tools/testing/selftests/net/udpgso_bench.sh
index 792fa4d0285e..850767befa47 100755
--- a/tools/testing/selftests/net/udpgso_bench.sh
+++ b/tools/testing/selftests/net/udpgso_bench.sh
@@ -35,9 +35,6 @@ run_udp() {
 
 	echo "udp gso"
 	run_in_netns ${args} -S
-
-	echo "udp gso zerocopy"
-	run_in_netns ${args} -S -z
 }
 
 run_tcp() {
-- 
2.18.0.203.gfac676dfb9-goog

^ permalink raw reply related

* [PATCH net] packet: reset network header if packet shorter than ll reserved space
From: Willem de Bruijn @ 2018-07-11 16:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, Willem de Bruijn
In-Reply-To: <20180711160046.198091-1-willemdebruijn.kernel@gmail.com>

From: Willem de Bruijn <willemb@google.com>

If variable length link layer headers result in a packet shorter
than dev->hard_header_len, reset the network header offset. Else
skb->mac_len may exceed skb->len after skb_mac_reset_len.

packet_sendmsg_spkt already has similar logic.

Fixes: b84bbaf7a6c8 ("packet: in packet_snd start writing at link layer allocation")
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
 net/packet/af_packet.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 57634bc3da74..9b27d0cd766d 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2878,6 +2878,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 			goto out_free;
 	} else if (reserve) {
 		skb_reserve(skb, -reserve);
+		if (len < reserve)
+			skb_reset_network_header(skb);
 	}
 
 	/* Returns -EFAULT on error */
-- 
2.18.0.203.gfac676dfb9-goog

^ permalink raw reply related

* [PATCH net] nsh: set mac len based on inner packet
From: Willem de Bruijn @ 2018-07-11 16:00 UTC (permalink / raw)
  To: netdev; +Cc: davem, Willem de Bruijn

From: Willem de Bruijn <willemb@google.com>

When pulling the NSH header in nsh_gso_segment, set the mac length
based on the encapsulated packet type.

skb_reset_mac_len computes an offset to the network header, which
here still points to the outer packet:

  >     skb_reset_network_header(skb);
  >     [...]
  >     __skb_pull(skb, nsh_len);
  >     skb_reset_mac_header(skb);    // now mac hdr starts nsh_len == 8B after net hdr
  >     skb_reset_mac_len(skb);       // mac len = net hdr - mac hdr == (u16) -8 == 65528
  >     [..]
  >     skb_mac_gso_segment(skb, ..)

Link: http://lkml.kernel.org/r/CAF=yD-KeAcTSOn4AxirAxL8m7QAS8GBBe1w09eziYwvPbbUeYA@mail.gmail.com
Reported-by: syzbot+7b9ed9872dab8c32305d@syzkaller.appspotmail.com
Fixes: c411ed854584 ("nsh: add GSO support")
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
 net/nsh/nsh.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
index 9696ef96b719..1a30e165eeb4 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -104,7 +104,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
 	__skb_pull(skb, nsh_len);
 
 	skb_reset_mac_header(skb);
-	skb_reset_mac_len(skb);
+	skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0;
 	skb->protocol = proto;
 
 	features &= NETIF_F_SG;
-- 
2.18.0.203.gfac676dfb9-goog

^ permalink raw reply related

* [PATCH net-next 10/10] s390/qeth: speed-up IPv4 OSA xmit
From: Julian Wiedmann @ 2018-07-11 15:42 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, linux-s390, Martin Schwidefsky, Heiko Carstens,
	Stefan Raspl, Ursula Braun, Julian Wiedmann
In-Reply-To: <20180711154247.5523-1-jwi@linux.ibm.com>

Move the xmit of offload-eligible (ie IPv4) traffic on OSA over to the
new, copy-free path.
As with L2, we'll need to preserve the skb_orphan() behaviour of the
old code path until TX completion is sufficiently fast.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
---
 drivers/s390/net/qeth_l3_main.c | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 0863ffa9ab59..062f62b49294 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2050,6 +2050,12 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
 		hdr->hdr.l3.vlan_id = skb_vlan_tag_get(skb);
 	}
 
+	if (!skb_is_gso(skb) && skb->ip_summed == CHECKSUM_PARTIAL) {
+		qeth_tx_csum(skb, &hdr->hdr.l3.ext_flags, ipv);
+		if (card->options.performance_stats)
+			card->perf_stats.tx_csum++;
+	}
+
 	/* OSA only: */
 	if (!ipv) {
 		hdr->hdr.l3.flags = QETH_HDR_PASSTHRU;
@@ -2164,8 +2170,8 @@ static int qeth_l3_xmit_offload(struct qeth_card *card, struct sk_buff *skb,
 	unsigned char eth_hdr[ETH_HLEN];
 	unsigned int hdr_elements = 0;
 	struct qeth_hdr *hdr = NULL;
+	int elements, push_len, rc;
 	unsigned int hd_len = 0;
-	int push_len, rc;
 
 	/* compress skb to fit into one IO buffer: */
 	if (!qeth_get_elements_no(card, skb, 0, 0)) {
@@ -2199,17 +2205,26 @@ static int qeth_l3_xmit_offload(struct qeth_card *card, struct sk_buff *skb,
 		hdr_elements = 1;
 	}
 
-	if (!qeth_get_elements_no(card, skb, hdr_elements, 0)) {
+	elements = qeth_get_elements_no(card, skb, hdr_elements, 0);
+	if (!elements) {
 		rc = -E2BIG;
 		goto out;
 	}
+	elements += hdr_elements;
 
 	if (skb->protocol == htons(ETH_P_AF_IUCV))
 		qeth_l3_fill_af_iucv_hdr(hdr, skb, frame_len);
 	else
 		qeth_l3_fill_header(card, hdr, skb, ipv, cast_type, frame_len);
 
-	rc = qeth_do_send_packet_fast(queue, skb, hdr, 0, hd_len);
+	if (IS_IQD(card)) {
+		rc = qeth_do_send_packet_fast(queue, skb, hdr, 0, hd_len);
+	} else {
+		/* TODO: drop skb_orphan() once TX completion is fast enough */
+		skb_orphan(skb);
+		rc = qeth_do_send_packet(card, queue, skb, hdr, 0, hd_len,
+					 elements);
+	}
 out:
 	if (!rc) {
 		if (card->options.performance_stats && nr_frags) {
@@ -2295,12 +2310,6 @@ static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
 		hdr = skb_push(new_skb, sizeof(struct qeth_hdr));
 		qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type,
 				    new_skb->len - sizeof(struct qeth_hdr));
-
-		if (new_skb->ip_summed == CHECKSUM_PARTIAL) {
-			qeth_tx_csum(new_skb, &hdr->hdr.l3.ext_flags, ipv);
-			if (card->options.performance_stats)
-				card->perf_stats.tx_csum++;
-		}
 	}
 
 	elements = use_tso ?
@@ -2384,7 +2393,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
 	}
 	netif_stop_queue(dev);
 
-	if (IS_IQD(card))
+	if (IS_IQD(card) || (!skb_is_gso(skb) && ipv == 4))
 		rc = qeth_l3_xmit_offload(card, skb, queue, ipv, cast_type);
 	else
 		rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type);
@@ -2563,9 +2572,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		if (!card->dev)
 			return -ENODEV;
 		card->dev->flags |= IFF_NOARP;
-		card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 		card->dev->netdev_ops = &qeth_l3_netdev_ops;
-		card->dev->needed_headroom = sizeof(struct qeth_hdr) - ETH_HLEN;
 
 		rc = qeth_l3_iqd_read_initial_mac(card);
 		if (rc)
@@ -2582,6 +2589,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 	card->dev->max_mtu = ETH_MAX_MTU;
 	card->dev->dev_port = card->info.portno;
 	card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
+	card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+	card->dev->needed_headroom = sizeof(struct qeth_hdr) - ETH_HLEN;
 	card->dev->features |=	NETIF_F_HW_VLAN_CTAG_TX |
 				NETIF_F_HW_VLAN_CTAG_RX |
 				NETIF_F_HW_VLAN_CTAG_FILTER;
-- 
2.16.4

^ permalink raw reply related

* [PATCH net-next 09/10] s390/qeth: speed-up L3 IQD xmit
From: Julian Wiedmann @ 2018-07-11 15:42 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, linux-s390, Martin Schwidefsky, Heiko Carstens,
	Stefan Raspl, Ursula Braun, Julian Wiedmann
In-Reply-To: <20180711154247.5523-1-jwi@linux.ibm.com>

This implements a new xmit path for L3 HiperSockets, which carves the
HW header from skb headroom instead of allocating it from the hdr cache.
It also adds NETIF_F_SG support.

The delta in qeth_l3_xmit() is all just removal of IQD-specific code and
some minor consolidation.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
---
 drivers/s390/net/qeth_l3_main.c | 211 ++++++++++++++++++++++++----------------
 1 file changed, 128 insertions(+), 83 deletions(-)

diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index b5a54cc07017..0863ffa9ab59 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2000,19 +2000,18 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
 	return RTN_UNICAST;
 }
 
-static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card,
-		struct qeth_hdr *hdr, struct sk_buff *skb)
+static void qeth_l3_fill_af_iucv_hdr(struct qeth_hdr *hdr, struct sk_buff *skb,
+				     unsigned int data_len)
 {
 	char daddr[16];
 	struct af_iucv_trans_hdr *iucv_hdr;
 
 	memset(hdr, 0, sizeof(struct qeth_hdr));
 	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
-	hdr->hdr.l3.ext_flags = 0;
-	hdr->hdr.l3.length = skb->len - ETH_HLEN;
+	hdr->hdr.l3.length = data_len;
 	hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
 
-	iucv_hdr = (struct af_iucv_trans_hdr *) (skb->data + ETH_HLEN);
+	iucv_hdr = (struct af_iucv_trans_hdr *)(skb_mac_header(skb) + ETH_HLEN);
 	memset(daddr, 0, sizeof(daddr));
 	daddr[0] = 0xfe;
 	daddr[1] = 0x80;
@@ -2156,63 +2155,122 @@ static int qeth_l3_get_elements_no_tso(struct qeth_card *card,
 	return elements;
 }
 
+static int qeth_l3_xmit_offload(struct qeth_card *card, struct sk_buff *skb,
+				struct qeth_qdio_out_q *queue, int ipv,
+				int cast_type)
+{
+	const unsigned int hw_hdr_len = sizeof(struct qeth_hdr);
+	unsigned int frame_len, nr_frags;
+	unsigned char eth_hdr[ETH_HLEN];
+	unsigned int hdr_elements = 0;
+	struct qeth_hdr *hdr = NULL;
+	unsigned int hd_len = 0;
+	int push_len, rc;
+
+	/* compress skb to fit into one IO buffer: */
+	if (!qeth_get_elements_no(card, skb, 0, 0)) {
+		rc = skb_linearize(skb);
+
+		if (card->options.performance_stats) {
+			if (rc)
+				card->perf_stats.tx_linfail++;
+			else
+				card->perf_stats.tx_lin++;
+		}
+		if (rc)
+			return rc;
+	}
+
+	/* re-use the L2 header area for the HW header: */
+	rc = skb_cow_head(skb, hw_hdr_len - ETH_HLEN);
+	if (rc)
+		return rc;
+	skb_copy_from_linear_data(skb, eth_hdr, ETH_HLEN);
+	skb_pull(skb, ETH_HLEN);
+	frame_len = skb->len;
+	nr_frags = skb_shinfo(skb)->nr_frags;
+
+	push_len = qeth_push_hdr(skb, &hdr, hw_hdr_len);
+	if (push_len < 0)
+		return push_len;
+	if (!push_len) {
+		/* hdr was added discontiguous from skb->data */
+		hd_len = hw_hdr_len;
+		hdr_elements = 1;
+	}
+
+	if (!qeth_get_elements_no(card, skb, hdr_elements, 0)) {
+		rc = -E2BIG;
+		goto out;
+	}
+
+	if (skb->protocol == htons(ETH_P_AF_IUCV))
+		qeth_l3_fill_af_iucv_hdr(hdr, skb, frame_len);
+	else
+		qeth_l3_fill_header(card, hdr, skb, ipv, cast_type, frame_len);
+
+	rc = qeth_do_send_packet_fast(queue, skb, hdr, 0, hd_len);
+out:
+	if (!rc) {
+		if (card->options.performance_stats && nr_frags) {
+			card->perf_stats.sg_skbs_sent++;
+			/* nr_frags + skb->data */
+			card->perf_stats.sg_frags_sent += nr_frags + 1;
+		}
+	} else {
+		if (!push_len)
+			kmem_cache_free(qeth_core_header_cache, hdr);
+		if (rc == -EBUSY) {
+			/* roll back to ETH header */
+			skb_pull(skb, push_len);
+			skb_push(skb, ETH_HLEN);
+			skb_copy_to_linear_data(skb, eth_hdr, ETH_HLEN);
+		}
+	}
+	return rc;
+}
+
 static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
 			struct qeth_qdio_out_q *queue, int ipv, int cast_type)
 {
-	int rc;
+	unsigned int hd_len, nr_frags;
+	int elements, len, rc;
 	__be16 *tag;
 	struct qeth_hdr *hdr = NULL;
 	int hdr_elements = 0;
-	int elements;
 	struct sk_buff *new_skb = NULL;
 	int tx_bytes = skb->len;
-	unsigned int hd_len = 0;
 	bool use_tso;
-	int data_offset = -1;
-	unsigned int nr_frags;
 
 	/* Ignore segment size from skb_is_gso(), 1 page is always used. */
 	use_tso = skb_is_gso(skb) &&
 		  (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4);
 
-	if (card->info.type == QETH_CARD_TYPE_IQD) {
-		new_skb = skb;
-		data_offset = ETH_HLEN;
-		hd_len = sizeof(*hdr);
-		hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
-		if (!hdr)
-			return -ENOMEM;
-		hdr_elements++;
-	} else {
-		/* create a clone with writeable headroom */
-		new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso)
-					+ VLAN_HLEN);
-		if (!new_skb)
-			return -ENOMEM;
-
-		if (ipv == 4) {
-			skb_pull(new_skb, ETH_HLEN);
-		}
+	/* create a clone with writeable headroom */
+	new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso) +
+					    VLAN_HLEN);
+	if (!new_skb)
+		return -ENOMEM;
 
-		if (ipv != 4 && skb_vlan_tag_present(new_skb)) {
-			skb_push(new_skb, VLAN_HLEN);
-			skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
-			skb_copy_to_linear_data_offset(new_skb, 4,
-				new_skb->data + 8, 4);
-			skb_copy_to_linear_data_offset(new_skb, 8,
-				new_skb->data + 12, 4);
-			tag = (__be16 *)(new_skb->data + 12);
-			*tag = cpu_to_be16(ETH_P_8021Q);
-			*(tag + 1) = cpu_to_be16(skb_vlan_tag_get(new_skb));
-		}
+	if (ipv == 4) {
+		skb_pull(new_skb, ETH_HLEN);
+	} else if (skb_vlan_tag_present(new_skb)) {
+		skb_push(new_skb, VLAN_HLEN);
+		skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
+		skb_copy_to_linear_data_offset(new_skb, 4,
+					       new_skb->data + 8, 4);
+		skb_copy_to_linear_data_offset(new_skb, 8,
+					       new_skb->data + 12, 4);
+		tag = (__be16 *)(new_skb->data + 12);
+		*tag = cpu_to_be16(ETH_P_8021Q);
+		*(tag + 1) = cpu_to_be16(skb_vlan_tag_get(new_skb));
 	}
 
 	/* fix hardware limitation: as long as we do not have sbal
 	 * chaining we can not send long frag lists
 	 */
-	if ((card->info.type != QETH_CARD_TYPE_IQD) &&
-	    ((use_tso && !qeth_l3_get_elements_no_tso(card, new_skb, 1)) ||
-	     (!use_tso && !qeth_get_elements_no(card, new_skb, 0, 0)))) {
+	if ((use_tso && !qeth_l3_get_elements_no_tso(card, new_skb, 1)) ||
+	    (!use_tso && !qeth_get_elements_no(card, new_skb, 0, 0))) {
 		rc = skb_linearize(new_skb);
 
 		if (card->options.performance_stats) {
@@ -2234,20 +2292,9 @@ static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
 		qeth_tso_fill_header(card, hdr, new_skb);
 		hdr_elements++;
 	} else {
-		if (data_offset < 0) {
-			hdr = skb_push(new_skb, sizeof(struct qeth_hdr));
-			qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type,
-					    new_skb->len -
-					    sizeof(struct qeth_hdr));
-		} else {
-			if (be16_to_cpu(new_skb->protocol) == ETH_P_AF_IUCV)
-				qeth_l3_fill_af_iucv_hdr(card, hdr, new_skb);
-			else {
-				qeth_l3_fill_header(card, hdr, new_skb, ipv,
-						    cast_type,
-						    new_skb->len - data_offset);
-			}
-		}
+		hdr = skb_push(new_skb, sizeof(struct qeth_hdr));
+		qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type,
+				    new_skb->len - sizeof(struct qeth_hdr));
 
 		if (new_skb->ip_summed == CHECKSUM_PARTIAL) {
 			qeth_tx_csum(new_skb, &hdr->hdr.l3.ext_flags, ipv);
@@ -2258,34 +2305,28 @@ static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
 
 	elements = use_tso ?
 		   qeth_l3_get_elements_no_tso(card, new_skb, hdr_elements) :
-		   qeth_get_elements_no(card, new_skb, hdr_elements,
-					(data_offset > 0) ? data_offset : 0);
+		   qeth_get_elements_no(card, new_skb, hdr_elements, 0);
 	if (!elements) {
 		rc = -E2BIG;
 		goto out;
 	}
 	elements += hdr_elements;
 
-	if (card->info.type != QETH_CARD_TYPE_IQD) {
-		int len;
-		if (use_tso) {
-			hd_len = sizeof(struct qeth_hdr_tso) +
-				 ip_hdrlen(new_skb) + tcp_hdrlen(new_skb);
-			len = hd_len;
-		} else {
-			len = sizeof(struct qeth_hdr_layer3);
-		}
-
-		if (qeth_hdr_chk_and_bounce(new_skb, &hdr, len)) {
-			rc = -EINVAL;
-			goto out;
-		}
-		rc = qeth_do_send_packet(card, queue, new_skb, hdr, hd_len,
-					 hd_len, elements);
-	} else
-		rc = qeth_do_send_packet_fast(queue, new_skb, hdr, data_offset,
-					      hd_len);
+	if (use_tso) {
+		hd_len = sizeof(struct qeth_hdr_tso) +
+			 ip_hdrlen(new_skb) + tcp_hdrlen(new_skb);
+		len = hd_len;
+	} else {
+		hd_len = 0;
+		len = sizeof(struct qeth_hdr_layer3);
+	}
 
+	if (qeth_hdr_chk_and_bounce(new_skb, &hdr, len)) {
+		rc = -EINVAL;
+		goto out;
+	}
+	rc = qeth_do_send_packet(card, queue, new_skb, hdr, hd_len, hd_len,
+				 elements);
 out:
 	if (!rc) {
 		if (new_skb != skb)
@@ -2304,8 +2345,6 @@ static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
 	} else {
 		if (new_skb != skb)
 			dev_kfree_skb_any(new_skb);
-		if (data_offset >= 0)
-			kmem_cache_free(qeth_core_header_cache, hdr);
 	}
 	return rc;
 }
@@ -2345,7 +2384,10 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
 	}
 	netif_stop_queue(dev);
 
-	rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type);
+	if (IS_IQD(card))
+		rc = qeth_l3_xmit_offload(card, skb, queue, ipv, cast_type);
+	else
+		rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type);
 
 	if (!rc) {
 		card->stats.tx_packets++;
@@ -2503,9 +2545,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
 			card->dev->dev_id = card->info.unique_id & 0xffff;
 
-		card->dev->hw_features |= NETIF_F_SG;
-		card->dev->vlan_features |= NETIF_F_SG;
-
 		if (!card->info.guestlan) {
 			card->dev->features |= NETIF_F_SG;
 			card->dev->hw_features |= NETIF_F_TSO |
@@ -2524,7 +2563,10 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 		if (!card->dev)
 			return -ENODEV;
 		card->dev->flags |= IFF_NOARP;
+		card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 		card->dev->netdev_ops = &qeth_l3_netdev_ops;
+		card->dev->needed_headroom = sizeof(struct qeth_hdr) - ETH_HLEN;
+
 		rc = qeth_l3_iqd_read_initial_mac(card);
 		if (rc)
 			return rc;
@@ -2543,6 +2585,9 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 	card->dev->features |=	NETIF_F_HW_VLAN_CTAG_TX |
 				NETIF_F_HW_VLAN_CTAG_RX |
 				NETIF_F_HW_VLAN_CTAG_FILTER;
+	card->dev->hw_features |= NETIF_F_SG;
+	card->dev->vlan_features |= NETIF_F_SG;
+
 	netif_keep_dst(card->dev);
 	if (card->dev->hw_features & NETIF_F_TSO)
 		netif_set_gso_max_size(card->dev,
-- 
2.16.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox