Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 09/16] virtio-net: drop config_mutex
From: Sergei Shtylyov @ 2014-10-06 11:46 UTC (permalink / raw)
  To: Michael S. Tsirkin, linux-kernel; +Cc: netdev, virtualization
In-Reply-To: <1412525038-15871-10-git-send-email-mst@redhat.com>

Hello.

On 10/5/2014 8:07 PM, Michael S. Tsirkin wrote:

> config_mutex served two purposes: prevent multiple concurrent config
> change handlers, and synchronize access to config_enable flag.

> Since commit dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1
>      workqueue: make all workqueues non-reentrant
> all workqueues are non-reentrant, and config_enable
> is now gone.

> Get rid of the unnecessary lock.

> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>   drivers/net/virtio_net.c | 7 +------
>   1 file changed, 1 insertion(+), 6 deletions(-)

> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index fa17afa..d80fef4 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
[...]
> @@ -1430,7 +1426,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
>   		netif_tx_stop_all_queues(vi->dev);
>   	}
>   done:
> -	mutex_unlock(&vi->config_lock);
> +	return;

    There's no need for this *return*.

>   }
>
>   static void virtnet_config_changed(struct virtio_device *vdev)

WBR, Sergei

^ permalink raw reply

* Re: [PATCH 08/16] virtio_net: drop config_enable
From: Cornelia Huck @ 2014-10-06 11:50 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <1412525038-15871-9-git-send-email-mst@redhat.com>

On Sun, 5 Oct 2014 19:07:13 +0300
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> Now that virtio core ensures config changes don't arrive during probing,
> drop config_enable flag in virtio net.
> On removal, flush is now sufficient to guarantee that no change work is
> queued.
> 
> This help simplify the driver, and will allow setting DRIVER_OK earlier
> without losing config change notifications.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  drivers/net/virtio_net.c | 23 ++---------------------
>  1 file changed, 2 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 59caa06..fa17afa 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c

> @@ -1876,16 +1869,12 @@ static void virtnet_remove(struct virtio_device *vdev)
>  	unregister_hotcpu_notifier(&vi->nb);
> 
>  	/* Prevent config work handler from accessing the device. */

Same comment as for the equivalent comment in the virtio-blk code.

> -	mutex_lock(&vi->config_lock);
> -	vi->config_enable = false;
> -	mutex_unlock(&vi->config_lock);
> +	flush_work(&vi->config_work);
> 
>  	unregister_netdev(vi->dev);
> 
>  	remove_vq_common(vi);
> 
> -	flush_work(&vi->config_work);
> -
>  	free_percpu(vi->stats);
>  	free_netdev(vi->dev);
>  }
> @@ -1899,9 +1888,7 @@ static int virtnet_freeze(struct virtio_device *vdev)
>  	unregister_hotcpu_notifier(&vi->nb);
> 
>  	/* Prevent config work handler from accessing the device */

dito

> -	mutex_lock(&vi->config_lock);
> -	vi->config_enable = false;
> -	mutex_unlock(&vi->config_lock);
> +	flush_work(&vi->config_work);
> 
>  	netif_device_detach(vi->dev);
>  	cancel_delayed_work_sync(&vi->refill);

^ permalink raw reply

* Re: [PATCH 09/16] virtio-net: drop config_mutex
From: Cornelia Huck @ 2014-10-06 11:56 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <1412525038-15871-10-git-send-email-mst@redhat.com>

On Sun, 5 Oct 2014 19:07:16 +0300
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> config_mutex served two purposes: prevent multiple concurrent config
> change handlers, and synchronize access to config_enable flag.
> 
> Since commit dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1
>     workqueue: make all workqueues non-reentrant
> all workqueues are non-reentrant, and config_enable
> is now gone.
> 
> Get rid of the unnecessary lock.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  drivers/net/virtio_net.c | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)
> 
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index fa17afa..d80fef4 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c

> @@ -1430,7 +1426,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
>  		netif_tx_stop_all_queues(vi->dev);
>  	}
>  done:
> -	mutex_unlock(&vi->config_lock);
> +	return;
>  }
> 
>  static void virtnet_config_changed(struct virtio_device *vdev)

I'd probably return directly in the remaining 'goto done;' cases, but still

Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>

^ permalink raw reply

* Re: [PATCH 09/16] virtio-net: drop config_mutex
From: Michael S. Tsirkin @ 2014-10-06 11:56 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <54328107.5090400@cogentembedded.com>

On Mon, Oct 06, 2014 at 03:46:15PM +0400, Sergei Shtylyov wrote:
> Hello.
> 
> On 10/5/2014 8:07 PM, Michael S. Tsirkin wrote:
> 
> >config_mutex served two purposes: prevent multiple concurrent config
> >change handlers, and synchronize access to config_enable flag.
> 
> >Since commit dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1
> >     workqueue: make all workqueues non-reentrant
> >all workqueues are non-reentrant, and config_enable
> >is now gone.
> 
> >Get rid of the unnecessary lock.
> 
> >Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> >---
> >  drivers/net/virtio_net.c | 7 +------
> >  1 file changed, 1 insertion(+), 6 deletions(-)
> 
> >diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> >index fa17afa..d80fef4 100644
> >--- a/drivers/net/virtio_net.c
> >+++ b/drivers/net/virtio_net.c
> [...]
> >@@ -1430,7 +1426,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
> >  		netif_tx_stop_all_queues(vi->dev);
> >  	}
> >  done:
> >-	mutex_unlock(&vi->config_lock);
> >+	return;
> 
>    There's no need for this *return*.
>

I know - it's removed by the follow-up patch.
It's formatted like this to make diff smaller
and make review easier.
 
> >  }
> >
> >  static void virtnet_config_changed(struct virtio_device *vdev)
> 
> WBR, Sergei

^ permalink raw reply

* Re: [PATCH 09/16] virtio-net: drop config_mutex
From: Michael S. Tsirkin @ 2014-10-06 12:01 UTC (permalink / raw)
  To: Cornelia Huck; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <20141006135610.537c263b.cornelia.huck@de.ibm.com>

On Mon, Oct 06, 2014 at 01:56:10PM +0200, Cornelia Huck wrote:
> On Sun, 5 Oct 2014 19:07:16 +0300
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
> > config_mutex served two purposes: prevent multiple concurrent config
> > change handlers, and synchronize access to config_enable flag.
> > 
> > Since commit dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1
> >     workqueue: make all workqueues non-reentrant
> > all workqueues are non-reentrant, and config_enable
> > is now gone.
> > 
> > Get rid of the unnecessary lock.
> > 
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> >  drivers/net/virtio_net.c | 7 +------
> >  1 file changed, 1 insertion(+), 6 deletions(-)
> > 
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index fa17afa..d80fef4 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> 
> > @@ -1430,7 +1426,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
> >  		netif_tx_stop_all_queues(vi->dev);
> >  	}
> >  done:
> > -	mutex_unlock(&vi->config_lock);
> > +	return;
> >  }
> > 
> >  static void virtnet_config_changed(struct virtio_device *vdev)
> 
> I'd probably return directly in the remaining 'goto done;' cases, but still
> 
> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>

Yes: this is exactly what
[PATCH 11/16] virtio_net: minor cleanup
does

-- 
MST

^ permalink raw reply

* [PATCH v3 net-next] r8169:add support for RTL8168EP
From: Chun-Hao Lin @ 2014-10-06 12:04 UTC (permalink / raw)
  To: netdev; +Cc: nic_swsd, linux-kernel, Chun-Hao Lin

RTL8168EP is Realtek PCIe Gigabit Ethernet controller with DASH support.
It is a successor chip of RTL8168DP.

For RTL8168EP, the read/write ocp register is via eri channel type 2, so
I modify ocp_read() ocp_write() and move related functions under
rtl_eri_read() rtl_eri_write().

The way of checking if dash is enabled and setting driver start/stop
are also different with RTL8168DP.

Right now, RTL8168EP phy mcu did not need patch firmware code, so I
did not add firmware code for it.

Signed-off-by: Chun-Hao Lin <hau@realtek.com>
---
 drivers/net/ethernet/realtek/r8169.c | 512 ++++++++++++++++++++++++++++++++---
 1 file changed, 467 insertions(+), 45 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 54476ba..1f63e0a 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -155,6 +155,9 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_46,
 	RTL_GIGA_MAC_VER_47,
 	RTL_GIGA_MAC_VER_48,
+	RTL_GIGA_MAC_VER_49,
+	RTL_GIGA_MAC_VER_50,
+	RTL_GIGA_MAC_VER_51,
 	RTL_GIGA_MAC_NONE   = 0xff,
 };
 
@@ -302,6 +305,15 @@ static const struct {
 	[RTL_GIGA_MAC_VER_48] =
 		_R("RTL8107e",		RTL_TD_1, FIRMWARE_8107E_2,
 							JUMBO_1K, false),
+	[RTL_GIGA_MAC_VER_49] =
+		_R("RTL8168ep/8111ep",	RTL_TD_1, NULL,
+							JUMBO_9K, false),
+	[RTL_GIGA_MAC_VER_50] =
+		_R("RTL8168ep/8111ep",	RTL_TD_1, NULL,
+							JUMBO_9K, false),
+	[RTL_GIGA_MAC_VER_51] =
+		_R("RTL8168ep/8111ep",	RTL_TD_1, NULL,
+							JUMBO_9K, false),
 };
 #undef _R
 
@@ -400,6 +412,10 @@ enum rtl_registers {
 	FuncEvent	= 0xf0,
 	FuncEventMask	= 0xf4,
 	FuncPresetState	= 0xf8,
+	IBCR0           = 0xf8,
+	IBCR2           = 0xf9,
+	IBIMR0          = 0xfa,
+	IBISR0          = 0xfb,
 	FuncForceEvent	= 0xfc,
 };
 
@@ -467,6 +483,7 @@ enum rtl8168_registers {
 #define ERIAR_EXGMAC			(0x00 << ERIAR_TYPE_SHIFT)
 #define ERIAR_MSIX			(0x01 << ERIAR_TYPE_SHIFT)
 #define ERIAR_ASF			(0x02 << ERIAR_TYPE_SHIFT)
+#define ERIAR_OOB			(0x02 << ERIAR_TYPE_SHIFT)
 #define ERIAR_MASK_SHIFT		12
 #define ERIAR_MASK_0001			(0x1 << ERIAR_MASK_SHIFT)
 #define ERIAR_MASK_0011			(0x3 << ERIAR_MASK_SHIFT)
@@ -935,40 +952,6 @@ static const struct rtl_cond name = {			\
 							\
 static bool name ## _check(struct rtl8169_private *tp)
 
-DECLARE_RTL_COND(rtl_ocpar_cond)
-{
-	void __iomem *ioaddr = tp->mmio_addr;
-
-	return RTL_R32(OCPAR) & OCPAR_FLAG;
-}
-
-static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
-{
-	void __iomem *ioaddr = tp->mmio_addr;
-
-	RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
-
-	return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
-		RTL_R32(OCPDR) : ~0;
-}
-
-static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
-{
-	void __iomem *ioaddr = tp->mmio_addr;
-
-	RTL_W32(OCPDR, data);
-	RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
-
-	rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
-}
-
-DECLARE_RTL_COND(rtl_eriar_cond)
-{
-	void __iomem *ioaddr = tp->mmio_addr;
-
-	return RTL_R32(ERIAR) & ERIAR_FLAG;
-}
-
 static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
 {
 	if (reg & 0xffff0001) {
@@ -1110,6 +1093,13 @@ static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
 	return value;
 }
 
+DECLARE_RTL_COND(rtl_ocpar_cond)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	return RTL_R32(OCPAR) & OCPAR_FLAG;
+}
+
 static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -1245,6 +1235,13 @@ static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
 		RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
 }
 
+DECLARE_RTL_COND(rtl_eriar_cond)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	return RTL_R32(ERIAR) & ERIAR_FLAG;
+}
+
 static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
 			  u32 val, int type)
 {
@@ -1276,6 +1273,52 @@ static void rtl_w0w1_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
 	rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
 }
 
+static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
+		return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
+			RTL_R32(OCPDR) : ~0;
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
+		return rtl_eri_read(tp, reg, ERIAR_OOB);
+	default:
+		BUG();
+		return ~0;
+	}
+}
+
+static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		RTL_W32(OCPDR, data);
+		RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 |
+			(reg & 0x0fff));
+		rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
+		break;
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
+		rtl_eri_write(tp, reg, ((u32)mask & 0x0f) << ERIAR_MASK_SHIFT,
+			      data, ERIAR_OOB);
+		break;
+	default:
+		BUG();
+		break;
+	}
+}
+
 static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
 {
 	rtl_eri_write(tp, 0xe8, ERIAR_MASK_0001, cmd, ERIAR_EXGMAC);
@@ -1301,25 +1344,84 @@ DECLARE_RTL_COND(rtl_ocp_read_cond)
 	return ocp_read(tp, 0x0f, reg) & 0x00000800;
 }
 
-static void rtl8168_driver_start(struct rtl8169_private *tp)
+DECLARE_RTL_COND(rtl_ep_ocp_read_cond)
 {
-	rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
+	return ocp_read(tp, 0x0f, 0x124) & 0x00000001;
+}
+
+DECLARE_RTL_COND(rtl_ocp_tx_cond)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
 
-	rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
+	return RTL_R8(IBISR0) & 0x02;
+}
+
+static void rtl8168_driver_start(struct rtl8169_private *tp)
+{
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
+		rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
+		break;
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
+		ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
+		ocp_write(tp, 0x01, 0x30, ocp_read(tp, 0x01, 0x30) | 0x01);
+		rtl_msleep_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10, 10);
+		break;
+	default:
+		BUG();
+		break;
+	}
 }
 
 static void rtl8168_driver_stop(struct rtl8169_private *tp)
 {
-	rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
+	void __iomem *ioaddr = tp->mmio_addr;
 
-	rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
+		rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
+		break;
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
+		RTL_W8(IBCR2, RTL_R8(IBCR2) & ~0x01);
+		rtl_msleep_loop_wait_low(tp, &rtl_ocp_tx_cond, 50, 2000);
+		RTL_W8(IBISR0, RTL_R8(IBISR0) | 0x20);
+		RTL_W8(IBCR0, RTL_R8(IBCR0) & ~0x01);
+		ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
+		ocp_write(tp, 0x01, 0x30, ocp_read(tp, 0x01, 0x30) | 0x01);
+		rtl_msleep_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10, 10);
+		break;
+	default:
+		BUG();
+		break;
+	}
 }
 
 static int r8168_check_dash(struct rtl8169_private *tp)
 {
 	u16 reg = rtl8168_get_ocp_reg(tp);
 
-	return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+	case RTL_GIGA_MAC_VER_31:
+		return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
+		return (ocp_read(tp, 0x0f, 0x128) & 0x00000001) ? 1 : 0;
+	default:
+		return 0;
+	}
 }
 
 struct exgmac_reg {
@@ -1553,6 +1655,9 @@ static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
 			wolopts |= WAKE_MAGIC;
 		break;
@@ -1620,6 +1725,9 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		tmp = ARRAY_SIZE(cfg) - 1;
 		if (wolopts & WAKE_MAGIC)
 			rtl_w0w1_eri(tp,
@@ -2126,6 +2234,11 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		u32 val;
 		int mac_version;
 	} mac_info[] = {
+		/* 8168EP family. */
+		{ 0x7cf00000, 0x50200000,	RTL_GIGA_MAC_VER_51 },
+		{ 0x7cf00000, 0x50100000,	RTL_GIGA_MAC_VER_50 },
+		{ 0x7cf00000, 0x50000000,	RTL_GIGA_MAC_VER_49 },
+
 		/* 8168H family. */
 		{ 0x7cf00000, 0x54100000,	RTL_GIGA_MAC_VER_46 },
 		{ 0x7cf00000, 0x54000000,	RTL_GIGA_MAC_VER_45 },
@@ -3741,6 +3854,139 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
+static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
+{
+	/* Enable PHY auto speed down */
+	rtl_writephy(tp, 0x1f, 0x0a44);
+	rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* patch 10M & ALDPS */
+	rtl_writephy(tp, 0x1f, 0x0bcc);
+	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100);
+	rtl_writephy(tp, 0x1f, 0x0a44);
+	rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x8084);
+	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000);
+	rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Enable EEE auto-fallback function */
+	rtl_writephy(tp, 0x1f, 0x0a4b);
+	rtl_w0w1_phy(tp, 0x11, 0x0004, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Enable UC LPF tune function */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x8012);
+	rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* set rg_sel_sdm_rate */
+	rtl_writephy(tp, 0x1f, 0x0c42);
+	rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Check ALDPS bit, disable it if enabled */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	if (rtl_readphy(tp, 0x10) & 0x0004)
+		rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp)
+{
+	/* patch 10M & ALDPS */
+	rtl_writephy(tp, 0x1f, 0x0bcc);
+	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100);
+	rtl_writephy(tp, 0x1f, 0x0a44);
+	rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x8084);
+	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000);
+	rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Enable UC LPF tune function */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x8012);
+	rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Set rg_sel_sdm_rate */
+	rtl_writephy(tp, 0x1f, 0x0c42);
+	rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Channel estimation parameters */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x80f3);
+	rtl_w0w1_phy(tp, 0x14, 0x8b00, ~0x8bff);
+	rtl_writephy(tp, 0x13, 0x80f0);
+	rtl_w0w1_phy(tp, 0x14, 0x3a00, ~0x3aff);
+	rtl_writephy(tp, 0x13, 0x80ef);
+	rtl_w0w1_phy(tp, 0x14, 0x0500, ~0x05ff);
+	rtl_writephy(tp, 0x13, 0x80f6);
+	rtl_w0w1_phy(tp, 0x14, 0x6e00, ~0x6eff);
+	rtl_writephy(tp, 0x13, 0x80ec);
+	rtl_w0w1_phy(tp, 0x14, 0x6800, ~0x68ff);
+	rtl_writephy(tp, 0x13, 0x80ed);
+	rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff);
+	rtl_writephy(tp, 0x13, 0x80f2);
+	rtl_w0w1_phy(tp, 0x14, 0xf400, ~0xf4ff);
+	rtl_writephy(tp, 0x13, 0x80f4);
+	rtl_w0w1_phy(tp, 0x14, 0x8500, ~0x85ff);
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x8110);
+	rtl_w0w1_phy(tp, 0x14, 0xa800, ~0xa8ff);
+	rtl_writephy(tp, 0x13, 0x810f);
+	rtl_w0w1_phy(tp, 0x14, 0x1d00, ~0x1dff);
+	rtl_writephy(tp, 0x13, 0x8111);
+	rtl_w0w1_phy(tp, 0x14, 0xf500, ~0xf5ff);
+	rtl_writephy(tp, 0x13, 0x8113);
+	rtl_w0w1_phy(tp, 0x14, 0x6100, ~0x61ff);
+	rtl_writephy(tp, 0x13, 0x8115);
+	rtl_w0w1_phy(tp, 0x14, 0x9200, ~0x92ff);
+	rtl_writephy(tp, 0x13, 0x810e);
+	rtl_w0w1_phy(tp, 0x14, 0x0400, ~0x04ff);
+	rtl_writephy(tp, 0x13, 0x810c);
+	rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff);
+	rtl_writephy(tp, 0x13, 0x810b);
+	rtl_w0w1_phy(tp, 0x14, 0x5a00, ~0x5aff);
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	rtl_writephy(tp, 0x13, 0x80d1);
+	rtl_w0w1_phy(tp, 0x14, 0xff00, ~0xffff);
+	rtl_writephy(tp, 0x13, 0x80cd);
+	rtl_w0w1_phy(tp, 0x14, 0x9e00, ~0x9eff);
+	rtl_writephy(tp, 0x13, 0x80d3);
+	rtl_w0w1_phy(tp, 0x14, 0x0e00, ~0x0eff);
+	rtl_writephy(tp, 0x13, 0x80d5);
+	rtl_w0w1_phy(tp, 0x14, 0xca00, ~0xcaff);
+	rtl_writephy(tp, 0x13, 0x80d7);
+	rtl_w0w1_phy(tp, 0x14, 0x8400, ~0x84ff);
+
+	/* Force PWM-mode */
+	rtl_writephy(tp, 0x1f, 0x0bcd);
+	rtl_writephy(tp, 0x14, 0x5065);
+	rtl_writephy(tp, 0x14, 0xd065);
+	rtl_writephy(tp, 0x1f, 0x0bc8);
+	rtl_writephy(tp, 0x12, 0x00ed);
+	rtl_writephy(tp, 0x1f, 0x0bcd);
+	rtl_writephy(tp, 0x14, 0x1065);
+	rtl_writephy(tp, 0x14, 0x9065);
+	rtl_writephy(tp, 0x14, 0x1065);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Check ALDPS bit, disable it if enabled */
+	rtl_writephy(tp, 0x1f, 0x0a43);
+	if (rtl_readphy(tp, 0x10) & 0x0004)
+		rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004);
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
 static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -3940,6 +4186,14 @@ static void rtl_hw_phy_config(struct net_device *dev)
 		rtl8168h_2_hw_phy_config(tp);
 		break;
 
+	case RTL_GIGA_MAC_VER_49:
+		rtl8168ep_1_hw_phy_config(tp);
+		break;
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
+		rtl8168ep_2_hw_phy_config(tp);
+		break;
+
 	case RTL_GIGA_MAC_VER_41:
 	default:
 		break;
@@ -4154,6 +4408,9 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		ops->write	= r8168g_mdio_write;
 		ops->read	= r8168g_mdio_read;
 		break;
@@ -4212,6 +4469,9 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		RTL_W32(RxConfig, RTL_R32(RxConfig) |
 			AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
 		break;
@@ -4356,7 +4616,10 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
 
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
 	     tp->mac_version == RTL_GIGA_MAC_VER_28 ||
-	     tp->mac_version == RTL_GIGA_MAC_VER_31) &&
+	     tp->mac_version == RTL_GIGA_MAC_VER_31 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_51) &&
 	    r8168_check_dash(tp)) {
 		return;
 	}
@@ -4387,10 +4650,13 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_44:
 	case RTL_GIGA_MAC_VER_45:
 	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
 		break;
 	case RTL_GIGA_MAC_VER_40:
 	case RTL_GIGA_MAC_VER_41:
+	case RTL_GIGA_MAC_VER_49:
 		rtl_w0w1_eri(tp, 0x1a8, ERIAR_MASK_1111, 0x00000000,
 			     0xfc000000, ERIAR_EXGMAC);
 		RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
@@ -4415,10 +4681,13 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_44:
 	case RTL_GIGA_MAC_VER_45:
 	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		RTL_W8(PMCH, RTL_R8(PMCH) | 0xc0);
 		break;
 	case RTL_GIGA_MAC_VER_40:
 	case RTL_GIGA_MAC_VER_41:
+	case RTL_GIGA_MAC_VER_49:
 		RTL_W8(PMCH, RTL_R8(PMCH) | 0xc0);
 		rtl_w0w1_eri(tp, 0x1a8, ERIAR_MASK_1111, 0xfc000000,
 			     0x00000000, ERIAR_EXGMAC);
@@ -4493,6 +4762,9 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_44:
 	case RTL_GIGA_MAC_VER_45:
 	case RTL_GIGA_MAC_VER_46:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		ops->down	= r8168_pll_power_down;
 		ops->up		= r8168_pll_power_up;
 		break;
@@ -4547,6 +4819,9 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
 		break;
 	default:
@@ -4712,6 +4987,9 @@ static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 	default:
 		ops->disable	= NULL;
 		ops->enable	= NULL;
@@ -4828,7 +5106,10 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
 		   tp->mac_version == RTL_GIGA_MAC_VER_45 ||
 		   tp->mac_version == RTL_GIGA_MAC_VER_46 ||
 		   tp->mac_version == RTL_GIGA_MAC_VER_47 ||
-		   tp->mac_version == RTL_GIGA_MAC_VER_48) {
+		   tp->mac_version == RTL_GIGA_MAC_VER_48 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_51) {
 		RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
 		rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
 	} else {
@@ -5754,6 +6035,120 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
 	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
 }
 
+static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
+	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
+
+	rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x00080002, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x2f, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x5f, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
+
+	rtl_csi_access_enable_1(tp);
+
+	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+	rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
+	rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
+
+	rtl_w0w1_eri(tp, 0xd4, ERIAR_MASK_1111, 0x1f80, 0x00, ERIAR_EXGMAC);
+
+	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87, ERIAR_EXGMAC);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+	RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
+	RTL_W8(MaxTxPacketSize, EarlySize);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+	/* Adjust EEE LED frequency */
+	RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+
+	rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) & ~TX_10M_PS_EN);
+
+	rtl_pcie_state_l2l3_enable(tp, false);
+}
+
+static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	static const struct ephy_info e_info_8168ep_1[] = {
+		{ 0x00, 0xffff,	0x10ab },
+		{ 0x06, 0xffff,	0xf030 },
+		{ 0x08, 0xffff,	0x2006 },
+		{ 0x0d, 0xffff,	0x1666 },
+		{ 0x0c, 0x3ff0,	0x0000 }
+	};
+
+	/* disable aspm and clock request before access ephy */
+	RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
+	RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
+	rtl_ephy_init(tp, e_info_8168ep_1, ARRAY_SIZE(e_info_8168ep_1));
+
+	rtl_hw_start_8168ep(tp);
+}
+
+static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	static const struct ephy_info e_info_8168ep_2[] = {
+		{ 0x00, 0xffff,	0x10a3 },
+		{ 0x19, 0xffff,	0xfc00 },
+		{ 0x1e, 0xffff,	0x20ea }
+	};
+
+	/* disable aspm and clock request before access ephy */
+	RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
+	RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
+	rtl_ephy_init(tp, e_info_8168ep_2, ARRAY_SIZE(e_info_8168ep_2));
+
+	rtl_hw_start_8168ep(tp);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
+	RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN);
+}
+
+static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	u32 data;
+	static const struct ephy_info e_info_8168ep_3[] = {
+		{ 0x00, 0xffff,	0x10a3 },
+		{ 0x19, 0xffff,	0x7c00 },
+		{ 0x1e, 0xffff,	0x20eb },
+		{ 0x0d, 0xffff,	0x1666 }
+	};
+
+	/* disable aspm and clock request before access ephy */
+	RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
+	RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
+	rtl_ephy_init(tp, e_info_8168ep_3, ARRAY_SIZE(e_info_8168ep_3));
+
+	rtl_hw_start_8168ep(tp);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
+	RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN);
+
+	data = r8168_mac_ocp_read(tp, 0xd3e2);
+	data &= 0xf000;
+	data |= 0x0271;
+	r8168_mac_ocp_write(tp, 0xd3e2, data);
+
+	data = r8168_mac_ocp_read(tp, 0xd3e4);
+	data &= 0xff00;
+	r8168_mac_ocp_write(tp, 0xd3e4, data);
+
+	data = r8168_mac_ocp_read(tp, 0xe860);
+	data |= 0x0080;
+	r8168_mac_ocp_write(tp, 0xe860, data);
+}
+
 static void rtl_hw_start_8168(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -5869,6 +6264,18 @@ static void rtl_hw_start_8168(struct net_device *dev)
 		rtl_hw_start_8168h_1(tp);
 		break;
 
+	case RTL_GIGA_MAC_VER_49:
+		rtl_hw_start_8168ep_1(tp);
+		break;
+
+	case RTL_GIGA_MAC_VER_50:
+		rtl_hw_start_8168ep_2(tp);
+		break;
+
+	case RTL_GIGA_MAC_VER_51:
+		rtl_hw_start_8168ep_3(tp);
+		break;
+
 	default:
 		printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
 			dev->name, tp->mac_version);
@@ -7399,7 +7806,10 @@ static void rtl_remove_one(struct pci_dev *pdev)
 
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
 	     tp->mac_version == RTL_GIGA_MAC_VER_28 ||
-	     tp->mac_version == RTL_GIGA_MAC_VER_31) &&
+	     tp->mac_version == RTL_GIGA_MAC_VER_31 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_51) &&
 	    r8168_check_dash(tp)) {
 		rtl8168_driver_stop(tp);
 	}
@@ -7556,6 +7966,9 @@ static void rtl_hw_initialize(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		rtl_hw_init_8168g(tp);
 		break;
 
@@ -7708,6 +8121,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	case RTL_GIGA_MAC_VER_46:
 	case RTL_GIGA_MAC_VER_47:
 	case RTL_GIGA_MAC_VER_48:
+	case RTL_GIGA_MAC_VER_49:
+	case RTL_GIGA_MAC_VER_50:
+	case RTL_GIGA_MAC_VER_51:
 		if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
 			tp->features |= RTL_FEATURE_WOL;
 		if ((RTL_R8(Config3) & LinkUp) != 0)
@@ -7756,7 +8172,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	    tp->mac_version == RTL_GIGA_MAC_VER_45 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_46 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_47 ||
-	    tp->mac_version == RTL_GIGA_MAC_VER_48) {
+	    tp->mac_version == RTL_GIGA_MAC_VER_48 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_51) {
 		u16 mac_addr[3];
 
 		*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
@@ -7835,7 +8254,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
 	     tp->mac_version == RTL_GIGA_MAC_VER_28 ||
-	     tp->mac_version == RTL_GIGA_MAC_VER_31) &&
+	     tp->mac_version == RTL_GIGA_MAC_VER_31 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_49 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_50 ||
+	     tp->mac_version == RTL_GIGA_MAC_VER_51) &&
 	    r8168_check_dash(tp)) {
 		rtl8168_driver_start(tp);
 	}
-- 
1.8.3.2

^ permalink raw reply related

* Re: [PATCH 11/16] virtio_net: minor cleanup
From: Cornelia Huck @ 2014-10-06 12:06 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <1412525038-15871-12-git-send-email-mst@redhat.com>

On Sun, 5 Oct 2014 19:07:21 +0300
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> 	goto done;
> done:
> 	return;
> is ugly, it was put there to make diff review easier.
> replace by open-coded return.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  drivers/net/virtio_net.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 

If you don't want to merge it into the mutex removal patch, maybe move
it one up in the series?

Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>

^ permalink raw reply

* Re: [PATCH 09/16] virtio-net: drop config_mutex
From: Sergei Shtylyov @ 2014-10-06 12:07 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <20141006115636.GA26184@redhat.com>

On 10/6/2014 3:56 PM, Michael S. Tsirkin wrote:

>>> config_mutex served two purposes: prevent multiple concurrent config
>>> change handlers, and synchronize access to config_enable flag.

>>> Since commit dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1
>>>      workqueue: make all workqueues non-reentrant
>>> all workqueues are non-reentrant, and config_enable
>>> is now gone.

>>> Get rid of the unnecessary lock.

>>> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>>> ---
>>>   drivers/net/virtio_net.c | 7 +------
>>>   1 file changed, 1 insertion(+), 6 deletions(-)

>>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>>> index fa17afa..d80fef4 100644
>>> --- a/drivers/net/virtio_net.c
>>> +++ b/drivers/net/virtio_net.c
>> [...]
>>> @@ -1430,7 +1426,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
>>>   		netif_tx_stop_all_queues(vi->dev);
>>>   	}
>>>   done:
>>> -	mutex_unlock(&vi->config_lock);
>>> +	return;

>>     There's no need for this *return*.

> I know - it's removed by the follow-up patch.

    Yeah, I saw.

> It's formatted like this to make diff smaller
> and make review easier.

    Don't understand how adding this line makes diff smaller though...
You first need to add it and then to delete it, where's the save?

WBR, Sergei

^ permalink raw reply

* Re: [PATCH 08/16] virtio_net: drop config_enable
From: Michael S. Tsirkin @ 2014-10-06 12:10 UTC (permalink / raw)
  To: Cornelia Huck; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <20141006135036.77fea7de.cornelia.huck@de.ibm.com>

On Mon, Oct 06, 2014 at 01:50:36PM +0200, Cornelia Huck wrote:
> On Sun, 5 Oct 2014 19:07:13 +0300
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
> > Now that virtio core ensures config changes don't arrive during probing,
> > drop config_enable flag in virtio net.
> > On removal, flush is now sufficient to guarantee that no change work is
> > queued.
> > 
> > This help simplify the driver, and will allow setting DRIVER_OK earlier
> > without losing config change notifications.
> > 
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> >  drivers/net/virtio_net.c | 23 ++---------------------
> >  1 file changed, 2 insertions(+), 21 deletions(-)
> > 
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 59caa06..fa17afa 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> 
> > @@ -1876,16 +1869,12 @@ static void virtnet_remove(struct virtio_device *vdev)
> >  	unregister_hotcpu_notifier(&vi->nb);
> > 
> >  	/* Prevent config work handler from accessing the device. */
> 
> Same comment as for the equivalent comment in the virtio-blk code.

Same answer :)

> > -	mutex_lock(&vi->config_lock);
> > -	vi->config_enable = false;
> > -	mutex_unlock(&vi->config_lock);
> > +	flush_work(&vi->config_work);
> > 
> >  	unregister_netdev(vi->dev);
> > 
> >  	remove_vq_common(vi);
> > 
> > -	flush_work(&vi->config_work);
> > -
> >  	free_percpu(vi->stats);
> >  	free_netdev(vi->dev);
> >  }
> > @@ -1899,9 +1888,7 @@ static int virtnet_freeze(struct virtio_device *vdev)
> >  	unregister_hotcpu_notifier(&vi->nb);
> > 
> >  	/* Prevent config work handler from accessing the device */
> 
> dito

Same here.

> > -	mutex_lock(&vi->config_lock);
> > -	vi->config_enable = false;
> > -	mutex_unlock(&vi->config_lock);
> > +	flush_work(&vi->config_work);
> > 
> >  	netif_device_detach(vi->dev);
> >  	cancel_delayed_work_sync(&vi->refill);

^ permalink raw reply

* RE: [PATCH net-next] net: introduce netdevice gso_min_segs attribute
From: Eric Dumazet @ 2014-10-06 12:14 UTC (permalink / raw)
  To: David Laight
  Cc: Amir Vadai, David S. Miller, Eric Dumazet, netdev@vger.kernel.org,
	Yevgeny Petrilin, Or Gerlitz, Ido Shamay
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D174AC1A3@AcuExch.aculab.com>

On Mon, 2014-10-06 at 10:20 +0000, David Laight wrote:
> From: Eric Dumazet <edumazet@google.com>
> > Some TSO engines might have a too heavy setup cost, that impacts
> > performance on hosts sending small bursts (2 MSS per packet).
> > 
> > This patch adds a device gso_min_segs, allowing drivers to set
> > a minimum segment size for TSO packets, according to the NIC
> > performance.
> > 
> > Tested on a mlx4 NIC, this allows to get a ~110% increase of
> > throughput when sending 2 MSS per packet.
> 
> Doesn't this all depend on what you need to optimise for.
> I can think of three^Wseveral main cases:
> 1) minimising cpu use while saturating the local network.
> 2) minimising latency for single packets.
> 3) maximising throughput for a single connection.
> 4) minimising cpu use when handling a large number of connections.
> plus all the variations in packet size.
> 
> I'm not sure what you are trading for what here.
> 

I am not sure you really understood.

What's the point having a 40GB NIC and not being able to reach 18 Gb on
it, even if you are willing to spend all the cpu cycles you want ?


> Maybe gso = tx_bursting is almost always faster on some hardware?
> (Especially if an idle mac engine is 'kicked' for the first packet
> of a burst.)

This has nothing to do with xmit_more.

I start 1200 flows rate limited to 3 MBytes each.
(1000 netperf -t TCP_STREAM, nothing fancy here)

Theoretical total of 3.6 GBytes per second.

Without patch :
# sar -n DEV 5 5 | grep eth0
05:07:56 AM      eth0 555621.60 1111203.20  35813.03 1642923.46      0.00      0.00      0.60
05:08:01 AM      eth0 555591.00 1111173.80  35810.47 1642877.52      0.00      0.00      0.40
05:08:06 AM      eth0 555586.20 1111162.60  35810.06 1642861.03      0.00      0.00      0.60
05:08:11 AM      eth0 555624.40 1111235.40  35812.75 1642974.19      0.00      0.00      0.60
05:08:16 AM      eth0 555639.60 1111266.80  35813.21 1643017.83      0.00      0.00      0.60
Average:         eth0 555612.56 1111208.36  35811.90 1642930.81      0.00      0.00      0.56

With patch :

# sar -n DEV 5 5 | grep eth0
05:07:04 AM      eth0 1179478.80 2358940.40  76022.47 3487725.22      0.00      0.00      0.60
05:07:09 AM      eth0 1178913.60 2357807.40  75986.60 3486044.00      0.00      0.00      0.40
05:07:14 AM      eth0 1178957.40 2357897.60  75988.98 3486177.50      0.00      0.00      0.60
05:07:19 AM      eth0 1177556.00 2355064.60  75899.37 3481993.37      0.00      0.00      0.60
05:07:24 AM      eth0 1180321.20 2360625.20  76077.15 3490209.58      0.00      0.00      0.40
Average:         eth0 1179045.40 2358067.04  75994.92 3486429.94      0.00      0.00      0.52

Ask yourself which one we prefer.

About cpu costs, we hardly see anything caused by GSO,
now we optimized __copy_skb_header()

     6.36%        swapper  [kernel.kallsyms]   [k] _raw_spin_lock                            
     5.24%        netperf  [kernel.kallsyms]   [k] copy_user_enhanced_fast_string            
     5.03%        swapper  [kernel.kallsyms]   [k] poll_idle                                 
     3.73%        swapper  [kernel.kallsyms]   [k] tcp_ack                                   
     2.73%        swapper  [kernel.kallsyms]   [k] memcpy                                    
     2.49%        swapper  [kernel.kallsyms]   [k] __skb_clone                               
     2.41%        swapper  [kernel.kallsyms]   [k] skb_release_data                          
     2.33%        swapper  [kernel.kallsyms]   [k] intel_idle                                
     2.23%        swapper  [kernel.kallsyms]   [k] tcp_init_tso_segs                         
     1.99%        swapper  [kernel.kallsyms]   [k] fq_dequeue                                
     1.94%        netperf  [kernel.kallsyms]   [k] tcp_sendmsg                               
     1.82%        swapper  [kernel.kallsyms]   [k] tcp_write_xmit                            
     1.28%        swapper  [kernel.kallsyms]   [k] __netif_receive_skb_core                  
     1.23%        swapper  [kernel.kallsyms]   [k] __copy_skb_header                         
     1.14%        swapper  [kernel.kallsyms]   [k] kfree                                     
     1.10%        swapper  [kernel.kallsyms]   [k] kmem_cache_free                           
     1.06%        swapper  [kernel.kallsyms]   [k] mlx4_en_xmit                              
     1.05%        swapper  [kernel.kallsyms]   [k] tcp_wfree                                 
     1.02%        swapper  [kernel.kallsyms]   [k] inet_gso_segment                          
     1.01%        swapper  [kernel.kallsyms]   [k] put_compound_page                         
     0.98%        swapper  [kernel.kallsyms]   [k] _raw_spin_lock_irqsave                    
     0.96%        netperf  [kernel.kallsyms]   [k] __alloc_skb                               
     0.92%        netperf  [kernel.kallsyms]   [k] _raw_spin_lock                            
     0.89%        swapper  [kernel.kallsyms]   [k] skb_segment                               
     0.88%        swapper  [kernel.kallsyms]   [k] tcp_transmit_skb                          
     0.82%        swapper  [kernel.kallsyms]   [k] ip_queue_xmit                             
     0.81%        swapper  [kernel.kallsyms]   [k] __inet_lookup_established                 
     0.76%        swapper  [kernel.kallsyms]   [k] __kfree_skb                               
     0.73%        swapper  [kernel.kallsyms]   [k] ipv4_dst_check                            
     0.66%        netperf  [kernel.kallsyms]   [k] tcp_ack                                   
     0.60%        swapper  [kernel.kallsyms]   [k] __alloc_skb                               
     0.56%        swapper  [kernel.kallsyms]   [k] ipt_do_table                              

^ permalink raw reply

* Re: [PATCH net-next] net: introduce netdevice gso_min_segs attribute
From: Eric Dumazet @ 2014-10-06 12:17 UTC (permalink / raw)
  To: Amir Vadai
  Cc: David S. Miller, Eric Dumazet, netdev, Yevgeny Petrilin,
	Or Gerlitz, Ido Shamay
In-Reply-To: <5432399B.3060406@mellanox.com>

On Mon, 2014-10-06 at 09:41 +0300, Amir Vadai wrote:
> On 10/5/2014 8:11 PM, Eric Dumazet wrote:
> > From: Eric Dumazet <edumazet@google.com>
> > 
> > Some TSO engines might have a too heavy setup cost, that impacts
> > performance on hosts sending small bursts (2 MSS per packet).
> > 
> > This patch adds a device gso_min_segs, allowing drivers to set
> > a minimum segment size for TSO packets, according to the NIC
> > performance.
> > 
> > Tested on a mlx4 NIC, this allows to get a ~110% increase of
> > throughput when sending 2 MSS per packet.
> > 
> 
> Amazing!
> 
> Shouldn't there be a netif_set_gso_min_size() too?

Good point, I'll add it in v2, thanks !

^ permalink raw reply

* Re: [PATCH 09/16] virtio-net: drop config_mutex
From: Michael S. Tsirkin @ 2014-10-06 12:22 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <54328604.30403@cogentembedded.com>

On Mon, Oct 06, 2014 at 04:07:32PM +0400, Sergei Shtylyov wrote:
> On 10/6/2014 3:56 PM, Michael S. Tsirkin wrote:
> 
> >>>config_mutex served two purposes: prevent multiple concurrent config
> >>>change handlers, and synchronize access to config_enable flag.
> 
> >>>Since commit dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1
> >>>     workqueue: make all workqueues non-reentrant
> >>>all workqueues are non-reentrant, and config_enable
> >>>is now gone.
> 
> >>>Get rid of the unnecessary lock.
> 
> >>>Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> >>>---
> >>>  drivers/net/virtio_net.c | 7 +------
> >>>  1 file changed, 1 insertion(+), 6 deletions(-)
> 
> >>>diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> >>>index fa17afa..d80fef4 100644
> >>>--- a/drivers/net/virtio_net.c
> >>>+++ b/drivers/net/virtio_net.c
> >>[...]
> >>>@@ -1430,7 +1426,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
> >>>  		netif_tx_stop_all_queues(vi->dev);
> >>>  	}
> >>>  done:
> >>>-	mutex_unlock(&vi->config_lock);
> >>>+	return;
> 
> >>    There's no need for this *return*.
> 
> >I know - it's removed by the follow-up patch.
> 
>    Yeah, I saw.
> 
> >It's formatted like this to make diff smaller
> >and make review easier.
> 
>    Don't understand how adding this line makes diff smaller though...
> You first need to add it and then to delete it, where's the save?
> 
> WBR, Sergei


If I don't add it, gcc generates a compiler warning: it does not like
labels at the end of functions.
So I don't want to just drop the return function: I must drop the label too.

^ permalink raw reply

* Re: [PATCH net-next] net: introduce netdevice gso_min_segs attribute
From: Eric Dumazet @ 2014-10-06 12:22 UTC (permalink / raw)
  To: Amir Vadai
  Cc: David S. Miller, Eric Dumazet, netdev, Yevgeny Petrilin,
	Or Gerlitz, Ido Shamay
In-Reply-To: <1412597876.11091.59.camel@edumazet-glaptop2.roam.corp.google.com>

On Mon, 2014-10-06 at 05:17 -0700, Eric Dumazet wrote:
> On Mon, 2014-10-06 at 09:41 +0300, Amir Vadai wrote:
> > On 10/5/2014 8:11 PM, Eric Dumazet wrote:
> > > From: Eric Dumazet <edumazet@google.com>
> > > 
> > > Some TSO engines might have a too heavy setup cost, that impacts
> > > performance on hosts sending small bursts (2 MSS per packet).
> > > 
> > > This patch adds a device gso_min_segs, allowing drivers to set
> > > a minimum segment size for TSO packets, according to the NIC
> > > performance.
> > > 
> > > Tested on a mlx4 NIC, this allows to get a ~110% increase of
> > > throughput when sending 2 MSS per packet.
> > > 
> > 
> > Amazing!
> > 
> > Shouldn't there be a netif_set_gso_min_size() too?
> 
> Good point, I'll add it in v2, thanks !

Well, no... I thought you were speaking of an hypothetical
netif_set_gso_{max|min}_segs()

But we don't have it. : Drivers simply change dev->gso_max_segs

drivers/net/ethernet/freescale/fec_main.c:3058:         ndev->gso_max_segs = FEC_MAX_TSO_SEGS;
drivers/net/ethernet/marvell/mv643xx_eth.c:3120:        dev->gso_max_segs = MV643XX_MAX_TSO_SEGS;
drivers/net/ethernet/marvell/mvneta.c:3057:     dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;
drivers/net/ethernet/sfc/efx.c:2300:    net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;

So my mlx4 patch was simply doing

	dev->gso_min_segs = MLX4_MIN_TSO_SEGS;

^ permalink raw reply

* Re: [PATCH 09/16] virtio-net: drop config_mutex
From: Sergei Shtylyov @ 2014-10-06 12:31 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <20141006122215.GA26790@redhat.com>

On 10/6/2014 4:22 PM, Michael S. Tsirkin wrote:

>>>>> config_mutex served two purposes: prevent multiple concurrent config
>>>>> change handlers, and synchronize access to config_enable flag.

>>>>> Since commit dbf2576e37da0fcc7aacbfbb9fd5d3de7888a3c1
>>>>>      workqueue: make all workqueues non-reentrant
>>>>> all workqueues are non-reentrant, and config_enable
>>>>> is now gone.

>>>>> Get rid of the unnecessary lock.

>>>>> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>>>>> ---
>>>>>   drivers/net/virtio_net.c | 7 +------
>>>>>   1 file changed, 1 insertion(+), 6 deletions(-)

>>>>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>>>>> index fa17afa..d80fef4 100644
>>>>> --- a/drivers/net/virtio_net.c
>>>>> +++ b/drivers/net/virtio_net.c
>>>> [...]
>>>>> @@ -1430,7 +1426,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
>>>>>   		netif_tx_stop_all_queues(vi->dev);
>>>>>   	}
>>>>>   done:
>>>>> -	mutex_unlock(&vi->config_lock);
>>>>> +	return;

>>>>     There's no need for this *return*.

>>> I know - it's removed by the follow-up patch.

>>     Yeah, I saw.

>>> It's formatted like this to make diff smaller
>>> and make review easier.

>>     Don't understand how adding this line makes diff smaller though...
>> You first need to add it and then to delete it, where's the save?

>> WBR, Sergei

> If I don't add it, gcc generates a compiler warning: it does not like
> labels at the end of functions.

    Ahh... nevermind then.

WBR, Sergei

^ permalink raw reply

* Re: [PATCH net-next V1 00/14] net/mlx4_en: Optimizations to TX flow
From: Eric Dumazet @ 2014-10-06 12:51 UTC (permalink / raw)
  To: Amir Vadai
  Cc: David S. Miller, Eric Dumazet, netdev, Yevgeny Petrilin,
	Or Gerlitz, Ido Shamay
In-Reply-To: <1412576163-7224-1-git-send-email-amirv@mellanox.com>

On Mon, 2014-10-06 at 09:15 +0300, Amir Vadai wrote:

> Changes from V0:
> - Patch 14/14 ("Use the new tx_copybreak to set inline threshold"):
>   - Use same coding convention as currently is in en_ethtool.c
> - Patch 1/14 ("Code cleanups in tx path") and Patch 9/14 ("Use local var in
>   tx flow for skb_shinfo(skb)"):
>   - local var shinfo was used by mistake in Patch 1/14 while declared at 9/14.
>     Fixed it for the sake of future bisections

Hmm... patches were already merged. I am afraid you need to provide one
patch on top of current net-next, if still needed. Too bad for the
bisection.

Thanks !

^ permalink raw reply

* Re: [PATCH net-next V1 00/14] net/mlx4_en: Optimizations to TX flow
From: Amir Vadai @ 2014-10-06 12:54 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David S. Miller, Eric Dumazet, netdev, Yevgeny Petrilin,
	Or Gerlitz, Ido Shamay
In-Reply-To: <1412599904.11091.66.camel@edumazet-glaptop2.roam.corp.google.com>

On 10/6/2014 3:51 PM, Eric Dumazet wrote:
> On Mon, 2014-10-06 at 09:15 +0300, Amir Vadai wrote:
> 
>> Changes from V0:
>> - Patch 14/14 ("Use the new tx_copybreak to set inline threshold"):
>>   - Use same coding convention as currently is in en_ethtool.c
>> - Patch 1/14 ("Code cleanups in tx path") and Patch 9/14 ("Use local var in
>>   tx flow for skb_shinfo(skb)"):
>>   - local var shinfo was used by mistake in Patch 1/14 while declared at 9/14.
>>     Fixed it for the sake of future bisections
> 
> Hmm... patches were already merged. I am afraid you need to provide one
> patch on top of current net-next, if still needed. Too bad for the
> bisection.
> 
> Thanks !
> 
> 

Yeh, I missed it somehow. Sorry for the spam.

Amir

^ permalink raw reply

* Re: macvlan: optimizing the receive path?
From: Vlad Yasevich @ 2014-10-06 13:04 UTC (permalink / raw)
  To: David Miller, jbaron; +Cc: netdev, kaber
In-Reply-To: <20141004.204203.2211720828886085354.davem@davemloft.net>

On 10/04/2014 08:42 PM, David Miller wrote:
> From: Jason Baron <jbaron@akamai.com>
> Date: Thu, 02 Oct 2014 16:28:13 -0400
> 
>> --- a/drivers/net/macvlan.c
>> +++ b/drivers/net/macvlan.c
>> @@ -321,8 +321,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
>>         skb->dev = dev;
>>         skb->pkt_type = PACKET_HOST;
>>  
>> -       ret = netif_rx(skb);
>> -
>> +      macvlan_count_rx(vlan, len, true, 0);
>> +      return RX_HANDLER_ANOTHER;
>>  out:
>>         macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0);
>>         return RX_HANDLER_CONSUMED;
> 
> That last argument to macvlan_count_rx() is a bool and thus should be
> specified as "false".  Yes I know other areas of this file get it
> wrong too.
> 
> Also, what about GRO?  Won't we get GRO processing if we do this via
> netif_rx() but not via the RX_HANDLER_ANOTHER route?  Just curious...

Wouldn't GRO already happen at the lower level?  For macvlan-to-macvlan,
you'd typically have large packets so no need for GRO.

-vlad

^ permalink raw reply

* Re: [PATCH] drivers/net/phy/Kconfig: Let MDIO_BCM_UNIMAC depend on HAS_IOMEM
From: Chen Gang @ 2014-10-06 13:05 UTC (permalink / raw)
  To: David Miller; +Cc: f.fainelli, netdev, linux-kernel, richard
In-Reply-To: <20141006.004646.685997864382345892.davem@davemloft.net>

On 10/6/14 12:46, David Miller wrote:
> From: Chen Gang <gang.chen.5i5j@gmail.com>
> Date: Sat, 04 Oct 2014 17:54:33 +0800
> 
>> MDIO_BCM_UNIMAC needs HAS_IOMEM, so depend on it, the related error (
>> with allmodconfig under um):
>>
>>     MODPOST 1205 modules
>>   ERROR: "devm_ioremap" [drivers/net/phy/mdio-bcm-unimac.ko] undefined!
>>
>> Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
> 
> Applied, thanks.
> 

Thank you for your work.

-- 
Chen Gang

Open, share, and attitude like air, water, and life which God blessed

^ permalink raw reply

* Re: [PATCH] sctp: handle association restarts when the socket is closed.
From: Vlad Yasevich @ 2014-10-06 13:08 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20141006.002229.1370132762577292096.davem@davemloft.net>

On 10/06/2014 12:22 AM, David Miller wrote:
> From: Vladislav Yasevich <vyasevich@gmail.com>
> Date: Fri,  3 Oct 2014 18:16:20 -0400
> 
>> From: Vlad Yasevich <vyasevich@gmail.com>
>>
>> Currently association restarts do not take into consideration the
>> state of the socket.  When a restart happens, the current assocation
>> simply transitions into established state.  This creates a condition
>> where a remote system, through a the restart procedure, may create a
>> local association that is no way reachable by user.  The conditions
>> to trigger this are as follows:
>>   1) Remote does not acknoledge some data causing data to remain
>>      outstanding.
>>   2) Local application calls close() on the socket.  Since data
>>      is still outstanding, the association is placed in SHUTDOWN_PENDING
>>      state.  However, the socket is closed.
>>   3) The remote tries to create a new association, triggering a restart
>>      on the local system.  The association moves from SHUTDOWN_PENDING
>>      to ESTABLISHED.  At this point, it is no longer reachable by
>>      any socket on the local system.
>>
>> This patch addresses the above situation by moving the newly ESTABLISHED
>> association into SHUTDOWN-SENT state and bundling a SHUTDOWN after
>> the COOKIE-ACK chunk.  This way, the restarted associate immidiately
>> enters the shutdown procedure and forces the termination of the
>> unreachable association.
>>
>> Reported-by: David Laight <David.Laight@aculab.com>
>> Signed-off-by: Vlad Yasevich <vyasevich@gmail.com>
> 
> Applied, thanks.
> 
> Candidate for -stable?
> 

I say yes.  If this problem is triggered it is total pain to get the memory
clean-up.

-vlad

^ permalink raw reply

* RE: [PATCH v2 net-next 15/15] tipc: remove old ASCII netlink API
From: Jon Maloy @ 2014-10-06 13:37 UTC (permalink / raw)
  To: David Miller, Richard Alpe
  Cc: netdev@vger.kernel.org, tipc-discussion@lists.sourceforge.net
In-Reply-To: <20141003.165038.2121547250200790300.davem@davemloft.net>



> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-
> owner@vger.kernel.org] On Behalf Of David Miller
> Sent: October-03-14 7:51 PM
> To: Richard Alpe
> Cc: netdev@vger.kernel.org; tipc-discussion@lists.sourceforge.net
> Subject: Re: [PATCH v2 net-next 15/15] tipc: remove old ASCII netlink API
> 
> From: <richard.alpe@ericsson.com>
> Date: Thu, 2 Oct 2014 16:58:41 +0200
> 
> > From: Richard Alpe <richard.alpe@ericsson.com>
> >
> > The API has been deprecated along with its user-space tool
> > "tipc-config". Users shall use the new kernel netlink API already in
> > place along with the new user space tool "tipc" that's part of the
> > tipc-utils package.
> >
> > Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
> > Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
> > Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
> > Acked-by: Ying Xue <ying.xue@windriver.com>
> 
> Sorry, no matter what your circumstances, you cannot just break binaries
> that might be out there.

I disagree.  We did of course consider this before we posted the patch.  
There is absolutely no reason to believe there are binaries "out there" 
using this API. It is intended for and used only by our own tool "tipc-config", 
and the half-baked documentation that exists about it is not even
correct. This is an TIPC-internal API/ABI, which has changed over the years,
and keeps changing.  To our best judgement there is no risk in removing the
old API.

However, we took great care to not break any scripts that might be using 
tipc-config. Therefore, we made this wrapper that provides the old 
tipc-config command API to existing users.

Regards
///jon
> 
> The rest of this patch series is fine, but I'm really not going to even entertain
> applying this one, sorry.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in the body
> of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net-next] qdisc: validate skb without holding lock
From: Jesper Dangaard Brouer @ 2014-10-06 14:12 UTC (permalink / raw)
  To: David Miller
  Cc: eric.dumazet, netdev, therbert, hannes, fw, dborkman, jhs,
	alexander.duyck, john.r.fastabend, dave.taht, toke, brouer
In-Reply-To: <20141003.153645.72976986956341944.davem@davemloft.net>

On Fri, 03 Oct 2014 15:36:45 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:

> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Fri, 03 Oct 2014 15:31:07 -0700
> 
> > From: Eric Dumazet <edumazet@google.com>
> > 
> > Validation of skb can be pretty expensive :
> > 
> > GSO segmentation and/or checksum computations.
> > 
> > We can do this without holding qdisc lock, so that other cpus
> > can queue additional packets.
> > 
[...]
> > 
> > Turning TSO on or off had no effect on throughput, only few more cpu
> > cycles. Lock contention on qdisc lock disappeared.

This is good work! Lock contention significantly reduced!

My 10G tests just 2x 10G netperf TCP_STREAM shows:

 With GSO=off TSO=off, _raw_spin_lock is now only at perf top#13 with
1.44% (80% from qdisc calls, 60% is from __dev_queue_xmit and 20% from
sch_direct_xmit) (before with qdisc bulking is was 2.66%).

 The "show off" case is GSO=on TSO=off, where raw_spin_lock is now only
at perf top#26 with 0.85% and only 54.74% comes from qdisc calls
(52.07% sch_direct_xmit and 2.67% __dev_queue_xmit).


This is some significant improvements to the kernels xmit layer,
me very happy!!! :-))) Thanks everyone!

-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Sr. Network Kernel Developer at Red Hat
  Author of http://www.iptv-analyzer.org
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply

* Re: [PATCH 16/16] virtio_net: fix use after free on allocation failure
From: Cornelia Huck @ 2014-10-06 14:17 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: netdev, linux-kernel, virtualization
In-Reply-To: <1412525038-15871-17-git-send-email-mst@redhat.com>

On Sun, 5 Oct 2014 19:07:38 +0300
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> In the extremely unlikely event that driver initialization fails after
> RX buffers are added, virtio net frees RX buffers while VQs are
> still active, potentially causing device to use a freed buffer.
> 
> To fix, reset device first - same as we do on device removal.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  drivers/net/virtio_net.c | 2 ++
>  1 file changed, 2 insertions(+)

Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>

^ permalink raw reply

* [PATCH linux v2 0/1] Optimize network interfaces creation
From: Nicolas Dichtel @ 2014-10-06 14:30 UTC (permalink / raw)
  To: netdev, linux-kernel
  Cc: davem, ebiederm, akpm, adobriyan, rui.xiang, viro, oleg, gorcunov,
	kirill.shutemov, grant.likely, tytso
In-Reply-To: <542EA009.4060009@6wind.com>

When a lot of netdevices are created, one of the bottleneck is the creation
of proc entries. This serie aims to accelerate this part.

I'm not sure against which tree this patch should be done. I've done it against
linux.git.

RFCv1 -> v2
 - use a red-black tree instead of a hash list

 fs/proc/generic.c  | 164 ++++++++++++++++++++++++++++++++++-------------------
 fs/proc/internal.h |  11 ++--
 fs/proc/proc_net.c |   1 +
 fs/proc/root.c     |   1 +
 4 files changed, 113 insertions(+), 64 deletions(-)

Comments are welcome.

Regards,
Nicolas

^ permalink raw reply

* [PATCH linux v2 1/1] fs/proc: use a rb tree for the directory entries
From: Nicolas Dichtel @ 2014-10-06 14:30 UTC (permalink / raw)
  To: netdev, linux-kernel
  Cc: davem, ebiederm, akpm, adobriyan, rui.xiang, viro, oleg, gorcunov,
	kirill.shutemov, grant.likely, tytso, Nicolas Dichtel
In-Reply-To: <1412605834-4417-1-git-send-email-nicolas.dichtel@6wind.com>

The current implementation for the directories in /proc is using a single
linked list. This is slow when handling directories with large numbers of
entries (eg netdevice-related entries when lots of tunnels are opened).

This patch replaces this linked list by a red-black tree.

Here are some numbers:

dummy30000.batch contains 30 000 times 'link add type dummy'.

Before the patch:
$ time ip -b dummy30000.batch
real	2m31.950s
user	0m0.440s
sys	2m21.440s
$ time rmmod dummy
real	1m35.764s
user	0m0.000s
sys	1m24.088s

After the patch:
$ time ip -b dummy30000.batch
real	2m0.874s
user	0m0.448s
sys	1m49.720s
$ time rmmod dummy
real	1m13.988s
user	0m0.000s
sys	1m1.008s

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 fs/proc/generic.c  | 164 ++++++++++++++++++++++++++++++++++-------------------
 fs/proc/internal.h |  11 ++--
 fs/proc/proc_net.c |   1 +
 fs/proc/root.c     |   1 +
 4 files changed, 113 insertions(+), 64 deletions(-)

diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 317b72641ebf..9f8fa1e5e8aa 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -31,9 +31,81 @@ static DEFINE_SPINLOCK(proc_subdir_lock);
 
 static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de)
 {
-	if (de->namelen != len)
-		return 0;
-	return !memcmp(name, de->name, len);
+	if (len < de->namelen)
+		return -1;
+	if (len > de->namelen)
+		return 1;
+
+	return memcmp(name, de->name, len);
+}
+
+static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir)
+{
+	struct rb_node *node = rb_first(&dir->subdir);
+
+	if (node == NULL)
+		return NULL;
+
+	return rb_entry(node, struct proc_dir_entry, subdir_node);
+}
+
+static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir)
+{
+	struct rb_node *node = rb_next(&dir->subdir_node);
+
+	if (node == NULL)
+		return NULL;
+
+	return rb_entry(node, struct proc_dir_entry, subdir_node);
+}
+
+static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
+					      const char *name,
+					      unsigned int len)
+{
+	struct rb_node *node = dir->subdir.rb_node;
+
+	while (node) {
+		struct proc_dir_entry *de = container_of(node,
+							 struct proc_dir_entry,
+							 subdir_node);
+		int result = proc_match(len, name, de);
+
+		if (result < 0)
+			node = node->rb_left;
+		else if (result > 0)
+			node = node->rb_right;
+		else
+			return de;
+	}
+	return NULL;
+}
+
+static bool pde_subdir_insert(struct proc_dir_entry *dir,
+			      struct proc_dir_entry *de)
+{
+	struct rb_root *root = &dir->subdir;
+	struct rb_node **new = &root->rb_node, *parent = NULL;
+
+	/* Figure out where to put new node */
+	while (*new) {
+		struct proc_dir_entry *this =
+			container_of(*new, struct proc_dir_entry, subdir_node);
+		int result = proc_match(de->namelen, de->name, this);
+
+		parent = *new;
+		if (result < 0)
+			new = &(*new)->rb_left;
+		else if (result > 0)
+			new = &(*new)->rb_right;
+		else
+			return false;
+	}
+
+	/* Add new node and rebalance tree. */
+	rb_link_node(&de->subdir_node, parent, new);
+	rb_insert_color(&de->subdir_node, root);
+	return true;
 }
 
 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
@@ -92,10 +164,7 @@ static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
 			break;
 
 		len = next - cp;
-		for (de = de->subdir; de ; de = de->next) {
-			if (proc_match(len, cp, de))
-				break;
-		}
+		de = pde_subdir_find(de, cp, len);
 		if (!de) {
 			WARN(1, "name '%s'\n", name);
 			return -ENOENT;
@@ -183,19 +252,16 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
 	struct inode *inode;
 
 	spin_lock(&proc_subdir_lock);
-	for (de = de->subdir; de ; de = de->next) {
-		if (de->namelen != dentry->d_name.len)
-			continue;
-		if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
-			pde_get(de);
-			spin_unlock(&proc_subdir_lock);
-			inode = proc_get_inode(dir->i_sb, de);
-			if (!inode)
-				return ERR_PTR(-ENOMEM);
-			d_set_d_op(dentry, &simple_dentry_operations);
-			d_add(dentry, inode);
-			return NULL;
-		}
+	de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len);
+	if (de) {
+		pde_get(de);
+		spin_unlock(&proc_subdir_lock);
+		inode = proc_get_inode(dir->i_sb, de);
+		if (!inode)
+			return ERR_PTR(-ENOMEM);
+		d_set_d_op(dentry, &simple_dentry_operations);
+		d_add(dentry, inode);
+		return NULL;
 	}
 	spin_unlock(&proc_subdir_lock);
 	return ERR_PTR(-ENOENT);
@@ -225,7 +291,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
 		return 0;
 
 	spin_lock(&proc_subdir_lock);
-	de = de->subdir;
+	de = pde_subdir_first(de);
 	i = ctx->pos - 2;
 	for (;;) {
 		if (!de) {
@@ -234,7 +300,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
 		}
 		if (!i)
 			break;
-		de = de->next;
+		de = pde_subdir_next(de);
 		i--;
 	}
 
@@ -249,7 +315,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
 		}
 		spin_lock(&proc_subdir_lock);
 		ctx->pos++;
-		next = de->next;
+		next = pde_subdir_next(de);
 		pde_put(de);
 		de = next;
 	} while (de);
@@ -286,9 +352,8 @@ static const struct inode_operations proc_dir_inode_operations = {
 
 static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
 {
-	struct proc_dir_entry *tmp;
 	int ret;
-	
+
 	ret = proc_alloc_inum(&dp->low_ino);
 	if (ret)
 		return ret;
@@ -308,17 +373,10 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
 	}
 
 	spin_lock(&proc_subdir_lock);
-
-	for (tmp = dir->subdir; tmp; tmp = tmp->next)
-		if (strcmp(tmp->name, dp->name) == 0) {
-			WARN(1, "proc_dir_entry '%s/%s' already registered\n",
-				dir->name, dp->name);
-			break;
-		}
-
-	dp->next = dir->subdir;
 	dp->parent = dir;
-	dir->subdir = dp;
+	if (pde_subdir_insert(dir, dp) == false)
+		WARN(1, "proc_dir_entry '%s/%s' already registered\n",
+		     dir->name, dp->name);
 	spin_unlock(&proc_subdir_lock);
 
 	return 0;
@@ -354,6 +412,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
 	ent->namelen = qstr.len;
 	ent->mode = mode;
 	ent->nlink = nlink;
+	ent->subdir = RB_ROOT;
 	atomic_set(&ent->count, 1);
 	spin_lock_init(&ent->pde_unload_lock);
 	INIT_LIST_HEAD(&ent->pde_openers);
@@ -485,7 +544,6 @@ void pde_put(struct proc_dir_entry *pde)
  */
 void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
 {
-	struct proc_dir_entry **p;
 	struct proc_dir_entry *de = NULL;
 	const char *fn = name;
 	unsigned int len;
@@ -497,14 +555,9 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
 	}
 	len = strlen(fn);
 
-	for (p = &parent->subdir; *p; p=&(*p)->next ) {
-		if (proc_match(len, fn, *p)) {
-			de = *p;
-			*p = de->next;
-			de->next = NULL;
-			break;
-		}
-	}
+	de = pde_subdir_find(parent, fn, len);
+	if (de)
+		rb_erase(&de->subdir_node, &parent->subdir);
 	spin_unlock(&proc_subdir_lock);
 	if (!de) {
 		WARN(1, "name '%s'\n", name);
@@ -516,16 +569,15 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
 	if (S_ISDIR(de->mode))
 		parent->nlink--;
 	de->nlink = 0;
-	WARN(de->subdir, "%s: removing non-empty directory "
-			 "'%s/%s', leaking at least '%s'\n", __func__,
-			 de->parent->name, de->name, de->subdir->name);
+	WARN(pde_subdir_first(de),
+	     "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n",
+	     __func__, de->parent->name, de->name, pde_subdir_first(de)->name);
 	pde_put(de);
 }
 EXPORT_SYMBOL(remove_proc_entry);
 
 int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
 {
-	struct proc_dir_entry **p;
 	struct proc_dir_entry *root = NULL, *de, *next;
 	const char *fn = name;
 	unsigned int len;
@@ -537,24 +589,18 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
 	}
 	len = strlen(fn);
 
-	for (p = &parent->subdir; *p; p=&(*p)->next ) {
-		if (proc_match(len, fn, *p)) {
-			root = *p;
-			*p = root->next;
-			root->next = NULL;
-			break;
-		}
-	}
+	root = pde_subdir_find(parent, fn, len);
 	if (!root) {
 		spin_unlock(&proc_subdir_lock);
 		return -ENOENT;
 	}
+	rb_erase(&root->subdir_node, &parent->subdir);
+
 	de = root;
 	while (1) {
-		next = de->subdir;
+		next = pde_subdir_first(de);
 		if (next) {
-			de->subdir = next->next;
-			next->next = NULL;
+			rb_erase(&next->subdir_node, &de->subdir);
 			de = next;
 			continue;
 		}
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 7da13e49128a..433557634c1b 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -24,10 +24,9 @@ struct mempolicy;
  * tree) of these proc_dir_entries, so that we can dynamically
  * add new files to /proc.
  *
- * The "next" pointer creates a linked list of one /proc directory,
- * while parent/subdir create the directory structure (every
- * /proc file has a parent, but "subdir" is NULL for all
- * non-directory entries).
+ * parent/subdir are used for the directory structure (every /proc file has a
+ * parent, but "subdir" is empty for all non-directory entries).
+ * subdir_node is used to build the rb tree "subdir" of the parent.
  */
 struct proc_dir_entry {
 	unsigned int low_ino;
@@ -38,7 +37,9 @@ struct proc_dir_entry {
 	loff_t size;
 	const struct inode_operations *proc_iops;
 	const struct file_operations *proc_fops;
-	struct proc_dir_entry *next, *parent, *subdir;
+	struct proc_dir_entry *parent;
+	struct rb_root subdir;
+	struct rb_node subdir_node;
 	void *data;
 	atomic_t count;		/* use count */
 	atomic_t in_use;	/* number of callers into module in progress; */
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index a63af3e0a612..1bde894bc624 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -192,6 +192,7 @@ static __net_init int proc_net_ns_init(struct net *net)
 	if (!netd)
 		goto out;
 
+	netd->subdir = RB_ROOT;
 	netd->data = net;
 	netd->nlink = 2;
 	netd->namelen = 3;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 094e44d4a6be..4eae849baedd 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -166,6 +166,7 @@ void __init proc_root_init(void)
 {
 	int err;
 
+	proc_root.subdir = RB_ROOT;
 	proc_init_inodecache();
 	err = register_filesystem(&proc_fs_type);
 	if (err)
-- 
2.1.0

^ permalink raw reply related

* Re: CPSW bug with AM437x SK
From: Felipe Balbi @ 2014-10-06 14:33 UTC (permalink / raw)
  To: Mugunthan V N
  Cc: balbi, davem, netdev, Linux OMAP Mailing List,
	Linux ARM Kernel Mailing List, Linux Kernel Mailing List
In-Reply-To: <543266F3.4090200@ti.com>

[-- Attachment #1: Type: text/plain, Size: 1382 bytes --]

Hi,

On Mon, Oct 06, 2014 at 03:24:59PM +0530, Mugunthan V N wrote:
> On Friday 03 October 2014 06:34 AM, Felipe Balbi wrote:
> > [  261.177168] [<c0648d48>] (skb_panic) from [<c0565edc>] (skb_put+0x5c/0x60)
> > [  261.184415] [<c0565edc>] (skb_put) from [<c0605aac>] (unix_stream_sendmsg+0x164/0x390)
> > [  261.192712] [<c0605aac>] (unix_stream_sendmsg) from [<c055b364>] (sock_aio_write+0xdc/0xfc)
> > [  261.201475] [<c055b364>] (sock_aio_write) from [<c014c42c>] (do_sync_write+0x8c/0xb4)
> > [  261.209697] [<c014c42c>] (do_sync_write) from [<c014cf70>] (vfs_write+0x118/0x1c0)
> > [  261.217652] [<c014cf70>] (vfs_write) from [<c014d564>] (SyS_write+0x4c/0xa0)
> > [  261.225054] [<c014d564>] (SyS_write) from [<c000ed40>] (ret_fast_syscall+0x0/0x48)
> > [  261.232988] Code: e58d4008 e58de00c e59f0008 ebfff48e (e7f001f2) 
> > [  261.239378] ---[ end trace d64258d586f40104 ]---
> 
> The BT shows that the warn came from a unix socket interface, so this
> cannot be a CPSW bug, its a bug in unix socket.
> 
> Are you not seeing this issue with file system in any other media?

Have not tried with other media, but since it comes from vfs_write() and
my rootfs sits in NFS I figured "that might be the cause". Could not
reproduce this with BeagleBone Black, btw.

> I will try to reproduce this locally with my AM437x EVMsk.

alright.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply


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