All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices
@ 2018-10-05 10:24 Igor Russkikh
  2018-10-05 10:24   ` [net-next,01/19] " Igor Russkikh
                   ` (20 more replies)
  0 siblings, 21 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh

This patchset introduces support for new multigig ethernet to USB dongle,
developed jointly by Aquantia (Phy) and ASIX (USB MAC).

The driver has similar structure with other ASIX MAC drivers (AX88179), but
with a number of important differences:
- Driver supports both direct Phy and custom firmware interface for Phy
  programming. This is due to different firmware modules available with this
  product.
- Driver handles new 2.5G/5G link speed configuration and reporting.
- Device support all speeds from 100M up to 5G.
- Device supports MTU up to 16K.

Device supports various standard networking features, like
checksum offloads, vlan tagging/filtering, TSO.

The code of this driver is based on original ASIX sources and was extended
by Aquantia for 5G multigig support. 

Dmitry Bezrukov (19):
  net: usb: aqc111: Driver skeleton for Aquantia AQtion USB to 5GbE
  net: usb: aqc111: Add bind and empty unbind callbacks
  net: usb: aqc111: Add implementation of read and write commands
  net: usb: aqc111: Various callbacks implementation
  net: usb: aqc111: Introduce PHY access
  net: usb: aqc111: Introduce link management
  net: usb: aqc111: Add support for getting and setting of MAC address
  net: usb: aqc111: Implement TX data path
  net: usb: aqc111: Implement RX data path
  net: usb: aqc111: Add checksum offload support
  net: usb: aqc111: Add support for changing MTU
  net: usb: aqc111: Add support for enable/disable checksum offload
  net: usb: aqc111: Add support for TSO
  net: usb: aqc111: Implement set_rx_mode callback
  net: usb: aqc111: Add support for VLAN_CTAG_TX/RX offload
  net: usb: aqc111: Add RX VLAN filtering support
  net: usb: aqc111: Initialize ethtool_ops structure
  net: usb: aqc111: Implement get/set_link_ksettings callbacks
  net: usb: aqc111: Add support for wake on LAN by MAGIC packet

 drivers/net/usb/Kconfig  |   12 +
 drivers/net/usb/Makefile |    1 +
 drivers/net/usb/aqc111.c | 1583 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  345 ++++++++++
 4 files changed, 1941 insertions(+)
 create mode 100644 drivers/net/usb/aqc111.c
 create mode 100644 drivers/net/usb/aqc111.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH net-next 01/19] net: usb: aqc111: Driver skeleton for Aquantia AQtion USB to 5GbE
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Initialize usb_driver structure skeleton

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/Kconfig  | 12 +++++++++++
 drivers/net/usb/Makefile |  1 +
 drivers/net/usb/aqc111.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+)
 create mode 100644 drivers/net/usb/aqc111.c

diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 418b0904cecb..e5fb8ef2d815 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -613,4 +613,16 @@ config USB_NET_CH9200
 	  To compile this driver as a module, choose M here: the
 	  module will be called ch9200.
 
+config USB_NET_AQC111
+	tristate "Aquantia AQtion USB to 5/2.5GbE Controllers support"
+	depends on USB_USBNET
+	select CRC32
+	default y
+	help
+	  This option adds support for Aquantia AQtion USB
+	  Ethernet adapters based on AQC111U/AQC112 chips.
+
+	  This driver should work with at least the following devices:
+	  * Aquantia AQtion USB to 5GbE
+
 endif # USB_NET_DRIVERS
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index 27307a4ab003..99fd12be2111 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -40,3 +40,4 @@ obj-$(CONFIG_USB_VL600)		+= lg-vl600.o
 obj-$(CONFIG_USB_NET_QMI_WWAN)	+= qmi_wwan.o
 obj-$(CONFIG_USB_NET_CDC_MBIM)	+= cdc_mbim.o
 obj-$(CONFIG_USB_NET_CH9200)	+= ch9200.o
+obj-$(CONFIG_USB_NET_AQC111)	+= aqc111.o
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
new file mode 100644
index 000000000000..250e8ff65110
--- /dev/null
+++ b/drivers/net/usb/aqc111.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Aquantia Corp. Aquantia AQtion USB to 5GbE Controller
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (C) 2002-2003 TiVo Inc.
+ * Copyright (C) 2017-2018 ASIX
+ * Copyright (C) 2018 Aquantia Corp.
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+
+static const struct driver_info aqc111_info = {
+	.description	= "Aquantia AQtion USB to 5GbE Controller",
+};
+
+#define AQC111_USB_ETH_DEV(vid, pid, table) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+			USB_DEVICE_ID_MATCH_INT_CLASS, \
+	USB_DEVICE(vid, pid), \
+	.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
+	.driver_info = (unsigned long)&table, \
+}, \
+{ \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+			USB_DEVICE_ID_MATCH_INT_INFO, \
+	USB_DEVICE(vid, pid), \
+	.bInterfaceClass = USB_CLASS_COMM, \
+	.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
+	.bInterfaceProtocol = USB_CDC_PROTO_NONE
+
+static const struct usb_device_id products[] = {
+	{AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)},
+	{ },/* END */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver aq_driver = {
+	.name		= "aqc111",
+	.id_table	= products,
+	.probe		= usbnet_probe,
+	.disconnect	= usbnet_disconnect,
+};
+
+module_usb_driver(aq_driver);
+
+MODULE_DESCRIPTION("Aquantia AQtion USB to 5/2.5GbE Controllers");
+MODULE_LICENSE("GPL");
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,01/19] net: usb: aqc111: Driver skeleton for Aquantia AQtion USB to 5GbE
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Initialize usb_driver structure skeleton

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/Kconfig  | 12 +++++++++++
 drivers/net/usb/Makefile |  1 +
 drivers/net/usb/aqc111.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+)
 create mode 100644 drivers/net/usb/aqc111.c

diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 418b0904cecb..e5fb8ef2d815 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -613,4 +613,16 @@ config USB_NET_CH9200
 	  To compile this driver as a module, choose M here: the
 	  module will be called ch9200.
 
+config USB_NET_AQC111
+	tristate "Aquantia AQtion USB to 5/2.5GbE Controllers support"
+	depends on USB_USBNET
+	select CRC32
+	default y
+	help
+	  This option adds support for Aquantia AQtion USB
+	  Ethernet adapters based on AQC111U/AQC112 chips.
+
+	  This driver should work with at least the following devices:
+	  * Aquantia AQtion USB to 5GbE
+
 endif # USB_NET_DRIVERS
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index 27307a4ab003..99fd12be2111 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -40,3 +40,4 @@ obj-$(CONFIG_USB_VL600)		+= lg-vl600.o
 obj-$(CONFIG_USB_NET_QMI_WWAN)	+= qmi_wwan.o
 obj-$(CONFIG_USB_NET_CDC_MBIM)	+= cdc_mbim.o
 obj-$(CONFIG_USB_NET_CH9200)	+= ch9200.o
+obj-$(CONFIG_USB_NET_AQC111)	+= aqc111.o
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
new file mode 100644
index 000000000000..250e8ff65110
--- /dev/null
+++ b/drivers/net/usb/aqc111.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Aquantia Corp. Aquantia AQtion USB to 5GbE Controller
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (C) 2002-2003 TiVo Inc.
+ * Copyright (C) 2017-2018 ASIX
+ * Copyright (C) 2018 Aquantia Corp.
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+
+static const struct driver_info aqc111_info = {
+	.description	= "Aquantia AQtion USB to 5GbE Controller",
+};
+
+#define AQC111_USB_ETH_DEV(vid, pid, table) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+			USB_DEVICE_ID_MATCH_INT_CLASS, \
+	USB_DEVICE(vid, pid), \
+	.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
+	.driver_info = (unsigned long)&table, \
+}, \
+{ \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+			USB_DEVICE_ID_MATCH_INT_INFO, \
+	USB_DEVICE(vid, pid), \
+	.bInterfaceClass = USB_CLASS_COMM, \
+	.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
+	.bInterfaceProtocol = USB_CDC_PROTO_NONE
+
+static const struct usb_device_id products[] = {
+	{AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)},
+	{ },/* END */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver aq_driver = {
+	.name		= "aqc111",
+	.id_table	= products,
+	.probe		= usbnet_probe,
+	.disconnect	= usbnet_disconnect,
+};
+
+module_usb_driver(aq_driver);
+
+MODULE_DESCRIPTION("Aquantia AQtion USB to 5/2.5GbE Controllers");
+MODULE_LICENSE("GPL");

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 02/19] net: usb: aqc111: Add bind and empty unbind callbacks
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Initialize net_device_ops structure

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 250e8ff65110..c914e19387f2 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -14,8 +14,43 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 
+static const struct net_device_ops aqc111_netdev_ops = {
+	.ndo_open		= usbnet_open,
+	.ndo_stop		= usbnet_stop,
+};
+
+static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	/* Check if vendor configuration */
+	if (udev->actconfig->desc.bConfigurationValue != 1) {
+		usb_driver_set_configuration(udev, 1);
+		return -ENODEV;
+	}
+
+	usb_reset_configuration(dev->udev);
+
+	ret = usbnet_get_endpoints(dev, intf);
+	if (ret < 0) {
+		netdev_dbg(dev->net, "usbnet_get_endpoints failed");
+		return ret;
+	}
+
+	dev->net->netdev_ops = &aqc111_netdev_ops;
+
+	return 0;
+}
+
+static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+}
+
 static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
+	.bind		= aqc111_bind,
+	.unbind		= aqc111_unbind,
 };
 
 #define AQC111_USB_ETH_DEV(vid, pid, table) \
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,02/19] net: usb: aqc111: Add bind and empty unbind callbacks
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Initialize net_device_ops structure

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 250e8ff65110..c914e19387f2 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -14,8 +14,43 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 
+static const struct net_device_ops aqc111_netdev_ops = {
+	.ndo_open		= usbnet_open,
+	.ndo_stop		= usbnet_stop,
+};
+
+static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	/* Check if vendor configuration */
+	if (udev->actconfig->desc.bConfigurationValue != 1) {
+		usb_driver_set_configuration(udev, 1);
+		return -ENODEV;
+	}
+
+	usb_reset_configuration(dev->udev);
+
+	ret = usbnet_get_endpoints(dev, intf);
+	if (ret < 0) {
+		netdev_dbg(dev->net, "usbnet_get_endpoints failed");
+		return ret;
+	}
+
+	dev->net->netdev_ops = &aqc111_netdev_ops;
+
+	return 0;
+}
+
+static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+}
+
 static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
+	.bind		= aqc111_bind,
+	.unbind		= aqc111_unbind,
 };
 
 #define AQC111_USB_ETH_DEV(vid, pid, table) \

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Read/write command register defines and functions

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  19 ++++++++
 2 files changed, 143 insertions(+)
 create mode 100644 drivers/net/usb/aqc111.h

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index c914e19387f2..7f3e5a615750 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -14,6 +14,130 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 
+#include "aqc111.h"
+
+static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			     u16 index, u16 size, void *data, int nopm)
+{
+	int ret;
+	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
+		  u16 index, void *data, u16 size);
+
+	if (nopm)
+		fn = usbnet_read_cmd_nopm;
+	else
+		fn = usbnet_read_cmd;
+
+	ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 value, index, data, size);
+	if (size == 2)
+		le16_to_cpus(data);
+
+	if (unlikely(ret < 0))
+		netdev_warn(dev->net,
+			    "Failed to read(0x%x) reg index 0x%04x: %d\n",
+			    cmd, index, ret);
+	return ret;
+}
+
+static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
+				u16 index, u16 size, void *data)
+{
+	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 1);
+}
+
+static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			   u16 index, u16 size, void *data)
+{
+	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 0);
+}
+
+static int __aq_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+			  u16 value, u16 index, const void *data, u16 size)
+{
+	void *buf = NULL;
+	int err = -ENOMEM;
+
+	netdev_dbg(dev->net,
+		   "%s cmd=%#x reqtype=%#x value=%#x index=%#x size=%d\n",
+		   __func__, cmd, reqtype, value, index, size);
+
+	if (data) {
+		buf = kmemdup(data, size, GFP_KERNEL);
+		if (!buf)
+			goto out;
+	}
+
+	if (size == 2)
+		cpu_to_le16s(buf);
+	else if (size == 4)
+		cpu_to_le32s(buf);
+
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			      cmd, reqtype, value, index, buf, size,
+			      (cmd == AQ_PHY_POWER) ? AQ_USB_PHY_SET_TIMEOUT :
+			      AQ_USB_SET_TIMEOUT);
+
+	kfree(buf);
+
+out:
+	return err;
+}
+
+static int aq_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+			     u16 value, u16 index, const void *data, u16 size)
+{
+	return __aq_write_cmd(dev, cmd, reqtype, value, index,
+			      data, size);
+}
+
+static int aq_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+			u16 value, u16 index, const void *data, u16 size)
+{
+	int ret;
+
+	if (usb_autopm_get_interface(dev->intf) < 0)
+		return -ENODEV;
+	ret = __aq_write_cmd(dev, cmd, reqtype, value, index, data, size);
+	usb_autopm_put_interface(dev->intf);
+	return ret;
+}
+
+static int __aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			      u16 index, u16 size, void *data, int nopm)
+{
+	int ret;
+	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
+		  u16 index, const void *data, u16 size);
+
+	if (nopm)
+		fn = aq_write_cmd_nopm;
+	else
+		fn = aq_write_cmd;
+
+	ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 value, index, data, size);
+
+	if (unlikely(ret < 0))
+		netdev_warn(dev->net,
+			    "Failed to write(0x%x) reg 0x%04x: %d\n",
+			    cmd, value, ret);
+
+	return ret;
+}
+
+static int aqc111_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
+				 u16 index, u16 size, void *data)
+{
+	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 1);
+}
+
+static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			    u16 index, u16 size, void *data)
+{
+	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
new file mode 100644
index 000000000000..1698a6a104fe
--- /dev/null
+++ b/drivers/net/usb/aqc111.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Aquantia Corp. Aquantia AQtion USB to 5GbE Controller
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (C) 2002-2003 TiVo Inc.
+ * Copyright (C) 2017-2018 ASIX
+ * Copyright (C) 2018 Aquantia Corp.
+ */
+
+#ifndef __LINUX_USBNET_AQC111_H
+#define __LINUX_USBNET_AQC111_H
+
+#define AQ_PHY_POWER			0x31
+
+#define AQ_USB_PHY_SET_TIMEOUT		10000
+#define AQ_USB_SET_TIMEOUT		4000
+
+#endif /* __LINUX_USBNET_AQC111_H */
+
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Read/write command register defines and functions

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  19 ++++++++
 2 files changed, 143 insertions(+)
 create mode 100644 drivers/net/usb/aqc111.h

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index c914e19387f2..7f3e5a615750 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -14,6 +14,130 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 
+#include "aqc111.h"
+
+static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			     u16 index, u16 size, void *data, int nopm)
+{
+	int ret;
+	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
+		  u16 index, void *data, u16 size);
+
+	if (nopm)
+		fn = usbnet_read_cmd_nopm;
+	else
+		fn = usbnet_read_cmd;
+
+	ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 value, index, data, size);
+	if (size == 2)
+		le16_to_cpus(data);
+
+	if (unlikely(ret < 0))
+		netdev_warn(dev->net,
+			    "Failed to read(0x%x) reg index 0x%04x: %d\n",
+			    cmd, index, ret);
+	return ret;
+}
+
+static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
+				u16 index, u16 size, void *data)
+{
+	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 1);
+}
+
+static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			   u16 index, u16 size, void *data)
+{
+	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 0);
+}
+
+static int __aq_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+			  u16 value, u16 index, const void *data, u16 size)
+{
+	void *buf = NULL;
+	int err = -ENOMEM;
+
+	netdev_dbg(dev->net,
+		   "%s cmd=%#x reqtype=%#x value=%#x index=%#x size=%d\n",
+		   __func__, cmd, reqtype, value, index, size);
+
+	if (data) {
+		buf = kmemdup(data, size, GFP_KERNEL);
+		if (!buf)
+			goto out;
+	}
+
+	if (size == 2)
+		cpu_to_le16s(buf);
+	else if (size == 4)
+		cpu_to_le32s(buf);
+
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			      cmd, reqtype, value, index, buf, size,
+			      (cmd == AQ_PHY_POWER) ? AQ_USB_PHY_SET_TIMEOUT :
+			      AQ_USB_SET_TIMEOUT);
+
+	kfree(buf);
+
+out:
+	return err;
+}
+
+static int aq_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+			     u16 value, u16 index, const void *data, u16 size)
+{
+	return __aq_write_cmd(dev, cmd, reqtype, value, index,
+			      data, size);
+}
+
+static int aq_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+			u16 value, u16 index, const void *data, u16 size)
+{
+	int ret;
+
+	if (usb_autopm_get_interface(dev->intf) < 0)
+		return -ENODEV;
+	ret = __aq_write_cmd(dev, cmd, reqtype, value, index, data, size);
+	usb_autopm_put_interface(dev->intf);
+	return ret;
+}
+
+static int __aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			      u16 index, u16 size, void *data, int nopm)
+{
+	int ret;
+	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
+		  u16 index, const void *data, u16 size);
+
+	if (nopm)
+		fn = aq_write_cmd_nopm;
+	else
+		fn = aq_write_cmd;
+
+	ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 value, index, data, size);
+
+	if (unlikely(ret < 0))
+		netdev_warn(dev->net,
+			    "Failed to write(0x%x) reg 0x%04x: %d\n",
+			    cmd, value, ret);
+
+	return ret;
+}
+
+static int aqc111_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
+				 u16 index, u16 size, void *data)
+{
+	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 1);
+}
+
+static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
+			    u16 index, u16 size, void *data)
+{
+	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
new file mode 100644
index 000000000000..1698a6a104fe
--- /dev/null
+++ b/drivers/net/usb/aqc111.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Aquantia Corp. Aquantia AQtion USB to 5GbE Controller
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (C) 2002-2003 TiVo Inc.
+ * Copyright (C) 2017-2018 ASIX
+ * Copyright (C) 2018 Aquantia Corp.
+ */
+
+#ifndef __LINUX_USBNET_AQC111_H
+#define __LINUX_USBNET_AQC111_H
+
+#define AQ_PHY_POWER			0x31
+
+#define AQ_USB_PHY_SET_TIMEOUT		10000
+#define AQ_USB_SET_TIMEOUT		4000
+
+#endif /* __LINUX_USBNET_AQC111_H */
+

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Reset, stop callbacks, driver unbind callback.
More register defines required for these callbacks.

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 149 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 7f3e5a615750..22bb259d71fb 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 
 static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
+	u8 reg8;
+	u16 reg16;
+
+	/* Force bz */
+	reg16 = SFR_PHYPWR_RSTCTL_BZ;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			      2, 2, &reg16);
+	reg16 = 0;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			      2, 2, &reg16);
+}
+
+static int aqc111_reset(struct usbnet *dev)
+{
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+
+	reg8 = 0xFF;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, &reg8);
+
+	reg8 = 0x0;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_SWP_CTRL, 1, 1, &reg8);
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, &reg8);
+	reg8 &= ~(SFR_MONITOR_MODE_EPHYRW | SFR_MONITOR_MODE_RWLC |
+		  SFR_MONITOR_MODE_RWMP | SFR_MONITOR_MODE_RWWF |
+		  SFR_MONITOR_MODE_RW_FLAG);
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, &reg8);
+
+	return 0;
+}
+
+static int aqc111_stop(struct usbnet *dev)
+{
+	u16 reg16 = 0;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			2, 2, &reg16);
+	reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			 2, 2, &reg16);
+	reg16 = 0;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			 2, 2, &reg16);
+
+	return 0;
 }
 
 static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
 	.bind		= aqc111_bind,
 	.unbind		= aqc111_unbind,
+	.reset		= aqc111_reset,
+	.stop		= aqc111_stop,
 };
 
 #define AQC111_USB_ETH_DEV(vid, pid, table) \
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 1698a6a104fe..6b34202fa22b 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -10,10 +10,111 @@
 #ifndef __LINUX_USBNET_AQC111_H
 #define __LINUX_USBNET_AQC111_H
 
+#define AQ_ACCESS_MAC			0x01
 #define AQ_PHY_POWER			0x31
 
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
 
+/* SFR Reg. ********************************************/
+
+#define SFR_GENERAL_STATUS		0x03
+#define SFR_CHIP_STATUS			0x05
+#define SFR_RX_CTL			0x0B
+	#define SFR_RX_CTL_TXPADCRC		0x0400
+	#define SFR_RX_CTL_IPE			0x0200
+	#define SFR_RX_CTL_DROPCRCERR		0x0100
+	#define SFR_RX_CTL_START		0x0080
+	#define SFR_RX_CTL_RF_WAK		0x0040
+	#define SFR_RX_CTL_AP			0x0020
+	#define SFR_RX_CTL_AM			0x0010
+	#define SFR_RX_CTL_AB			0x0008
+	#define SFR_RX_CTL_AMALL		0x0002
+	#define SFR_RX_CTL_PRO			0x0001
+	#define SFR_RX_CTL_STOP			0x0000
+#define SFR_INTER_PACKET_GAP_0		0x0D
+#define SFR_NODE_ID			0x10
+#define SFR_MULTI_FILTER_ARRY		0x16
+#define SFR_MEDIUM_STATUS_MODE		0x22
+	#define SFR_MEDIUM_XGMIIMODE		0x0001
+	#define SFR_MEDIUM_FULL_DUPLEX		0x0002
+	#define SFR_MEDIUM_RXFLOW_CTRLEN	0x0010
+	#define SFR_MEDIUM_TXFLOW_CTRLEN	0x0020
+	#define SFR_MEDIUM_JUMBO_EN		0x0040
+	#define SFR_MEDIUM_RECEIVE_EN		0x0100
+#define SFR_MONITOR_MODE		0x24
+	#define SFR_MONITOR_MODE_EPHYRW		0x01
+	#define SFR_MONITOR_MODE_RWLC		0x02
+	#define SFR_MONITOR_MODE_RWMP		0x04
+	#define SFR_MONITOR_MODE_RWWF		0x08
+	#define SFR_MONITOR_MODE_RW_FLAG	0x10
+	#define SFR_MONITOR_MODE_PMEPOL		0x20
+	#define SFR_MONITOR_MODE_PMETYPE	0x40
+#define SFR_PHYPWR_RSTCTL		0x26
+	#define SFR_PHYPWR_RSTCTL_BZ		0x0010
+	#define SFR_PHYPWR_RSTCTL_IPRL		0x0020
+#define SFR_VLAN_ID_ADDRESS		0x2A
+#define SFR_VLAN_ID_CONTROL		0x2B
+	#define SFR_VLAN_CONTROL_WE		0x0001
+	#define SFR_VLAN_CONTROL_RD		0x0002
+	#define SFR_VLAN_CONTROL_VSO		0x0010
+	#define SFR_VLAN_CONTROL_VFE		0x0020
+#define SFR_VLAN_ID_DATA0		0x2C
+#define SFR_VLAN_ID_DATA1		0x2D
+#define SFR_RX_BULKIN_QCTRL		0x2E
+	#define SFR_RX_BULKIN_QCTRL_TIME	0x01
+	#define SFR_RX_BULKIN_QCTRL_IFG		0x02
+	#define SFR_RX_BULKIN_QCTRL_SIZE	0x04
+#define SFR_RX_BULKIN_QTIMR_LOW		0x2F
+#define SFR_RX_BULKIN_QTIMR_HIGH	0x30
+#define SFR_RX_BULKIN_QSIZE		0x31
+#define SFR_RX_BULKIN_QIFG		0x32
+#define SFR_RXCOE_CTL			0x34
+	#define SFR_RXCOE_IP			0x01
+	#define SFR_RXCOE_TCP			0x02
+	#define SFR_RXCOE_UDP			0x04
+	#define SFR_RXCOE_ICMP			0x08
+	#define SFR_RXCOE_IGMP			0x10
+	#define SFR_RXCOE_TCPV6			0x20
+	#define SFR_RXCOE_UDPV6			0x40
+	#define SFR_RXCOE_ICMV6			0x80
+#define SFR_TXCOE_CTL			0x35
+	#define SFR_TXCOE_IP			0x01
+	#define SFR_TXCOE_TCP			0x02
+	#define SFR_TXCOE_UDP			0x04
+	#define SFR_TXCOE_ICMP			0x08
+	#define SFR_TXCOE_IGMP			0x10
+	#define SFR_TXCOE_TCPV6			0x20
+	#define SFR_TXCOE_UDPV6			0x40
+	#define SFR_TXCOE_ICMV6			0x80
+#define SFR_BM_INT_MASK			0x41
+#define SFR_BMRX_DMA_CONTROL		0x43
+	#define SFR_BMRX_DMA_EN			0x80
+#define SFR_BMTX_DMA_CONTROL		0x46
+#define SFR_PAUSE_WATERLVL_LOW		0x54
+#define SFR_PAUSE_WATERLVL_HIGH		0x55
+#define SFR_ARC_CTRL			0x9E
+#define SFR_SWP_CTRL			0xB1
+#define SFR_TX_PAUSE_RESEND_T		0xB2
+#define SFR_ETH_MAC_PATH		0xB7
+	#define SFR_RX_PATH_READY		0x01
+#define SFR_BULK_OUT_CTRL		0xB9
+	#define SFR_BULK_OUT_FLUSH_EN		0x01
+	#define SFR_BULK_OUT_EFF_EN		0x02
+
+static struct {
+	unsigned char ctrl;
+	unsigned char timer_l;
+	unsigned char timer_h;
+	unsigned char size;
+	unsigned char ifg;
+} AQC111_BULKIN_SIZE[] = {
+	/* xHCI & EHCI & OHCI */
+	{7, 0x00, 0x01, 0x1E, 0xFF},/* 10G, 5G, 2.5G, 1G */
+	{7, 0xA0, 0x00, 0x14, 0x00},/* 100M */
+	/* Jumbo packet */
+	{7, 0x00, 0x01, 0x18, 0xFF},
+};
+
 #endif /* __LINUX_USBNET_AQC111_H */
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Reset, stop callbacks, driver unbind callback.
More register defines required for these callbacks.

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 149 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 7f3e5a615750..22bb259d71fb 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 
 static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
+	u8 reg8;
+	u16 reg16;
+
+	/* Force bz */
+	reg16 = SFR_PHYPWR_RSTCTL_BZ;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			      2, 2, &reg16);
+	reg16 = 0;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			      2, 2, &reg16);
+}
+
+static int aqc111_reset(struct usbnet *dev)
+{
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+
+	reg8 = 0xFF;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, &reg8);
+
+	reg8 = 0x0;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_SWP_CTRL, 1, 1, &reg8);
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, &reg8);
+	reg8 &= ~(SFR_MONITOR_MODE_EPHYRW | SFR_MONITOR_MODE_RWLC |
+		  SFR_MONITOR_MODE_RWMP | SFR_MONITOR_MODE_RWWF |
+		  SFR_MONITOR_MODE_RW_FLAG);
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, &reg8);
+
+	return 0;
+}
+
+static int aqc111_stop(struct usbnet *dev)
+{
+	u16 reg16 = 0;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			2, 2, &reg16);
+	reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			 2, 2, &reg16);
+	reg16 = 0;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			 2, 2, &reg16);
+
+	return 0;
 }
 
 static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
 	.bind		= aqc111_bind,
 	.unbind		= aqc111_unbind,
+	.reset		= aqc111_reset,
+	.stop		= aqc111_stop,
 };
 
 #define AQC111_USB_ETH_DEV(vid, pid, table) \
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 1698a6a104fe..6b34202fa22b 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -10,10 +10,111 @@
 #ifndef __LINUX_USBNET_AQC111_H
 #define __LINUX_USBNET_AQC111_H
 
+#define AQ_ACCESS_MAC			0x01
 #define AQ_PHY_POWER			0x31
 
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
 
+/* SFR Reg. ********************************************/
+
+#define SFR_GENERAL_STATUS		0x03
+#define SFR_CHIP_STATUS			0x05
+#define SFR_RX_CTL			0x0B
+	#define SFR_RX_CTL_TXPADCRC		0x0400
+	#define SFR_RX_CTL_IPE			0x0200
+	#define SFR_RX_CTL_DROPCRCERR		0x0100
+	#define SFR_RX_CTL_START		0x0080
+	#define SFR_RX_CTL_RF_WAK		0x0040
+	#define SFR_RX_CTL_AP			0x0020
+	#define SFR_RX_CTL_AM			0x0010
+	#define SFR_RX_CTL_AB			0x0008
+	#define SFR_RX_CTL_AMALL		0x0002
+	#define SFR_RX_CTL_PRO			0x0001
+	#define SFR_RX_CTL_STOP			0x0000
+#define SFR_INTER_PACKET_GAP_0		0x0D
+#define SFR_NODE_ID			0x10
+#define SFR_MULTI_FILTER_ARRY		0x16
+#define SFR_MEDIUM_STATUS_MODE		0x22
+	#define SFR_MEDIUM_XGMIIMODE		0x0001
+	#define SFR_MEDIUM_FULL_DUPLEX		0x0002
+	#define SFR_MEDIUM_RXFLOW_CTRLEN	0x0010
+	#define SFR_MEDIUM_TXFLOW_CTRLEN	0x0020
+	#define SFR_MEDIUM_JUMBO_EN		0x0040
+	#define SFR_MEDIUM_RECEIVE_EN		0x0100
+#define SFR_MONITOR_MODE		0x24
+	#define SFR_MONITOR_MODE_EPHYRW		0x01
+	#define SFR_MONITOR_MODE_RWLC		0x02
+	#define SFR_MONITOR_MODE_RWMP		0x04
+	#define SFR_MONITOR_MODE_RWWF		0x08
+	#define SFR_MONITOR_MODE_RW_FLAG	0x10
+	#define SFR_MONITOR_MODE_PMEPOL		0x20
+	#define SFR_MONITOR_MODE_PMETYPE	0x40
+#define SFR_PHYPWR_RSTCTL		0x26
+	#define SFR_PHYPWR_RSTCTL_BZ		0x0010
+	#define SFR_PHYPWR_RSTCTL_IPRL		0x0020
+#define SFR_VLAN_ID_ADDRESS		0x2A
+#define SFR_VLAN_ID_CONTROL		0x2B
+	#define SFR_VLAN_CONTROL_WE		0x0001
+	#define SFR_VLAN_CONTROL_RD		0x0002
+	#define SFR_VLAN_CONTROL_VSO		0x0010
+	#define SFR_VLAN_CONTROL_VFE		0x0020
+#define SFR_VLAN_ID_DATA0		0x2C
+#define SFR_VLAN_ID_DATA1		0x2D
+#define SFR_RX_BULKIN_QCTRL		0x2E
+	#define SFR_RX_BULKIN_QCTRL_TIME	0x01
+	#define SFR_RX_BULKIN_QCTRL_IFG		0x02
+	#define SFR_RX_BULKIN_QCTRL_SIZE	0x04
+#define SFR_RX_BULKIN_QTIMR_LOW		0x2F
+#define SFR_RX_BULKIN_QTIMR_HIGH	0x30
+#define SFR_RX_BULKIN_QSIZE		0x31
+#define SFR_RX_BULKIN_QIFG		0x32
+#define SFR_RXCOE_CTL			0x34
+	#define SFR_RXCOE_IP			0x01
+	#define SFR_RXCOE_TCP			0x02
+	#define SFR_RXCOE_UDP			0x04
+	#define SFR_RXCOE_ICMP			0x08
+	#define SFR_RXCOE_IGMP			0x10
+	#define SFR_RXCOE_TCPV6			0x20
+	#define SFR_RXCOE_UDPV6			0x40
+	#define SFR_RXCOE_ICMV6			0x80
+#define SFR_TXCOE_CTL			0x35
+	#define SFR_TXCOE_IP			0x01
+	#define SFR_TXCOE_TCP			0x02
+	#define SFR_TXCOE_UDP			0x04
+	#define SFR_TXCOE_ICMP			0x08
+	#define SFR_TXCOE_IGMP			0x10
+	#define SFR_TXCOE_TCPV6			0x20
+	#define SFR_TXCOE_UDPV6			0x40
+	#define SFR_TXCOE_ICMV6			0x80
+#define SFR_BM_INT_MASK			0x41
+#define SFR_BMRX_DMA_CONTROL		0x43
+	#define SFR_BMRX_DMA_EN			0x80
+#define SFR_BMTX_DMA_CONTROL		0x46
+#define SFR_PAUSE_WATERLVL_LOW		0x54
+#define SFR_PAUSE_WATERLVL_HIGH		0x55
+#define SFR_ARC_CTRL			0x9E
+#define SFR_SWP_CTRL			0xB1
+#define SFR_TX_PAUSE_RESEND_T		0xB2
+#define SFR_ETH_MAC_PATH		0xB7
+	#define SFR_RX_PATH_READY		0x01
+#define SFR_BULK_OUT_CTRL		0xB9
+	#define SFR_BULK_OUT_FLUSH_EN		0x01
+	#define SFR_BULK_OUT_EFF_EN		0x02
+
+static struct {
+	unsigned char ctrl;
+	unsigned char timer_l;
+	unsigned char timer_h;
+	unsigned char size;
+	unsigned char ifg;
+} AQC111_BULKIN_SIZE[] = {
+	/* xHCI & EHCI & OHCI */
+	{7, 0x00, 0x01, 0x1E, 0xFF},/* 10G, 5G, 2.5G, 1G */
+	{7, 0xA0, 0x00, 0x14, 0x00},/* 100M */
+	/* Jumbo packet */
+	{7, 0x00, 0x01, 0x18, 0xFF},
+};
+
 #endif /* __LINUX_USBNET_AQC111_H */
 

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Implement PHY power up/down sequences.
AQC111, depending on FW used, may has PHY being controlled either
directly (dpa = 1) or via vendor command interface (dpa = 0).
Drivers supports both themes.
We determine this from firmware versioning agreement.

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 70 ++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 22bb259d71fb..30219bb6ddfd 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -138,15 +138,44 @@ static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
 	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
 }
 
+static int aq_mdio_read_cmd(struct usbnet *dev, u16 value, u16 index,
+			    u16 size, void *data)
+{
+	return aqc111_read_cmd(dev, AQ_PHY_CMD, value, index, size, data);
+}
+
+static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
+			     u16 size, void *data)
+{
+	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
 };
 
+static void aqc111_read_fw_version(struct usbnet *dev,
+				   struct aqc111_data *aqc111_data)
+{
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
+			1, 1, &aqc111_data->fw_ver.major);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
+			1, 1, &aqc111_data->fw_ver.minor);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
+			1, 1, &aqc111_data->fw_ver.rev);
+
+	if (aqc111_data->fw_ver.major & 0x80)
+		aqc111_data->fw_ver.major &= ~0x80;
+	else
+		aqc111_data->dpa = 1;
+}
+
 static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret;
 	struct usb_device *udev = interface_to_usbdev(intf);
+	struct aqc111_data *aqc111_data;
 
 	/* Check if vendor configuration */
 	if (udev->actconfig->desc.bConfigurationValue != 1) {
@@ -162,8 +191,18 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 		return ret;
 	}
 
+	aqc111_data = kzalloc(sizeof(*aqc111_data), GFP_KERNEL);
+	if (!aqc111_data)
+		return -ENOMEM;
+
+	/* store aqc111_data pointer in device data field */
+	dev->data[0] = (unsigned long)aqc111_data;
+	memset(aqc111_data, 0, sizeof(*aqc111_data));
+
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
+	aqc111_read_fw_version(dev, aqc111_data);
+
 	return 0;
 }
 
@@ -172,6 +211,8 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 	u8 reg8;
 	u16 reg16;
 
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
 	/* Force bz */
 	reg16 = SFR_PHYPWR_RSTCTL_BZ;
 	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
@@ -179,12 +220,52 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 	reg16 = 0;
 	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
 			      2, 2, &reg16);
+
+	/* Power down ethernet PHY */
+	if (aqc111_data->dpa) {
+		reg8 = 0x00;
+		aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
+				      0, 1, &reg8);
+	} else {
+		aqc111_data->phy_ops.low_power = 1;
+		aqc111_data->phy_ops.phy_power = 0;
+		aqc111_write_cmd_nopm(dev, AQ_PHY_OPS, 0, 0,
+				      4, &aqc111_data->phy_ops);
+	}
+
+	kfree(aqc111_data);
 }
 
 static int aqc111_reset(struct usbnet *dev)
 {
 	u8 reg8 = 0;
 	u16 reg16 = 0;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	/* Power up ethernet PHY */
+	aqc111_data->phy_ops.phy_ctrl1 = 0;
+	aqc111_data->phy_ops.phy_ctrl2 = 0;
+
+	aqc111_data->phy_ops.phy_power = 1;
+	if (aqc111_data->dpa) {
+		aqc111_read_cmd(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
+		if (reg8 == 0x00) {
+			reg8 = 0x02;
+			aqc111_write_cmd(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
+			msleep(200);
+		}
+
+		aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+				 2, &reg16);
+		if (reg16 & AQ_PHY_LOW_POWER_MODE) {
+			reg16 &= ~AQ_PHY_LOW_POWER_MODE;
+			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
+					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
+		}
+	} else {
+		aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+				 4, &aqc111_data->phy_ops);
+	}
 
 	reg8 = 0xFF;
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, &reg8);
@@ -204,6 +285,7 @@ static int aqc111_reset(struct usbnet *dev)
 static int aqc111_stop(struct usbnet *dev)
 {
 	u16 reg16 = 0;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 
 	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 			2, 2, &reg16);
@@ -214,6 +296,17 @@ static int aqc111_stop(struct usbnet *dev)
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
 			 2, 2, &reg16);
 
+	/* Put PHY to low power*/
+	if (aqc111_data->dpa) {
+		reg16 = AQ_PHY_LOW_POWER_MODE;
+		aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+				  2, &reg16);
+	} else {
+		aqc111_data->phy_ops.low_power = 1;
+		aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+				 4, &aqc111_data->phy_ops);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 6b34202fa22b..8738d2c4ae90 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -12,6 +12,17 @@
 
 #define AQ_ACCESS_MAC			0x01
 #define AQ_PHY_POWER			0x31
+#define AQ_PHY_CMD			0x32
+#define AQ_PHY_OPS			0x61
+
+#define AQC111_PHY_ID			0x00
+#define AQ_PHY_ADDR(mmd)		((AQC111_PHY_ID << 8) | mmd)
+
+#define AQ_PHY_GLOBAL_MMD		0x1E
+#define AQ_PHY_GLOBAL_ADDR		AQ_PHY_ADDR(AQ_PHY_GLOBAL_MMD)
+
+#define AQ_GLB_STD_CTRL_REG		0x0000
+	#define AQ_PHY_LOW_POWER_MODE		0x0800
 
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
@@ -102,6 +113,65 @@
 	#define SFR_BULK_OUT_FLUSH_EN		0x01
 	#define SFR_BULK_OUT_EFF_EN		0x02
 
+#define AQ_FW_VER_MAJOR			0xDA
+#define AQ_FW_VER_MINOR			0xDB
+#define AQ_FW_VER_REV			0xDC
+
+/******************************************************************************/
+
+struct aqc111_phy_options {
+	union {
+		struct {
+			u8 adv_100M:	1;
+			u8 adv_1G:	1;
+			u8 adv_2G5:	1;
+			u8 adv_5G:	1;
+			u8 rsvd1:	4;
+		};
+		u8 advertising;
+	};
+	union {
+		struct {
+			u8 eee_100M:	1;
+			u8 eee_1G:	1;
+			u8 eee_2G5:	1;
+			u8 eee_5G:	1;
+			u8 rsvd2:	4;
+		};
+		u8 eee;
+	};
+	union {
+		struct {
+			u8 pause:	1;
+			u8 asym_pause:	1;
+			u8 low_power:	1;
+			u8 phy_power:	1;
+			u8 wol:		1;
+			u8 downshift:	1;
+			u8 rsvd4:	2;
+		};
+		u8 phy_ctrl1;
+	};
+	union {
+		struct {
+		u8 dsh_ret_cnt:	4;
+		u8 magic_packet:1;
+		u8 rsvd5:	3;
+		};
+		u8 phy_ctrl2;
+	};
+};
+
+struct aqc111_data {
+	struct {
+		u8 major;
+		u8 minor;
+		u8 rev;
+	} fw_ver;
+	u8 dpa; /*direct PHY access*/
+	struct aqc111_phy_options phy_ops;
+} __packed;
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Implement PHY power up/down sequences.
AQC111, depending on FW used, may has PHY being controlled either
directly (dpa = 1) or via vendor command interface (dpa = 0).
Drivers supports both themes.
We determine this from firmware versioning agreement.

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 70 ++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 22bb259d71fb..30219bb6ddfd 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -138,15 +138,44 @@ static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
 	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
 }
 
+static int aq_mdio_read_cmd(struct usbnet *dev, u16 value, u16 index,
+			    u16 size, void *data)
+{
+	return aqc111_read_cmd(dev, AQ_PHY_CMD, value, index, size, data);
+}
+
+static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
+			     u16 size, void *data)
+{
+	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
 };
 
+static void aqc111_read_fw_version(struct usbnet *dev,
+				   struct aqc111_data *aqc111_data)
+{
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
+			1, 1, &aqc111_data->fw_ver.major);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
+			1, 1, &aqc111_data->fw_ver.minor);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
+			1, 1, &aqc111_data->fw_ver.rev);
+
+	if (aqc111_data->fw_ver.major & 0x80)
+		aqc111_data->fw_ver.major &= ~0x80;
+	else
+		aqc111_data->dpa = 1;
+}
+
 static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret;
 	struct usb_device *udev = interface_to_usbdev(intf);
+	struct aqc111_data *aqc111_data;
 
 	/* Check if vendor configuration */
 	if (udev->actconfig->desc.bConfigurationValue != 1) {
@@ -162,8 +191,18 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 		return ret;
 	}
 
+	aqc111_data = kzalloc(sizeof(*aqc111_data), GFP_KERNEL);
+	if (!aqc111_data)
+		return -ENOMEM;
+
+	/* store aqc111_data pointer in device data field */
+	dev->data[0] = (unsigned long)aqc111_data;
+	memset(aqc111_data, 0, sizeof(*aqc111_data));
+
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
+	aqc111_read_fw_version(dev, aqc111_data);
+
 	return 0;
 }
 
@@ -172,6 +211,8 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 	u8 reg8;
 	u16 reg16;
 
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
 	/* Force bz */
 	reg16 = SFR_PHYPWR_RSTCTL_BZ;
 	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
@@ -179,12 +220,52 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 	reg16 = 0;
 	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
 			      2, 2, &reg16);
+
+	/* Power down ethernet PHY */
+	if (aqc111_data->dpa) {
+		reg8 = 0x00;
+		aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
+				      0, 1, &reg8);
+	} else {
+		aqc111_data->phy_ops.low_power = 1;
+		aqc111_data->phy_ops.phy_power = 0;
+		aqc111_write_cmd_nopm(dev, AQ_PHY_OPS, 0, 0,
+				      4, &aqc111_data->phy_ops);
+	}
+
+	kfree(aqc111_data);
 }
 
 static int aqc111_reset(struct usbnet *dev)
 {
 	u8 reg8 = 0;
 	u16 reg16 = 0;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	/* Power up ethernet PHY */
+	aqc111_data->phy_ops.phy_ctrl1 = 0;
+	aqc111_data->phy_ops.phy_ctrl2 = 0;
+
+	aqc111_data->phy_ops.phy_power = 1;
+	if (aqc111_data->dpa) {
+		aqc111_read_cmd(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
+		if (reg8 == 0x00) {
+			reg8 = 0x02;
+			aqc111_write_cmd(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
+			msleep(200);
+		}
+
+		aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+				 2, &reg16);
+		if (reg16 & AQ_PHY_LOW_POWER_MODE) {
+			reg16 &= ~AQ_PHY_LOW_POWER_MODE;
+			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
+					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
+		}
+	} else {
+		aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+				 4, &aqc111_data->phy_ops);
+	}
 
 	reg8 = 0xFF;
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, &reg8);
@@ -204,6 +285,7 @@ static int aqc111_reset(struct usbnet *dev)
 static int aqc111_stop(struct usbnet *dev)
 {
 	u16 reg16 = 0;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 
 	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 			2, 2, &reg16);
@@ -214,6 +296,17 @@ static int aqc111_stop(struct usbnet *dev)
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
 			 2, 2, &reg16);
 
+	/* Put PHY to low power*/
+	if (aqc111_data->dpa) {
+		reg16 = AQ_PHY_LOW_POWER_MODE;
+		aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+				  2, &reg16);
+	} else {
+		aqc111_data->phy_ops.low_power = 1;
+		aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+				 4, &aqc111_data->phy_ops);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 6b34202fa22b..8738d2c4ae90 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -12,6 +12,17 @@
 
 #define AQ_ACCESS_MAC			0x01
 #define AQ_PHY_POWER			0x31
+#define AQ_PHY_CMD			0x32
+#define AQ_PHY_OPS			0x61
+
+#define AQC111_PHY_ID			0x00
+#define AQ_PHY_ADDR(mmd)		((AQC111_PHY_ID << 8) | mmd)
+
+#define AQ_PHY_GLOBAL_MMD		0x1E
+#define AQ_PHY_GLOBAL_ADDR		AQ_PHY_ADDR(AQ_PHY_GLOBAL_MMD)
+
+#define AQ_GLB_STD_CTRL_REG		0x0000
+	#define AQ_PHY_LOW_POWER_MODE		0x0800
 
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
@@ -102,6 +113,65 @@
 	#define SFR_BULK_OUT_FLUSH_EN		0x01
 	#define SFR_BULK_OUT_EFF_EN		0x02
 
+#define AQ_FW_VER_MAJOR			0xDA
+#define AQ_FW_VER_MINOR			0xDB
+#define AQ_FW_VER_REV			0xDC
+
+/******************************************************************************/
+
+struct aqc111_phy_options {
+	union {
+		struct {
+			u8 adv_100M:	1;
+			u8 adv_1G:	1;
+			u8 adv_2G5:	1;
+			u8 adv_5G:	1;
+			u8 rsvd1:	4;
+		};
+		u8 advertising;
+	};
+	union {
+		struct {
+			u8 eee_100M:	1;
+			u8 eee_1G:	1;
+			u8 eee_2G5:	1;
+			u8 eee_5G:	1;
+			u8 rsvd2:	4;
+		};
+		u8 eee;
+	};
+	union {
+		struct {
+			u8 pause:	1;
+			u8 asym_pause:	1;
+			u8 low_power:	1;
+			u8 phy_power:	1;
+			u8 wol:		1;
+			u8 downshift:	1;
+			u8 rsvd4:	2;
+		};
+		u8 phy_ctrl1;
+	};
+	union {
+		struct {
+		u8 dsh_ret_cnt:	4;
+		u8 magic_packet:1;
+		u8 rsvd5:	3;
+		};
+		u8 phy_ctrl2;
+	};
+};
+
+struct aqc111_data {
+	struct {
+		u8 major;
+		u8 minor;
+		u8 rev;
+	} fw_ver;
+	u8 dpa; /*direct PHY access*/
+	struct aqc111_phy_options phy_ops;
+} __packed;
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Add full hardware initialization sequence and link configuration logic

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 330 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  51 ++++++++
 2 files changed, 381 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 30219bb6ddfd..1d366f4a1c51 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -150,6 +150,122 @@ static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
 	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
 }
 
+static void aqc111_set_phy_speed_fw_iface(struct usbnet *dev,
+					  struct aqc111_data *aqc111_data)
+{
+	aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0, 4, &aqc111_data->phy_ops);
+}
+
+static void aqc111_set_phy_speed_direct(struct usbnet *dev,
+					struct aqc111_data *aqc111_data)
+{
+	u16 reg16_1 = 0;
+	u16 reg16_2 = 0;
+	u16 reg16_3 = 0;
+
+	/* Disable auto-negotiation */
+	reg16_1 = AQ_ANEG_EX_PAGE_CTRL;
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_STD_CTRL_REG, AQ_PHY_AUTONEG_ADDR,
+			  2, &reg16_1);
+
+	reg16_1 = AQ_ANEG_EX_PHY_ID | AQ_ANEG_ADV_AQRATE;
+	if (aqc111_data->phy_ops.downshift) {
+		reg16_1 |= AQ_ANEG_EN_DSH;
+		reg16_1 |= aqc111_data->phy_ops.dsh_ret_cnt & 0x0F;
+	}
+
+	reg16_2 = AQ_ANEG_ADV_LT;
+	if (aqc111_data->phy_ops.pause)
+		reg16_3 |= AQ_ANEG_PAUSE;
+
+	if (aqc111_data->phy_ops.asym_pause)
+		reg16_3 |= AQ_ANEG_ASYM_PAUSE;
+
+	if (aqc111_data->phy_ops.adv_5G) {
+		reg16_1 |= AQ_ANEG_ADV_5G_N;
+		reg16_2 |= AQ_ANEG_ADV_5G_T;
+	}
+	if (aqc111_data->phy_ops.adv_2G5) {
+		reg16_1 |= AQ_ANEG_ADV_2G5_N;
+		reg16_2 |= AQ_ANEG_ADV_2G5_T;
+	}
+	if (aqc111_data->phy_ops.adv_1G)
+		reg16_1 |= AQ_ANEG_ADV_1G;
+
+	if (aqc111_data->phy_ops.adv_5G)
+		reg16_3 |= AQ_ANEG_100M;
+
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_VEN_PROV1_REG,
+			  AQ_PHY_AUTONEG_ADDR, 2, &reg16_1);
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_10GT_CTRL_REG,
+			  AQ_PHY_AUTONEG_ADDR, 2, &reg16_2);
+
+	aq_mdio_read_cmd(dev, AQ_AUTONEG_ADV_REG, AQ_PHY_AUTONEG_ADDR,
+			 2, &reg16_1);
+	reg16_1 &= ~AQ_ANEG_ABILITY_MASK;
+	reg16_1 |= reg16_3;
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_ADV_REG, AQ_PHY_AUTONEG_ADDR,
+			  2, &reg16_1);
+
+	/* Restart auto-negotiation */
+	reg16_1 = AQ_ANEG_EX_PAGE_CTRL | AQ_ANEG_EN_ANEG |
+		  AQ_ANEG_RESTART_ANEG;
+
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_STD_CTRL_REG,
+			  AQ_PHY_AUTONEG_ADDR, 2, &reg16_1);
+}
+
+static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
+{
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	aqc111_data->phy_ops.advertising = 0;
+	aqc111_data->phy_ops.pause = 1;
+	aqc111_data->phy_ops.asym_pause = 1;
+	aqc111_data->phy_ops.downshift = 1;
+	aqc111_data->phy_ops.dsh_ret_cnt = 3;
+	if (autoneg == AUTONEG_ENABLE) {
+		switch (speed) {
+		case SPEED_5000:
+			aqc111_data->phy_ops.adv_5G = 1;
+		case SPEED_2500:
+			aqc111_data->phy_ops.adv_2G5 = 1;
+		case SPEED_1000:
+			aqc111_data->phy_ops.adv_1G = 1;
+		case SPEED_100:
+			aqc111_data->phy_ops.adv_100M = 1;
+		}
+	} else {
+		switch (speed) {
+		case SPEED_5000:
+		{
+			aqc111_data->phy_ops.adv_5G = 1;
+			break;
+		}
+		case SPEED_2500:
+		{
+			aqc111_data->phy_ops.adv_2G5 = 1;
+			break;
+		}
+		case SPEED_1000:
+		{
+			aqc111_data->phy_ops.adv_1G = 1;
+			break;
+		}
+		case SPEED_100:
+		{
+			aqc111_data->phy_ops.adv_100M = 1;
+			break;
+		}
+		}
+	}
+
+	if (aqc111_data->dpa)
+		aqc111_set_phy_speed_direct(dev, aqc111_data);
+	else
+		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
@@ -176,6 +292,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	int ret;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct aqc111_data *aqc111_data;
+	enum usb_device_speed usb_speed = dev->udev->speed;
 
 	/* Check if vendor configuration */
 	if (udev->actconfig->desc.bConfigurationValue != 1) {
@@ -202,6 +319,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
 	aqc111_read_fw_version(dev, aqc111_data);
+	aqc111_data->autoneg = AUTONEG_ENABLE;
+	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
+					 SPEED_5000 : SPEED_1000;
 
 	return 0;
 }
@@ -227,6 +347,7 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 		aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
 				      0, 1, &reg8);
 	} else {
+		aqc111_data->phy_ops.advertising = 0;
 		aqc111_data->phy_ops.low_power = 1;
 		aqc111_data->phy_ops.phy_power = 0;
 		aqc111_write_cmd_nopm(dev, AQ_PHY_OPS, 0, 0,
@@ -236,13 +357,212 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 	kfree(aqc111_data);
 }
 
+static void aqc111_status(struct usbnet *dev, struct urb *urb)
+{
+	struct aqc111_int_data *event = NULL;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	int link = 0;
+
+	if (urb->actual_length < 8)
+		return;
+
+	event = urb->transfer_buffer;
+
+	if (event->link_status)
+		link = 1;
+	else
+		link = 0;
+
+	aqc111_data->link_speed = event->link_speed;
+	aqc111_data->link = link;
+
+	if (netif_carrier_ok(dev->net) != link)
+		usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+}
+
+static void aqc111_configure_rx(struct usbnet *dev,
+				struct aqc111_data *aqc111_data)
+{
+	u8 reg8 = 0;
+	u8 queue_num = 0;
+	u16 reg16 = 0;
+	u16 link_speed = 0, usb_host = 0;
+	u8 buf[5] = { 0 };
+	enum usb_device_speed usb_speed = dev->udev->speed;
+
+	buf[0] = 0x00;
+	buf[1] = 0xF8;
+	buf[2] = 0x07;
+	switch (aqc111_data->link_speed) {
+	case AQ_INT_SPEED_5G:
+	{
+		link_speed = 5000;
+		reg8 = 0x05;
+		reg16 = 0x001F;
+		break;
+	}
+	case AQ_INT_SPEED_2_5G:
+	{
+		link_speed = 2500;
+		reg16 = 0x003F;
+		break;
+	}
+	case AQ_INT_SPEED_1G:
+	{
+		link_speed = 1000;
+		reg16 = 0x009F;
+		break;
+	}
+	case AQ_INT_SPEED_100M:
+	{
+		link_speed = 100;
+		queue_num = 1;
+		reg16 = 0x063F;
+		buf[1] = 0xFB;
+		buf[2] = 0x4;
+		break;
+	}
+	}
+
+	if (aqc111_data->dpa) {
+		/* Set Phy Flow control */
+		aq_mdio_write_cmd(dev, AQ_GLB_ING_PAUSE_CTRL_REG,
+				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
+		aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
+				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
+	}
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
+			 1, 1, &reg8);
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TX_PAUSE_RESEND_T, 3, 3, buf);
+
+	switch (usb_speed) {
+	case USB_SPEED_SUPER:
+	{
+		usb_host = 3;
+		break;
+	}
+	case USB_SPEED_HIGH:
+	{
+		usb_host = 2;
+		break;
+	}
+	case USB_SPEED_FULL:
+	case USB_SPEED_LOW:
+	{
+		usb_host = 1;
+		queue_num = 0;
+		break;
+	}
+	default:
+	{
+		usb_host = 0;
+		break;
+	}
+	}
+
+	memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5);
+	/* RX bulk configuration */
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf);
+
+	/* Set high low water level */
+	reg16 = 0x0810;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
+			 2, 2, &reg16);
+	netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host);
+}
+
+static int aqc111_link_reset(struct usbnet *dev)
+{
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	if (aqc111_data->link == 1) { /* Link up */
+		aqc111_configure_rx(dev, aqc111_data);
+
+		/* Vlan Tag Filter */
+		reg8 = SFR_VLAN_CONTROL_VSO;
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+				 1, 1, &reg8);
+
+		reg8 = 0x0;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+				 1, 1, &reg8);
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMTX_DMA_CONTROL,
+				 1, 1, &reg8);
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, &reg8);
+
+		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+		reg8 = SFR_RX_PATH_READY;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+				 1, 1, &reg8);
+
+		reg8 = SFR_BULK_OUT_EFF_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+				 1, 1, &reg8);
+
+		reg16 = 0;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		reg16 = SFR_MEDIUM_XGMIIMODE | SFR_MEDIUM_FULL_DUPLEX;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				2, 2, &reg16);
+
+		reg16 |= SFR_MEDIUM_RECEIVE_EN | SFR_MEDIUM_RXFLOW_CTRLEN |
+			 SFR_MEDIUM_TXFLOW_CTRLEN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB | SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+		netif_carrier_on(dev->net);
+	} else {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				2, 2, &reg16);
+		reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+		reg16 &= ~SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+		reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+				 1, 1, &reg8);
+		reg8 = SFR_BULK_OUT_EFF_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+				 1, 1, &reg8);
+
+		netif_carrier_off(dev->net);
+	}
+	return 0;
+}
+
 static int aqc111_reset(struct usbnet *dev)
 {
 	u8 reg8 = 0;
 	u16 reg16 = 0;
+	enum usb_device_speed usb_speed;
 	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 
+	usb_speed = dev->udev->speed;
+
 	/* Power up ethernet PHY */
+	aqc111_data->phy_ops.advertising = 0;
 	aqc111_data->phy_ops.phy_ctrl1 = 0;
 	aqc111_data->phy_ops.phy_ctrl2 = 0;
 
@@ -279,6 +599,12 @@ static int aqc111_reset(struct usbnet *dev)
 		  SFR_MONITOR_MODE_RW_FLAG);
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, &reg8);
 
+	netif_carrier_off(dev->net);
+
+	/* Phy advertise */
+	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+			     aqc111_data->advertised_speed);
+
 	return 0;
 }
 
@@ -307,6 +633,8 @@ static int aqc111_stop(struct usbnet *dev)
 				 4, &aqc111_data->phy_ops);
 	}
 
+	netif_carrier_off(dev->net);
+
 	return 0;
 }
 
@@ -314,6 +642,8 @@ static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
 	.bind		= aqc111_bind,
 	.unbind		= aqc111_unbind,
+	.status		= aqc111_status,
+	.link_reset	= aqc111_link_reset,
 	.reset		= aqc111_reset,
 	.stop		= aqc111_stop,
 };
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 8738d2c4ae90..5c5602e6d236 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -18,12 +18,44 @@
 #define AQC111_PHY_ID			0x00
 #define AQ_PHY_ADDR(mmd)		((AQC111_PHY_ID << 8) | mmd)
 
+#define AQ_PHY_AUTONEG_MMD		0x07
+#define AQ_PHY_AUTONEG_ADDR		AQ_PHY_ADDR(AQ_PHY_AUTONEG_MMD)
+
+#define AQ_AUTONEG_STD_CTRL_REG		0x0000
+	#define AQ_ANEG_EX_PAGE_CTRL		0x2000
+	#define AQ_ANEG_EN_ANEG			0x1000
+	#define AQ_ANEG_RESTART_ANEG		0x0200
+
+#define AQ_AUTONEG_ADV_REG		0x0010
+	#define AQ_ANEG_100M			0x0100
+	#define AQ_ANEG_PAUSE			0x0400
+	#define AQ_ANEG_ASYM_PAUSE		0x0800
+	#define AQ_ANEG_ABILITY_MASK		0x0FE0
+
+#define AQ_AUTONEG_10GT_CTRL_REG	0x0020
+	#define AQ_ANEG_ADV_10G_T		0x1000
+	#define AQ_ANEG_ADV_5G_T		0x0100
+	#define AQ_ANEG_ADV_2G5_T		0x0080
+	#define AQ_ANEG_ADV_LT			0x0001
+
+#define AQ_AUTONEG_VEN_PROV1_REG	0xC400
+	#define AQ_ANEG_ADV_1G			0x8000
+	#define AQ_ANEG_ADV_AQRATE		0x1000
+	#define AQ_ANEG_ADV_5G_N		0x0800
+	#define AQ_ANEG_ADV_2G5_N		0x0400
+	#define AQ_ANEG_EX_PHY_ID		0x0040
+	#define AQ_ANEG_EN_DSH			0x0010
+	#define AQ_ANEG_DSH_RETRY		0x0003
+
 #define AQ_PHY_GLOBAL_MMD		0x1E
 #define AQ_PHY_GLOBAL_ADDR		AQ_PHY_ADDR(AQ_PHY_GLOBAL_MMD)
 
 #define AQ_GLB_STD_CTRL_REG		0x0000
 	#define AQ_PHY_LOW_POWER_MODE		0x0800
 
+#define AQ_GLB_ING_PAUSE_CTRL_REG	0x7148
+#define AQ_GLB_EGR_PAUSE_CTRL_REG	0x4148
+
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
 
@@ -163,6 +195,10 @@ struct aqc111_phy_options {
 };
 
 struct aqc111_data {
+	u8 link_speed;
+	u8 link;
+	u8 autoneg;
+	u32 advertised_speed;
 	struct {
 		u8 major;
 		u8 minor;
@@ -172,6 +208,21 @@ struct aqc111_data {
 	struct aqc111_phy_options phy_ops;
 } __packed;
 
+struct aqc111_int_data {
+	u8 res1;
+	u8 link_speed: 7;
+	u8 link_status: 1;
+	__le16 res2;
+	__le16 res3;
+	__le16 res4;
+} __packed;
+
+#define AQ_INT_SPEED_10G	0x0E
+#define AQ_INT_SPEED_5G		0x0F
+#define AQ_INT_SPEED_2_5G	0x10
+#define AQ_INT_SPEED_1G		0x11
+#define AQ_INT_SPEED_100M	0x13
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Add full hardware initialization sequence and link configuration logic

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 330 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  51 ++++++++
 2 files changed, 381 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 30219bb6ddfd..1d366f4a1c51 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -150,6 +150,122 @@ static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
 	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
 }
 
+static void aqc111_set_phy_speed_fw_iface(struct usbnet *dev,
+					  struct aqc111_data *aqc111_data)
+{
+	aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0, 4, &aqc111_data->phy_ops);
+}
+
+static void aqc111_set_phy_speed_direct(struct usbnet *dev,
+					struct aqc111_data *aqc111_data)
+{
+	u16 reg16_1 = 0;
+	u16 reg16_2 = 0;
+	u16 reg16_3 = 0;
+
+	/* Disable auto-negotiation */
+	reg16_1 = AQ_ANEG_EX_PAGE_CTRL;
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_STD_CTRL_REG, AQ_PHY_AUTONEG_ADDR,
+			  2, &reg16_1);
+
+	reg16_1 = AQ_ANEG_EX_PHY_ID | AQ_ANEG_ADV_AQRATE;
+	if (aqc111_data->phy_ops.downshift) {
+		reg16_1 |= AQ_ANEG_EN_DSH;
+		reg16_1 |= aqc111_data->phy_ops.dsh_ret_cnt & 0x0F;
+	}
+
+	reg16_2 = AQ_ANEG_ADV_LT;
+	if (aqc111_data->phy_ops.pause)
+		reg16_3 |= AQ_ANEG_PAUSE;
+
+	if (aqc111_data->phy_ops.asym_pause)
+		reg16_3 |= AQ_ANEG_ASYM_PAUSE;
+
+	if (aqc111_data->phy_ops.adv_5G) {
+		reg16_1 |= AQ_ANEG_ADV_5G_N;
+		reg16_2 |= AQ_ANEG_ADV_5G_T;
+	}
+	if (aqc111_data->phy_ops.adv_2G5) {
+		reg16_1 |= AQ_ANEG_ADV_2G5_N;
+		reg16_2 |= AQ_ANEG_ADV_2G5_T;
+	}
+	if (aqc111_data->phy_ops.adv_1G)
+		reg16_1 |= AQ_ANEG_ADV_1G;
+
+	if (aqc111_data->phy_ops.adv_5G)
+		reg16_3 |= AQ_ANEG_100M;
+
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_VEN_PROV1_REG,
+			  AQ_PHY_AUTONEG_ADDR, 2, &reg16_1);
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_10GT_CTRL_REG,
+			  AQ_PHY_AUTONEG_ADDR, 2, &reg16_2);
+
+	aq_mdio_read_cmd(dev, AQ_AUTONEG_ADV_REG, AQ_PHY_AUTONEG_ADDR,
+			 2, &reg16_1);
+	reg16_1 &= ~AQ_ANEG_ABILITY_MASK;
+	reg16_1 |= reg16_3;
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_ADV_REG, AQ_PHY_AUTONEG_ADDR,
+			  2, &reg16_1);
+
+	/* Restart auto-negotiation */
+	reg16_1 = AQ_ANEG_EX_PAGE_CTRL | AQ_ANEG_EN_ANEG |
+		  AQ_ANEG_RESTART_ANEG;
+
+	aq_mdio_write_cmd(dev, AQ_AUTONEG_STD_CTRL_REG,
+			  AQ_PHY_AUTONEG_ADDR, 2, &reg16_1);
+}
+
+static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
+{
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	aqc111_data->phy_ops.advertising = 0;
+	aqc111_data->phy_ops.pause = 1;
+	aqc111_data->phy_ops.asym_pause = 1;
+	aqc111_data->phy_ops.downshift = 1;
+	aqc111_data->phy_ops.dsh_ret_cnt = 3;
+	if (autoneg == AUTONEG_ENABLE) {
+		switch (speed) {
+		case SPEED_5000:
+			aqc111_data->phy_ops.adv_5G = 1;
+		case SPEED_2500:
+			aqc111_data->phy_ops.adv_2G5 = 1;
+		case SPEED_1000:
+			aqc111_data->phy_ops.adv_1G = 1;
+		case SPEED_100:
+			aqc111_data->phy_ops.adv_100M = 1;
+		}
+	} else {
+		switch (speed) {
+		case SPEED_5000:
+		{
+			aqc111_data->phy_ops.adv_5G = 1;
+			break;
+		}
+		case SPEED_2500:
+		{
+			aqc111_data->phy_ops.adv_2G5 = 1;
+			break;
+		}
+		case SPEED_1000:
+		{
+			aqc111_data->phy_ops.adv_1G = 1;
+			break;
+		}
+		case SPEED_100:
+		{
+			aqc111_data->phy_ops.adv_100M = 1;
+			break;
+		}
+		}
+	}
+
+	if (aqc111_data->dpa)
+		aqc111_set_phy_speed_direct(dev, aqc111_data);
+	else
+		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
@@ -176,6 +292,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	int ret;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct aqc111_data *aqc111_data;
+	enum usb_device_speed usb_speed = dev->udev->speed;
 
 	/* Check if vendor configuration */
 	if (udev->actconfig->desc.bConfigurationValue != 1) {
@@ -202,6 +319,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
 	aqc111_read_fw_version(dev, aqc111_data);
+	aqc111_data->autoneg = AUTONEG_ENABLE;
+	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
+					 SPEED_5000 : SPEED_1000;
 
 	return 0;
 }
@@ -227,6 +347,7 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 		aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
 				      0, 1, &reg8);
 	} else {
+		aqc111_data->phy_ops.advertising = 0;
 		aqc111_data->phy_ops.low_power = 1;
 		aqc111_data->phy_ops.phy_power = 0;
 		aqc111_write_cmd_nopm(dev, AQ_PHY_OPS, 0, 0,
@@ -236,13 +357,212 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
 	kfree(aqc111_data);
 }
 
+static void aqc111_status(struct usbnet *dev, struct urb *urb)
+{
+	struct aqc111_int_data *event = NULL;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	int link = 0;
+
+	if (urb->actual_length < 8)
+		return;
+
+	event = urb->transfer_buffer;
+
+	if (event->link_status)
+		link = 1;
+	else
+		link = 0;
+
+	aqc111_data->link_speed = event->link_speed;
+	aqc111_data->link = link;
+
+	if (netif_carrier_ok(dev->net) != link)
+		usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+}
+
+static void aqc111_configure_rx(struct usbnet *dev,
+				struct aqc111_data *aqc111_data)
+{
+	u8 reg8 = 0;
+	u8 queue_num = 0;
+	u16 reg16 = 0;
+	u16 link_speed = 0, usb_host = 0;
+	u8 buf[5] = { 0 };
+	enum usb_device_speed usb_speed = dev->udev->speed;
+
+	buf[0] = 0x00;
+	buf[1] = 0xF8;
+	buf[2] = 0x07;
+	switch (aqc111_data->link_speed) {
+	case AQ_INT_SPEED_5G:
+	{
+		link_speed = 5000;
+		reg8 = 0x05;
+		reg16 = 0x001F;
+		break;
+	}
+	case AQ_INT_SPEED_2_5G:
+	{
+		link_speed = 2500;
+		reg16 = 0x003F;
+		break;
+	}
+	case AQ_INT_SPEED_1G:
+	{
+		link_speed = 1000;
+		reg16 = 0x009F;
+		break;
+	}
+	case AQ_INT_SPEED_100M:
+	{
+		link_speed = 100;
+		queue_num = 1;
+		reg16 = 0x063F;
+		buf[1] = 0xFB;
+		buf[2] = 0x4;
+		break;
+	}
+	}
+
+	if (aqc111_data->dpa) {
+		/* Set Phy Flow control */
+		aq_mdio_write_cmd(dev, AQ_GLB_ING_PAUSE_CTRL_REG,
+				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
+		aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
+				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
+	}
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
+			 1, 1, &reg8);
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TX_PAUSE_RESEND_T, 3, 3, buf);
+
+	switch (usb_speed) {
+	case USB_SPEED_SUPER:
+	{
+		usb_host = 3;
+		break;
+	}
+	case USB_SPEED_HIGH:
+	{
+		usb_host = 2;
+		break;
+	}
+	case USB_SPEED_FULL:
+	case USB_SPEED_LOW:
+	{
+		usb_host = 1;
+		queue_num = 0;
+		break;
+	}
+	default:
+	{
+		usb_host = 0;
+		break;
+	}
+	}
+
+	memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5);
+	/* RX bulk configuration */
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf);
+
+	/* Set high low water level */
+	reg16 = 0x0810;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
+			 2, 2, &reg16);
+	netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host);
+}
+
+static int aqc111_link_reset(struct usbnet *dev)
+{
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	if (aqc111_data->link == 1) { /* Link up */
+		aqc111_configure_rx(dev, aqc111_data);
+
+		/* Vlan Tag Filter */
+		reg8 = SFR_VLAN_CONTROL_VSO;
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+				 1, 1, &reg8);
+
+		reg8 = 0x0;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+				 1, 1, &reg8);
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMTX_DMA_CONTROL,
+				 1, 1, &reg8);
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, &reg8);
+
+		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+		reg8 = SFR_RX_PATH_READY;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+				 1, 1, &reg8);
+
+		reg8 = SFR_BULK_OUT_EFF_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+				 1, 1, &reg8);
+
+		reg16 = 0;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		reg16 = SFR_MEDIUM_XGMIIMODE | SFR_MEDIUM_FULL_DUPLEX;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				2, 2, &reg16);
+
+		reg16 |= SFR_MEDIUM_RECEIVE_EN | SFR_MEDIUM_RXFLOW_CTRLEN |
+			 SFR_MEDIUM_TXFLOW_CTRLEN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB | SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+		netif_carrier_on(dev->net);
+	} else {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				2, 2, &reg16);
+		reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				 2, 2, &reg16);
+
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+		reg16 &= ~SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+		reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+				 1, 1, &reg8);
+		reg8 = SFR_BULK_OUT_EFF_EN;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+				 1, 1, &reg8);
+
+		netif_carrier_off(dev->net);
+	}
+	return 0;
+}
+
 static int aqc111_reset(struct usbnet *dev)
 {
 	u8 reg8 = 0;
 	u16 reg16 = 0;
+	enum usb_device_speed usb_speed;
 	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 
+	usb_speed = dev->udev->speed;
+
 	/* Power up ethernet PHY */
+	aqc111_data->phy_ops.advertising = 0;
 	aqc111_data->phy_ops.phy_ctrl1 = 0;
 	aqc111_data->phy_ops.phy_ctrl2 = 0;
 
@@ -279,6 +599,12 @@ static int aqc111_reset(struct usbnet *dev)
 		  SFR_MONITOR_MODE_RW_FLAG);
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, &reg8);
 
+	netif_carrier_off(dev->net);
+
+	/* Phy advertise */
+	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+			     aqc111_data->advertised_speed);
+
 	return 0;
 }
 
@@ -307,6 +633,8 @@ static int aqc111_stop(struct usbnet *dev)
 				 4, &aqc111_data->phy_ops);
 	}
 
+	netif_carrier_off(dev->net);
+
 	return 0;
 }
 
@@ -314,6 +642,8 @@ static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
 	.bind		= aqc111_bind,
 	.unbind		= aqc111_unbind,
+	.status		= aqc111_status,
+	.link_reset	= aqc111_link_reset,
 	.reset		= aqc111_reset,
 	.stop		= aqc111_stop,
 };
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 8738d2c4ae90..5c5602e6d236 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -18,12 +18,44 @@
 #define AQC111_PHY_ID			0x00
 #define AQ_PHY_ADDR(mmd)		((AQC111_PHY_ID << 8) | mmd)
 
+#define AQ_PHY_AUTONEG_MMD		0x07
+#define AQ_PHY_AUTONEG_ADDR		AQ_PHY_ADDR(AQ_PHY_AUTONEG_MMD)
+
+#define AQ_AUTONEG_STD_CTRL_REG		0x0000
+	#define AQ_ANEG_EX_PAGE_CTRL		0x2000
+	#define AQ_ANEG_EN_ANEG			0x1000
+	#define AQ_ANEG_RESTART_ANEG		0x0200
+
+#define AQ_AUTONEG_ADV_REG		0x0010
+	#define AQ_ANEG_100M			0x0100
+	#define AQ_ANEG_PAUSE			0x0400
+	#define AQ_ANEG_ASYM_PAUSE		0x0800
+	#define AQ_ANEG_ABILITY_MASK		0x0FE0
+
+#define AQ_AUTONEG_10GT_CTRL_REG	0x0020
+	#define AQ_ANEG_ADV_10G_T		0x1000
+	#define AQ_ANEG_ADV_5G_T		0x0100
+	#define AQ_ANEG_ADV_2G5_T		0x0080
+	#define AQ_ANEG_ADV_LT			0x0001
+
+#define AQ_AUTONEG_VEN_PROV1_REG	0xC400
+	#define AQ_ANEG_ADV_1G			0x8000
+	#define AQ_ANEG_ADV_AQRATE		0x1000
+	#define AQ_ANEG_ADV_5G_N		0x0800
+	#define AQ_ANEG_ADV_2G5_N		0x0400
+	#define AQ_ANEG_EX_PHY_ID		0x0040
+	#define AQ_ANEG_EN_DSH			0x0010
+	#define AQ_ANEG_DSH_RETRY		0x0003
+
 #define AQ_PHY_GLOBAL_MMD		0x1E
 #define AQ_PHY_GLOBAL_ADDR		AQ_PHY_ADDR(AQ_PHY_GLOBAL_MMD)
 
 #define AQ_GLB_STD_CTRL_REG		0x0000
 	#define AQ_PHY_LOW_POWER_MODE		0x0800
 
+#define AQ_GLB_ING_PAUSE_CTRL_REG	0x7148
+#define AQ_GLB_EGR_PAUSE_CTRL_REG	0x4148
+
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
 
@@ -163,6 +195,10 @@ struct aqc111_phy_options {
 };
 
 struct aqc111_data {
+	u8 link_speed;
+	u8 link;
+	u8 autoneg;
+	u32 advertised_speed;
 	struct {
 		u8 major;
 		u8 minor;
@@ -172,6 +208,21 @@ struct aqc111_data {
 	struct aqc111_phy_options phy_ops;
 } __packed;
 
+struct aqc111_int_data {
+	u8 res1;
+	u8 link_speed: 7;
+	u8 link_status: 1;
+	__le16 res2;
+	__le16 res3;
+	__le16 res4;
+} __packed;
+
+#define AQ_INT_SPEED_10G	0x0E
+#define AQ_INT_SPEED_5G		0x0F
+#define AQ_INT_SPEED_2_5G	0x10
+#define AQ_INT_SPEED_1G		0x11
+#define AQ_INT_SPEED_100M	0x13
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  1 +
 2 files changed, 52 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 1d366f4a1c51..075f51cd04ab 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -11,6 +11,7 @@
 #include <linux/netdevice.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/if_vlan.h>
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 
@@ -266,11 +267,46 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static int aqc111_set_mac_addr(struct net_device *net, void *p)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct sockaddr *addr = p;
+
+	if (netif_running(net))
+		return -EBUSY;
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
+
+	/* Set the MAC address */
+	return aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN,
+				ETH_ALEN, net->dev_addr);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
+	.ndo_set_mac_address	= aqc111_set_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
 };
 
+static int aqc111_get_mac(struct usbnet *dev, u8 *buf)
+{
+	int ret;
+
+	ret = aqc111_read_cmd(dev, AQ_FLASH_PARAMETERS, 0, 0, 6, buf);
+	if (ret < 0)
+		goto out;
+
+	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
+
+	return 0;
+out:
+	return ret;
+}
+
 static void aqc111_read_fw_version(struct usbnet *dev,
 				   struct aqc111_data *aqc111_data)
 {
@@ -289,6 +325,7 @@ static void aqc111_read_fw_version(struct usbnet *dev,
 
 static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 {
+	u8 buf[6] = { 0 };
 	int ret;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct aqc111_data *aqc111_data;
@@ -316,6 +353,12 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->data[0] = (unsigned long)aqc111_data;
 	memset(aqc111_data, 0, sizeof(*aqc111_data));
 
+	/* Get the MAC address */
+	memset(buf, 0, ETH_ALEN);
+	ret = aqc111_get_mac(dev, buf);
+	if (ret)
+		goto out;
+
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
 	aqc111_read_fw_version(dev, aqc111_data);
@@ -324,6 +367,10 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 					 SPEED_5000 : SPEED_1000;
 
 	return 0;
+
+out:
+	kfree(aqc111_data);
+	return ret;
 }
 
 static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
@@ -587,6 +634,10 @@ static int aqc111_reset(struct usbnet *dev)
 				 4, &aqc111_data->phy_ops);
 	}
 
+	/* Set the MAC address */
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN,
+			 ETH_ALEN, dev->net->dev_addr);
+
 	reg8 = 0xFF;
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, &reg8);
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 5c5602e6d236..7ca5c5a6ec82 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -11,6 +11,7 @@
 #define __LINUX_USBNET_AQC111_H
 
 #define AQ_ACCESS_MAC			0x01
+#define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
 #define AQ_PHY_CMD			0x32
 #define AQ_PHY_OPS			0x61
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-05 10:24   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:24 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  1 +
 2 files changed, 52 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 1d366f4a1c51..075f51cd04ab 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -11,6 +11,7 @@
 #include <linux/netdevice.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/if_vlan.h>
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 
@@ -266,11 +267,46 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static int aqc111_set_mac_addr(struct net_device *net, void *p)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct sockaddr *addr = p;
+
+	if (netif_running(net))
+		return -EBUSY;
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
+
+	/* Set the MAC address */
+	return aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN,
+				ETH_ALEN, net->dev_addr);
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
+	.ndo_set_mac_address	= aqc111_set_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
 };
 
+static int aqc111_get_mac(struct usbnet *dev, u8 *buf)
+{
+	int ret;
+
+	ret = aqc111_read_cmd(dev, AQ_FLASH_PARAMETERS, 0, 0, 6, buf);
+	if (ret < 0)
+		goto out;
+
+	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
+
+	return 0;
+out:
+	return ret;
+}
+
 static void aqc111_read_fw_version(struct usbnet *dev,
 				   struct aqc111_data *aqc111_data)
 {
@@ -289,6 +325,7 @@ static void aqc111_read_fw_version(struct usbnet *dev,
 
 static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 {
+	u8 buf[6] = { 0 };
 	int ret;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct aqc111_data *aqc111_data;
@@ -316,6 +353,12 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->data[0] = (unsigned long)aqc111_data;
 	memset(aqc111_data, 0, sizeof(*aqc111_data));
 
+	/* Get the MAC address */
+	memset(buf, 0, ETH_ALEN);
+	ret = aqc111_get_mac(dev, buf);
+	if (ret)
+		goto out;
+
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
 	aqc111_read_fw_version(dev, aqc111_data);
@@ -324,6 +367,10 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 					 SPEED_5000 : SPEED_1000;
 
 	return 0;
+
+out:
+	kfree(aqc111_data);
+	return ret;
 }
 
 static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
@@ -587,6 +634,10 @@ static int aqc111_reset(struct usbnet *dev)
 				 4, &aqc111_data->phy_ops);
 	}
 
+	/* Set the MAC address */
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN,
+			 ETH_ALEN, dev->net->dev_addr);
+
 	reg8 = 0xFF;
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, &reg8);
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 5c5602e6d236..7ca5c5a6ec82 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -11,6 +11,7 @@
 #define __LINUX_USBNET_AQC111_H
 
 #define AQ_ACCESS_MAC			0x01
+#define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
 #define AQ_PHY_CMD			0x32
 #define AQ_PHY_OPS			0x61

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 22 +++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 075f51cd04ab..46832fd56f0a 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -287,6 +287,9 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
+	.ndo_start_xmit		= usbnet_start_xmit,
+	.ndo_tx_timeout		= usbnet_tx_timeout,
+	.ndo_get_stats64	= usbnet_get_stats64,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
@@ -359,8 +362,18 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (ret)
 		goto out;
 
+	/* Set TX needed headroom & tailroom */
+	dev->net->needed_headroom += AQ_TX_HEADER_SIZE;
+	dev->net->needed_tailroom += AQ_TX_HEADER_SIZE;
+
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
+	if (usb_device_no_sg_constraint(dev->udev))
+		dev->can_dma_sg = 1;
+
+	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
+	dev->net->features |= AQ_SUPPORT_FEATURE;
+
 	aqc111_read_fw_version(dev, aqc111_data);
 	aqc111_data->autoneg = AUTONEG_ENABLE;
 	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
@@ -608,6 +621,12 @@ static int aqc111_reset(struct usbnet *dev)
 
 	usb_speed = dev->udev->speed;
 
+	if (usb_device_no_sg_constraint(dev->udev))
+		dev->can_dma_sg = 1;
+
+	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
+	dev->net->features |= AQ_SUPPORT_FEATURE;
+
 	/* Power up ethernet PHY */
 	aqc111_data->phy_ops.advertising = 0;
 	aqc111_data->phy_ops.phy_ctrl1 = 0;
@@ -689,6 +708,57 @@ static int aqc111_stop(struct usbnet *dev)
 	return 0;
 }
 
+static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+				       gfp_t flags)
+{
+	struct aq_tx_packet_desc tx_hdr;
+	int frame_size = dev->maxpacket;
+	int headroom = 0;
+	int tailroom = 0;
+	int padding_size = 0;
+	struct sk_buff *new_skb = NULL;
+
+	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
+
+	/*Length of actual data*/
+	tx_hdr.length = (skb->len & 0x1FFFFF);
+
+	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
+	if (headroom != 0)
+		padding_size = 8 - headroom;
+
+	if (((skb->len + AQ_TX_HEADER_SIZE + padding_size) % frame_size) == 0) {
+		padding_size += 8;
+		tx_hdr.drop_padding = 1;
+	}
+
+	if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
+	    skb_linearize(skb))
+		return NULL;
+
+	headroom = skb_headroom(skb);
+	tailroom = skb_tailroom(skb);
+
+	if (!(headroom >= AQ_TX_HEADER_SIZE && tailroom >= padding_size)) {
+		new_skb = skb_copy_expand(skb, AQ_TX_HEADER_SIZE,
+					  padding_size, flags);
+		dev_kfree_skb_any(skb);
+		skb = new_skb;
+		if (!skb)
+			return NULL;
+	}
+	if (padding_size != 0)
+		skb_put(skb, padding_size);
+	/* Copy TX header */
+	skb_push(skb, AQ_TX_HEADER_SIZE);
+	cpu_to_le64s(&tx_hdr);
+	skb_copy_to_linear_data(skb, &tx_hdr, 8);
+
+	usbnet_set_skb_tx_stats(skb, 1, 0);
+
+	return skb;
+}
+
 static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
 	.bind		= aqc111_bind,
@@ -697,6 +767,9 @@ static const struct driver_info aqc111_info = {
 	.link_reset	= aqc111_link_reset,
 	.reset		= aqc111_reset,
 	.stop		= aqc111_stop,
+	.flags		= FLAG_ETHER | FLAG_FRAMING_AX |
+			  FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+	.tx_fixup	= aqc111_tx_fixup,
 };
 
 #define AQC111_USB_ETH_DEV(vid, pid, table) \
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 7ca5c5a6ec82..049012e26b26 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -60,6 +60,10 @@
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
 
+/* Feature. ********************************************/
+#define AQ_SUPPORT_FEATURE	(NETIF_F_SG)
+#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG)
+
 /* SFR Reg. ********************************************/
 
 #define SFR_GENERAL_STATUS		0x03
@@ -224,6 +228,24 @@ struct aqc111_int_data {
 #define AQ_INT_SPEED_1G		0x11
 #define AQ_INT_SPEED_100M	0x13
 
+struct aq_tx_packet_desc {
+	struct {
+		u32 length:21;
+		u32 checksum:7;
+		u32 drop_padding:1;
+		u32 vlan_tag:1;
+		u32 cphi:1;
+		u32 dicf:1;
+	};
+	struct {
+		u32 max_seg_size:15;
+		u32 reserved:1;
+		u32 vlan_info:16;
+	};
+};
+
+#define AQ_TX_HEADER_SIZE sizeof(struct aq_tx_packet_desc)
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 22 +++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 075f51cd04ab..46832fd56f0a 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -287,6 +287,9 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
+	.ndo_start_xmit		= usbnet_start_xmit,
+	.ndo_tx_timeout		= usbnet_tx_timeout,
+	.ndo_get_stats64	= usbnet_get_stats64,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
@@ -359,8 +362,18 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (ret)
 		goto out;
 
+	/* Set TX needed headroom & tailroom */
+	dev->net->needed_headroom += AQ_TX_HEADER_SIZE;
+	dev->net->needed_tailroom += AQ_TX_HEADER_SIZE;
+
 	dev->net->netdev_ops = &aqc111_netdev_ops;
 
+	if (usb_device_no_sg_constraint(dev->udev))
+		dev->can_dma_sg = 1;
+
+	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
+	dev->net->features |= AQ_SUPPORT_FEATURE;
+
 	aqc111_read_fw_version(dev, aqc111_data);
 	aqc111_data->autoneg = AUTONEG_ENABLE;
 	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
@@ -608,6 +621,12 @@ static int aqc111_reset(struct usbnet *dev)
 
 	usb_speed = dev->udev->speed;
 
+	if (usb_device_no_sg_constraint(dev->udev))
+		dev->can_dma_sg = 1;
+
+	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
+	dev->net->features |= AQ_SUPPORT_FEATURE;
+
 	/* Power up ethernet PHY */
 	aqc111_data->phy_ops.advertising = 0;
 	aqc111_data->phy_ops.phy_ctrl1 = 0;
@@ -689,6 +708,57 @@ static int aqc111_stop(struct usbnet *dev)
 	return 0;
 }
 
+static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+				       gfp_t flags)
+{
+	struct aq_tx_packet_desc tx_hdr;
+	int frame_size = dev->maxpacket;
+	int headroom = 0;
+	int tailroom = 0;
+	int padding_size = 0;
+	struct sk_buff *new_skb = NULL;
+
+	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
+
+	/*Length of actual data*/
+	tx_hdr.length = (skb->len & 0x1FFFFF);
+
+	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
+	if (headroom != 0)
+		padding_size = 8 - headroom;
+
+	if (((skb->len + AQ_TX_HEADER_SIZE + padding_size) % frame_size) == 0) {
+		padding_size += 8;
+		tx_hdr.drop_padding = 1;
+	}
+
+	if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
+	    skb_linearize(skb))
+		return NULL;
+
+	headroom = skb_headroom(skb);
+	tailroom = skb_tailroom(skb);
+
+	if (!(headroom >= AQ_TX_HEADER_SIZE && tailroom >= padding_size)) {
+		new_skb = skb_copy_expand(skb, AQ_TX_HEADER_SIZE,
+					  padding_size, flags);
+		dev_kfree_skb_any(skb);
+		skb = new_skb;
+		if (!skb)
+			return NULL;
+	}
+	if (padding_size != 0)
+		skb_put(skb, padding_size);
+	/* Copy TX header */
+	skb_push(skb, AQ_TX_HEADER_SIZE);
+	cpu_to_le64s(&tx_hdr);
+	skb_copy_to_linear_data(skb, &tx_hdr, 8);
+
+	usbnet_set_skb_tx_stats(skb, 1, 0);
+
+	return skb;
+}
+
 static const struct driver_info aqc111_info = {
 	.description	= "Aquantia AQtion USB to 5GbE Controller",
 	.bind		= aqc111_bind,
@@ -697,6 +767,9 @@ static const struct driver_info aqc111_info = {
 	.link_reset	= aqc111_link_reset,
 	.reset		= aqc111_reset,
 	.stop		= aqc111_stop,
+	.flags		= FLAG_ETHER | FLAG_FRAMING_AX |
+			  FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+	.tx_fixup	= aqc111_tx_fixup,
 };
 
 #define AQC111_USB_ETH_DEV(vid, pid, table) \
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 7ca5c5a6ec82..049012e26b26 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -60,6 +60,10 @@
 #define AQ_USB_PHY_SET_TIMEOUT		10000
 #define AQ_USB_SET_TIMEOUT		4000
 
+/* Feature. ********************************************/
+#define AQ_SUPPORT_FEATURE	(NETIF_F_SG)
+#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG)
+
 /* SFR Reg. ********************************************/
 
 #define SFR_GENERAL_STATUS		0x03
@@ -224,6 +228,24 @@ struct aqc111_int_data {
 #define AQ_INT_SPEED_1G		0x11
 #define AQ_INT_SPEED_100M	0x13
 
+struct aq_tx_packet_desc {
+	struct {
+		u32 length:21;
+		u32 checksum:7;
+		u32 drop_padding:1;
+		u32 vlan_tag:1;
+		u32 cphi:1;
+		u32 dicf:1;
+	};
+	struct {
+		u32 max_seg_size:15;
+		u32 reserved:1;
+		u32 vlan_info:16;
+	};
+};
+
+#define AQ_TX_HEADER_SIZE sizeof(struct aq_tx_packet_desc)
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 09/19] net: usb: aqc111: Implement RX data path
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  39 ++++++++++++++++++
 2 files changed, 139 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 46832fd56f0a..fc068e731335 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -362,6 +362,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (ret)
 		goto out;
 
+	/* Set Rx urb size */
+	dev->rx_urb_size = URB_SIZE;
+
 	/* Set TX needed headroom & tailroom */
 	dev->net->needed_headroom += AQ_TX_HEADER_SIZE;
 	dev->net->needed_tailroom += AQ_TX_HEADER_SIZE;
@@ -621,6 +624,8 @@ static int aqc111_reset(struct usbnet *dev)
 
 	usb_speed = dev->udev->speed;
 
+	dev->rx_urb_size = URB_SIZE;
+
 	if (usb_device_no_sg_constraint(dev->udev))
 		dev->can_dma_sg = 1;
 
@@ -708,6 +713,100 @@ static int aqc111_stop(struct usbnet *dev)
 	return 0;
 }
 
+static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	struct sk_buff *new_skb = NULL;
+	u32 skb_len = 0;
+	u32 desc_offset = 0; /*RX Header Offset*/
+	u32 start_of_descs = 0;
+	u16 pkt_count = 0;
+	u32 pkt_total_offset = 0;
+	struct aq_rx_packet_desc *pkt_desc = NULL;
+	struct aq_rx_desc_header desc_hdr;
+
+	if (!skb)
+		goto err;
+
+	if (skb->len == 0)
+		goto err;
+
+	skb_len = skb->len;
+	/* RX Offset Header */
+	skb_trim(skb, skb->len - sizeof(struct aq_rx_desc_header));
+	memcpy(&desc_hdr, skb_tail_pointer(skb),
+	       sizeof(struct aq_rx_desc_header));
+	le64_to_cpus(&desc_hdr);
+
+	/* Check these packets */
+	desc_offset = (u32)desc_hdr.desc_offset;
+	pkt_count = desc_hdr.pkt_count;
+	start_of_descs = skb_len - ((pkt_count + 1) *
+			 sizeof(struct aq_rx_desc_header));
+
+	/* self check descs position */
+	if (start_of_descs != desc_offset)
+		goto err;
+
+	/* self check desc_offset from header*/
+	if (desc_offset >= skb_len)
+		goto err;
+
+	if (pkt_count == 0)
+		goto err;
+
+	/* Get the first RX packet header */
+	pkt_desc = (struct aq_rx_packet_desc *)(skb->data + desc_offset);
+
+	while (pkt_count--) {
+		u32 pkt_len = (u32)(pkt_desc->length & 0x7FFF);
+		u32 pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8);
+
+		le64_to_cpus(pkt_desc);
+
+		pkt_total_offset += pkt_len_with_padd;
+		if (pkt_total_offset > desc_offset ||
+		    (pkt_count == 0 && pkt_total_offset != desc_offset)) {
+			goto err;
+		}
+
+		if (pkt_desc->drop || !pkt_desc->rx_ok ||
+		    pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) {
+			skb_pull(skb, pkt_len_with_padd);
+			/* Next RX Packet Header */
+			pkt_desc++;
+			continue;
+		}
+
+		/* Clone SKB */
+		new_skb = skb_clone(skb, GFP_ATOMIC);
+
+		if (!new_skb)
+			goto err;
+
+		new_skb->len = pkt_len;
+		skb_pull(new_skb, AQ_RX_HW_PAD);
+		skb_set_tail_pointer(new_skb, new_skb->len);
+
+		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
+
+		usbnet_skb_return(dev, new_skb);
+		if (pkt_count == 0)
+			break;
+
+		skb_pull(skb, pkt_len_with_padd);
+
+		/* Next RX Packet Header */
+		pkt_desc++;
+
+		new_skb = NULL;
+	}
+
+	return 1;
+
+err:
+	return 0;
+}
+
 static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 				       gfp_t flags)
 {
@@ -769,6 +868,7 @@ static const struct driver_info aqc111_info = {
 	.stop		= aqc111_stop,
 	.flags		= FLAG_ETHER | FLAG_FRAMING_AX |
 			  FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+	.rx_fixup	= aqc111_rx_fixup,
 	.tx_fixup	= aqc111_tx_fixup,
 };
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 049012e26b26..679ca9f992f7 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -10,6 +10,8 @@
 #ifndef __LINUX_USBNET_AQC111_H
 #define __LINUX_USBNET_AQC111_H
 
+#define URB_SIZE	(1024 * 62)
+
 #define AQ_ACCESS_MAC			0x01
 #define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
@@ -228,6 +230,8 @@ struct aqc111_int_data {
 #define AQ_INT_SPEED_1G		0x11
 #define AQ_INT_SPEED_100M	0x13
 
+#define AQ_RX_HW_PAD			0x02
+
 struct aq_tx_packet_desc {
 	struct {
 		u32 length:21;
@@ -246,6 +250,41 @@ struct aq_tx_packet_desc {
 
 #define AQ_TX_HEADER_SIZE sizeof(struct aq_tx_packet_desc)
 
+struct aq_rx_packet_desc {
+	struct {
+		u16 l4_err:1;
+		u16 l3_err:1;
+		u16 l4_pkt_type:3;
+		u16 l3_pkt_type:2;
+		u16 ce:1;
+		u16 tco_match:1;
+		u16 node_id_match:1;
+		u16 vlan_ind : 1;
+		u16 rx_ok:1;
+		u16 reserved1 : 3;
+		u16 bmc:1;
+	};
+	struct {
+		u16 length:15;
+		u16 drop:1;
+	};
+	u16 vlan_tag;
+	struct {
+		u8 wuf_detect:1;
+		u8 wuf_wake:1;
+		u8 wuf_ind:6;
+		u8 reserved2:8;
+	};
+};
+
+struct aq_rx_desc_header {
+	struct {
+		u32 pkt_count:13;
+		u32 desc_offset:19;
+	};
+	u32 rx_throughput;
+};
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,09/19] net: usb: aqc111: Implement RX data path
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  39 ++++++++++++++++++
 2 files changed, 139 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 46832fd56f0a..fc068e731335 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -362,6 +362,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	if (ret)
 		goto out;
 
+	/* Set Rx urb size */
+	dev->rx_urb_size = URB_SIZE;
+
 	/* Set TX needed headroom & tailroom */
 	dev->net->needed_headroom += AQ_TX_HEADER_SIZE;
 	dev->net->needed_tailroom += AQ_TX_HEADER_SIZE;
@@ -621,6 +624,8 @@ static int aqc111_reset(struct usbnet *dev)
 
 	usb_speed = dev->udev->speed;
 
+	dev->rx_urb_size = URB_SIZE;
+
 	if (usb_device_no_sg_constraint(dev->udev))
 		dev->can_dma_sg = 1;
 
@@ -708,6 +713,100 @@ static int aqc111_stop(struct usbnet *dev)
 	return 0;
 }
 
+static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	struct sk_buff *new_skb = NULL;
+	u32 skb_len = 0;
+	u32 desc_offset = 0; /*RX Header Offset*/
+	u32 start_of_descs = 0;
+	u16 pkt_count = 0;
+	u32 pkt_total_offset = 0;
+	struct aq_rx_packet_desc *pkt_desc = NULL;
+	struct aq_rx_desc_header desc_hdr;
+
+	if (!skb)
+		goto err;
+
+	if (skb->len == 0)
+		goto err;
+
+	skb_len = skb->len;
+	/* RX Offset Header */
+	skb_trim(skb, skb->len - sizeof(struct aq_rx_desc_header));
+	memcpy(&desc_hdr, skb_tail_pointer(skb),
+	       sizeof(struct aq_rx_desc_header));
+	le64_to_cpus(&desc_hdr);
+
+	/* Check these packets */
+	desc_offset = (u32)desc_hdr.desc_offset;
+	pkt_count = desc_hdr.pkt_count;
+	start_of_descs = skb_len - ((pkt_count + 1) *
+			 sizeof(struct aq_rx_desc_header));
+
+	/* self check descs position */
+	if (start_of_descs != desc_offset)
+		goto err;
+
+	/* self check desc_offset from header*/
+	if (desc_offset >= skb_len)
+		goto err;
+
+	if (pkt_count == 0)
+		goto err;
+
+	/* Get the first RX packet header */
+	pkt_desc = (struct aq_rx_packet_desc *)(skb->data + desc_offset);
+
+	while (pkt_count--) {
+		u32 pkt_len = (u32)(pkt_desc->length & 0x7FFF);
+		u32 pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8);
+
+		le64_to_cpus(pkt_desc);
+
+		pkt_total_offset += pkt_len_with_padd;
+		if (pkt_total_offset > desc_offset ||
+		    (pkt_count == 0 && pkt_total_offset != desc_offset)) {
+			goto err;
+		}
+
+		if (pkt_desc->drop || !pkt_desc->rx_ok ||
+		    pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) {
+			skb_pull(skb, pkt_len_with_padd);
+			/* Next RX Packet Header */
+			pkt_desc++;
+			continue;
+		}
+
+		/* Clone SKB */
+		new_skb = skb_clone(skb, GFP_ATOMIC);
+
+		if (!new_skb)
+			goto err;
+
+		new_skb->len = pkt_len;
+		skb_pull(new_skb, AQ_RX_HW_PAD);
+		skb_set_tail_pointer(new_skb, new_skb->len);
+
+		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
+
+		usbnet_skb_return(dev, new_skb);
+		if (pkt_count == 0)
+			break;
+
+		skb_pull(skb, pkt_len_with_padd);
+
+		/* Next RX Packet Header */
+		pkt_desc++;
+
+		new_skb = NULL;
+	}
+
+	return 1;
+
+err:
+	return 0;
+}
+
 static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 				       gfp_t flags)
 {
@@ -769,6 +868,7 @@ static const struct driver_info aqc111_info = {
 	.stop		= aqc111_stop,
 	.flags		= FLAG_ETHER | FLAG_FRAMING_AX |
 			  FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+	.rx_fixup	= aqc111_rx_fixup,
 	.tx_fixup	= aqc111_tx_fixup,
 };
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 049012e26b26..679ca9f992f7 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -10,6 +10,8 @@
 #ifndef __LINUX_USBNET_AQC111_H
 #define __LINUX_USBNET_AQC111_H
 
+#define URB_SIZE	(1024 * 62)
+
 #define AQ_ACCESS_MAC			0x01
 #define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
@@ -228,6 +230,8 @@ struct aqc111_int_data {
 #define AQ_INT_SPEED_1G		0x11
 #define AQ_INT_SPEED_100M	0x13
 
+#define AQ_RX_HW_PAD			0x02
+
 struct aq_tx_packet_desc {
 	struct {
 		u32 length:21;
@@ -246,6 +250,41 @@ struct aq_tx_packet_desc {
 
 #define AQ_TX_HEADER_SIZE sizeof(struct aq_tx_packet_desc)
 
+struct aq_rx_packet_desc {
+	struct {
+		u16 l4_err:1;
+		u16 l3_err:1;
+		u16 l4_pkt_type:3;
+		u16 l3_pkt_type:2;
+		u16 ce:1;
+		u16 tco_match:1;
+		u16 node_id_match:1;
+		u16 vlan_ind : 1;
+		u16 rx_ok:1;
+		u16 reserved1 : 3;
+		u16 bmc:1;
+	};
+	struct {
+		u16 length:15;
+		u16 drop:1;
+	};
+	u16 vlan_tag;
+	struct {
+		u8 wuf_detect:1;
+		u8 wuf_wake:1;
+		u8 wuf_ind:6;
+		u8 reserved2:8;
+	};
+};
+
+struct aq_rx_desc_header {
+	struct {
+		u32 pkt_count:13;
+		u32 desc_offset:19;
+	};
+	u32 rx_throughput;
+};
+
 static struct {
 	unsigned char ctrl;
 	unsigned char timer_l;

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 10/19] net: usb: aqc111: Add checksum offload support
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 23 +++++++++++++++++++++--
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index fc068e731335..5967f7adeab4 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -537,6 +537,26 @@ static void aqc111_configure_rx(struct usbnet *dev,
 	netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host);
 }
 
+static void aqc111_configure_csum_offload(struct usbnet *dev)
+{
+	u8 reg8 = 0;
+
+	if (dev->net->features & NETIF_F_RXCSUM) {
+		reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
+			SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6;
+	}
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
+
+	reg8 = 0;
+	if (dev->net->features & NETIF_F_IP_CSUM)
+		reg8 |= SFR_TXCOE_IP | SFR_TXCOE_TCP | SFR_TXCOE_UDP;
+
+	if (dev->net->features & NETIF_F_IPV6_CSUM)
+		reg8 |= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
+}
+
 static int aqc111_link_reset(struct usbnet *dev)
 {
 	u8 reg8 = 0;
@@ -580,6 +600,8 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				 2, 2, &reg16);
 
+		aqc111_configure_csum_offload(dev);
+
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				2, 2, &reg16);
 
@@ -713,6 +735,21 @@ static int aqc111_stop(struct usbnet *dev)
 	return 0;
 }
 
+static void aqc111_rx_checksum(struct sk_buff *skb, void *pkt_hdr)
+{
+	struct aq_rx_packet_desc *hdr = (struct aq_rx_packet_desc *)pkt_hdr;
+
+	skb->ip_summed = CHECKSUM_NONE;
+	/* checksum error bit is set */
+	if (hdr->l4_err || hdr->l3_err)
+		return;
+
+	/* It must be a TCP or UDP packet with a valid checksum */
+	if (hdr->l4_pkt_type == AQ_RXHDR_L4_TYPE_TCP ||
+	    hdr->l4_pkt_type == AQ_RXHDR_L4_TYPE_UDP)
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
 static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	struct sk_buff *new_skb = NULL;
@@ -788,6 +825,7 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		skb_set_tail_pointer(new_skb, new_skb->len);
 
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
+		aqc111_rx_checksum(new_skb, &pkt_desc);
 
 		usbnet_skb_return(dev, new_skb);
 		if (pkt_count == 0)
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 679ca9f992f7..1632e78ebe9b 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -63,8 +63,11 @@
 #define AQ_USB_SET_TIMEOUT		4000
 
 /* Feature. ********************************************/
-#define AQ_SUPPORT_FEATURE	(NETIF_F_SG)
-#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG)
+#define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
+
+#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
 
 /* SFR Reg. ********************************************/
 
@@ -230,6 +233,22 @@ struct aqc111_int_data {
 #define AQ_INT_SPEED_1G		0x11
 #define AQ_INT_SPEED_100M	0x13
 
+#define AQ_RXHDR_L4_ERR		BIT(8)
+#define AQ_RXHDR_L3_ERR		BIT(9)
+
+#define AQ_RXHDR_L4_TYPE_ICMP		0x02
+#define AQ_RXHDR_L4_TYPE_IGMP		0x03
+#define AQ_RXHDR_L4_TYPE_TCMPV6		0x05
+
+#define AQ_RXHDR_L3_TYPE_IP		0x01
+#define AQ_RXHDR_L3_TYPE_IPV6		0x02
+
+#define AQ_RXHDR_L4_TYPE_MASK		0x1c
+#define AQ_RXHDR_L4_TYPE_UDP		0x04
+#define AQ_RXHDR_L4_TYPE_TCP		0x10
+#define AQ_RXHDR_L3CSUM_ERR		0x02
+#define AQ_RXHDR_L4CSUM_ERR		0x01
+
 #define AQ_RX_HW_PAD			0x02
 
 struct aq_tx_packet_desc {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,10/19] net: usb: aqc111: Add checksum offload support
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h | 23 +++++++++++++++++++++--
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index fc068e731335..5967f7adeab4 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -537,6 +537,26 @@ static void aqc111_configure_rx(struct usbnet *dev,
 	netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host);
 }
 
+static void aqc111_configure_csum_offload(struct usbnet *dev)
+{
+	u8 reg8 = 0;
+
+	if (dev->net->features & NETIF_F_RXCSUM) {
+		reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
+			SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6;
+	}
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
+
+	reg8 = 0;
+	if (dev->net->features & NETIF_F_IP_CSUM)
+		reg8 |= SFR_TXCOE_IP | SFR_TXCOE_TCP | SFR_TXCOE_UDP;
+
+	if (dev->net->features & NETIF_F_IPV6_CSUM)
+		reg8 |= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
+}
+
 static int aqc111_link_reset(struct usbnet *dev)
 {
 	u8 reg8 = 0;
@@ -580,6 +600,8 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				 2, 2, &reg16);
 
+		aqc111_configure_csum_offload(dev);
+
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				2, 2, &reg16);
 
@@ -713,6 +735,21 @@ static int aqc111_stop(struct usbnet *dev)
 	return 0;
 }
 
+static void aqc111_rx_checksum(struct sk_buff *skb, void *pkt_hdr)
+{
+	struct aq_rx_packet_desc *hdr = (struct aq_rx_packet_desc *)pkt_hdr;
+
+	skb->ip_summed = CHECKSUM_NONE;
+	/* checksum error bit is set */
+	if (hdr->l4_err || hdr->l3_err)
+		return;
+
+	/* It must be a TCP or UDP packet with a valid checksum */
+	if (hdr->l4_pkt_type == AQ_RXHDR_L4_TYPE_TCP ||
+	    hdr->l4_pkt_type == AQ_RXHDR_L4_TYPE_UDP)
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
 static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	struct sk_buff *new_skb = NULL;
@@ -788,6 +825,7 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		skb_set_tail_pointer(new_skb, new_skb->len);
 
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
+		aqc111_rx_checksum(new_skb, &pkt_desc);
 
 		usbnet_skb_return(dev, new_skb);
 		if (pkt_count == 0)
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 679ca9f992f7..1632e78ebe9b 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -63,8 +63,11 @@
 #define AQ_USB_SET_TIMEOUT		4000
 
 /* Feature. ********************************************/
-#define AQ_SUPPORT_FEATURE	(NETIF_F_SG)
-#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG)
+#define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
+
+#define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
 
 /* SFR Reg. ********************************************/
 
@@ -230,6 +233,22 @@ struct aqc111_int_data {
 #define AQ_INT_SPEED_1G		0x11
 #define AQ_INT_SPEED_100M	0x13
 
+#define AQ_RXHDR_L4_ERR		BIT(8)
+#define AQ_RXHDR_L3_ERR		BIT(9)
+
+#define AQ_RXHDR_L4_TYPE_ICMP		0x02
+#define AQ_RXHDR_L4_TYPE_IGMP		0x03
+#define AQ_RXHDR_L4_TYPE_TCMPV6		0x05
+
+#define AQ_RXHDR_L3_TYPE_IP		0x01
+#define AQ_RXHDR_L3_TYPE_IPV6		0x02
+
+#define AQ_RXHDR_L4_TYPE_MASK		0x1c
+#define AQ_RXHDR_L4_TYPE_UDP		0x04
+#define AQ_RXHDR_L4_TYPE_TCP		0x10
+#define AQ_RXHDR_L3CSUM_ERR		0x02
+#define AQ_RXHDR_L4CSUM_ERR		0x01
+
 #define AQ_RX_HW_PAD			0x02
 
 struct aq_tx_packet_desc {

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 11/19] net: usb: aqc111: Add support for changing MTU
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 5967f7adeab4..134cfc632584 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -267,6 +267,54 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static int aqc111_change_mtu(struct net_device *net, int new_mtu)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u16 reg16 = 0;
+	u8 buf[5];
+
+	if (new_mtu <= 0 || new_mtu > 16334) {
+		netdev_info(net, "Invalid MTU %d requested, hw max 16334",
+			    new_mtu);
+		return -EINVAL;
+	}
+
+	net->mtu = new_mtu;
+	dev->hard_mtu = net->mtu + net->hard_header_len;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			2, 2, &reg16);
+	if (net->mtu > 1500)
+		reg16 |= SFR_MEDIUM_JUMBO_EN;
+	else
+		reg16 &= ~SFR_MEDIUM_JUMBO_EN;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			 2, 2, &reg16);
+
+	if (dev->net->mtu > 12500 && dev->net->mtu < 16384) {
+		memcpy(buf, &AQC111_BULKIN_SIZE[2], 5);
+		/* RX bulk configuration */
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL,
+				 5, 5, buf);
+	}
+
+	/* Set high low water level */
+	if (dev->net->mtu <= 4500)
+		reg16 = 0x0810;
+	else if (dev->net->mtu <= 9500)
+		reg16 = 0x1020;
+	else if (dev->net->mtu <= 12500)
+		reg16 = 0x1420;
+	else if (dev->net->mtu < 16384)
+		reg16 = 0x1A20;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
+			 2, 2, &reg16);
+
+	return 0;
+}
+
 static int aqc111_set_mac_addr(struct net_device *net, void *p)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -290,6 +338,7 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_start_xmit		= usbnet_start_xmit,
 	.ndo_tx_timeout		= usbnet_tx_timeout,
 	.ndo_get_stats64	= usbnet_get_stats64,
+	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
@@ -524,13 +573,22 @@ static void aqc111_configure_rx(struct usbnet *dev,
 		break;
 	}
 	}
+	if (dev->net->mtu > 12500 && dev->net->mtu < 16384)
+		queue_num = 2; /* For Jumbo packet 16KB */
 
 	memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5);
 	/* RX bulk configuration */
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf);
 
 	/* Set high low water level */
-	reg16 = 0x0810;
+	if (dev->net->mtu <= 4500)
+		reg16 = 0x0810;
+	else if (dev->net->mtu <= 9500)
+		reg16 = 0x1020;
+	else if (dev->net->mtu <= 12500)
+		reg16 = 0x1420;
+	else if (dev->net->mtu < 16384)
+		reg16 = 0x1A20;
 
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
 			 2, 2, &reg16);
@@ -605,6 +663,9 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				2, 2, &reg16);
 
+		if (dev->net->mtu > 1500)
+			reg16 |= SFR_MEDIUM_JUMBO_EN;
+
 		reg16 |= SFR_MEDIUM_RECEIVE_EN | SFR_MEDIUM_RXFLOW_CTRLEN |
 			 SFR_MEDIUM_TXFLOW_CTRLEN;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,11/19] net: usb: aqc111: Add support for changing MTU
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 5967f7adeab4..134cfc632584 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -267,6 +267,54 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static int aqc111_change_mtu(struct net_device *net, int new_mtu)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u16 reg16 = 0;
+	u8 buf[5];
+
+	if (new_mtu <= 0 || new_mtu > 16334) {
+		netdev_info(net, "Invalid MTU %d requested, hw max 16334",
+			    new_mtu);
+		return -EINVAL;
+	}
+
+	net->mtu = new_mtu;
+	dev->hard_mtu = net->mtu + net->hard_header_len;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			2, 2, &reg16);
+	if (net->mtu > 1500)
+		reg16 |= SFR_MEDIUM_JUMBO_EN;
+	else
+		reg16 &= ~SFR_MEDIUM_JUMBO_EN;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+			 2, 2, &reg16);
+
+	if (dev->net->mtu > 12500 && dev->net->mtu < 16384) {
+		memcpy(buf, &AQC111_BULKIN_SIZE[2], 5);
+		/* RX bulk configuration */
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL,
+				 5, 5, buf);
+	}
+
+	/* Set high low water level */
+	if (dev->net->mtu <= 4500)
+		reg16 = 0x0810;
+	else if (dev->net->mtu <= 9500)
+		reg16 = 0x1020;
+	else if (dev->net->mtu <= 12500)
+		reg16 = 0x1420;
+	else if (dev->net->mtu < 16384)
+		reg16 = 0x1A20;
+
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
+			 2, 2, &reg16);
+
+	return 0;
+}
+
 static int aqc111_set_mac_addr(struct net_device *net, void *p)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -290,6 +338,7 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_start_xmit		= usbnet_start_xmit,
 	.ndo_tx_timeout		= usbnet_tx_timeout,
 	.ndo_get_stats64	= usbnet_get_stats64,
+	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
@@ -524,13 +573,22 @@ static void aqc111_configure_rx(struct usbnet *dev,
 		break;
 	}
 	}
+	if (dev->net->mtu > 12500 && dev->net->mtu < 16384)
+		queue_num = 2; /* For Jumbo packet 16KB */
 
 	memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5);
 	/* RX bulk configuration */
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf);
 
 	/* Set high low water level */
-	reg16 = 0x0810;
+	if (dev->net->mtu <= 4500)
+		reg16 = 0x0810;
+	else if (dev->net->mtu <= 9500)
+		reg16 = 0x1020;
+	else if (dev->net->mtu <= 12500)
+		reg16 = 0x1420;
+	else if (dev->net->mtu < 16384)
+		reg16 = 0x1A20;
 
 	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
 			 2, 2, &reg16);
@@ -605,6 +663,9 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				2, 2, &reg16);
 
+		if (dev->net->mtu > 1500)
+			reg16 |= SFR_MEDIUM_JUMBO_EN;
+
 		reg16 |= SFR_MEDIUM_RECEIVE_EN | SFR_MEDIUM_RXFLOW_CTRLEN |
 			 SFR_MEDIUM_TXFLOW_CTRLEN;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 12/19] net: usb: aqc111: Add support for enable/disable checksum offload
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/usb/aqc111.h |  1 +
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 134cfc632584..6efd9a9ad44e 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -332,6 +332,46 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 				ETH_ALEN, net->dev_addr);
 }
 
+static int aqc111_set_features(struct net_device *net,
+			       netdev_features_t features)
+{
+	u8 reg8 = 0;
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	netdev_features_t changed = net->features ^ features;
+
+	if (changed & NETIF_F_IP_CSUM) {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
+		reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+				 1, 1, &reg8);
+	}
+
+	if (changed & NETIF_F_IPV6_CSUM) {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
+		reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+				 1, 1, &reg8);
+	}
+
+	if (changed & NETIF_F_RXCSUM) {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
+		if (features & NETIF_F_RXCSUM) {
+			aqc111_data->rx_checksum = 1;
+			reg8 &= ~(SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
+				  SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6);
+		} else {
+			aqc111_data->rx_checksum = 0;
+			reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
+				SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6;
+		}
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL,
+				 1, 1, &reg8);
+	}
+	return 0;
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
@@ -341,6 +381,7 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_features	= aqc111_set_features,
 };
 
 static int aqc111_get_mac(struct usbnet *dev, u8 *buf)
@@ -814,6 +855,7 @@ static void aqc111_rx_checksum(struct sk_buff *skb, void *pkt_hdr)
 static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	struct sk_buff *new_skb = NULL;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 	u32 skb_len = 0;
 	u32 desc_offset = 0; /*RX Header Offset*/
 	u32 start_of_descs = 0;
@@ -886,7 +928,8 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		skb_set_tail_pointer(new_skb, new_skb->len);
 
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
-		aqc111_rx_checksum(new_skb, &pkt_desc);
+		if (aqc111_data->rx_checksum)
+			aqc111_rx_checksum(new_skb, &pkt_desc);
 
 		usbnet_skb_return(dev, new_skb);
 		if (pkt_count == 0)
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 1632e78ebe9b..0be2e4cbb00a 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -205,6 +205,7 @@ struct aqc111_phy_options {
 };
 
 struct aqc111_data {
+	u8 rx_checksum;
 	u8 link_speed;
 	u8 link;
 	u8 autoneg;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,12/19] net: usb: aqc111: Add support for enable/disable checksum offload
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/usb/aqc111.h |  1 +
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 134cfc632584..6efd9a9ad44e 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -332,6 +332,46 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 				ETH_ALEN, net->dev_addr);
 }
 
+static int aqc111_set_features(struct net_device *net,
+			       netdev_features_t features)
+{
+	u8 reg8 = 0;
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	netdev_features_t changed = net->features ^ features;
+
+	if (changed & NETIF_F_IP_CSUM) {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
+		reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+				 1, 1, &reg8);
+	}
+
+	if (changed & NETIF_F_IPV6_CSUM) {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, &reg8);
+		reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+				 1, 1, &reg8);
+	}
+
+	if (changed & NETIF_F_RXCSUM) {
+		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, &reg8);
+		if (features & NETIF_F_RXCSUM) {
+			aqc111_data->rx_checksum = 1;
+			reg8 &= ~(SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
+				  SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6);
+		} else {
+			aqc111_data->rx_checksum = 0;
+			reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP |
+				SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6;
+		}
+
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL,
+				 1, 1, &reg8);
+	}
+	return 0;
+}
+
 static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
@@ -341,6 +381,7 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_features	= aqc111_set_features,
 };
 
 static int aqc111_get_mac(struct usbnet *dev, u8 *buf)
@@ -814,6 +855,7 @@ static void aqc111_rx_checksum(struct sk_buff *skb, void *pkt_hdr)
 static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	struct sk_buff *new_skb = NULL;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 	u32 skb_len = 0;
 	u32 desc_offset = 0; /*RX Header Offset*/
 	u32 start_of_descs = 0;
@@ -886,7 +928,8 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		skb_set_tail_pointer(new_skb, new_skb->len);
 
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
-		aqc111_rx_checksum(new_skb, &pkt_desc);
+		if (aqc111_data->rx_checksum)
+			aqc111_rx_checksum(new_skb, &pkt_desc);
 
 		usbnet_skb_return(dev, new_skb);
 		if (pkt_count == 0)
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 1632e78ebe9b..0be2e4cbb00a 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -205,6 +205,7 @@ struct aqc111_phy_options {
 };
 
 struct aqc111_data {
+	u8 rx_checksum;
 	u8 link_speed;
 	u8 link;
 	u8 autoneg;

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 13/19] net: usb: aqc111: Add support for TSO
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 3 +++
 drivers/net/usb/aqc111.h | 6 ++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 6efd9a9ad44e..f61fa7446b72 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -964,6 +964,9 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 	/*Length of actual data*/
 	tx_hdr.length = (skb->len & 0x1FFFFF);
 
+	/* TSO MSS */
+	tx_hdr.max_seg_size = skb_shinfo(skb)->gso_size;
+
 	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
 	if (headroom != 0)
 		padding_size = 8 - headroom;
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 0be2e4cbb00a..9cf357777df9 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -64,10 +64,12 @@
 
 /* Feature. ********************************************/
 #define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
-				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
+				 NETIF_F_TSO)
 
 #define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
-				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
+				 NETIF_F_TSO)
 
 /* SFR Reg. ********************************************/
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,13/19] net: usb: aqc111: Add support for TSO
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 3 +++
 drivers/net/usb/aqc111.h | 6 ++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 6efd9a9ad44e..f61fa7446b72 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -964,6 +964,9 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 	/*Length of actual data*/
 	tx_hdr.length = (skb->len & 0x1FFFFF);
 
+	/* TSO MSS */
+	tx_hdr.max_seg_size = skb_shinfo(skb)->gso_size;
+
 	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
 	if (headroom != 0)
 		padding_size = 8 - headroom;
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 0be2e4cbb00a..9cf357777df9 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -64,10 +64,12 @@
 
 /* Feature. ********************************************/
 #define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
-				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
+				 NETIF_F_TSO)
 
 #define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
-				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
+				 NETIF_F_TSO)
 
 /* SFR Reg. ********************************************/
 

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 14/19] net: usb: aqc111: Implement set_rx_mode callback
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 72 ++++++++++++++++++++++++++++++++++++++++++++----
 drivers/net/usb/aqc111.h |  4 +++
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index f61fa7446b72..cc23c39beab3 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -11,6 +11,7 @@
 #include <linux/netdevice.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/crc32.h>
 #include <linux/if_vlan.h>
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
@@ -139,6 +140,24 @@ static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
 	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
 }
 
+static void aqc111_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
+				   u16 index, u16 size, void *data)
+{
+	if (size == 2) {
+		u16 buf;
+
+		buf = *((u16 *)data);
+		cpu_to_le16s(&buf);
+		usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
+				       USB_RECIP_DEVICE, value, index, &buf,
+				       size);
+	} else {
+		usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
+				       USB_RECIP_DEVICE, value, index, data,
+				       size);
+	}
+}
+
 static int aq_mdio_read_cmd(struct usbnet *dev, u16 value, u16 index,
 			    u16 size, void *data)
 {
@@ -332,6 +351,44 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 				ETH_ALEN, net->dev_addr);
 }
 
+static void aqc111_set_rx_mode(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u8 *m_filter = ((u8 *)dev->data) + 12;
+	int mc_count = 0;
+
+	mc_count = netdev_mc_count(net);
+
+	aqc111_data->rxctl &= ~(SFR_RX_CTL_PRO | SFR_RX_CTL_AMALL |
+				SFR_RX_CTL_AM);
+
+	if (net->flags & IFF_PROMISC) {
+		aqc111_data->rxctl |= SFR_RX_CTL_PRO;
+	} else if ((net->flags & IFF_ALLMULTI) || mc_count > AQ_MAX_MCAST) {
+		aqc111_data->rxctl |= SFR_RX_CTL_AMALL;
+	} else if (!netdev_mc_empty(net)) {
+		u32 crc_bits = 0;
+		struct netdev_hw_addr *ha = NULL;
+
+		memset(m_filter, 0, AQ_MCAST_FILTER_SIZE);
+		netdev_for_each_mc_addr(ha, net) {
+			crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+			m_filter[crc_bits >> 3] |= BIT(crc_bits & 7);
+		}
+
+		aqc111_write_cmd_async(dev, AQ_ACCESS_MAC,
+				       SFR_MULTI_FILTER_ARRY,
+				       AQ_MCAST_FILTER_SIZE,
+				       AQ_MCAST_FILTER_SIZE, m_filter);
+
+		aqc111_data->rxctl |= SFR_RX_CTL_AM;
+	}
+
+	aqc111_write_cmd_async(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			       2, 2, &aqc111_data->rxctl);
+}
+
 static int aqc111_set_features(struct net_device *net,
 			       netdev_features_t features)
 {
@@ -381,6 +438,7 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_rx_mode	= aqc111_set_rx_mode,
 	.ndo_set_features	= aqc111_set_features,
 };
 
@@ -681,6 +739,7 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, &reg8);
 
 		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB;
+		aqc111_data->rxctl = reg16;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
 
 		reg8 = SFR_RX_PATH_READY;
@@ -701,6 +760,8 @@ static int aqc111_link_reset(struct usbnet *dev)
 
 		aqc111_configure_csum_offload(dev);
 
+		aqc111_set_rx_mode(dev->net);
+
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				2, 2, &reg16);
 
@@ -712,8 +773,9 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				 2, 2, &reg16);
 
-		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB | SFR_RX_CTL_START;
-		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+		aqc111_data->rxctl |= SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+				 2, 2, &aqc111_data->rxctl);
 
 		netif_carrier_on(dev->net);
 	} else {
@@ -723,9 +785,9 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				 2, 2, &reg16);
 
-		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
-		reg16 &= ~SFR_RX_CTL_START;
-		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+		aqc111_data->rxctl &= ~SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+				 2, 2, &aqc111_data->rxctl);
 
 		reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 9cf357777df9..2f324ec66a65 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -12,6 +12,9 @@
 
 #define URB_SIZE	(1024 * 62)
 
+#define AQ_MCAST_FILTER_SIZE		8
+#define AQ_MAX_MCAST			64
+
 #define AQ_ACCESS_MAC			0x01
 #define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
@@ -207,6 +210,7 @@ struct aqc111_phy_options {
 };
 
 struct aqc111_data {
+	u16 rxctl;
 	u8 rx_checksum;
 	u8 link_speed;
 	u8 link;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,14/19] net: usb: aqc111: Implement set_rx_mode callback
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 72 ++++++++++++++++++++++++++++++++++++++++++++----
 drivers/net/usb/aqc111.h |  4 +++
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index f61fa7446b72..cc23c39beab3 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -11,6 +11,7 @@
 #include <linux/netdevice.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/crc32.h>
 #include <linux/if_vlan.h>
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
@@ -139,6 +140,24 @@ static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
 	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
 }
 
+static void aqc111_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
+				   u16 index, u16 size, void *data)
+{
+	if (size == 2) {
+		u16 buf;
+
+		buf = *((u16 *)data);
+		cpu_to_le16s(&buf);
+		usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
+				       USB_RECIP_DEVICE, value, index, &buf,
+				       size);
+	} else {
+		usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
+				       USB_RECIP_DEVICE, value, index, data,
+				       size);
+	}
+}
+
 static int aq_mdio_read_cmd(struct usbnet *dev, u16 value, u16 index,
 			    u16 size, void *data)
 {
@@ -332,6 +351,44 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 				ETH_ALEN, net->dev_addr);
 }
 
+static void aqc111_set_rx_mode(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u8 *m_filter = ((u8 *)dev->data) + 12;
+	int mc_count = 0;
+
+	mc_count = netdev_mc_count(net);
+
+	aqc111_data->rxctl &= ~(SFR_RX_CTL_PRO | SFR_RX_CTL_AMALL |
+				SFR_RX_CTL_AM);
+
+	if (net->flags & IFF_PROMISC) {
+		aqc111_data->rxctl |= SFR_RX_CTL_PRO;
+	} else if ((net->flags & IFF_ALLMULTI) || mc_count > AQ_MAX_MCAST) {
+		aqc111_data->rxctl |= SFR_RX_CTL_AMALL;
+	} else if (!netdev_mc_empty(net)) {
+		u32 crc_bits = 0;
+		struct netdev_hw_addr *ha = NULL;
+
+		memset(m_filter, 0, AQ_MCAST_FILTER_SIZE);
+		netdev_for_each_mc_addr(ha, net) {
+			crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+			m_filter[crc_bits >> 3] |= BIT(crc_bits & 7);
+		}
+
+		aqc111_write_cmd_async(dev, AQ_ACCESS_MAC,
+				       SFR_MULTI_FILTER_ARRY,
+				       AQ_MCAST_FILTER_SIZE,
+				       AQ_MCAST_FILTER_SIZE, m_filter);
+
+		aqc111_data->rxctl |= SFR_RX_CTL_AM;
+	}
+
+	aqc111_write_cmd_async(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			       2, 2, &aqc111_data->rxctl);
+}
+
 static int aqc111_set_features(struct net_device *net,
 			       netdev_features_t features)
 {
@@ -381,6 +438,7 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_rx_mode	= aqc111_set_rx_mode,
 	.ndo_set_features	= aqc111_set_features,
 };
 
@@ -681,6 +739,7 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, &reg8);
 
 		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB;
+		aqc111_data->rxctl = reg16;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
 
 		reg8 = SFR_RX_PATH_READY;
@@ -701,6 +760,8 @@ static int aqc111_link_reset(struct usbnet *dev)
 
 		aqc111_configure_csum_offload(dev);
 
+		aqc111_set_rx_mode(dev->net);
+
 		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				2, 2, &reg16);
 
@@ -712,8 +773,9 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				 2, 2, &reg16);
 
-		reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB | SFR_RX_CTL_START;
-		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+		aqc111_data->rxctl |= SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+				 2, 2, &aqc111_data->rxctl);
 
 		netif_carrier_on(dev->net);
 	} else {
@@ -723,9 +785,9 @@ static int aqc111_link_reset(struct usbnet *dev)
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
 				 2, 2, &reg16);
 
-		aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
-		reg16 &= ~SFR_RX_CTL_START;
-		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+		aqc111_data->rxctl &= ~SFR_RX_CTL_START;
+		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+				 2, 2, &aqc111_data->rxctl);
 
 		reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN;
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 9cf357777df9..2f324ec66a65 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -12,6 +12,9 @@
 
 #define URB_SIZE	(1024 * 62)
 
+#define AQ_MCAST_FILTER_SIZE		8
+#define AQ_MAX_MCAST			64
+
 #define AQ_ACCESS_MAC			0x01
 #define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
@@ -207,6 +210,7 @@ struct aqc111_phy_options {
 };
 
 struct aqc111_data {
+	u16 rxctl;
 	u8 rx_checksum;
 	u8 link_speed;
 	u8 link;

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 15/19] net: usb: aqc111: Add support for VLAN_CTAG_TX/RX offload
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 14 ++++++++++++++
 drivers/net/usb/aqc111.h |  7 ++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index cc23c39beab3..a9051dd7c5bd 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -524,6 +524,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 
 	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
 	dev->net->features |= AQ_SUPPORT_FEATURE;
+	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
 
 	aqc111_read_fw_version(dev, aqc111_data);
 	aqc111_data->autoneg = AUTONEG_ENABLE;
@@ -817,6 +818,7 @@ static int aqc111_reset(struct usbnet *dev)
 
 	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
 	dev->net->features |= AQ_SUPPORT_FEATURE;
+	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
 
 	/* Power up ethernet PHY */
 	aqc111_data->phy_ops.advertising = 0;
@@ -992,6 +994,11 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
 		if (aqc111_data->rx_checksum)
 			aqc111_rx_checksum(new_skb, &pkt_desc);
+		if (pkt_desc->vlan_ind)
+			__vlan_hwaccel_put_tag(new_skb,
+					       htons(ETH_P_8021Q),
+					       pkt_desc->vlan_tag &
+					       VLAN_VID_MASK);
 
 		usbnet_skb_return(dev, new_skb);
 		if (pkt_count == 0)
@@ -1020,6 +1027,7 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 	int tailroom = 0;
 	int padding_size = 0;
 	struct sk_buff *new_skb = NULL;
+	u16 tci = 0;
 
 	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
 
@@ -1038,6 +1046,12 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 		tx_hdr.drop_padding = 1;
 	}
 
+	/* Vlan Tag */
+	if (vlan_get_tag(skb, &tci) >= 0) {
+		tx_hdr.vlan_tag = 1;
+		tx_hdr.vlan_info = tci;
+	}
+
 	if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
 	    skb_linearize(skb))
 		return NULL;
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 2f324ec66a65..e33459d90ddd 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -68,12 +68,17 @@
 /* Feature. ********************************************/
 #define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-				 NETIF_F_TSO)
+				 NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX |\
+				 NETIF_F_HW_VLAN_CTAG_RX)
 
 #define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
 				 NETIF_F_TSO)
 
+#define AQ_SUPPORT_VLAN_FEATURE (NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
+				 NETIF_F_TSO)
+
 /* SFR Reg. ********************************************/
 
 #define SFR_GENERAL_STATUS		0x03
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,15/19] net: usb: aqc111: Add support for VLAN_CTAG_TX/RX offload
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 14 ++++++++++++++
 drivers/net/usb/aqc111.h |  7 ++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index cc23c39beab3..a9051dd7c5bd 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -524,6 +524,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 
 	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
 	dev->net->features |= AQ_SUPPORT_FEATURE;
+	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
 
 	aqc111_read_fw_version(dev, aqc111_data);
 	aqc111_data->autoneg = AUTONEG_ENABLE;
@@ -817,6 +818,7 @@ static int aqc111_reset(struct usbnet *dev)
 
 	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
 	dev->net->features |= AQ_SUPPORT_FEATURE;
+	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
 
 	/* Power up ethernet PHY */
 	aqc111_data->phy_ops.advertising = 0;
@@ -992,6 +994,11 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
 		if (aqc111_data->rx_checksum)
 			aqc111_rx_checksum(new_skb, &pkt_desc);
+		if (pkt_desc->vlan_ind)
+			__vlan_hwaccel_put_tag(new_skb,
+					       htons(ETH_P_8021Q),
+					       pkt_desc->vlan_tag &
+					       VLAN_VID_MASK);
 
 		usbnet_skb_return(dev, new_skb);
 		if (pkt_count == 0)
@@ -1020,6 +1027,7 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 	int tailroom = 0;
 	int padding_size = 0;
 	struct sk_buff *new_skb = NULL;
+	u16 tci = 0;
 
 	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
 
@@ -1038,6 +1046,12 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 		tx_hdr.drop_padding = 1;
 	}
 
+	/* Vlan Tag */
+	if (vlan_get_tag(skb, &tci) >= 0) {
+		tx_hdr.vlan_tag = 1;
+		tx_hdr.vlan_info = tci;
+	}
+
 	if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
 	    skb_linearize(skb))
 		return NULL;
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 2f324ec66a65..e33459d90ddd 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -68,12 +68,17 @@
 /* Feature. ********************************************/
 #define AQ_SUPPORT_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-				 NETIF_F_TSO)
+				 NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX |\
+				 NETIF_F_HW_VLAN_CTAG_RX)
 
 #define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
 				 NETIF_F_TSO)
 
+#define AQ_SUPPORT_VLAN_FEATURE (NETIF_F_SG | NETIF_F_IP_CSUM |\
+				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
+				 NETIF_F_TSO)
+
 /* SFR Reg. ********************************************/
 
 #define SFR_GENERAL_STATUS		0x03

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 16/19] net: usb: aqc111: Add RX VLAN filtering support
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  2 +-
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index a9051dd7c5bd..9908b0a04da6 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -351,6 +351,57 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 				ETH_ALEN, net->dev_addr);
 }
 
+static int aqc111_vlan_rx_kill_vid(struct net_device *net,
+				   __be16 proto, u16 vid)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+	u8 vlan_ctrl = 0;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	vlan_ctrl = reg8;
+
+	/* Address */
+	reg8 = (vid / 16);
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, &reg8);
+	/* Data */
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg16 &= ~(1 << (vid % 16));
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+
+	return 0;
+}
+
+static int aqc111_vlan_rx_add_vid(struct net_device *net, __be16 proto, u16 vid)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+	u8 vlan_ctrl = 0;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	vlan_ctrl = reg8;
+
+	/* Address */
+	reg8 = (vid / 16);
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, &reg8);
+	/* Data */
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg16 |= (1 << (vid % 16));
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+
+	return 0;
+}
+
 static void aqc111_set_rx_mode(struct net_device *net)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -393,6 +444,7 @@ static int aqc111_set_features(struct net_device *net,
 			       netdev_features_t features)
 {
 	u8 reg8 = 0;
+	u16 reg16 = 0;
 	struct usbnet *dev = netdev_priv(net);
 	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 	netdev_features_t changed = net->features ^ features;
@@ -426,6 +478,39 @@ static int aqc111_set_features(struct net_device *net,
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL,
 				 1, 1, &reg8);
 	}
+	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+		if (features & NETIF_F_HW_VLAN_CTAG_FILTER) {
+			u16 i = 0;
+
+			for (i = 0; i < 256; i++) {
+				/* Address */
+				reg8 = i;
+				aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+						 SFR_VLAN_ID_ADDRESS,
+						 1, 1, &reg8);
+				/* Data */
+				aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+						 SFR_VLAN_ID_DATA0,
+						 2, 2, &reg16);
+				reg8 = SFR_VLAN_CONTROL_WE;
+				aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+						 SFR_VLAN_ID_CONTROL,
+						 1, 1, &reg8);
+			}
+			aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+					1, 1, &reg8);
+			reg8 |= SFR_VLAN_CONTROL_VFE;
+			aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+					 SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+		} else {
+			aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+					1, 1, &reg8);
+			reg8 &= ~SFR_VLAN_CONTROL_VFE;
+			aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+					 SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+		}
+	}
+
 	return 0;
 }
 
@@ -438,6 +523,8 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_vlan_rx_add_vid	= aqc111_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= aqc111_vlan_rx_kill_vid,
 	.ndo_set_rx_mode	= aqc111_set_rx_mode,
 	.ndo_set_features	= aqc111_set_features,
 };
@@ -726,6 +813,8 @@ static int aqc111_link_reset(struct usbnet *dev)
 
 		/* Vlan Tag Filter */
 		reg8 = SFR_VLAN_CONTROL_VSO;
+		if (dev->net->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+			reg8 |= SFR_VLAN_CONTROL_VFE;
 
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
 				 1, 1, &reg8);
@@ -994,6 +1083,7 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
 		if (aqc111_data->rx_checksum)
 			aqc111_rx_checksum(new_skb, &pkt_desc);
+
 		if (pkt_desc->vlan_ind)
 			__vlan_hwaccel_put_tag(new_skb,
 					       htons(ETH_P_8021Q),
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index e33459d90ddd..a7ccee225e93 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -73,7 +73,7 @@
 
 #define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-				 NETIF_F_TSO)
+				 NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_FILTER)
 
 #define AQ_SUPPORT_VLAN_FEATURE (NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,16/19] net: usb: aqc111: Add RX VLAN filtering support
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  2 +-
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index a9051dd7c5bd..9908b0a04da6 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -351,6 +351,57 @@ static int aqc111_set_mac_addr(struct net_device *net, void *p)
 				ETH_ALEN, net->dev_addr);
 }
 
+static int aqc111_vlan_rx_kill_vid(struct net_device *net,
+				   __be16 proto, u16 vid)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+	u8 vlan_ctrl = 0;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	vlan_ctrl = reg8;
+
+	/* Address */
+	reg8 = (vid / 16);
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, &reg8);
+	/* Data */
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg16 &= ~(1 << (vid % 16));
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+
+	return 0;
+}
+
+static int aqc111_vlan_rx_add_vid(struct net_device *net, __be16 proto, u16 vid)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u8 reg8 = 0;
+	u16 reg16 = 0;
+	u8 vlan_ctrl = 0;
+
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	vlan_ctrl = reg8;
+
+	/* Address */
+	reg8 = (vid / 16);
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, &reg8);
+	/* Data */
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+	aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg16 |= (1 << (vid % 16));
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, &reg16);
+	reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+
+	return 0;
+}
+
 static void aqc111_set_rx_mode(struct net_device *net)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -393,6 +444,7 @@ static int aqc111_set_features(struct net_device *net,
 			       netdev_features_t features)
 {
 	u8 reg8 = 0;
+	u16 reg16 = 0;
 	struct usbnet *dev = netdev_priv(net);
 	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
 	netdev_features_t changed = net->features ^ features;
@@ -426,6 +478,39 @@ static int aqc111_set_features(struct net_device *net,
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL,
 				 1, 1, &reg8);
 	}
+	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+		if (features & NETIF_F_HW_VLAN_CTAG_FILTER) {
+			u16 i = 0;
+
+			for (i = 0; i < 256; i++) {
+				/* Address */
+				reg8 = i;
+				aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+						 SFR_VLAN_ID_ADDRESS,
+						 1, 1, &reg8);
+				/* Data */
+				aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+						 SFR_VLAN_ID_DATA0,
+						 2, 2, &reg16);
+				reg8 = SFR_VLAN_CONTROL_WE;
+				aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+						 SFR_VLAN_ID_CONTROL,
+						 1, 1, &reg8);
+			}
+			aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+					1, 1, &reg8);
+			reg8 |= SFR_VLAN_CONTROL_VFE;
+			aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+					 SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+		} else {
+			aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+					1, 1, &reg8);
+			reg8 &= ~SFR_VLAN_CONTROL_VFE;
+			aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+					 SFR_VLAN_ID_CONTROL, 1, 1, &reg8);
+		}
+	}
+
 	return 0;
 }
 
@@ -438,6 +523,8 @@ static const struct net_device_ops aqc111_netdev_ops = {
 	.ndo_change_mtu		= aqc111_change_mtu,
 	.ndo_set_mac_address	= aqc111_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_vlan_rx_add_vid	= aqc111_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= aqc111_vlan_rx_kill_vid,
 	.ndo_set_rx_mode	= aqc111_set_rx_mode,
 	.ndo_set_features	= aqc111_set_features,
 };
@@ -726,6 +813,8 @@ static int aqc111_link_reset(struct usbnet *dev)
 
 		/* Vlan Tag Filter */
 		reg8 = SFR_VLAN_CONTROL_VSO;
+		if (dev->net->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+			reg8 |= SFR_VLAN_CONTROL_VFE;
 
 		aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
 				 1, 1, &reg8);
@@ -994,6 +1083,7 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
 		if (aqc111_data->rx_checksum)
 			aqc111_rx_checksum(new_skb, &pkt_desc);
+
 		if (pkt_desc->vlan_ind)
 			__vlan_hwaccel_put_tag(new_skb,
 					       htons(ETH_P_8021Q),
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index e33459d90ddd..a7ccee225e93 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -73,7 +73,7 @@
 
 #define AQ_SUPPORT_HW_FEATURE	(NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\
-				 NETIF_F_TSO)
+				 NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_FILTER)
 
 #define AQ_SUPPORT_VLAN_FEATURE (NETIF_F_SG | NETIF_F_IP_CSUM |\
 				 NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |\

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 17/19] net: usb: aqc111: Initialize ethtool_ops structure
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Implement get_drvinfo, set/get_msglevel, get_link callbacks

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 9908b0a04da6..ade2b60b4811 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -9,6 +9,7 @@
 
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/crc32.h>
@@ -18,6 +19,9 @@
 
 #include "aqc111.h"
 
+#define DRIVER_VERSION "1.0.0.0"
+#define DRIVER_NAME "Aquantia AQtion USB to 5GbE"
+
 static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
 			     u16 index, u16 size, void *data, int nopm)
 {
@@ -170,6 +174,24 @@ static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
 	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
 }
 
+static void aqc111_get_drvinfo(struct net_device *net,
+			       struct ethtool_drvinfo *info)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	/* Inherit standard device info */
+	usbnet_get_drvinfo(net, info);
+	strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+	strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
+	snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u",
+		 aqc111_data->fw_ver.major,
+		 aqc111_data->fw_ver.minor,
+		 aqc111_data->fw_ver.rev);
+	info->eedump_len = 0x00;
+	info->regdump_len = 0x00;
+}
+
 static void aqc111_set_phy_speed_fw_iface(struct usbnet *dev,
 					  struct aqc111_data *aqc111_data)
 {
@@ -286,6 +308,13 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static const struct ethtool_ops aqc111_ethtool_ops = {
+	.get_drvinfo = aqc111_get_drvinfo,
+	.get_msglevel = usbnet_get_msglevel,
+	.set_msglevel = usbnet_set_msglevel,
+	.get_link = ethtool_op_get_link,
+};
+
 static int aqc111_change_mtu(struct net_device *net, int new_mtu)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -605,6 +634,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->net->needed_tailroom += AQ_TX_HEADER_SIZE;
 
 	dev->net->netdev_ops = &aqc111_netdev_ops;
+	dev->net->ethtool_ops = &aqc111_ethtool_ops;
 
 	if (usb_device_no_sg_constraint(dev->udev))
 		dev->can_dma_sg = 1;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,17/19] net: usb: aqc111: Initialize ethtool_ops structure
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Implement get_drvinfo, set/get_msglevel, get_link callbacks

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 9908b0a04da6..ade2b60b4811 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -9,6 +9,7 @@
 
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
 #include <linux/crc32.h>
@@ -18,6 +19,9 @@
 
 #include "aqc111.h"
 
+#define DRIVER_VERSION "1.0.0.0"
+#define DRIVER_NAME "Aquantia AQtion USB to 5GbE"
+
 static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
 			     u16 index, u16 size, void *data, int nopm)
 {
@@ -170,6 +174,24 @@ static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
 	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
 }
 
+static void aqc111_get_drvinfo(struct net_device *net,
+			       struct ethtool_drvinfo *info)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	/* Inherit standard device info */
+	usbnet_get_drvinfo(net, info);
+	strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+	strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
+	snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u",
+		 aqc111_data->fw_ver.major,
+		 aqc111_data->fw_ver.minor,
+		 aqc111_data->fw_ver.rev);
+	info->eedump_len = 0x00;
+	info->regdump_len = 0x00;
+}
+
 static void aqc111_set_phy_speed_fw_iface(struct usbnet *dev,
 					  struct aqc111_data *aqc111_data)
 {
@@ -286,6 +308,13 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static const struct ethtool_ops aqc111_ethtool_ops = {
+	.get_drvinfo = aqc111_get_drvinfo,
+	.get_msglevel = usbnet_get_msglevel,
+	.set_msglevel = usbnet_set_msglevel,
+	.get_link = ethtool_op_get_link,
+};
+
 static int aqc111_change_mtu(struct net_device *net, int new_mtu)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -605,6 +634,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
 	dev->net->needed_tailroom += AQ_TX_HEADER_SIZE;
 
 	dev->net->netdev_ops = &aqc111_netdev_ops;
+	dev->net->ethtool_ops = &aqc111_ethtool_ops;
 
 	if (usb_device_no_sg_constraint(dev->udev))
 		dev->can_dma_sg = 1;

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index ade2b60b4811..20d4347ea3ad 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -192,6 +192,97 @@ static void aqc111_get_drvinfo(struct net_device *net,
 	info->regdump_len = 0x00;
 }
 
+static void aqc111_speed_to_link_mode(u32 speed,
+				      struct ethtool_link_ksettings *elk)
+{
+	switch (speed) {
+	case SPEED_5000: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     5000baseT_Full);
+		break;
+	}
+	case SPEED_2500: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     2500baseT_Full);
+		break;
+	}
+	case SPEED_1000: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     1000baseT_Full);
+		break;
+	}
+	case SPEED_100: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     100baseT_Full);
+		break;
+	}
+	}
+}
+
+static int aqc111_get_link_ksettings(struct net_device *net,
+				     struct ethtool_link_ksettings *elk)
+{
+	struct usbnet *dev = netdev_priv(net);
+	enum usb_device_speed usb_speed = dev->udev->speed;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u32 speed = SPEED_UNKNOWN;
+
+	ethtool_link_ksettings_zero_link_mode(elk, supported);
+	ethtool_link_ksettings_add_link_mode(elk, supported,
+					     100baseT_Full);
+	ethtool_link_ksettings_add_link_mode(elk, supported,
+					     1000baseT_Full);
+	if (usb_speed == USB_SPEED_SUPER) {
+		ethtool_link_ksettings_add_link_mode(elk, supported,
+						     2500baseT_Full);
+		ethtool_link_ksettings_add_link_mode(elk, supported,
+						     5000baseT_Full);
+	}
+	ethtool_link_ksettings_add_link_mode(elk, supported, TP);
+	ethtool_link_ksettings_add_link_mode(elk, supported, Autoneg);
+
+	elk->base.port = PORT_TP;
+	elk->base.transceiver = XCVR_INTERNAL;
+
+	elk->base.mdio_support = 0x00; /*Not supported*/
+
+	if (aqc111_data->autoneg)
+		bitmap_copy(elk->link_modes.advertising,
+			    elk->link_modes.supported,
+			    __ETHTOOL_LINK_MODE_MASK_NBITS);
+	else
+		aqc111_speed_to_link_mode(aqc111_data->advertised_speed, elk);
+
+	elk->base.autoneg = aqc111_data->autoneg;
+
+	switch (aqc111_data->link_speed) {
+	case AQ_INT_SPEED_5G:
+	{
+		speed = SPEED_5000;
+		break;
+	}
+	case AQ_INT_SPEED_2_5G:
+	{
+		speed = SPEED_2500;
+		break;
+	}
+	case AQ_INT_SPEED_1G:
+	{
+		speed = SPEED_1000;
+		break;
+	}
+	case AQ_INT_SPEED_100M:
+	{
+		speed = SPEED_100;
+		break;
+	}
+	}
+	elk->base.duplex = DUPLEX_FULL;
+	elk->base.speed = speed;
+
+	return 0;
+}
+
 static void aqc111_set_phy_speed_fw_iface(struct usbnet *dev,
 					  struct aqc111_data *aqc111_data)
 {
@@ -308,11 +399,53 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static int aqc111_set_link_ksettings(struct net_device *net,
+				     const struct ethtool_link_ksettings *elk)
+{
+	struct usbnet *dev = netdev_priv(net);
+	enum usb_device_speed usb_speed = dev->udev->speed;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u32 speed = elk->base.speed;
+	u8 autoneg = elk->base.autoneg;
+
+	if (autoneg == AUTONEG_ENABLE) {
+		if (aqc111_data->autoneg != AUTONEG_ENABLE) {
+			aqc111_data->autoneg = AUTONEG_ENABLE;
+			aqc111_data->advertised_speed =
+					(usb_speed == USB_SPEED_SUPER) ?
+					 SPEED_5000 : SPEED_1000;
+			aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+					     aqc111_data->advertised_speed);
+		}
+	} else {
+		if (speed != SPEED_100 &&
+		    speed != SPEED_1000 &&
+		    speed != SPEED_2500 &&
+		    speed != SPEED_5000 &&
+		    speed != SPEED_UNKNOWN)
+			return -EINVAL;
+
+		if (usb_speed != USB_SPEED_SUPER && speed > SPEED_1000)
+			return -EINVAL;
+
+		aqc111_data->autoneg = AUTONEG_DISABLE;
+		if (speed != SPEED_UNKNOWN)
+			aqc111_data->advertised_speed = speed;
+
+		aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+				     aqc111_data->advertised_speed);
+	}
+
+	return 0;
+}
+
 static const struct ethtool_ops aqc111_ethtool_ops = {
 	.get_drvinfo = aqc111_get_drvinfo,
 	.get_msglevel = usbnet_get_msglevel,
 	.set_msglevel = usbnet_set_msglevel,
 	.get_link = ethtool_op_get_link,
+	.get_link_ksettings = aqc111_get_link_ksettings,
+	.set_link_ksettings = aqc111_set_link_ksettings
 };
 
 static int aqc111_change_mtu(struct net_device *net, int new_mtu)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index ade2b60b4811..20d4347ea3ad 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -192,6 +192,97 @@ static void aqc111_get_drvinfo(struct net_device *net,
 	info->regdump_len = 0x00;
 }
 
+static void aqc111_speed_to_link_mode(u32 speed,
+				      struct ethtool_link_ksettings *elk)
+{
+	switch (speed) {
+	case SPEED_5000: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     5000baseT_Full);
+		break;
+	}
+	case SPEED_2500: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     2500baseT_Full);
+		break;
+	}
+	case SPEED_1000: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     1000baseT_Full);
+		break;
+	}
+	case SPEED_100: {
+		ethtool_link_ksettings_add_link_mode(elk, advertising,
+						     100baseT_Full);
+		break;
+	}
+	}
+}
+
+static int aqc111_get_link_ksettings(struct net_device *net,
+				     struct ethtool_link_ksettings *elk)
+{
+	struct usbnet *dev = netdev_priv(net);
+	enum usb_device_speed usb_speed = dev->udev->speed;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u32 speed = SPEED_UNKNOWN;
+
+	ethtool_link_ksettings_zero_link_mode(elk, supported);
+	ethtool_link_ksettings_add_link_mode(elk, supported,
+					     100baseT_Full);
+	ethtool_link_ksettings_add_link_mode(elk, supported,
+					     1000baseT_Full);
+	if (usb_speed == USB_SPEED_SUPER) {
+		ethtool_link_ksettings_add_link_mode(elk, supported,
+						     2500baseT_Full);
+		ethtool_link_ksettings_add_link_mode(elk, supported,
+						     5000baseT_Full);
+	}
+	ethtool_link_ksettings_add_link_mode(elk, supported, TP);
+	ethtool_link_ksettings_add_link_mode(elk, supported, Autoneg);
+
+	elk->base.port = PORT_TP;
+	elk->base.transceiver = XCVR_INTERNAL;
+
+	elk->base.mdio_support = 0x00; /*Not supported*/
+
+	if (aqc111_data->autoneg)
+		bitmap_copy(elk->link_modes.advertising,
+			    elk->link_modes.supported,
+			    __ETHTOOL_LINK_MODE_MASK_NBITS);
+	else
+		aqc111_speed_to_link_mode(aqc111_data->advertised_speed, elk);
+
+	elk->base.autoneg = aqc111_data->autoneg;
+
+	switch (aqc111_data->link_speed) {
+	case AQ_INT_SPEED_5G:
+	{
+		speed = SPEED_5000;
+		break;
+	}
+	case AQ_INT_SPEED_2_5G:
+	{
+		speed = SPEED_2500;
+		break;
+	}
+	case AQ_INT_SPEED_1G:
+	{
+		speed = SPEED_1000;
+		break;
+	}
+	case AQ_INT_SPEED_100M:
+	{
+		speed = SPEED_100;
+		break;
+	}
+	}
+	elk->base.duplex = DUPLEX_FULL;
+	elk->base.speed = speed;
+
+	return 0;
+}
+
 static void aqc111_set_phy_speed_fw_iface(struct usbnet *dev,
 					  struct aqc111_data *aqc111_data)
 {
@@ -308,11 +399,53 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
 		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
 }
 
+static int aqc111_set_link_ksettings(struct net_device *net,
+				     const struct ethtool_link_ksettings *elk)
+{
+	struct usbnet *dev = netdev_priv(net);
+	enum usb_device_speed usb_speed = dev->udev->speed;
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u32 speed = elk->base.speed;
+	u8 autoneg = elk->base.autoneg;
+
+	if (autoneg == AUTONEG_ENABLE) {
+		if (aqc111_data->autoneg != AUTONEG_ENABLE) {
+			aqc111_data->autoneg = AUTONEG_ENABLE;
+			aqc111_data->advertised_speed =
+					(usb_speed == USB_SPEED_SUPER) ?
+					 SPEED_5000 : SPEED_1000;
+			aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+					     aqc111_data->advertised_speed);
+		}
+	} else {
+		if (speed != SPEED_100 &&
+		    speed != SPEED_1000 &&
+		    speed != SPEED_2500 &&
+		    speed != SPEED_5000 &&
+		    speed != SPEED_UNKNOWN)
+			return -EINVAL;
+
+		if (usb_speed != USB_SPEED_SUPER && speed > SPEED_1000)
+			return -EINVAL;
+
+		aqc111_data->autoneg = AUTONEG_DISABLE;
+		if (speed != SPEED_UNKNOWN)
+			aqc111_data->advertised_speed = speed;
+
+		aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+				     aqc111_data->advertised_speed);
+	}
+
+	return 0;
+}
+
 static const struct ethtool_ops aqc111_ethtool_ops = {
 	.get_drvinfo = aqc111_get_drvinfo,
 	.get_msglevel = usbnet_get_msglevel,
 	.set_msglevel = usbnet_set_msglevel,
 	.get_link = ethtool_op_get_link,
+	.get_link_ksettings = aqc111_get_link_ksettings,
+	.set_link_ksettings = aqc111_set_link_ksettings
 };
 
 static int aqc111_change_mtu(struct net_device *net, int new_mtu)

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH net-next 19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  11 +++
 2 files changed, 214 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 20d4347ea3ad..e2ea8dc54d3a 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -192,6 +192,35 @@ static void aqc111_get_drvinfo(struct net_device *net,
 	info->regdump_len = 0x00;
 }
 
+static void aqc111_get_wol(struct net_device *net,
+			   struct ethtool_wolinfo *wolinfo)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	wolinfo->supported = WAKE_MAGIC;
+	wolinfo->wolopts = 0;
+
+	if (aqc111_data->wol_cfg.flags & AQ_WOL_FLAG_MP)
+		wolinfo->wolopts |= WAKE_MAGIC;
+}
+
+static int aqc111_set_wol(struct net_device *net,
+			  struct ethtool_wolinfo *wolinfo)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	if (wolinfo->wolopts & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	aqc111_data->wol_cfg.flags = 0;
+	if (wolinfo->wolopts & WAKE_MAGIC)
+		aqc111_data->wol_cfg.flags |= AQ_WOL_FLAG_MP;
+
+	return 0;
+}
+
 static void aqc111_speed_to_link_mode(u32 speed,
 				      struct ethtool_link_ksettings *elk)
 {
@@ -441,6 +470,8 @@ static int aqc111_set_link_ksettings(struct net_device *net,
 
 static const struct ethtool_ops aqc111_ethtool_ops = {
 	.get_drvinfo = aqc111_get_drvinfo,
+	.get_wol = aqc111_get_wol,
+	.set_wol = aqc111_set_wol,
 	.get_msglevel = usbnet_get_msglevel,
 	.set_msglevel = usbnet_set_msglevel,
 	.get_link = ethtool_op_get_link,
@@ -1346,6 +1377,176 @@ static const struct driver_info aqc111_info = {
 	.tx_fixup	= aqc111_tx_fixup,
 };
 
+static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u8 reg8;
+	u16 reg16;
+	u16 temp_rx_ctrl = 0x00;
+
+	usbnet_suspend(intf, message);
+
+	aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+	temp_rx_ctrl = reg16;
+	/* Stop RX operations*/
+	reg16 &= ~SFR_RX_CTL_START;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			      2, 2, &reg16);
+	/* Force bz */
+	aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			     2, 2, &reg16);
+	reg16 |= SFR_PHYPWR_RSTCTL_BZ;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			      2, 2, &reg16);
+
+	reg8 = SFR_BULK_OUT_EFF_EN;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+			      1, 1, &reg8);
+
+	temp_rx_ctrl &= ~(SFR_RX_CTL_START | SFR_RX_CTL_RF_WAK |
+			  SFR_RX_CTL_AP | SFR_RX_CTL_AM);
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			      2, 2, &temp_rx_ctrl);
+
+	reg8 = 0x00;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+			      1, 1, &reg8);
+
+	if (aqc111_data->wol_cfg.flags) {
+		aqc111_data->phy_ops.wol = 1;
+		if (aqc111_data->dpa) {
+			reg8 = 0;
+			if (aqc111_data->wol_cfg.flags & AQ_WOL_FLAG_MP)
+				reg8 |= SFR_MONITOR_MODE_RWMP;
+			aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+					      SFR_MONITOR_MODE, 1, 1, &reg8);
+		} else {
+			memcpy(aqc111_data->wol_cfg.hw_addr,
+			       dev->net->dev_addr, ETH_ALEN);
+		}
+
+		temp_rx_ctrl |= (SFR_RX_CTL_AB | SFR_RX_CTL_START);
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+				      2, 2, &temp_rx_ctrl);
+		reg8 = 0x00;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+				      1, 1, &reg8);
+		reg8 = SFR_BMRX_DMA_EN;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+				      1, 1, &reg8);
+		reg8 = SFR_RX_PATH_READY;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+				      1, 1, &reg8);
+		reg8 = 0x07;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL,
+				      1, 1, &reg8);
+		reg8 = 0x00;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_RX_BULKIN_QTIMR_LOW, 1, 1, &reg8);
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_RX_BULKIN_QTIMR_HIGH, 1, 1, &reg8);
+		reg8 = 0xFF;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QSIZE,
+				      1, 1, &reg8);
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QIFG,
+				      1, 1, &reg8);
+
+		aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				     2, 2, &reg16);
+		reg16 |= SFR_MEDIUM_RECEIVE_EN;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+
+		if (aqc111_data->dpa) {
+			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);
+		} else {
+			aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0,
+					 WOL_CFG_SIZE, &aqc111_data->wol_cfg);
+			aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+					 4, &aqc111_data->phy_ops);
+		}
+	} else {
+		aqc111_data->phy_ops.low_power = 1;
+		if (!aqc111_data->dpa) {
+			aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+					 4, &aqc111_data->phy_ops);
+		} else {
+			reg16 = AQ_PHY_LOW_POWER_MODE;
+			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
+					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
+		}
+
+		/* Disable RX path */
+		aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC,
+				     SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+		reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+	}
+
+	return 0;
+}
+
+static int aqc111_resume(struct usb_interface *intf)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u8 reg8;
+	u16 reg16;
+
+	netif_carrier_off(dev->net);
+
+	/* Power up ethernet PHY */
+	aqc111_data->phy_ops.phy_power = 1;
+	aqc111_data->phy_ops.low_power = 0;
+	aqc111_data->phy_ops.wol = 0;
+	if (aqc111_data->dpa) {
+		aqc111_read_cmd_nopm(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
+		if (reg8 == 0x00) {
+			reg8 = 0x02;
+			aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
+					      1, &reg8);
+			msleep(200);
+		}
+
+		aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+				 2, &reg16);
+		if (reg16 & AQ_PHY_LOW_POWER_MODE) {
+			reg16 &= ~AQ_PHY_LOW_POWER_MODE;
+			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
+					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
+		}
+	}
+
+	reg8 = 0xFF;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+			      1, 1, &reg8);
+	/* Configure RX control register => start operation */
+	reg16 = aqc111_data->rxctl;
+	reg16 &= ~SFR_RX_CTL_START;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+	reg16 |= SFR_RX_CTL_START;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+			     aqc111_data->advertised_speed);
+
+	aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC,
+			     SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+	reg16 |= SFR_MEDIUM_RECEIVE_EN;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+			      SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+	reg8 = SFR_RX_PATH_READY;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+			      1, 1, &reg8);
+	reg8 = 0x0;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 1, 1, &reg8);
+
+	return usbnet_resume(intf);
+}
+
 #define AQC111_USB_ETH_DEV(vid, pid, table) \
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
 			USB_DEVICE_ID_MATCH_INT_CLASS, \
@@ -1371,6 +1572,8 @@ static struct usb_driver aq_driver = {
 	.name		= "aqc111",
 	.id_table	= products,
 	.probe		= usbnet_probe,
+	.suspend	= aqc111_suspend,
+	.resume		= aqc111_resume,
 	.disconnect	= usbnet_disconnect,
 };
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index a7ccee225e93..9a900c325273 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -19,6 +19,7 @@
 #define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
 #define AQ_PHY_CMD			0x32
+#define AQ_WOL_CFG			0x60
 #define AQ_PHY_OPS			0x61
 
 #define AQC111_PHY_ID			0x00
@@ -169,6 +170,7 @@
 #define AQ_FW_VER_MINOR			0xDB
 #define AQ_FW_VER_REV			0xDC
 
+#define AQ_WOL_FLAG_MP			0x2
 /******************************************************************************/
 
 struct aqc111_phy_options {
@@ -214,6 +216,14 @@ struct aqc111_phy_options {
 	};
 };
 
+struct aqc111_wol_cfg {
+	u8 hw_addr[6];
+	u8 flags;
+	u8 rsvd[283];
+};
+
+#define WOL_CFG_SIZE sizeof(struct aqc111_wol_cfg)
+
 struct aqc111_data {
 	u16 rxctl;
 	u8 rx_checksum;
@@ -228,6 +238,7 @@ struct aqc111_data {
 	} fw_ver;
 	u8 dpa; /*direct PHY access*/
 	struct aqc111_phy_options phy_ops;
+	struct aqc111_wol_cfg wol_cfg;
 } __packed;
 
 struct aqc111_int_data {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [net-next,19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-05 10:25   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-05 10:25 UTC (permalink / raw)
  To: David S . Miller; +Cc: linux-usb, netdev, Igor Russkikh, Dmitry Bezrukov

From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>

Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 drivers/net/usb/aqc111.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/aqc111.h |  11 +++
 2 files changed, 214 insertions(+)

diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 20d4347ea3ad..e2ea8dc54d3a 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -192,6 +192,35 @@ static void aqc111_get_drvinfo(struct net_device *net,
 	info->regdump_len = 0x00;
 }
 
+static void aqc111_get_wol(struct net_device *net,
+			   struct ethtool_wolinfo *wolinfo)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	wolinfo->supported = WAKE_MAGIC;
+	wolinfo->wolopts = 0;
+
+	if (aqc111_data->wol_cfg.flags & AQ_WOL_FLAG_MP)
+		wolinfo->wolopts |= WAKE_MAGIC;
+}
+
+static int aqc111_set_wol(struct net_device *net,
+			  struct ethtool_wolinfo *wolinfo)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+
+	if (wolinfo->wolopts & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	aqc111_data->wol_cfg.flags = 0;
+	if (wolinfo->wolopts & WAKE_MAGIC)
+		aqc111_data->wol_cfg.flags |= AQ_WOL_FLAG_MP;
+
+	return 0;
+}
+
 static void aqc111_speed_to_link_mode(u32 speed,
 				      struct ethtool_link_ksettings *elk)
 {
@@ -441,6 +470,8 @@ static int aqc111_set_link_ksettings(struct net_device *net,
 
 static const struct ethtool_ops aqc111_ethtool_ops = {
 	.get_drvinfo = aqc111_get_drvinfo,
+	.get_wol = aqc111_get_wol,
+	.set_wol = aqc111_set_wol,
 	.get_msglevel = usbnet_get_msglevel,
 	.set_msglevel = usbnet_set_msglevel,
 	.get_link = ethtool_op_get_link,
@@ -1346,6 +1377,176 @@ static const struct driver_info aqc111_info = {
 	.tx_fixup	= aqc111_tx_fixup,
 };
 
+static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u8 reg8;
+	u16 reg16;
+	u16 temp_rx_ctrl = 0x00;
+
+	usbnet_suspend(intf, message);
+
+	aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+	temp_rx_ctrl = reg16;
+	/* Stop RX operations*/
+	reg16 &= ~SFR_RX_CTL_START;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			      2, 2, &reg16);
+	/* Force bz */
+	aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			     2, 2, &reg16);
+	reg16 |= SFR_PHYPWR_RSTCTL_BZ;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+			      2, 2, &reg16);
+
+	reg8 = SFR_BULK_OUT_EFF_EN;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+			      1, 1, &reg8);
+
+	temp_rx_ctrl &= ~(SFR_RX_CTL_START | SFR_RX_CTL_RF_WAK |
+			  SFR_RX_CTL_AP | SFR_RX_CTL_AM);
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+			      2, 2, &temp_rx_ctrl);
+
+	reg8 = 0x00;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+			      1, 1, &reg8);
+
+	if (aqc111_data->wol_cfg.flags) {
+		aqc111_data->phy_ops.wol = 1;
+		if (aqc111_data->dpa) {
+			reg8 = 0;
+			if (aqc111_data->wol_cfg.flags & AQ_WOL_FLAG_MP)
+				reg8 |= SFR_MONITOR_MODE_RWMP;
+			aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+					      SFR_MONITOR_MODE, 1, 1, &reg8);
+		} else {
+			memcpy(aqc111_data->wol_cfg.hw_addr,
+			       dev->net->dev_addr, ETH_ALEN);
+		}
+
+		temp_rx_ctrl |= (SFR_RX_CTL_AB | SFR_RX_CTL_START);
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+				      2, 2, &temp_rx_ctrl);
+		reg8 = 0x00;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+				      1, 1, &reg8);
+		reg8 = SFR_BMRX_DMA_EN;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+				      1, 1, &reg8);
+		reg8 = SFR_RX_PATH_READY;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+				      1, 1, &reg8);
+		reg8 = 0x07;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL,
+				      1, 1, &reg8);
+		reg8 = 0x00;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_RX_BULKIN_QTIMR_LOW, 1, 1, &reg8);
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_RX_BULKIN_QTIMR_HIGH, 1, 1, &reg8);
+		reg8 = 0xFF;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QSIZE,
+				      1, 1, &reg8);
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QIFG,
+				      1, 1, &reg8);
+
+		aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+				     2, 2, &reg16);
+		reg16 |= SFR_MEDIUM_RECEIVE_EN;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+
+		if (aqc111_data->dpa) {
+			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);
+		} else {
+			aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0,
+					 WOL_CFG_SIZE, &aqc111_data->wol_cfg);
+			aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+					 4, &aqc111_data->phy_ops);
+		}
+	} else {
+		aqc111_data->phy_ops.low_power = 1;
+		if (!aqc111_data->dpa) {
+			aqc111_write_cmd(dev, AQ_PHY_OPS, 0, 0,
+					 4, &aqc111_data->phy_ops);
+		} else {
+			reg16 = AQ_PHY_LOW_POWER_MODE;
+			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
+					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
+		}
+
+		/* Disable RX path */
+		aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC,
+				     SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+		reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+		aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+				      SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+	}
+
+	return 0;
+}
+
+static int aqc111_resume(struct usb_interface *intf)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
+	u8 reg8;
+	u16 reg16;
+
+	netif_carrier_off(dev->net);
+
+	/* Power up ethernet PHY */
+	aqc111_data->phy_ops.phy_power = 1;
+	aqc111_data->phy_ops.low_power = 0;
+	aqc111_data->phy_ops.wol = 0;
+	if (aqc111_data->dpa) {
+		aqc111_read_cmd_nopm(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
+		if (reg8 == 0x00) {
+			reg8 = 0x02;
+			aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
+					      1, &reg8);
+			msleep(200);
+		}
+
+		aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+				 2, &reg16);
+		if (reg16 & AQ_PHY_LOW_POWER_MODE) {
+			reg16 &= ~AQ_PHY_LOW_POWER_MODE;
+			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
+					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
+		}
+	}
+
+	reg8 = 0xFF;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+			      1, 1, &reg8);
+	/* Configure RX control register => start operation */
+	reg16 = aqc111_data->rxctl;
+	reg16 &= ~SFR_RX_CTL_START;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+	reg16 |= SFR_RX_CTL_START;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
+
+	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+			     aqc111_data->advertised_speed);
+
+	aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC,
+			     SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+	reg16 |= SFR_MEDIUM_RECEIVE_EN;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+			      SFR_MEDIUM_STATUS_MODE, 2, 2, &reg16);
+	reg8 = SFR_RX_PATH_READY;
+	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+			      1, 1, &reg8);
+	reg8 = 0x0;
+	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 1, 1, &reg8);
+
+	return usbnet_resume(intf);
+}
+
 #define AQC111_USB_ETH_DEV(vid, pid, table) \
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
 			USB_DEVICE_ID_MATCH_INT_CLASS, \
@@ -1371,6 +1572,8 @@ static struct usb_driver aq_driver = {
 	.name		= "aqc111",
 	.id_table	= products,
 	.probe		= usbnet_probe,
+	.suspend	= aqc111_suspend,
+	.resume		= aqc111_resume,
 	.disconnect	= usbnet_disconnect,
 };
 
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index a7ccee225e93..9a900c325273 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -19,6 +19,7 @@
 #define AQ_FLASH_PARAMETERS		0x20
 #define AQ_PHY_POWER			0x31
 #define AQ_PHY_CMD			0x32
+#define AQ_WOL_CFG			0x60
 #define AQ_PHY_OPS			0x61
 
 #define AQC111_PHY_ID			0x00
@@ -169,6 +170,7 @@
 #define AQ_FW_VER_MINOR			0xDB
 #define AQ_FW_VER_REV			0xDC
 
+#define AQ_WOL_FLAG_MP			0x2
 /******************************************************************************/
 
 struct aqc111_phy_options {
@@ -214,6 +216,14 @@ struct aqc111_phy_options {
 	};
 };
 
+struct aqc111_wol_cfg {
+	u8 hw_addr[6];
+	u8 flags;
+	u8 rsvd[283];
+};
+
+#define WOL_CFG_SIZE sizeof(struct aqc111_wol_cfg)
+
 struct aqc111_data {
 	u16 rxctl;
 	u8 rx_checksum;
@@ -228,6 +238,7 @@ struct aqc111_data {
 	} fw_ver;
 	u8 dpa; /*direct PHY access*/
 	struct aqc111_phy_options phy_ops;
+	struct aqc111_wol_cfg wol_cfg;
 } __packed;
 
 struct aqc111_int_data {

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-05 17:11     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-05 17:11 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:24:55AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Add full hardware initialization sequence and link configuration logic

Hi Igor, Dmitry

Please could you explain why you decided to not use drivers/net/phy?
The previous patch introduced basically what you need to export a
standard Linux MDIO bus. From that you can use a standard Linux PHY
driver.

	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-05 17:11     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-05 17:11 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:24:55AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Add full hardware initialization sequence and link configuration logic

Hi Igor, Dmitry

Please could you explain why you decided to not use drivers/net/phy?
The previous patch introduced basically what you need to export a
standard Linux MDIO bus. From that you can use a standard Linux PHY
driver.

	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 02/19] net: usb: aqc111: Add bind and empty unbind callbacks
@ 2018-10-05 17:39     ` David Miller
  0 siblings, 0 replies; 133+ messages in thread
From: David Miller @ 2018-10-05 17:39 UTC (permalink / raw)
  To: Igor.Russkikh; +Cc: linux-usb, netdev, Dmitry.Bezrukov

From: Igor Russkikh <Igor.Russkikh@aquantia.com>
Date: Fri, 5 Oct 2018 10:24:42 +0000

> +static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
> +{
> +	int ret;
> +	struct usb_device *udev = interface_to_usbdev(intf);

Please always order local variable declarations from longest to shortest
line (reverse christmas tree).

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,02/19] net: usb: aqc111: Add bind and empty unbind callbacks
@ 2018-10-05 17:39     ` David Miller
  0 siblings, 0 replies; 133+ messages in thread
From: David Miller @ 2018-10-05 17:39 UTC (permalink / raw)
  To: Igor.Russkikh; +Cc: linux-usb, netdev, Dmitry.Bezrukov

From: Igor Russkikh <Igor.Russkikh@aquantia.com>
Date: Fri, 5 Oct 2018 10:24:42 +0000

> +static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
> +{
> +	int ret;
> +	struct usb_device *udev = interface_to_usbdev(intf);

Please always order local variable declarations from longest to shortest
line (reverse christmas tree).

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-05 17:40     ` David Miller
  0 siblings, 0 replies; 133+ messages in thread
From: David Miller @ 2018-10-05 17:40 UTC (permalink / raw)
  To: Igor.Russkikh; +Cc: linux-usb, netdev, Dmitry.Bezrukov

From: Igor Russkikh <Igor.Russkikh@aquantia.com>
Date: Fri, 5 Oct 2018 10:24:44 +0000

> +static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			     u16 index, u16 size, void *data, int nopm)
> +{
> +	int ret;
> +	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
> +		  u16 index, void *data, u16 size);

Again, please order local variables from longest to shortest line.

I won't explicitly point out the others, you need to audit your entire
submission for this problem and fix it up.

Thank you.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-05 17:40     ` David Miller
  0 siblings, 0 replies; 133+ messages in thread
From: David Miller @ 2018-10-05 17:40 UTC (permalink / raw)
  To: Igor.Russkikh; +Cc: linux-usb, netdev, Dmitry.Bezrukov

From: Igor Russkikh <Igor.Russkikh@aquantia.com>
Date: Fri, 5 Oct 2018 10:24:44 +0000

> +static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			     u16 index, u16 size, void *data, int nopm)
> +{
> +	int ret;
> +	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
> +		  u16 index, void *data, u16 size);

Again, please order local variables from longest to shortest line.

I won't explicitly point out the others, you need to audit your entire
submission for this problem and fix it up.

Thank you.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-05 17:46     ` David Miller
  0 siblings, 0 replies; 133+ messages in thread
From: David Miller @ 2018-10-05 17:46 UTC (permalink / raw)
  To: Igor.Russkikh; +Cc: linux-usb, netdev, Dmitry.Bezrukov

From: Igor Russkikh <Igor.Russkikh@aquantia.com>
Date: Fri, 5 Oct 2018 10:24:55 +0000

> +	switch (aqc111_data->link_speed) {
> +	case AQ_INT_SPEED_5G:
> +	{
> +		link_speed = 5000;
> +		reg8 = 0x05;
> +		reg16 = 0x001F;
> +		break;
> +	}

Please do not put curly braces around switch cases.

You aren't declaring local scope variables in these case statements so
the curly braces are completely unnecessary and look ugly.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-05 17:46     ` David Miller
  0 siblings, 0 replies; 133+ messages in thread
From: David Miller @ 2018-10-05 17:46 UTC (permalink / raw)
  To: Igor.Russkikh; +Cc: linux-usb, netdev, Dmitry.Bezrukov

From: Igor Russkikh <Igor.Russkikh@aquantia.com>
Date: Fri, 5 Oct 2018 10:24:55 +0000

> +	switch (aqc111_data->link_speed) {
> +	case AQ_INT_SPEED_5G:
> +	{
> +		link_speed = 5000;
> +		reg8 = 0x05;
> +		reg16 = 0x001F;
> +		break;
> +	}

Please do not put curly braces around switch cases.

You aren't declaring local scope variables in these case statements so
the curly braces are completely unnecessary and look ugly.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-05 22:04     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-05 22:04 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:24:53AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Implement PHY power up/down sequences.
> AQC111, depending on FW used, may has PHY being controlled either
> directly (dpa = 1) or via vendor command interface (dpa = 0).

Hi Igor

dpa is not a very descriptive name.

Once we figure out if phylib is going to be used, or even phylink, i
suggest you rename this to something like aqc111_data->use_phylib.

> @@ -172,6 +211,8 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>  	u8 reg8;
>  	u16 reg16;
>  
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];

Having to do this cast all the time is quiet ugly. It seems like some
other usb_net drivers use netdev_priv().

> +
>  	/* Force bz */
g/>  	reg16 = SFR_PHYPWR_RSTCTL_BZ;
>  	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
> @@ -179,12 +220,52 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>  	reg16 = 0;
>  	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
>  			      2, 2, &reg16);
> +
> +	/* Power down ethernet PHY */
> +	if (aqc111_data->dpa) {
> +		reg8 = 0x00;
> +		aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
> +				      0, 1, &reg8);
> +	} else {
> +		aqc111_data->phy_ops.low_power = 1;
> +		aqc111_data->phy_ops.phy_power = 0;
> +		aqc111_write_cmd_nopm(dev, AQ_PHY_OPS, 0, 0,
> +				      4, &aqc111_data->phy_ops);
> +	}
> +
> +	kfree(aqc111_data);
>  }
>  

> +struct aqc111_phy_options {
> +	union {
> +		struct {
> +			u8 adv_100M:	1;
> +			u8 adv_1G:	1;
> +			u8 adv_2G5:	1;
> +			u8 adv_5G:	1;
> +			u8 rsvd1:	4;
> +		};
> +		u8 advertising;
> +	};
> +	union {
> +		struct {
> +			u8 eee_100M:	1;
> +			u8 eee_1G:	1;
> +			u8 eee_2G5:	1;
> +			u8 eee_5G:	1;
> +			u8 rsvd2:	4;
> +		};
> +		u8 eee;
> +	};
> +	union {
> +		struct {
> +			u8 pause:	1;
> +			u8 asym_pause:	1;
> +			u8 low_power:	1;
> +			u8 phy_power:	1;
> +			u8 wol:		1;
> +			u8 downshift:	1;
> +			u8 rsvd4:	2;
> +		};
> +		u8 phy_ctrl1;
> +	};
> +	union {
> +		struct {
> +		u8 dsh_ret_cnt:	4;
> +		u8 magic_packet:1;
> +		u8 rsvd5:	3;

The indentation looks wrong here.

> +		};
> +		u8 phy_ctrl2;
> +	};
> +};
> +
> +struct aqc111_data {
> +	struct {
> +		u8 major;
> +		u8 minor;
> +		u8 rev;
> +	} fw_ver;
> +	u8 dpa; /*direct PHY access*/
> +	struct aqc111_phy_options phy_ops;
> +} __packed;

Why pack this? Do you send it to the firmware?

    Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-05 22:04     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-05 22:04 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:24:53AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Implement PHY power up/down sequences.
> AQC111, depending on FW used, may has PHY being controlled either
> directly (dpa = 1) or via vendor command interface (dpa = 0).

Hi Igor

dpa is not a very descriptive name.

Once we figure out if phylib is going to be used, or even phylink, i
suggest you rename this to something like aqc111_data->use_phylib.

> @@ -172,6 +211,8 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>  	u8 reg8;
>  	u16 reg16;
>  
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];

Having to do this cast all the time is quiet ugly. It seems like some
other usb_net drivers use netdev_priv().

> +
>  	/* Force bz */
g/>  	reg16 = SFR_PHYPWR_RSTCTL_BZ;
>  	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
> @@ -179,12 +220,52 @@ static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>  	reg16 = 0;
>  	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
>  			      2, 2, &reg16);
> +
> +	/* Power down ethernet PHY */
> +	if (aqc111_data->dpa) {
> +		reg8 = 0x00;
> +		aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
> +				      0, 1, &reg8);
> +	} else {
> +		aqc111_data->phy_ops.low_power = 1;
> +		aqc111_data->phy_ops.phy_power = 0;
> +		aqc111_write_cmd_nopm(dev, AQ_PHY_OPS, 0, 0,
> +				      4, &aqc111_data->phy_ops);
> +	}
> +
> +	kfree(aqc111_data);
>  }
>  

> +struct aqc111_phy_options {
> +	union {
> +		struct {
> +			u8 adv_100M:	1;
> +			u8 adv_1G:	1;
> +			u8 adv_2G5:	1;
> +			u8 adv_5G:	1;
> +			u8 rsvd1:	4;
> +		};
> +		u8 advertising;
> +	};
> +	union {
> +		struct {
> +			u8 eee_100M:	1;
> +			u8 eee_1G:	1;
> +			u8 eee_2G5:	1;
> +			u8 eee_5G:	1;
> +			u8 rsvd2:	4;
> +		};
> +		u8 eee;
> +	};
> +	union {
> +		struct {
> +			u8 pause:	1;
> +			u8 asym_pause:	1;
> +			u8 low_power:	1;
> +			u8 phy_power:	1;
> +			u8 wol:		1;
> +			u8 downshift:	1;
> +			u8 rsvd4:	2;
> +		};
> +		u8 phy_ctrl1;
> +	};
> +	union {
> +		struct {
> +		u8 dsh_ret_cnt:	4;
> +		u8 magic_packet:1;
> +		u8 rsvd5:	3;

The indentation looks wrong here.

> +		};
> +		u8 phy_ctrl2;
> +	};
> +};
> +
> +struct aqc111_data {
> +	struct {
> +		u8 major;
> +		u8 minor;
> +		u8 rev;
> +	} fw_ver;
> +	u8 dpa; /*direct PHY access*/
> +	struct aqc111_phy_options phy_ops;
> +} __packed;

Why pack this? Do you send it to the firmware?

    Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-06  1:03     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06  1:03 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:24:58AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/usb/aqc111.h |  1 +
>  2 files changed, 52 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 1d366f4a1c51..075f51cd04ab 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -11,6 +11,7 @@
>  #include <linux/netdevice.h>
>  #include <linux/mii.h>
>  #include <linux/usb.h>
> +#include <linux/if_vlan.h>
>  #include <linux/usb/cdc.h>
>  #include <linux/usb/usbnet.h>
>  
> @@ -266,11 +267,46 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
>  		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
>  }
>  
> +static int aqc111_set_mac_addr(struct net_device *net, void *p)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	struct sockaddr *addr = p;
> +
> +	if (netif_running(net))
> +		return -EBUSY;
> +	if (!is_valid_ether_addr(addr->sa_data))
> +		return -EADDRNOTAVAIL;

It is probably better to use eth_mac_addr().

> +
> +	memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
> +
> +	/* Set the MAC address */
> +	return aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN,
> +				ETH_ALEN, net->dev_addr);
> +}
> +
>  static const struct net_device_ops aqc111_netdev_ops = {
>  	.ndo_open		= usbnet_open,
>  	.ndo_stop		= usbnet_stop,
> +	.ndo_set_mac_address	= aqc111_set_mac_addr,
> +	.ndo_validate_addr	= eth_validate_addr,
>  };
>  
> +static int aqc111_get_mac(struct usbnet *dev, u8 *buf)
> +{
> +	int ret;
> +
> +	ret = aqc111_read_cmd(dev, AQ_FLASH_PARAMETERS, 0, 0, 6, buf);

ETH_ALEN instead of 6?

> +	if (ret < 0)
> +		goto out;
> +
> +	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
> +	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);

Is this really the permanent address? If i call aqc111_set_mac_addr()
followed by aqc111_get_mac() i still get what is in the OTP EEPROM?

 +
> +	return 0;
> +out:
> +	return ret;
> +}
> +
>  static void aqc111_read_fw_version(struct usbnet *dev,
>  				   struct aqc111_data *aqc111_data)
>  {
> @@ -289,6 +325,7 @@ static void aqc111_read_fw_version(struct usbnet *dev,
>  
>  static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  {
> +	u8 buf[6] = { 0 };

ETH_ALEN

>  	int ret;
>  	struct usb_device *udev = interface_to_usbdev(intf);
>  	struct aqc111_data *aqc111_data;
> @@ -316,6 +353,12 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  	dev->data[0] = (unsigned long)aqc111_data;
>  	memset(aqc111_data, 0, sizeof(*aqc111_data));
>  
> +	/* Get the MAC address */
> +	memset(buf, 0, ETH_ALEN);

You initialized it above as {0}. You don't need to memset it here.

> +	ret = aqc111_get_mac(dev, buf);

Do you even need to zero it? If aqc111_get_mac() fails, it will be
left undefined, but you fail the bind anyway.

> +	if (ret)
> +		goto out;
> +
>  	dev->net->netdev_ops = &aqc111_netdev_ops;
>  
>  	aqc111_read_fw_version(dev, aqc111_data);
> @@ -324,6 +367,10 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  					 SPEED_5000 : SPEED_1000;
>  
>  	return 0;
> +
> +out:
> +	kfree(aqc111_data);
> +	return ret;
>  }

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-06  1:03     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06  1:03 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:24:58AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/usb/aqc111.h |  1 +
>  2 files changed, 52 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 1d366f4a1c51..075f51cd04ab 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -11,6 +11,7 @@
>  #include <linux/netdevice.h>
>  #include <linux/mii.h>
>  #include <linux/usb.h>
> +#include <linux/if_vlan.h>
>  #include <linux/usb/cdc.h>
>  #include <linux/usb/usbnet.h>
>  
> @@ -266,11 +267,46 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
>  		aqc111_set_phy_speed_fw_iface(dev, aqc111_data);
>  }
>  
> +static int aqc111_set_mac_addr(struct net_device *net, void *p)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	struct sockaddr *addr = p;
> +
> +	if (netif_running(net))
> +		return -EBUSY;
> +	if (!is_valid_ether_addr(addr->sa_data))
> +		return -EADDRNOTAVAIL;

It is probably better to use eth_mac_addr().

> +
> +	memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
> +
> +	/* Set the MAC address */
> +	return aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN,
> +				ETH_ALEN, net->dev_addr);
> +}
> +
>  static const struct net_device_ops aqc111_netdev_ops = {
>  	.ndo_open		= usbnet_open,
>  	.ndo_stop		= usbnet_stop,
> +	.ndo_set_mac_address	= aqc111_set_mac_addr,
> +	.ndo_validate_addr	= eth_validate_addr,
>  };
>  
> +static int aqc111_get_mac(struct usbnet *dev, u8 *buf)
> +{
> +	int ret;
> +
> +	ret = aqc111_read_cmd(dev, AQ_FLASH_PARAMETERS, 0, 0, 6, buf);

ETH_ALEN instead of 6?

> +	if (ret < 0)
> +		goto out;
> +
> +	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
> +	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);

Is this really the permanent address? If i call aqc111_set_mac_addr()
followed by aqc111_get_mac() i still get what is in the OTP EEPROM?

 +
> +	return 0;
> +out:
> +	return ret;
> +}
> +
>  static void aqc111_read_fw_version(struct usbnet *dev,
>  				   struct aqc111_data *aqc111_data)
>  {
> @@ -289,6 +325,7 @@ static void aqc111_read_fw_version(struct usbnet *dev,
>  
>  static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  {
> +	u8 buf[6] = { 0 };

ETH_ALEN

>  	int ret;
>  	struct usb_device *udev = interface_to_usbdev(intf);
>  	struct aqc111_data *aqc111_data;
> @@ -316,6 +353,12 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  	dev->data[0] = (unsigned long)aqc111_data;
>  	memset(aqc111_data, 0, sizeof(*aqc111_data));
>  
> +	/* Get the MAC address */
> +	memset(buf, 0, ETH_ALEN);

You initialized it above as {0}. You don't need to memset it here.

> +	ret = aqc111_get_mac(dev, buf);

Do you even need to zero it? If aqc111_get_mac() fails, it will be
left undefined, but you fail the bind anyway.

> +	if (ret)
> +		goto out;
> +
>  	dev->net->netdev_ops = &aqc111_netdev_ops;
>  
>  	aqc111_read_fw_version(dev, aqc111_data);
> @@ -324,6 +367,10 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  					 SPEED_5000 : SPEED_1000;
>  
>  	return 0;
> +
> +out:
> +	kfree(aqc111_data);
> +	return ret;
>  }

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-06  1:13     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06  1:13 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
> +				       gfp_t flags)
> +{
> +	struct aq_tx_packet_desc tx_hdr;
> +	int frame_size = dev->maxpacket;
> +	int headroom = 0;
> +	int tailroom = 0;
> +	int padding_size = 0;
> +	struct sk_buff *new_skb = NULL;
> +
> +	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
> +
> +	/*Length of actual data*/
> +	tx_hdr.length = (skb->len & 0x1FFFFF);
> +
> +	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
> +	if (headroom != 0)
> +		padding_size = 8 - headroom;
> +
> +	if (((skb->len + AQ_TX_HEADER_SIZE + padding_size) % frame_size) == 0) {
> +		padding_size += 8;
> +		tx_hdr.drop_padding = 1;
> +	}
> +
> +	if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
> +	    skb_linearize(skb))
> +		return NULL;
> +
> +	headroom = skb_headroom(skb);
> +	tailroom = skb_tailroom(skb);
> +
> +	if (!(headroom >= AQ_TX_HEADER_SIZE && tailroom >= padding_size)) {
> +		new_skb = skb_copy_expand(skb, AQ_TX_HEADER_SIZE,
> +					  padding_size, flags);
> +		dev_kfree_skb_any(skb);
> +		skb = new_skb;
> +		if (!skb)
> +			return NULL;
> +	}
> +	if (padding_size != 0)
> +		skb_put(skb, padding_size);
> +	/* Copy TX header */
> +	skb_push(skb, AQ_TX_HEADER_SIZE);
> +	cpu_to_le64s(&tx_hdr);

Is that portable? tx_hdr is a structure of 2x u32 bitfields.  What
endian have you tested that one?

> +	skb_copy_to_linear_data(skb, &tx_hdr, 8);
> +
> +	usbnet_set_skb_tx_stats(skb, 1, 0);
> +
> +	return skb;
> +}

> +struct aq_tx_packet_desc {
> +	struct {
> +		u32 length:21;
> +		u32 checksum:7;
> +		u32 drop_padding:1;
> +		u32 vlan_tag:1;
> +		u32 cphi:1;
> +		u32 dicf:1;
> +	};
> +	struct {
> +		u32 max_seg_size:15;
> +		u32 reserved:1;
> +		u32 vlan_info:16;
> +	};
> +};

  Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-06  1:13     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06  1:13 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
> +				       gfp_t flags)
> +{
> +	struct aq_tx_packet_desc tx_hdr;
> +	int frame_size = dev->maxpacket;
> +	int headroom = 0;
> +	int tailroom = 0;
> +	int padding_size = 0;
> +	struct sk_buff *new_skb = NULL;
> +
> +	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
> +
> +	/*Length of actual data*/
> +	tx_hdr.length = (skb->len & 0x1FFFFF);
> +
> +	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
> +	if (headroom != 0)
> +		padding_size = 8 - headroom;
> +
> +	if (((skb->len + AQ_TX_HEADER_SIZE + padding_size) % frame_size) == 0) {
> +		padding_size += 8;
> +		tx_hdr.drop_padding = 1;
> +	}
> +
> +	if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) &&
> +	    skb_linearize(skb))
> +		return NULL;
> +
> +	headroom = skb_headroom(skb);
> +	tailroom = skb_tailroom(skb);
> +
> +	if (!(headroom >= AQ_TX_HEADER_SIZE && tailroom >= padding_size)) {
> +		new_skb = skb_copy_expand(skb, AQ_TX_HEADER_SIZE,
> +					  padding_size, flags);
> +		dev_kfree_skb_any(skb);
> +		skb = new_skb;
> +		if (!skb)
> +			return NULL;
> +	}
> +	if (padding_size != 0)
> +		skb_put(skb, padding_size);
> +	/* Copy TX header */
> +	skb_push(skb, AQ_TX_HEADER_SIZE);
> +	cpu_to_le64s(&tx_hdr);

Is that portable? tx_hdr is a structure of 2x u32 bitfields.  What
endian have you tested that one?

> +	skb_copy_to_linear_data(skb, &tx_hdr, 8);
> +
> +	usbnet_set_skb_tx_stats(skb, 1, 0);
> +
> +	return skb;
> +}

> +struct aq_tx_packet_desc {
> +	struct {
> +		u32 length:21;
> +		u32 checksum:7;
> +		u32 drop_padding:1;
> +		u32 vlan_tag:1;
> +		u32 cphi:1;
> +		u32 dicf:1;
> +	};
> +	struct {
> +		u32 max_seg_size:15;
> +		u32 reserved:1;
> +		u32 vlan_info:16;
> +	};
> +};

  Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 09/19] net: usb: aqc111: Implement RX data path
@ 2018-10-06  1:18     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06  1:18 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
> +{
> +	struct sk_buff *new_skb = NULL;
> +	u32 skb_len = 0;
> +	u32 desc_offset = 0; /*RX Header Offset*/
> +	u32 start_of_descs = 0;
> +	u16 pkt_count = 0;
> +	u32 pkt_total_offset = 0;
> +	struct aq_rx_packet_desc *pkt_desc = NULL;
> +	struct aq_rx_desc_header desc_hdr;
> +
> +	if (!skb)
> +		goto err;
> +
> +	if (skb->len == 0)
> +		goto err;
> +
> +	skb_len = skb->len;
> +	/* RX Offset Header */
> +	skb_trim(skb, skb->len - sizeof(struct aq_rx_desc_header));
> +	memcpy(&desc_hdr, skb_tail_pointer(skb),
> +	       sizeof(struct aq_rx_desc_header));
> +	le64_to_cpus(&desc_hdr);

Same question as for TX.

> +
> +	/* Check these packets */
> +	desc_offset = (u32)desc_hdr.desc_offset;

I don't think you need the cast here.

Please review all your casts and remove any that are not needed.

       Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,09/19] net: usb: aqc111: Implement RX data path
@ 2018-10-06  1:18     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06  1:18 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
> +{
> +	struct sk_buff *new_skb = NULL;
> +	u32 skb_len = 0;
> +	u32 desc_offset = 0; /*RX Header Offset*/
> +	u32 start_of_descs = 0;
> +	u16 pkt_count = 0;
> +	u32 pkt_total_offset = 0;
> +	struct aq_rx_packet_desc *pkt_desc = NULL;
> +	struct aq_rx_desc_header desc_hdr;
> +
> +	if (!skb)
> +		goto err;
> +
> +	if (skb->len == 0)
> +		goto err;
> +
> +	skb_len = skb->len;
> +	/* RX Offset Header */
> +	skb_trim(skb, skb->len - sizeof(struct aq_rx_desc_header));
> +	memcpy(&desc_hdr, skb_tail_pointer(skb),
> +	       sizeof(struct aq_rx_desc_header));
> +	le64_to_cpus(&desc_hdr);

Same question as for TX.

> +
> +	/* Check these packets */
> +	desc_offset = (u32)desc_hdr.desc_offset;

I don't think you need the cast here.

Please review all your casts and remove any that are not needed.

       Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 11/19] net: usb: aqc111: Add support for changing MTU
@ 2018-10-06 16:56     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 16:56 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static int aqc111_change_mtu(struct net_device *net, int new_mtu)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	u16 reg16 = 0;
> +	u8 buf[5];
> +
> +	if (new_mtu <= 0 || new_mtu > 16334) {
> +		netdev_info(net, "Invalid MTU %d requested, hw max 16334",
> +			    new_mtu);
> +		return -EINVAL;
> +	}

Please set net->min_mtu, and net->max_mtu, and the core should do this
checking for you. See dev_set_mtu_ext().

	 Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,11/19] net: usb: aqc111: Add support for changing MTU
@ 2018-10-06 16:56     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 16:56 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static int aqc111_change_mtu(struct net_device *net, int new_mtu)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	u16 reg16 = 0;
> +	u8 buf[5];
> +
> +	if (new_mtu <= 0 || new_mtu > 16334) {
> +		netdev_info(net, "Invalid MTU %d requested, hw max 16334",
> +			    new_mtu);
> +		return -EINVAL;
> +	}

Please set net->min_mtu, and net->max_mtu, and the core should do this
checking for you. See dev_set_mtu_ext().

	 Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 14/19] net: usb: aqc111: Implement set_rx_mode callback
@ 2018-10-06 17:03     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:03 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static void aqc111_set_rx_mode(struct net_device *net)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];

> +	u8 *m_filter = ((u8 *)dev->data) + 12;

Please could you explain is.

       Thanks
		Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,14/19] net: usb: aqc111: Implement set_rx_mode callback
@ 2018-10-06 17:03     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:03 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static void aqc111_set_rx_mode(struct net_device *net)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];

> +	u8 *m_filter = ((u8 *)dev->data) + 12;

Please could you explain is.

       Thanks
		Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 16/19] net: usb: aqc111: Add RX VLAN filtering support
@ 2018-10-06 17:05     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:05 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> @@ -994,6 +1083,7 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>  		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
>  		if (aqc111_data->rx_checksum)
>  			aqc111_rx_checksum(new_skb, &pkt_desc);
> +
>  		if (pkt_desc->vlan_ind)
>  			__vlan_hwaccel_put_tag(new_skb,
>  					       htons(ETH_P_8021Q),

Please squash this hunk into the correct patch.

       Thanks
	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,16/19] net: usb: aqc111: Add RX VLAN filtering support
@ 2018-10-06 17:05     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:05 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> @@ -994,6 +1083,7 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>  		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
>  		if (aqc111_data->rx_checksum)
>  			aqc111_rx_checksum(new_skb, &pkt_desc);
> +
>  		if (pkt_desc->vlan_ind)
>  			__vlan_hwaccel_put_tag(new_skb,
>  					       htons(ETH_P_8021Q),

Please squash this hunk into the correct patch.

       Thanks
	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 17/19] net: usb: aqc111: Initialize ethtool_ops structure
@ 2018-10-06 17:08     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:08 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:25:22AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Implement get_drvinfo, set/get_msglevel, get_link callbacks
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 9908b0a04da6..ade2b60b4811 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -9,6 +9,7 @@
>  
>  #include <linux/module.h>
>  #include <linux/netdevice.h>
> +#include <linux/ethtool.h>
>  #include <linux/mii.h>
>  #include <linux/usb.h>
>  #include <linux/crc32.h>
> @@ -18,6 +19,9 @@
>  
>  #include "aqc111.h"
>  
> +#define DRIVER_VERSION "1.0.0.0"

Hi Igor

This is been discussed a number of times before, and i expect it to be
discussed again. Driver versions of useless. Please drop it.

> +#define DRIVER_NAME "Aquantia AQtion USB to 5GbE"

It might be nice to include the module name in here, making it easy to
link the module to the driver.

> +
>  static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
>  			     u16 index, u16 size, void *data, int nopm)
>  {
> @@ -170,6 +174,24 @@ static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
>  	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
>  }
>  

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,17/19] net: usb: aqc111: Initialize ethtool_ops structure
@ 2018-10-06 17:08     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:08 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Fri, Oct 05, 2018 at 10:25:22AM +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Implement get_drvinfo, set/get_msglevel, get_link callbacks
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 9908b0a04da6..ade2b60b4811 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -9,6 +9,7 @@
>  
>  #include <linux/module.h>
>  #include <linux/netdevice.h>
> +#include <linux/ethtool.h>
>  #include <linux/mii.h>
>  #include <linux/usb.h>
>  #include <linux/crc32.h>
> @@ -18,6 +19,9 @@
>  
>  #include "aqc111.h"
>  
> +#define DRIVER_VERSION "1.0.0.0"

Hi Igor

This is been discussed a number of times before, and i expect it to be
discussed again. Driver versions of useless. Please drop it.

> +#define DRIVER_NAME "Aquantia AQtion USB to 5GbE"

It might be nice to include the module name in here, making it easy to
link the module to the driver.

> +
>  static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
>  			     u16 index, u16 size, void *data, int nopm)
>  {
> @@ -170,6 +174,24 @@ static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
>  	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
>  }
>  

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-06 17:35     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:35 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> @@ -202,6 +319,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  	dev->net->netdev_ops = &aqc111_netdev_ops;
>  
>  	aqc111_read_fw_version(dev, aqc111_data);
> +	aqc111_data->autoneg = AUTONEG_ENABLE;
> +	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
> +					 SPEED_5000 : SPEED_1000;

Hi Igor

I'd be interested in knowing the reasoning behind this.

USB 3 has a raw bandwidth of 5Gbps. But it is a shared bus. So you
have no guaranteed you are actually going to get the needed bandwidth
to support line rate.

USB 2.0 only gives you 480Mbps. So it won't even give you the full
1G. So using the same reasoning for USB3, maybe you should limit it to
100Mbps?

I personally would not apply restrictions on the PHY depending on what
USB is being used.

This becomes more important when using SFPs. If i have an SFP peer
which is expecting 2500Base-X, but because the device is plugged into
USB 2 port it is forced to use 1000Base-X, it is not going to get
link.

	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-06 17:35     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:35 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> @@ -202,6 +319,9 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  	dev->net->netdev_ops = &aqc111_netdev_ops;
>  
>  	aqc111_read_fw_version(dev, aqc111_data);
> +	aqc111_data->autoneg = AUTONEG_ENABLE;
> +	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
> +					 SPEED_5000 : SPEED_1000;

Hi Igor

I'd be interested in knowing the reasoning behind this.

USB 3 has a raw bandwidth of 5Gbps. But it is a shared bus. So you
have no guaranteed you are actually going to get the needed bandwidth
to support line rate.

USB 2.0 only gives you 480Mbps. So it won't even give you the full
1G. So using the same reasoning for USB3, maybe you should limit it to
100Mbps?

I personally would not apply restrictions on the PHY depending on what
USB is being used.

This becomes more important when using SFPs. If i have an SFP peer
which is expecting 2500Base-X, but because the device is plugged into
USB 2 port it is forced to use 1000Base-X, it is not going to get
link.

	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks
@ 2018-10-06 17:38     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:38 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static int aqc111_set_link_ksettings(struct net_device *net,
> +				     const struct ethtool_link_ksettings *elk)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	enum usb_device_speed usb_speed = dev->udev->speed;
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> +	u32 speed = elk->base.speed;
> +	u8 autoneg = elk->base.autoneg;
> +
> +	if (autoneg == AUTONEG_ENABLE) {
> +		if (aqc111_data->autoneg != AUTONEG_ENABLE) {
> +			aqc111_data->autoneg = AUTONEG_ENABLE;
> +			aqc111_data->advertised_speed =
> +					(usb_speed == USB_SPEED_SUPER) ?
> +					 SPEED_5000 : SPEED_1000;
> +			aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> +					     aqc111_data->advertised_speed);
> +		}
> +	} else {
> +		if (speed != SPEED_100 &&
> +		    speed != SPEED_1000 &&
> +		    speed != SPEED_2500 &&
> +		    speed != SPEED_5000 &&
> +		    speed != SPEED_UNKNOWN)
> +			return -EINVAL;
> +
> +		if (usb_speed != USB_SPEED_SUPER && speed > SPEED_1000)
> +			return -EINVAL;
> +

Hi Igor

Maybe you are missing a check for duplex here?

> +		aqc111_data->autoneg = AUTONEG_DISABLE;
> +		if (speed != SPEED_UNKNOWN)
> +			aqc111_data->advertised_speed = speed;
> +
> +		aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> +				     aqc111_data->advertised_speed);
> +	}
> +
> +	return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks
@ 2018-10-06 17:38     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:38 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +static int aqc111_set_link_ksettings(struct net_device *net,
> +				     const struct ethtool_link_ksettings *elk)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	enum usb_device_speed usb_speed = dev->udev->speed;
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> +	u32 speed = elk->base.speed;
> +	u8 autoneg = elk->base.autoneg;
> +
> +	if (autoneg == AUTONEG_ENABLE) {
> +		if (aqc111_data->autoneg != AUTONEG_ENABLE) {
> +			aqc111_data->autoneg = AUTONEG_ENABLE;
> +			aqc111_data->advertised_speed =
> +					(usb_speed == USB_SPEED_SUPER) ?
> +					 SPEED_5000 : SPEED_1000;
> +			aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> +					     aqc111_data->advertised_speed);
> +		}
> +	} else {
> +		if (speed != SPEED_100 &&
> +		    speed != SPEED_1000 &&
> +		    speed != SPEED_2500 &&
> +		    speed != SPEED_5000 &&
> +		    speed != SPEED_UNKNOWN)
> +			return -EINVAL;
> +
> +		if (usb_speed != USB_SPEED_SUPER && speed > SPEED_1000)
> +			return -EINVAL;
> +

Hi Igor

Maybe you are missing a check for duplex here?

> +		aqc111_data->autoneg = AUTONEG_DISABLE;
> +		if (speed != SPEED_UNKNOWN)
> +			aqc111_data->advertised_speed = speed;
> +
> +		aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> +				     aqc111_data->advertised_speed);
> +	}
> +
> +	return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-06 17:49     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:49 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +		if (aqc111_data->dpa) {
> +			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);

I don't think that works. You should leave AUTONEG on, but only
advertise SPEED_100 and trigger auto-neg. If you force it to 100,
there is no guarantee the peer will figure out what the new link speed
is. I've often seen failed auto-net result in 10/Half. So you will
loose the link, making WoL pointless.

> +static int aqc111_resume(struct usb_interface *intf)
> +{
> +	struct usbnet *dev = usb_get_intfdata(intf);
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> +	u8 reg8;
> +	u16 reg16;
> +
> +	netif_carrier_off(dev->net);
> +
> +	/* Power up ethernet PHY */
> +	aqc111_data->phy_ops.phy_power = 1;
> +	aqc111_data->phy_ops.low_power = 0;
> +	aqc111_data->phy_ops.wol = 0;
> +	if (aqc111_data->dpa) {
> +		aqc111_read_cmd_nopm(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
> +		if (reg8 == 0x00) {
> +			reg8 = 0x02;
> +			aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
> +					      1, &reg8);
> +			msleep(200);
> +		}
> +
> +		aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
> +				 2, &reg16);
> +		if (reg16 & AQ_PHY_LOW_POWER_MODE) {
> +			reg16 &= ~AQ_PHY_LOW_POWER_MODE;
> +			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
> +					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
> +		}
> +	}
> +
> +	reg8 = 0xFF;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
> +			      1, 1, &reg8);
> +	/* Configure RX control register => start operation */
> +	reg16 = aqc111_data->rxctl;
> +	reg16 &= ~SFR_RX_CTL_START;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
> +
> +	reg16 |= SFR_RX_CTL_START;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
> +
> +	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> +			     aqc111_data->advertised_speed);
> +

Should that be conditional on aqc111_data->dpa?

> +struct aqc111_wol_cfg {
> +	u8 hw_addr[6];
> +	u8 flags;
> +	u8 rsvd[283];
> +};

Do you really need these 283 bytes??

> +
> +#define WOL_CFG_SIZE sizeof(struct aqc111_wol_cfg)
> +
>  struct aqc111_data {
>  	u16 rxctl;
>  	u8 rx_checksum;
> @@ -228,6 +238,7 @@ struct aqc111_data {
>  	} fw_ver;
>  	u8 dpa; /*direct PHY access*/
>  	struct aqc111_phy_options phy_ops;
> +	struct aqc111_wol_cfg wol_cfg;

Those 283 bytes make this whole structure bigger...

      Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-06 17:49     ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:49 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

> +		if (aqc111_data->dpa) {
> +			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);

I don't think that works. You should leave AUTONEG on, but only
advertise SPEED_100 and trigger auto-neg. If you force it to 100,
there is no guarantee the peer will figure out what the new link speed
is. I've often seen failed auto-net result in 10/Half. So you will
loose the link, making WoL pointless.

> +static int aqc111_resume(struct usb_interface *intf)
> +{
> +	struct usbnet *dev = usb_get_intfdata(intf);
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> +	u8 reg8;
> +	u16 reg16;
> +
> +	netif_carrier_off(dev->net);
> +
> +	/* Power up ethernet PHY */
> +	aqc111_data->phy_ops.phy_power = 1;
> +	aqc111_data->phy_ops.low_power = 0;
> +	aqc111_data->phy_ops.wol = 0;
> +	if (aqc111_data->dpa) {
> +		aqc111_read_cmd_nopm(dev, AQ_PHY_POWER, 0, 0, 1, &reg8);
> +		if (reg8 == 0x00) {
> +			reg8 = 0x02;
> +			aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
> +					      1, &reg8);
> +			msleep(200);
> +		}
> +
> +		aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
> +				 2, &reg16);
> +		if (reg16 & AQ_PHY_LOW_POWER_MODE) {
> +			reg16 &= ~AQ_PHY_LOW_POWER_MODE;
> +			aq_mdio_write_cmd(dev, AQ_GLB_STD_CTRL_REG,
> +					  AQ_PHY_GLOBAL_ADDR, 2, &reg16);
> +		}
> +	}
> +
> +	reg8 = 0xFF;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
> +			      1, 1, &reg8);
> +	/* Configure RX control register => start operation */
> +	reg16 = aqc111_data->rxctl;
> +	reg16 &= ~SFR_RX_CTL_START;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
> +
> +	reg16 |= SFR_RX_CTL_START;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, &reg16);
> +
> +	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> +			     aqc111_data->advertised_speed);
> +

Should that be conditional on aqc111_data->dpa?

> +struct aqc111_wol_cfg {
> +	u8 hw_addr[6];
> +	u8 flags;
> +	u8 rsvd[283];
> +};

Do you really need these 283 bytes??

> +
> +#define WOL_CFG_SIZE sizeof(struct aqc111_wol_cfg)
> +
>  struct aqc111_data {
>  	u16 rxctl;
>  	u8 rx_checksum;
> @@ -228,6 +238,7 @@ struct aqc111_data {
>  	} fw_ver;
>  	u8 dpa; /*direct PHY access*/
>  	struct aqc111_phy_options phy_ops;
> +	struct aqc111_wol_cfg wol_cfg;

Those 283 bytes make this whole structure bigger...

      Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices
  2018-10-05 10:24 [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices Igor Russkikh
                   ` (18 preceding siblings ...)
  2018-10-05 10:25   ` [net-next,19/19] " Igor Russkikh
@ 2018-10-06 17:51 ` Andrew Lunn
  2018-10-08  7:58   ` Igor Russkikh
  2018-10-08 14:21 ` Oliver Neukum
  20 siblings, 1 reply; 133+ messages in thread
From: Andrew Lunn @ 2018-10-06 17:51 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev

On Fri, Oct 05, 2018 at 10:24:37AM +0000, Igor Russkikh wrote:
> This patchset introduces support for new multigig ethernet to USB dongle,
> developed jointly by Aquantia (Phy) and ASIX (USB MAC).
> 
> The driver has similar structure with other ASIX MAC drivers (AX88179), but
> with a number of important differences:
> - Driver supports both direct Phy and custom firmware interface for Phy
>   programming. This is due to different firmware modules available with this
>   product.
> - Driver handles new 2.5G/5G link speed configuration and reporting.
> - Device support all speeds from 100M up to 5G.
> - Device supports MTU up to 16K.
> 
> Device supports various standard networking features, like
> checksum offloads, vlan tagging/filtering, TSO.
> 
> The code of this driver is based on original ASIX sources and was extended
> by Aquantia for 5G multigig support. 
> 

Hi Igor, Dmitry

Nice patch set, well broken up, easy to review.

     Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices
  2018-10-06 17:51 ` [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices Andrew Lunn
@ 2018-10-08  7:58   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08  7:58 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: David S . Miller, linux-usb, netdev, Simon Edelhaus,
	Nadezhda Krupnina, Dmitry.Bezrukov

Hi Andrew,

> Nice patch set, well broken up, easy to review.
> 

Thanks a lot for your detailed review, your comments are really useful!
I'll respond to some of your comments separately.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08  9:09       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08  9:09 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>>  
>> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> 
> Having to do this cast all the time is quiet ugly. It seems like some
> other usb_net drivers use netdev_priv().

As I see most of usb usbnet based devices use the same theme with accessing
private data via dev->data.

netdev_priv() is used to store struct usbnet itself.

>> +	u8 dpa; /*direct PHY access*/
>> +	struct aqc111_phy_options phy_ops;
>> +} __packed;
> 
> Why pack this? Do you send it to the firmware?

Agreed, no. We have to pack phy_ops and wol_config only.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08  9:09       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08  9:09 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>>  
>> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> 
> Having to do this cast all the time is quiet ugly. It seems like some
> other usb_net drivers use netdev_priv().

As I see most of usb usbnet based devices use the same theme with accessing
private data via dev->data.

netdev_priv() is used to store struct usbnet itself.

>> +	u8 dpa; /*direct PHY access*/
>> +	struct aqc111_phy_options phy_ops;
>> +} __packed;
> 
> Why pack this? Do you send it to the firmware?

Agreed, no. We have to pack phy_ops and wol_config only.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08  9:29       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08  9:29 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>>  	aqc111_read_fw_version(dev, aqc111_data);
>> +	aqc111_data->autoneg = AUTONEG_ENABLE;
>> +	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
>> +					 SPEED_5000 : SPEED_1000;
> 

> USB 3 has a raw bandwidth of 5Gbps. But it is a shared bus. So you
> have no guaranteed you are actually going to get the needed bandwidth
> to support line rate.
> 
> USB 2.0 only gives you 480Mbps. So it won't even give you the full
> 1G. So using the same reasoning for USB3, maybe you should limit it to
> 100Mbps?
> 
> I personally would not apply restrictions on the PHY depending on what
> USB is being used.

First argument here is to reduce power consumption on USB2.
2.5G/5G uses OCSGMII/XFI serdes which consumes more power.
Of course in normal conditions usb2 is capable to feed that, but
the risk still exists on legacy usb2 hardware.

> This becomes more important when using SFPs. If i have an SFP peer
> which is expecting 2500Base-X, but because the device is plugged into
> USB 2 port it is forced to use 1000Base-X, it is not going to get
> link.

Do you mean here 2500Base-T? This particular device is an integrated
mac+phy, thus we can't easily link it with -X SFP endpoint.

Although its not a common usecase for the consumer dongle to connect to SFP
endpoints, think your comment is quite reasonable.
We'll clarify this internally.


Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08  9:29       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08  9:29 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>>  	aqc111_read_fw_version(dev, aqc111_data);
>> +	aqc111_data->autoneg = AUTONEG_ENABLE;
>> +	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
>> +					 SPEED_5000 : SPEED_1000;
> 

> USB 3 has a raw bandwidth of 5Gbps. But it is a shared bus. So you
> have no guaranteed you are actually going to get the needed bandwidth
> to support line rate.
> 
> USB 2.0 only gives you 480Mbps. So it won't even give you the full
> 1G. So using the same reasoning for USB3, maybe you should limit it to
> 100Mbps?
> 
> I personally would not apply restrictions on the PHY depending on what
> USB is being used.

First argument here is to reduce power consumption on USB2.
2.5G/5G uses OCSGMII/XFI serdes which consumes more power.
Of course in normal conditions usb2 is capable to feed that, but
the risk still exists on legacy usb2 hardware.

> This becomes more important when using SFPs. If i have an SFP peer
> which is expecting 2500Base-X, but because the device is plugged into
> USB 2 port it is forced to use 1000Base-X, it is not going to get
> link.

Do you mean here 2500Base-T? This particular device is an integrated
mac+phy, thus we can't easily link it with -X SFP endpoint.

Although its not a common usecase for the consumer dongle to connect to SFP
endpoints, think your comment is quite reasonable.
We'll clarify this internally.


Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08 12:12         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-08 12:12 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 09:29:26AM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >>  	aqc111_read_fw_version(dev, aqc111_data);
> >> +	aqc111_data->autoneg = AUTONEG_ENABLE;
> >> +	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
> >> +					 SPEED_5000 : SPEED_1000;
> > 
> 
> > USB 3 has a raw bandwidth of 5Gbps. But it is a shared bus. So you
> > have no guaranteed you are actually going to get the needed bandwidth
> > to support line rate.
> > 
> > USB 2.0 only gives you 480Mbps. So it won't even give you the full
> > 1G. So using the same reasoning for USB3, maybe you should limit it to
> > 100Mbps?
> > 
> > I personally would not apply restrictions on the PHY depending on what
> > USB is being used.
> 
> First argument here is to reduce power consumption on USB2.
> 2.5G/5G uses OCSGMII/XFI serdes which consumes more power.
> Of course in normal conditions usb2 is capable to feed that, but
> the risk still exists on legacy usb2 hardware.

O.K, that sounds like a sensible argument. Please add a comment. I
hope the Marketing Department also understand this. It should probably
explain this on the product packaging.

> > This becomes more important when using SFPs. If i have an SFP peer
> > which is expecting 2500Base-X, but because the device is plugged into
> > USB 2 port it is forced to use 1000Base-X, it is not going to get
> > link.
> 
> Do you mean here 2500Base-T? This particular device is an integrated
> mac+phy, thus we can't easily link it with -X SFP endpoint.

I only went to find the product brief after finishing the
review. Without an external SERDES interface, SFP is not possible. But
from your comment above, i does sound like internally it has such a
SERDES. So it is not out of the question a follow up device is
produced which could connect to an SFP. I actually have a no-name USB
based SFP dongle...

      Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08 12:12         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-08 12:12 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 09:29:26AM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >>  	aqc111_read_fw_version(dev, aqc111_data);
> >> +	aqc111_data->autoneg = AUTONEG_ENABLE;
> >> +	aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ?
> >> +					 SPEED_5000 : SPEED_1000;
> > 
> 
> > USB 3 has a raw bandwidth of 5Gbps. But it is a shared bus. So you
> > have no guaranteed you are actually going to get the needed bandwidth
> > to support line rate.
> > 
> > USB 2.0 only gives you 480Mbps. So it won't even give you the full
> > 1G. So using the same reasoning for USB3, maybe you should limit it to
> > 100Mbps?
> > 
> > I personally would not apply restrictions on the PHY depending on what
> > USB is being used.
> 
> First argument here is to reduce power consumption on USB2.
> 2.5G/5G uses OCSGMII/XFI serdes which consumes more power.
> Of course in normal conditions usb2 is capable to feed that, but
> the risk still exists on legacy usb2 hardware.

O.K, that sounds like a sensible argument. Please add a comment. I
hope the Marketing Department also understand this. It should probably
explain this on the product packaging.

> > This becomes more important when using SFPs. If i have an SFP peer
> > which is expecting 2500Base-X, but because the device is plugged into
> > USB 2 port it is forced to use 1000Base-X, it is not going to get
> > link.
> 
> Do you mean here 2500Base-T? This particular device is an integrated
> mac+phy, thus we can't easily link it with -X SFP endpoint.

I only went to find the product brief after finishing the
review. Without an external SERDES interface, SFP is not possible. But
from your comment above, i does sound like internally it has such a
SERDES. So it is not out of the question a follow up device is
produced which could connect to an SFP. I actually have a no-name USB
based SFP dongle...

      Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 12:17         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-08 12:17 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 09:09:54AM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >>  
> >> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> > 
> > Having to do this cast all the time is quiet ugly. It seems like some
> > other usb_net drivers use netdev_priv().
> 
> As I see most of usb usbnet based devices use the same theme with accessing
> private data via dev->data.

It is just ugly. It would of been better if dev->data[] was a void
pointer. This is the first usbnet driver i've reviewed, so i don't
know the history behind this. I wonder if adding a void *priv would be
accepted?

	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 12:17         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-08 12:17 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 09:09:54AM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >>  
> >> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> > 
> > Having to do this cast all the time is quiet ugly. It seems like some
> > other usb_net drivers use netdev_priv().
> 
> As I see most of usb usbnet based devices use the same theme with accessing
> private data via dev->data.

It is just ugly. It would of been better if dev->data[] was a void
pointer. This is the first usbnet driver i've reviewed, so i don't
know the history behind this. I wonder if adding a void *priv would be
accepted?

	Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08 13:22       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 13:22 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov


Hi Andrew,

> Hi Igor, Dmitry
> 
> Please could you explain why you decided to not use drivers/net/phy?
> The previous patch introduced basically what you need to export a
> standard Linux MDIO bus. From that you can use a standard Linux PHY
> driver.

Thats again because of this product has tightly integrated MAC+Phy.
MAC FW controls system interface and reports/alters link state
as a joint state on copper and SIF (even in dpa direct phy mode).

We can't extract phy api into a standalone fully functional phylib therefore.
Also as far as I know this particular phy is not available in the wild.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08 13:22       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 13:22 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

> Hi Igor, Dmitry
> 
> Please could you explain why you decided to not use drivers/net/phy?
> The previous patch introduced basically what you need to export a
> standard Linux MDIO bus. From that you can use a standard Linux PHY
> driver.

Thats again because of this product has tightly integrated MAC+Phy.
MAC FW controls system interface and reports/alters link state
as a joint state on copper and SIF (even in dpa direct phy mode).

We can't extract phy api into a standalone fully functional phylib therefore.
Also as far as I know this particular phy is not available in the wild.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-08 13:43       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 13:43 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov


>> +	skb_push(skb, AQ_TX_HEADER_SIZE);
>> +	cpu_to_le64s(&tx_hdr);
> 
> Is that portable? tx_hdr is a structure of 2x u32 bitfields.  What
> endian have you tested that one?
> 

You are right, this is wrong for BE hardware.

We don't have such a hardware to check unfortunately.
Think its better to drop endianess conversions and declare
the driver as little endian only.

Do you think that'll be acceptable?

Regards,
   Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-08 13:43       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 13:43 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

>> +	skb_push(skb, AQ_TX_HEADER_SIZE);
>> +	cpu_to_le64s(&tx_hdr);
> 
> Is that portable? tx_hdr is a structure of 2x u32 bitfields.  What
> endian have you tested that one?
> 

You are right, this is wrong for BE hardware.

We don't have such a hardware to check unfortunately.
Think its better to drop endianess conversions and declare
the driver as little endian only.

Do you think that'll be acceptable?

Regards,
   Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-08 13:44     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:44 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Read/write command register defines and functions
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/usb/aqc111.h |  19 ++++++++
>  2 files changed, 143 insertions(+)
>  create mode 100644 drivers/net/usb/aqc111.h
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index c914e19387f2..7f3e5a615750 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -14,6 +14,130 @@
>  #include <linux/usb/cdc.h>
>  #include <linux/usb/usbnet.h>
>  
> +#include "aqc111.h"
> +
> +static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			     u16 index, u16 size, void *data, int nopm)
> +{
> +	int ret;
> +	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
> +		  u16 index, void *data, u16 size);
> +
> +	if (nopm)
> +		fn = usbnet_read_cmd_nopm;
> +	else
> +		fn = usbnet_read_cmd;

If you really want to do this, pass the function.

> +
> +	ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +		 value, index, data, size);
> +	if (size == 2)
> +		le16_to_cpus(data);

That is incredibly dirty

> +
> +	if (unlikely(ret < 0))
> +		netdev_warn(dev->net,
> +			    "Failed to read(0x%x) reg index 0x%04x: %d\n",
> +			    cmd, index, ret);
> +	return ret;
> +}
> +
> +static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
> +				u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 1);
> +}
> +
> +static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			   u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 0);
> +}
> +
> +static int __aq_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
> +			  u16 value, u16 index, const void *data, u16 size)
> +{
> +	void *buf = NULL;
> +	int err = -ENOMEM;
> +
> +	netdev_dbg(dev->net,
> +		   "%s cmd=%#x reqtype=%#x value=%#x index=%#x size=%d\n",
> +		   __func__, cmd, reqtype, value, index, size);
> +
> +	if (data) {
> +		buf = kmemdup(data, size, GFP_KERNEL);

Under which contexts is this used?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-08 13:44     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:44 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Read/write command register defines and functions
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/usb/aqc111.h |  19 ++++++++
>  2 files changed, 143 insertions(+)
>  create mode 100644 drivers/net/usb/aqc111.h
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index c914e19387f2..7f3e5a615750 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -14,6 +14,130 @@
>  #include <linux/usb/cdc.h>
>  #include <linux/usb/usbnet.h>
>  
> +#include "aqc111.h"
> +
> +static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			     u16 index, u16 size, void *data, int nopm)
> +{
> +	int ret;
> +	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
> +		  u16 index, void *data, u16 size);
> +
> +	if (nopm)
> +		fn = usbnet_read_cmd_nopm;
> +	else
> +		fn = usbnet_read_cmd;

If you really want to do this, pass the function.

> +
> +	ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +		 value, index, data, size);
> +	if (size == 2)
> +		le16_to_cpus(data);

That is incredibly dirty

> +
> +	if (unlikely(ret < 0))
> +		netdev_warn(dev->net,
> +			    "Failed to read(0x%x) reg index 0x%04x: %d\n",
> +			    cmd, index, ret);
> +	return ret;
> +}
> +
> +static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
> +				u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 1);
> +}
> +
> +static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			   u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 0);
> +}
> +
> +static int __aq_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
> +			  u16 value, u16 index, const void *data, u16 size)
> +{
> +	void *buf = NULL;
> +	int err = -ENOMEM;
> +
> +	netdev_dbg(dev->net,
> +		   "%s cmd=%#x reqtype=%#x value=%#x index=%#x size=%d\n",
> +		   __func__, cmd, reqtype, value, index, size);
> +
> +	if (data) {
> +		buf = kmemdup(data, size, GFP_KERNEL);

Under which contexts is this used?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-08 13:47     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:47 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Reset, stop callbacks, driver unbind callback.
> More register defines required for these callbacks.
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
>  drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 149 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 7f3e5a615750..22bb259d71fb 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  
>  static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>  {
> +	u8 reg8;
> +	u16 reg16;
> +
> +	/* Force bz */
> +	reg16 = SFR_PHYPWR_RSTCTL_BZ;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
> +			      2, 2, &reg16);

No, I am sorry, you are doing DMA on the kernel stack. That is not
allowed. These functions will all have to be fixed.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-08 13:47     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:47 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Reset, stop callbacks, driver unbind callback.
> More register defines required for these callbacks.
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
>  drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 149 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 7f3e5a615750..22bb259d71fb 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  
>  static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>  {
> +	u8 reg8;
> +	u16 reg16;
> +
> +	/* Force bz */
> +	reg16 = SFR_PHYPWR_RSTCTL_BZ;
> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
> +			      2, 2, &reg16);

No, I am sorry, you are doing DMA on the kernel stack. That is not
allowed. These functions will all have to be fixed.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 14/19] net: usb: aqc111: Implement set_rx_mode callback
@ 2018-10-08 13:49       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 13:49 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>> +{
>> +	struct usbnet *dev = netdev_priv(net);
>> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> 
>> +	u8 *m_filter = ((u8 *)dev->data) + 12;
> 
> Please could you explain is.

Oh, that was a legacy code, the idea is it used spare area in dev->data array to
keep permanently 8 bytes for mcast filter request.

But the truth is usbnet_write anyway preallocates the data buffer and copies the data in there.

Therefore its really better to just allocate m_filter on stack to make the code clean.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,14/19] net: usb: aqc111: Implement set_rx_mode callback
@ 2018-10-08 13:49       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 13:49 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>> +{
>> +	struct usbnet *dev = netdev_priv(net);
>> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> 
>> +	u8 *m_filter = ((u8 *)dev->data) + 12;
> 
> Please could you explain is.

Oh, that was a legacy code, the idea is it used spare area in dev->data array to
keep permanently 8 bytes for mcast filter request.

But the truth is usbnet_write anyway preallocates the data buffer and copies the data in there.

Therefore its really better to just allocate m_filter on stack to make the code clean.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 13:52     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:52 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Implement PHY power up/down sequences.
> AQC111, depending on FW used, may has PHY being controlled either
> directly (dpa = 1) or via vendor command interface (dpa = 0).
> Drivers supports both themes.
> We determine this from firmware versioning agreement.
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/usb/aqc111.h | 70 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 163 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 22bb259d71fb..30219bb6ddfd 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -138,15 +138,44 @@ static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
>  	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
>  }
>  
> +static int aq_mdio_read_cmd(struct usbnet *dev, u16 value, u16 index,
> +			    u16 size, void *data)
> +{
> +	return aqc111_read_cmd(dev, AQ_PHY_CMD, value, index, size, data);
> +}
> +
> +static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
> +			     u16 size, void *data)
> +{
> +	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
> +}
> +
>  static const struct net_device_ops aqc111_netdev_ops = {
>  	.ndo_open		= usbnet_open,
>  	.ndo_stop		= usbnet_stop,
>  };
>  
> +static void aqc111_read_fw_version(struct usbnet *dev,
> +				   struct aqc111_data *aqc111_data)
> +{
> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
> +			1, 1, &aqc111_data->fw_ver.major);
> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
> +			1, 1, &aqc111_data->fw_ver.minor);
> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
> +			1, 1, &aqc111_data->fw_ver.rev);

Why read the stuff you don't need?

> +
> +	if (aqc111_data->fw_ver.major & 0x80)
> +		aqc111_data->fw_ver.major &= ~0x80;
> +	else
> +		aqc111_data->dpa = 1;
> +}
> +
>  static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  {
>  	int ret;
>  	struct usb_device *udev = interface_to_usbdev(intf);
> +	struct aqc111_data *aqc111_data;
>  
>  	/* Check if vendor configuration */
>  	if (udev->actconfig->desc.bConfigurationValue != 1) {
> @@ -162,8 +191,18 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  		return ret;
>  	}
>  
> +	aqc111_data = kzalloc(sizeof(*aqc111_data), GFP_KERNEL);
> +	if (!aqc111_data)
> +		return -ENOMEM;
> +
> +	/* store aqc111_data pointer in device data field */
> +	dev->data[0] = (unsigned long)aqc111_data;
> +	memset(aqc111_data, 0, sizeof(*aqc111_data));

Either kzalloc() or a memset. Not both.
> +
>  	dev->net->netdev_ops = &aqc111_netdev_ops;
>  
> +	aqc111_read_fw_version(dev, aqc111_data);
> +
>  	return 0;
>  }

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 13:52     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:52 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Implement PHY power up/down sequences.
> AQC111, depending on FW used, may has PHY being controlled either
> directly (dpa = 1) or via vendor command interface (dpa = 0).
> Drivers supports both themes.
> We determine this from firmware versioning agreement.
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/usb/aqc111.h | 70 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 163 insertions(+)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 22bb259d71fb..30219bb6ddfd 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -138,15 +138,44 @@ static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value,
>  	return __aqc111_write_cmd(dev, cmd, value, index, size, data, 0);
>  }
>  
> +static int aq_mdio_read_cmd(struct usbnet *dev, u16 value, u16 index,
> +			    u16 size, void *data)
> +{
> +	return aqc111_read_cmd(dev, AQ_PHY_CMD, value, index, size, data);
> +}
> +
> +static int aq_mdio_write_cmd(struct usbnet *dev, u16 value, u16 index,
> +			     u16 size, void *data)
> +{
> +	return aqc111_write_cmd(dev, AQ_PHY_CMD, value, index, size, data);
> +}
> +
>  static const struct net_device_ops aqc111_netdev_ops = {
>  	.ndo_open		= usbnet_open,
>  	.ndo_stop		= usbnet_stop,
>  };
>  
> +static void aqc111_read_fw_version(struct usbnet *dev,
> +				   struct aqc111_data *aqc111_data)
> +{
> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
> +			1, 1, &aqc111_data->fw_ver.major);
> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
> +			1, 1, &aqc111_data->fw_ver.minor);
> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
> +			1, 1, &aqc111_data->fw_ver.rev);

Why read the stuff you don't need?

> +
> +	if (aqc111_data->fw_ver.major & 0x80)
> +		aqc111_data->fw_ver.major &= ~0x80;
> +	else
> +		aqc111_data->dpa = 1;
> +}
> +
>  static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  {
>  	int ret;
>  	struct usb_device *udev = interface_to_usbdev(intf);
> +	struct aqc111_data *aqc111_data;
>  
>  	/* Check if vendor configuration */
>  	if (udev->actconfig->desc.bConfigurationValue != 1) {
> @@ -162,8 +191,18 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  		return ret;
>  	}
>  
> +	aqc111_data = kzalloc(sizeof(*aqc111_data), GFP_KERNEL);
> +	if (!aqc111_data)
> +		return -ENOMEM;
> +
> +	/* store aqc111_data pointer in device data field */
> +	dev->data[0] = (unsigned long)aqc111_data;
> +	memset(aqc111_data, 0, sizeof(*aqc111_data));

Either kzalloc() or a memset. Not both.
> +
>  	dev->net->netdev_ops = &aqc111_netdev_ops;
>  
> +	aqc111_read_fw_version(dev, aqc111_data);
> +
>  	return 0;
>  }

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08 13:59     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:59 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> +static void aqc111_configure_rx(struct usbnet *dev,
> +				struct aqc111_data *aqc111_data)
> +{
> +	u8 reg8 = 0;
> +	u8 queue_num = 0;
> +	u16 reg16 = 0;
> +	u16 link_speed = 0, usb_host = 0;
> +	u8 buf[5] = { 0 };

DMA on stack.

> +	enum usb_device_speed usb_speed = dev->udev->speed;
> +
> +	buf[0] = 0x00;
> +	buf[1] = 0xF8;
> +	buf[2] = 0x07;
> +	switch (aqc111_data->link_speed) {
> +	case AQ_INT_SPEED_5G:
> +	{
> +		link_speed = 5000;
> +		reg8 = 0x05;
> +		reg16 = 0x001F;
> +		break;
> +	}
> +	case AQ_INT_SPEED_2_5G:
> +	{
> +		link_speed = 2500;
> +		reg16 = 0x003F;
> +		break;
> +	}
> +	case AQ_INT_SPEED_1G:
> +	{
> +		link_speed = 1000;
> +		reg16 = 0x009F;
> +		break;
> +	}
> +	case AQ_INT_SPEED_100M:
> +	{
> +		link_speed = 100;
> +		queue_num = 1;
> +		reg16 = 0x063F;
> +		buf[1] = 0xFB;
> +		buf[2] = 0x4;
> +		break;
> +	}
> +	}
> +
> +	if (aqc111_data->dpa) {
> +		/* Set Phy Flow control */
> +		aq_mdio_write_cmd(dev, AQ_GLB_ING_PAUSE_CTRL_REG,
> +				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
> +		aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
> +				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
> +	}
> +
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
> +			 1, 1, &reg8);
> +
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TX_PAUSE_RESEND_T, 3, 3, buf);
> +
> +	switch (usb_speed) {

Needs to handle all speeds. And please add a comment explaining the
rationale.

> +	case USB_SPEED_SUPER:
> +	{
> +		usb_host = 3;
> +		break;
> +	}
> +	case USB_SPEED_HIGH:
> +	{
> +		usb_host = 2;
> +		break;
> +	}
> +	case USB_SPEED_FULL:
> +	case USB_SPEED_LOW:
> +	{
> +		usb_host = 1;
> +		queue_num = 0;
> +		break;
> +	}
> +	default:
> +	{
> +		usb_host = 0;
> +		break;
> +	}
> +	}
> +
> +	memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5);
> +	/* RX bulk configuration */
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf);
> +
> +	/* Set high low water level */
> +	reg16 = 0x0810;
> +
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
> +			 2, 2, &reg16);
> +	netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host);
> +}

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,06/19] net: usb: aqc111: Introduce link management
@ 2018-10-08 13:59     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 13:59 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> +static void aqc111_configure_rx(struct usbnet *dev,
> +				struct aqc111_data *aqc111_data)
> +{
> +	u8 reg8 = 0;
> +	u8 queue_num = 0;
> +	u16 reg16 = 0;
> +	u16 link_speed = 0, usb_host = 0;
> +	u8 buf[5] = { 0 };

DMA on stack.

> +	enum usb_device_speed usb_speed = dev->udev->speed;
> +
> +	buf[0] = 0x00;
> +	buf[1] = 0xF8;
> +	buf[2] = 0x07;
> +	switch (aqc111_data->link_speed) {
> +	case AQ_INT_SPEED_5G:
> +	{
> +		link_speed = 5000;
> +		reg8 = 0x05;
> +		reg16 = 0x001F;
> +		break;
> +	}
> +	case AQ_INT_SPEED_2_5G:
> +	{
> +		link_speed = 2500;
> +		reg16 = 0x003F;
> +		break;
> +	}
> +	case AQ_INT_SPEED_1G:
> +	{
> +		link_speed = 1000;
> +		reg16 = 0x009F;
> +		break;
> +	}
> +	case AQ_INT_SPEED_100M:
> +	{
> +		link_speed = 100;
> +		queue_num = 1;
> +		reg16 = 0x063F;
> +		buf[1] = 0xFB;
> +		buf[2] = 0x4;
> +		break;
> +	}
> +	}
> +
> +	if (aqc111_data->dpa) {
> +		/* Set Phy Flow control */
> +		aq_mdio_write_cmd(dev, AQ_GLB_ING_PAUSE_CTRL_REG,
> +				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
> +		aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
> +				  AQ_PHY_AUTONEG_ADDR, 2, &reg16);
> +	}
> +
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
> +			 1, 1, &reg8);
> +
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TX_PAUSE_RESEND_T, 3, 3, buf);
> +
> +	switch (usb_speed) {

Needs to handle all speeds. And please add a comment explaining the
rationale.

> +	case USB_SPEED_SUPER:
> +	{
> +		usb_host = 3;
> +		break;
> +	}
> +	case USB_SPEED_HIGH:
> +	{
> +		usb_host = 2;
> +		break;
> +	}
> +	case USB_SPEED_FULL:
> +	case USB_SPEED_LOW:
> +	{
> +		usb_host = 1;
> +		queue_num = 0;
> +		break;
> +	}
> +	default:
> +	{
> +		usb_host = 0;
> +		break;
> +	}
> +	}
> +
> +	memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5);
> +	/* RX bulk configuration */
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf);
> +
> +	/* Set high low water level */
> +	reg16 = 0x0810;
> +
> +	aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW,
> +			 2, 2, &reg16);
> +	netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host);
> +}

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 14:07           ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 14:07 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov


Hi Andrew,

>>>> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
>>>
>>> Having to do this cast all the time is quiet ugly. It seems like some
>>> other usb_net drivers use netdev_priv().
>>
>> As I see most of usb usbnet based devices use the same theme with accessing
>> private data via dev->data.
> 
> It is just ugly. It would of been better if dev->data[] was a void
> pointer. This is the first usbnet driver i've reviewed, so i don't
> know the history behind this. I wonder if adding a void *priv would be
> accepted?

I can't comment on history of this, but...

net-next/drivers/net/usb$ grep "dev->data" * | wc -l
173

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 14:07           ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 14:07 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>>>> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
>>>
>>> Having to do this cast all the time is quiet ugly. It seems like some
>>> other usb_net drivers use netdev_priv().
>>
>> As I see most of usb usbnet based devices use the same theme with accessing
>> private data via dev->data.
> 
> It is just ugly. It would of been better if dev->data[] was a void
> pointer. This is the first usbnet driver i've reviewed, so i don't
> know the history behind this. I wonder if adding a void *priv would be
> accepted?

I can't comment on history of this, but...

net-next/drivers/net/usb$ grep "dev->data" * | wc -l
173

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-08 14:07         ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:07 UTC (permalink / raw)
  To: Igor Russkikh, Andrew Lunn
  Cc: Dmitry Bezrukov, David S . Miller, linux-usb, netdev

On Mo, 2018-10-08 at 13:43 +0000, Igor Russkikh wrote:
> > > +	skb_push(skb, AQ_TX_HEADER_SIZE);
> > > +	cpu_to_le64s(&tx_hdr);
> > 
> > Is that portable? tx_hdr is a structure of 2x u32 bitfields.  What
> > endian have you tested that one?
> > 
> 
> You are right, this is wrong for BE hardware.
> 
> We don't have such a hardware to check unfortunately.
> Think its better to drop endianess conversions and declare
> the driver as little endian only.
> 
> Do you think that'll be acceptable?

No. If worse comes to worse define it u64 and set the values
manually.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-08 14:07         ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:07 UTC (permalink / raw)
  To: Igor Russkikh, Andrew Lunn
  Cc: Dmitry Bezrukov, David S . Miller, linux-usb, netdev

On Mo, 2018-10-08 at 13:43 +0000, Igor Russkikh wrote:
> > > +	skb_push(skb, AQ_TX_HEADER_SIZE);
> > > +	cpu_to_le64s(&tx_hdr);
> > 
> > Is that portable? tx_hdr is a structure of 2x u32 bitfields.  What
> > endian have you tested that one?
> > 
> 
> You are right, this is wrong for BE hardware.
> 
> We don't have such a hardware to check unfortunately.
> Think its better to drop endianess conversions and declare
> the driver as little endian only.
> 
> Do you think that'll be acceptable?

No. If worse comes to worse define it u64 and set the values
manually.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 14:10       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 14:10 UTC (permalink / raw)
  To: Oliver Neukum, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

Hi Oliver,

>> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
>> +			1, 1, &aqc111_data->fw_ver.major);
>> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
>> +			1, 1, &aqc111_data->fw_ver.minor);
>> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
>> +			1, 1, &aqc111_data->fw_ver.rev);
> 
> Why read the stuff you don't need?

fw_ver is used below to determine phy access mode.

fw_ver.rev is not used in this exact patch, thats true,
but it gets reported in later patches in the set.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 14:10       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 14:10 UTC (permalink / raw)
  To: Oliver Neukum, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

Hi Oliver,

>> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
>> +			1, 1, &aqc111_data->fw_ver.major);
>> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
>> +			1, 1, &aqc111_data->fw_ver.minor);
>> +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
>> +			1, 1, &aqc111_data->fw_ver.rev);
> 
> Why read the stuff you don't need?

fw_ver is used below to determine phy access mode.

fw_ver.rev is not used in this exact patch, thats true,
but it gets reported in later patches in the set.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 13/19] net: usb: aqc111: Add support for TSO
@ 2018-10-08 14:12     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:12 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:25 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 3 +++
>  drivers/net/usb/aqc111.h | 6 ++++--
>  2 files changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 6efd9a9ad44e..f61fa7446b72 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -964,6 +964,9 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
>  	/*Length of actual data*/
>  	tx_hdr.length = (skb->len & 0x1FFFFF);
>  
> +	/* TSO MSS */
> +	tx_hdr.max_seg_size = skb_shinfo(skb)->gso_size;

Endianness
> +
>  	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
>  	if (headroom != 0)
>  		padding_size = 8 - headroom;

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,13/19] net: usb: aqc111: Add support for TSO
@ 2018-10-08 14:12     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:12 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:25 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 3 +++
>  drivers/net/usb/aqc111.h | 6 ++++--
>  2 files changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index 6efd9a9ad44e..f61fa7446b72 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -964,6 +964,9 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
>  	/*Length of actual data*/
>  	tx_hdr.length = (skb->len & 0x1FFFFF);
>  
> +	/* TSO MSS */
> +	tx_hdr.max_seg_size = skb_shinfo(skb)->gso_size;

Endianness
> +
>  	headroom = (skb->len + AQ_TX_HEADER_SIZE) % 8;
>  	if (headroom != 0)
>  		padding_size = 8 - headroom;

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-08 14:12       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 14:12 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>> +		if (aqc111_data->dpa) {
>> +			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);
> 
> I don't think that works. You should leave AUTONEG on, but only
> advertise SPEED_100 and trigger auto-neg. If you force it to 100,
> there is no guarantee the peer will figure out what the new link speed
> is. I've often seen failed auto-net result in 10/Half. So you will
> loose the link, making WoL pointless.

Phy does not support 10M, low power mode explicitly uses 100M
for power safety reasons.

It is meaningless here to add Autoneg to 100M because thats the only
speedmask bit anyway.


>> +	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
>> +			     aqc111_data->advertised_speed);
>> +
> 
> Should that be conditional on aqc111_data->dpa?

Actually no, because set_phy_speed internally checks this flag.

>> +	u8 rsvd[283];
>> +};
> 
> Do you really need these 283 bytes??

>>  	struct aqc111_phy_options phy_ops;
>> +	struct aqc111_wol_cfg wol_cfg;
> 
> Those 283 bytes make this whole structure bigger...

FW interface expects the WOL config request WOL_CFG_SIZE bytes.
These reserved fields are just not used now by linux driver.
They configure extra wol features like a sleep proxy.
Thus, we anyway have to allocate this somewhere.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-08 14:12       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 14:12 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>> +		if (aqc111_data->dpa) {
>> +			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);
> 
> I don't think that works. You should leave AUTONEG on, but only
> advertise SPEED_100 and trigger auto-neg. If you force it to 100,
> there is no guarantee the peer will figure out what the new link speed
> is. I've often seen failed auto-net result in 10/Half. So you will
> loose the link, making WoL pointless.

Phy does not support 10M, low power mode explicitly uses 100M
for power safety reasons.

It is meaningless here to add Autoneg to 100M because thats the only
speedmask bit anyway.


>> +	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
>> +			     aqc111_data->advertised_speed);
>> +
> 
> Should that be conditional on aqc111_data->dpa?

Actually no, because set_phy_speed internally checks this flag.

>> +	u8 rsvd[283];
>> +};
> 
> Do you really need these 283 bytes??

>>  	struct aqc111_phy_options phy_ops;
>> +	struct aqc111_wol_cfg wol_cfg;
> 
> Those 283 bytes make this whole structure bigger...

FW interface expects the WOL config request WOL_CFG_SIZE bytes.
These reserved fields are just not used now by linux driver.
They configure extra wol features like a sleep proxy.
Thus, we anyway have to allocate this somewhere.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 15/19] net: usb: aqc111: Add support for VLAN_CTAG_TX/RX offload
@ 2018-10-08 14:14     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:14 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:25 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 14 ++++++++++++++
>  drivers/net/usb/aqc111.h |  7 ++++++-
>  2 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index cc23c39beab3..a9051dd7c5bd 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -524,6 +524,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  
>  	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
>  	dev->net->features |= AQ_SUPPORT_FEATURE;
> +	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
>  
>  	aqc111_read_fw_version(dev, aqc111_data);
>  	aqc111_data->autoneg = AUTONEG_ENABLE;
> @@ -817,6 +818,7 @@ static int aqc111_reset(struct usbnet *dev)
>  
>  	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
>  	dev->net->features |= AQ_SUPPORT_FEATURE;
> +	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
>  
>  	/* Power up ethernet PHY */
>  	aqc111_data->phy_ops.advertising = 0;
> @@ -992,6 +994,11 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>  		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
>  		if (aqc111_data->rx_checksum)
>  			aqc111_rx_checksum(new_skb, &pkt_desc);
> +		if (pkt_desc->vlan_ind)
> +			__vlan_hwaccel_put_tag(new_skb,
> +					       htons(ETH_P_8021Q),
> +					       pkt_desc->vlan_tag &
> +					       VLAN_VID_MASK);
>  
>  		usbnet_skb_return(dev, new_skb);
>  		if (pkt_count == 0)
> @@ -1020,6 +1027,7 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
>  	int tailroom = 0;
>  	int padding_size = 0;
>  	struct sk_buff *new_skb = NULL;
> +	u16 tci = 0;
>  
>  	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
>  
> @@ -1038,6 +1046,12 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
>  		tx_hdr.drop_padding = 1;
>  	}
>  
> +	/* Vlan Tag */
> +	if (vlan_get_tag(skb, &tci) >= 0) {
> +		tx_hdr.vlan_tag = 1;
> +		tx_hdr.vlan_info = tci;

Endianness

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,15/19] net: usb: aqc111: Add support for VLAN_CTAG_TX/RX offload
@ 2018-10-08 14:14     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:14 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:25 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---
>  drivers/net/usb/aqc111.c | 14 ++++++++++++++
>  drivers/net/usb/aqc111.h |  7 ++++++-
>  2 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> index cc23c39beab3..a9051dd7c5bd 100644
> --- a/drivers/net/usb/aqc111.c
> +++ b/drivers/net/usb/aqc111.c
> @@ -524,6 +524,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>  
>  	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
>  	dev->net->features |= AQ_SUPPORT_FEATURE;
> +	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
>  
>  	aqc111_read_fw_version(dev, aqc111_data);
>  	aqc111_data->autoneg = AUTONEG_ENABLE;
> @@ -817,6 +818,7 @@ static int aqc111_reset(struct usbnet *dev)
>  
>  	dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE;
>  	dev->net->features |= AQ_SUPPORT_FEATURE;
> +	dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE;
>  
>  	/* Power up ethernet PHY */
>  	aqc111_data->phy_ops.advertising = 0;
> @@ -992,6 +994,11 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
>  		new_skb->truesize = new_skb->len + sizeof(struct sk_buff);
>  		if (aqc111_data->rx_checksum)
>  			aqc111_rx_checksum(new_skb, &pkt_desc);
> +		if (pkt_desc->vlan_ind)
> +			__vlan_hwaccel_put_tag(new_skb,
> +					       htons(ETH_P_8021Q),
> +					       pkt_desc->vlan_tag &
> +					       VLAN_VID_MASK);
>  
>  		usbnet_skb_return(dev, new_skb);
>  		if (pkt_count == 0)
> @@ -1020,6 +1027,7 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
>  	int tailroom = 0;
>  	int padding_size = 0;
>  	struct sk_buff *new_skb = NULL;
> +	u16 tci = 0;
>  
>  	memset(&tx_hdr, 0x00, sizeof(tx_hdr));
>  
> @@ -1038,6 +1046,12 @@ static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
>  		tx_hdr.drop_padding = 1;
>  	}
>  
> +	/* Vlan Tag */
> +	if (vlan_get_tag(skb, &tci) >= 0) {
> +		tx_hdr.vlan_tag = 1;
> +		tx_hdr.vlan_info = tci;

Endianness

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks
@ 2018-10-08 14:18     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:18 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:25 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> +static int aqc111_get_link_ksettings(struct net_device *net,
> +				     struct ethtool_link_ksettings *elk)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	enum usb_device_speed usb_speed = dev->udev->speed;
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> +	u32 speed = SPEED_UNKNOWN;
> +
> +	ethtool_link_ksettings_zero_link_mode(elk, supported);
> +	ethtool_link_ksettings_add_link_mode(elk, supported,
> +					     100baseT_Full);
> +	ethtool_link_ksettings_add_link_mode(elk, supported,
> +					     1000baseT_Full);
> +	if (usb_speed == USB_SPEED_SUPER) {

And SUPER_PLUS?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks
@ 2018-10-08 14:18     ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:18 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Fr, 2018-10-05 at 10:25 +0000, Igor Russkikh wrote:
> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> 
> +static int aqc111_get_link_ksettings(struct net_device *net,
> +				     struct ethtool_link_ksettings *elk)
> +{
> +	struct usbnet *dev = netdev_priv(net);
> +	enum usb_device_speed usb_speed = dev->udev->speed;
> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> +	u32 speed = SPEED_UNKNOWN;
> +
> +	ethtool_link_ksettings_zero_link_mode(elk, supported);
> +	ethtool_link_ksettings_add_link_mode(elk, supported,
> +					     100baseT_Full);
> +	ethtool_link_ksettings_add_link_mode(elk, supported,
> +					     1000baseT_Full);
> +	if (usb_speed == USB_SPEED_SUPER) {

And SUPER_PLUS?

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices
  2018-10-05 10:24 [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices Igor Russkikh
                   ` (19 preceding siblings ...)
  2018-10-06 17:51 ` [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices Andrew Lunn
@ 2018-10-08 14:21 ` Oliver Neukum
  2018-10-08 14:52   ` Igor Russkikh
  20 siblings, 1 reply; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:21 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: linux-usb, netdev

On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> This patchset introduces support for new multigig ethernet to USB dongle,
> developed jointly by Aquantia (Phy) and ASIX (USB MAC).
> 
> The driver has similar structure with other ASIX MAC drivers (AX88179), but
> with a number of important differences:
> - Driver supports both direct Phy and custom firmware interface for Phy
>   programming. This is due to different firmware modules available with this
>   product.
> - Driver handles new 2.5G/5G link speed configuration and reporting.
> - Device support all speeds from 100M up to 5G.
> - Device supports MTU up to 16K.
> 
> Device supports various standard networking features, like
> checksum offloads, vlan tagging/filtering, TSO.
> 
> The code of this driver is based on original ASIX sources and was extended
> by Aquantia for 5G multigig support. 

Thank you for the driver. It is good to see drivers for cool hardware.
Unfortunately there have been a few issues I have tried to point out
in reviews. Please fix them and resubmit.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 14:24         ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:24 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Mo, 2018-10-08 at 17:10 +0300, Igor Russkikh wrote:
> Hi Oliver,
> 
> > > +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
> > > +			1, 1, &aqc111_data->fw_ver.major);
> > > +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
> > > +			1, 1, &aqc111_data->fw_ver.minor);
> > > +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
> > > +			1, 1, &aqc111_data->fw_ver.rev);
> > 
> > Why read the stuff you don't need?
> 
> fw_ver is used below to determine phy access mode.
> 
> fw_ver.rev is not used in this exact patch, thats true,
> but it gets reported in later patches in the set.

Hi,

OK that makes sense.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-08 14:24         ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-08 14:24 UTC (permalink / raw)
  To: Igor Russkikh, David S . Miller; +Cc: Dmitry Bezrukov, linux-usb, netdev

On Mo, 2018-10-08 at 17:10 +0300, Igor Russkikh wrote:
> Hi Oliver,
> 
> > > +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR,
> > > +			1, 1, &aqc111_data->fw_ver.major);
> > > +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR,
> > > +			1, 1, &aqc111_data->fw_ver.minor);
> > > +	aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV,
> > > +			1, 1, &aqc111_data->fw_ver.rev);
> > 
> > Why read the stuff you don't need?
> 
> fw_ver is used below to determine phy access mode.
> 
> fw_ver.rev is not used in this exact patch, thats true,
> but it gets reported in later patches in the set.

Hi,

OK that makes sense.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-08 14:47         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-08 14:47 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 02:12:59PM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >> +		if (aqc111_data->dpa) {
> >> +			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);
> > 
> > I don't think that works. You should leave AUTONEG on, but only
> > advertise SPEED_100 and trigger auto-neg. If you force it to 100,
> > there is no guarantee the peer will figure out what the new link speed
> > is. I've often seen failed auto-net result in 10/Half. So you will
> > loose the link, making WoL pointless.
> 
> Phy does not support 10M, low power mode explicitly uses 100M
> for power safety reasons.
> 
> It is meaningless here to add Autoneg to 100M because thats the only
> speedmask bit anyway.

If you have AUTONEG_DISABLE, i would assume you PHY is not even trying
to auto_neg. So the speedmask is irrelevent, it is not sent to the
peer. And since the peer is not receiving any auto-neg information, it
will fail to auto-neg, and most likely default to 10/Half.

To do this right, please take a look at this commit

commit 2b9672ddb6f347467d7b33b86c5dfc4d5c0501a8
Author: Heiner Kallweit <hkallweit1@gmail.com>
Date:   Thu Jul 12 21:32:53 2018 +0200

    net: phy: add phy_speed_down and phy_speed_up
    
    Some network drivers include functionality to speed down the PHY when
    suspending and just waiting for a WoL packet because this saves energy.
    This functionality is quite generic, therefore let's factor it out to
    phylib.
    
> 
> >> +	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> >> +			     aqc111_data->advertised_speed);
> >> +
> > 
> > Should that be conditional on aqc111_data->dpa?
> 
> Actually no, because set_phy_speed internally checks this flag.

So you should probably remove the check above when forcing the speed
to 100. Make the code symmetrical. 

> 
> >> +	u8 rsvd[283];
> >> +};
> > 
> > Do you really need these 283 bytes??
> 
> >>  	struct aqc111_phy_options phy_ops;
> >> +	struct aqc111_wol_cfg wol_cfg;
> > 
> > Those 283 bytes make this whole structure bigger...
> 
> FW interface expects the WOL config request WOL_CFG_SIZE bytes.
> These reserved fields are just not used now by linux driver.
> They configure extra wol features like a sleep proxy.
> Thus, we anyway have to allocate this somewhere.

Well, i think your low level function for actually sending a command
does a dup before sending. You don't actually send this, you send a
copy. Maybe you can pad it out then?

      Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
@ 2018-10-08 14:47         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-08 14:47 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 02:12:59PM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >> +		if (aqc111_data->dpa) {
> >> +			aqc111_set_phy_speed(dev, AUTONEG_DISABLE, SPEED_100);
> > 
> > I don't think that works. You should leave AUTONEG on, but only
> > advertise SPEED_100 and trigger auto-neg. If you force it to 100,
> > there is no guarantee the peer will figure out what the new link speed
> > is. I've often seen failed auto-net result in 10/Half. So you will
> > loose the link, making WoL pointless.
> 
> Phy does not support 10M, low power mode explicitly uses 100M
> for power safety reasons.
> 
> It is meaningless here to add Autoneg to 100M because thats the only
> speedmask bit anyway.

If you have AUTONEG_DISABLE, i would assume you PHY is not even trying
to auto_neg. So the speedmask is irrelevent, it is not sent to the
peer. And since the peer is not receiving any auto-neg information, it
will fail to auto-neg, and most likely default to 10/Half.

To do this right, please take a look at this commit

commit 2b9672ddb6f347467d7b33b86c5dfc4d5c0501a8
Author: Heiner Kallweit <hkallweit1@gmail.com>
Date:   Thu Jul 12 21:32:53 2018 +0200

    net: phy: add phy_speed_down and phy_speed_up
    
    Some network drivers include functionality to speed down the PHY when
    suspending and just waiting for a WoL packet because this saves energy.
    This functionality is quite generic, therefore let's factor it out to
    phylib.
    
> 
> >> +	aqc111_set_phy_speed(dev, aqc111_data->autoneg,
> >> +			     aqc111_data->advertised_speed);
> >> +
> > 
> > Should that be conditional on aqc111_data->dpa?
> 
> Actually no, because set_phy_speed internally checks this flag.

So you should probably remove the check above when forcing the speed
to 100. Make the code symmetrical. 

> 
> >> +	u8 rsvd[283];
> >> +};
> > 
> > Do you really need these 283 bytes??
> 
> >>  	struct aqc111_phy_options phy_ops;
> >> +	struct aqc111_wol_cfg wol_cfg;
> > 
> > Those 283 bytes make this whole structure bigger...
> 
> FW interface expects the WOL config request WOL_CFG_SIZE bytes.
> These reserved fields are just not used now by linux driver.
> They configure extra wol features like a sleep proxy.
> Thus, we anyway have to allocate this somewhere.

Well, i think your low level function for actually sending a command
does a dup before sending. You don't actually send this, you send a
copy. Maybe you can pad it out then?

      Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices
  2018-10-08 14:21 ` Oliver Neukum
@ 2018-10-08 14:52   ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-08 14:52 UTC (permalink / raw)
  To: Oliver Neukum, David S . Miller; +Cc: linux-usb, netdev, Dmitry Bezrukov



On 08.10.2018 17:21, Oliver Neukum wrote:

>> The code of this driver is based on original ASIX sources and was extended
>> by Aquantia for 5G multigig support. 
> 
> Thank you for the driver. It is good to see drivers for cool hardware.
> Unfortunately there have been a few issues I have tried to point out
> in reviews. Please fix them and resubmit.
> 

Thank you Oliver for valuable input, working on this already.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-09 13:27       ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:27 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Igor Russkikh, David S . Miller, Dmitry Bezrukov, linux-usb, netdev

Oliver Neukum <oneukum@suse.com> writes:

> On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
>> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
>> 
>> Reset, stop callbacks, driver unbind callback.
>> More register defines required for these callbacks.
>> 
>> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
>> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
>> ---
>>  drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
>>  drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 149 insertions(+)
>> 
>> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
>> index 7f3e5a615750..22bb259d71fb 100644
>> --- a/drivers/net/usb/aqc111.c
>> +++ b/drivers/net/usb/aqc111.c
>> @@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>>  
>>  static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>>  {
>> +	u8 reg8;
>> +	u16 reg16;
>> +
>> +	/* Force bz */
>> +	reg16 = SFR_PHYPWR_RSTCTL_BZ;
>> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
>> +			      2, 2, &reg16);
>
> No, I am sorry, you are doing DMA on the kernel stack. That is not
> allowed. These functions will all have to be fixed.

Huh?  No, he doesn't.  That's the whole point with
usbnet_read_cmd_nopm(), isn't it?



Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-09 13:27       ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:27 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Igor Russkikh, David S . Miller, Dmitry Bezrukov, linux-usb, netdev

Oliver Neukum <oneukum@suse.com> writes:

> On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
>> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
>> 
>> Reset, stop callbacks, driver unbind callback.
>> More register defines required for these callbacks.
>> 
>> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
>> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
>> ---
>>  drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
>>  drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 149 insertions(+)
>> 
>> diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
>> index 7f3e5a615750..22bb259d71fb 100644
>> --- a/drivers/net/usb/aqc111.c
>> +++ b/drivers/net/usb/aqc111.c
>> @@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
>>  
>>  static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
>>  {
>> +	u8 reg8;
>> +	u16 reg16;
>> +
>> +	/* Force bz */
>> +	reg16 = SFR_PHYPWR_RSTCTL_BZ;
>> +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
>> +			      2, 2, &reg16);
>
> No, I am sorry, you are doing DMA on the kernel stack. That is not
> allowed. These functions will all have to be fixed.

Huh?  No, he doesn't.  That's the whole point with
usbnet_read_cmd_nopm(), isn't it?



Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-09 13:33     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:33 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

> +static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			     u16 index, u16 size, void *data, int nopm)
> +{
> +	int ret;
> +	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
> +		  u16 index, void *data, u16 size);
> +
> +	if (nopm)
> +		fn = usbnet_read_cmd_nopm;
> +	else
> +		fn = usbnet_read_cmd;
> +
> +	ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +		 value, index, data, size);
> +	if (size == 2)
> +		le16_to_cpus(data);
> +
> +	if (unlikely(ret < 0))
> +		netdev_warn(dev->net,
> +			    "Failed to read(0x%x) reg index 0x%04x: %d\n",
> +			    cmd, index, ret);
> +	return ret;
> +}
> +
> +static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
> +				u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 1);
> +}
> +
> +static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			   u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 0);
> +}
> +

Why would you want to do something like this instead of simply
implementing aqc111_read_cmd_nopm() and aqc111_read_cmd() as separate
functions?  The function pointer stuff is incredibly ugly, as Oliver
pointed out.  It wasn't done like that in usbnet.c, so why should we do
it like that here?

And the "if (size == 2) le16_to_cpus(data)" looks like something that
will come back and haunt you.  Will this code never read larger
integers?  Maybe add some sanity checks then, just in case...

Or simply add more helpers.  An additional pair of helpers for reading
16bit integers might simplify your code quite a bit.


Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,03/19] net: usb: aqc111: Add implementation of read and write commands
@ 2018-10-09 13:33     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:33 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

> +static int __aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			     u16 index, u16 size, void *data, int nopm)
> +{
> +	int ret;
> +	int (*fn)(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value,
> +		  u16 index, void *data, u16 size);
> +
> +	if (nopm)
> +		fn = usbnet_read_cmd_nopm;
> +	else
> +		fn = usbnet_read_cmd;
> +
> +	ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> +		 value, index, data, size);
> +	if (size == 2)
> +		le16_to_cpus(data);
> +
> +	if (unlikely(ret < 0))
> +		netdev_warn(dev->net,
> +			    "Failed to read(0x%x) reg index 0x%04x: %d\n",
> +			    cmd, index, ret);
> +	return ret;
> +}
> +
> +static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
> +				u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 1);
> +}
> +
> +static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
> +			   u16 index, u16 size, void *data)
> +{
> +	return __aqc111_read_cmd(dev, cmd, value, index, size, data, 0);
> +}
> +

Why would you want to do something like this instead of simply
implementing aqc111_read_cmd_nopm() and aqc111_read_cmd() as separate
functions?  The function pointer stuff is incredibly ugly, as Oliver
pointed out.  It wasn't done like that in usbnet.c, so why should we do
it like that here?

And the "if (size == 2) le16_to_cpus(data)" looks like something that
will come back and haunt you.  Will this code never read larger
integers?  Maybe add some sanity checks then, just in case...

Or simply add more helpers.  An additional pair of helpers for reading
16bit integers might simplify your code quite a bit.


Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 01/19] net: usb: aqc111: Driver skeleton for Aquantia AQtion USB to 5GbE
@ 2018-10-09 13:37     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:37 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

>> +static const struct driver_info aqc111_info = {
> +	.description	= "Aquantia AQtion USB to 5GbE Controller",
> +};
> +
> +#define AQC111_USB_ETH_DEV(vid, pid, table) \
> +	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
> +			USB_DEVICE_ID_MATCH_INT_CLASS, \
> +	USB_DEVICE(vid, pid), \
> +	.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
> +	.driver_info = (unsigned long)&table, \
> +}, \
> +{ \
> +	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
> +			USB_DEVICE_ID_MATCH_INT_INFO, \
> +	USB_DEVICE(vid, pid), \
> +	.bInterfaceClass = USB_CLASS_COMM, \
> +	.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
> +	.bInterfaceProtocol = USB_CDC_PROTO_NONE
> +

Is the missing .driver_info for the CDC class intentional?  If so, then
why include it at all?



Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,01/19] net: usb: aqc111: Driver skeleton for Aquantia AQtion USB to 5GbE
@ 2018-10-09 13:37     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:37 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

>> +static const struct driver_info aqc111_info = {
> +	.description	= "Aquantia AQtion USB to 5GbE Controller",
> +};
> +
> +#define AQC111_USB_ETH_DEV(vid, pid, table) \
> +	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
> +			USB_DEVICE_ID_MATCH_INT_CLASS, \
> +	USB_DEVICE(vid, pid), \
> +	.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
> +	.driver_info = (unsigned long)&table, \
> +}, \
> +{ \
> +	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
> +			USB_DEVICE_ID_MATCH_INT_INFO, \
> +	USB_DEVICE(vid, pid), \
> +	.bInterfaceClass = USB_CLASS_COMM, \
> +	.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
> +	.bInterfaceProtocol = USB_CDC_PROTO_NONE
> +

Is the missing .driver_info for the CDC class intentional?  If so, then
why include it at all?



Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 09/19] net: usb: aqc111: Implement RX data path
@ 2018-10-09 13:39     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:39 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
>
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---

You'd want some description here.



Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,09/19] net: usb: aqc111: Implement RX data path
@ 2018-10-09 13:39     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:39 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

> From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
>
> Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> ---

You'd want some description here.



Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-09 13:50     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:50 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

> +struct aq_tx_packet_desc {
> +	struct {
> +		u32 length:21;
> +		u32 checksum:7;
> +		u32 drop_padding:1;
> +		u32 vlan_tag:1;
> +		u32 cphi:1;
> +		u32 dicf:1;
> +	};
> +	struct {
> +		u32 max_seg_size:15;
> +		u32 reserved:1;
> +		u32 vlan_info:16;
> +	};
> +};


You might want to shift and mask instead to avoid going insane when
trying to use this header on a BE system...


Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,08/19] net: usb: aqc111: Implement TX data path
@ 2018-10-09 13:50     ` Bjørn Mork
  0 siblings, 0 replies; 133+ messages in thread
From: Bjørn Mork @ 2018-10-09 13:50 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Igor Russkikh <Igor.Russkikh@aquantia.com> writes:

> +struct aq_tx_packet_desc {
> +	struct {
> +		u32 length:21;
> +		u32 checksum:7;
> +		u32 drop_padding:1;
> +		u32 vlan_tag:1;
> +		u32 cphi:1;
> +		u32 dicf:1;
> +	};
> +	struct {
> +		u32 max_seg_size:15;
> +		u32 reserved:1;
> +		u32 vlan_info:16;
> +	};
> +};


You might want to shift and mask instead to avoid going insane when
trying to use this header on a BE system...


Bjørn

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-09 14:34       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-09 14:34 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>> +	if (ret < 0)
>> +		goto out;
>> +
>> +	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
>> +	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
> 
> Is this really the permanent address? If i call aqc111_set_mac_addr()
> followed by aqc111_get_mac() i still get what is in the OTP EEPROM?

Thats actually a confusion with function name here.
Think its better to name it aqc111_init_mac() since it gets called
only once on bind.

It really initializes perm_addr once, thus standard ndev callback will give
the perm mac you want.

> 
> You initialized it above as {0}. You don't need to memset it here.
> 
>> +	ret = aqc111_get_mac(dev, buf);
> 
> Do you even need to zero it? If aqc111_get_mac() fails, it will be
> left undefined, but you fail the bind anyway.

We even don't need this `buf` here at all. We'll move it into
above init_mac function.

BR, Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-09 14:34       ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-09 14:34 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

Hi Andrew,

>> +	if (ret < 0)
>> +		goto out;
>> +
>> +	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
>> +	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
> 
> Is this really the permanent address? If i call aqc111_set_mac_addr()
> followed by aqc111_get_mac() i still get what is in the OTP EEPROM?

Thats actually a confusion with function name here.
Think its better to name it aqc111_init_mac() since it gets called
only once on bind.

It really initializes perm_addr once, thus standard ndev callback will give
the perm mac you want.

> 
> You initialized it above as {0}. You don't need to memset it here.
> 
>> +	ret = aqc111_get_mac(dev, buf);
> 
> Do you even need to zero it? If aqc111_get_mac() fails, it will be
> left undefined, but you fail the bind anyway.

We even don't need this `buf` here at all. We'll move it into
above init_mac function.

BR, Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-09 14:46         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-09 14:46 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Tue, Oct 09, 2018 at 02:34:36PM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >> +	if (ret < 0)
> >> +		goto out;
> >> +
> >> +	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
> >> +	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
> > 
> > Is this really the permanent address? If i call aqc111_set_mac_addr()
> > followed by aqc111_get_mac() i still get what is in the OTP EEPROM?
> 
> Thats actually a confusion with function name here.
> Think its better to name it aqc111_init_mac() since it gets called
> only once on bind.

Hi Igor

Or aqc111_get_otp_mac()?

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,07/19] net: usb: aqc111: Add support for getting and setting of MAC address
@ 2018-10-09 14:46         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-09 14:46 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Tue, Oct 09, 2018 at 02:34:36PM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >> +	if (ret < 0)
> >> +		goto out;
> >> +
> >> +	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
> >> +	memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
> > 
> > Is this really the permanent address? If i call aqc111_set_mac_addr()
> > followed by aqc111_get_mac() i still get what is in the OTP EEPROM?
> 
> Thats actually a confusion with function name here.
> Think its better to name it aqc111_init_mac() since it gets called
> only once on bind.

Hi Igor

Or aqc111_get_otp_mac()?

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-10  0:58         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-10  0:58 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 09:09:54AM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >>  
> >> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> > 
> > Having to do this cast all the time is quiet ugly. It seems like some
> > other usb_net drivers use netdev_priv().
> 
> As I see most of usb usbnet based devices use the same theme with accessing
> private data via dev->data.

Hi Igor

I just discovered driver_priv.

https://elixir.bootlin.com/linux/v4.19-rc7/source/include/linux/usb/usbnet.h#L33

It would be good to use that, to avoid the casts.

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-10  0:58         ` Andrew Lunn
  0 siblings, 0 replies; 133+ messages in thread
From: Andrew Lunn @ 2018-10-10  0:58 UTC (permalink / raw)
  To: Igor Russkikh; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On Mon, Oct 08, 2018 at 09:09:54AM +0000, Igor Russkikh wrote:
> Hi Andrew,
> 
> >>  
> >> +	struct aqc111_data *aqc111_data = (struct aqc111_data *)dev->data[0];
> > 
> > Having to do this cast all the time is quiet ugly. It seems like some
> > other usb_net drivers use netdev_priv().
> 
> As I see most of usb usbnet based devices use the same theme with accessing
> private data via dev->data.

Hi Igor

I just discovered driver_priv.

https://elixir.bootlin.com/linux/v4.19-rc7/source/include/linux/usb/usbnet.h#L33

It would be good to use that, to avoid the casts.

   Andrew

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-10  7:54           ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-10  7:54 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov



On 10.10.2018 03:58, Andrew Lunn wrote:

> 
> I just discovered driver_priv.
> 
> https://elixir.bootlin.com/linux/v4.19-rc7/source/include/linux/usb/usbnet.h#L33
> 
> It would be good to use that, to avoid the casts.

Looks good to me, thanks.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,05/19] net: usb: aqc111: Introduce PHY access
@ 2018-10-10  7:54           ` Igor Russkikh
  0 siblings, 0 replies; 133+ messages in thread
From: Igor Russkikh @ 2018-10-10  7:54 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: David S . Miller, linux-usb, netdev, Dmitry Bezrukov

On 10.10.2018 03:58, Andrew Lunn wrote:

> 
> I just discovered driver_priv.
> 
> https://elixir.bootlin.com/linux/v4.19-rc7/source/include/linux/usb/usbnet.h#L33
> 
> It would be good to use that, to avoid the casts.

Looks good to me, thanks.

Regards,
  Igor

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH net-next 04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-10 11:33         ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-10 11:33 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Dmitry Bezrukov, Igor Russkikh, David S . Miller, linux-usb, netdev

On Di, 2018-10-09 at 15:27 +0200, Bjørn Mork  wrote:
> Oliver Neukum <oneukum@suse.com> writes:
> 
> > On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> > > From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> > > 
> > > Reset, stop callbacks, driver unbind callback.
> > > More register defines required for these callbacks.
> > > 
> > > Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> > > Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> > > ---
> > >  drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
> > >  drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 149 insertions(+)
> > > 
> > > diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> > > index 7f3e5a615750..22bb259d71fb 100644
> > > --- a/drivers/net/usb/aqc111.c
> > > +++ b/drivers/net/usb/aqc111.c
> > > @@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
> > >  
> > >  static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
> > >  {
> > > +	u8 reg8;
> > > +	u16 reg16;
> > > +
> > > +	/* Force bz */
> > > +	reg16 = SFR_PHYPWR_RSTCTL_BZ;
> > > +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
> > > +			      2, 2, &reg16);
> > 
> > No, I am sorry, you are doing DMA on the kernel stack. That is not
> > allowed. These functions will all have to be fixed.
> 
> Huh?  No, he doesn't.  That's the whole point with
> usbnet_read_cmd_nopm(), isn't it?

Right. Too many indirections for me.
Please disregard my comment.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [net-next,04/19] net: usb: aqc111: Various callbacks implementation
@ 2018-10-10 11:33         ` Oliver Neukum
  0 siblings, 0 replies; 133+ messages in thread
From: Oliver Neukum @ 2018-10-10 11:33 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Dmitry Bezrukov, Igor Russkikh, David S . Miller, linux-usb, netdev

On Di, 2018-10-09 at 15:27 +0200, Bjørn Mork  wrote:
> Oliver Neukum <oneukum@suse.com> writes:
> 
> > On Fr, 2018-10-05 at 10:24 +0000, Igor Russkikh wrote:
> > > From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> > > 
> > > Reset, stop callbacks, driver unbind callback.
> > > More register defines required for these callbacks.
> > > 
> > > Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
> > > Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
> > > ---
> > >  drivers/net/usb/aqc111.c |  48 ++++++++++++++++++++++
> > >  drivers/net/usb/aqc111.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 149 insertions(+)
> > > 
> > > diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
> > > index 7f3e5a615750..22bb259d71fb 100644
> > > --- a/drivers/net/usb/aqc111.c
> > > +++ b/drivers/net/usb/aqc111.c
> > > @@ -169,12 +169,60 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
> > >  
> > >  static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf)
> > >  {
> > > +	u8 reg8;
> > > +	u16 reg16;
> > > +
> > > +	/* Force bz */
> > > +	reg16 = SFR_PHYPWR_RSTCTL_BZ;
> > > +	aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
> > > +			      2, 2, &reg16);
> > 
> > No, I am sorry, you are doing DMA on the kernel stack. That is not
> > allowed. These functions will all have to be fixed.
> 
> Huh?  No, he doesn't.  That's the whole point with
> usbnet_read_cmd_nopm(), isn't it?

Right. Too many indirections for me.
Please disregard my comment.

	Regards
		Oliver

^ permalink raw reply	[flat|nested] 133+ messages in thread

end of thread, other threads:[~2018-10-10 19:04 UTC | newest]

Thread overview: 133+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-05 10:24 [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices Igor Russkikh
2018-10-05 10:24 ` [PATCH net-next 01/19] net: usb: aqc111: Driver skeleton for Aquantia AQtion USB to 5GbE Igor Russkikh
2018-10-05 10:24   ` [net-next,01/19] " Igor Russkikh
2018-10-09 13:37   ` [PATCH net-next 01/19] " Bjørn Mork
2018-10-09 13:37     ` [net-next,01/19] " Bjørn Mork
2018-10-05 10:24 ` [PATCH net-next 02/19] net: usb: aqc111: Add bind and empty unbind callbacks Igor Russkikh
2018-10-05 10:24   ` [net-next,02/19] " Igor Russkikh
2018-10-05 17:39   ` [PATCH net-next 02/19] " David Miller
2018-10-05 17:39     ` [net-next,02/19] " David Miller
2018-10-05 10:24 ` [PATCH net-next 03/19] net: usb: aqc111: Add implementation of read and write commands Igor Russkikh
2018-10-05 10:24   ` [net-next,03/19] " Igor Russkikh
2018-10-05 17:40   ` [PATCH net-next 03/19] " David Miller
2018-10-05 17:40     ` [net-next,03/19] " David Miller
2018-10-08 13:44   ` [PATCH net-next 03/19] " Oliver Neukum
2018-10-08 13:44     ` [net-next,03/19] " Oliver Neukum
2018-10-09 13:33   ` [PATCH net-next 03/19] " Bjørn Mork
2018-10-09 13:33     ` [net-next,03/19] " Bjørn Mork
2018-10-05 10:24 ` [PATCH net-next 04/19] net: usb: aqc111: Various callbacks implementation Igor Russkikh
2018-10-05 10:24   ` [net-next,04/19] " Igor Russkikh
2018-10-08 13:47   ` [PATCH net-next 04/19] " Oliver Neukum
2018-10-08 13:47     ` [net-next,04/19] " Oliver Neukum
2018-10-09 13:27     ` [PATCH net-next 04/19] " Bjørn Mork
2018-10-09 13:27       ` [net-next,04/19] " Bjørn Mork
2018-10-10 11:33       ` [PATCH net-next 04/19] " Oliver Neukum
2018-10-10 11:33         ` [net-next,04/19] " Oliver Neukum
2018-10-05 10:24 ` [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access Igor Russkikh
2018-10-05 10:24   ` [net-next,05/19] " Igor Russkikh
2018-10-05 22:04   ` [PATCH net-next 05/19] " Andrew Lunn
2018-10-05 22:04     ` [net-next,05/19] " Andrew Lunn
2018-10-08  9:09     ` [PATCH net-next 05/19] " Igor Russkikh
2018-10-08  9:09       ` [net-next,05/19] " Igor Russkikh
2018-10-08 12:17       ` [PATCH net-next 05/19] " Andrew Lunn
2018-10-08 12:17         ` [net-next,05/19] " Andrew Lunn
2018-10-08 14:07         ` [PATCH net-next 05/19] " Igor Russkikh
2018-10-08 14:07           ` [net-next,05/19] " Igor Russkikh
2018-10-10  0:58       ` [PATCH net-next 05/19] " Andrew Lunn
2018-10-10  0:58         ` [net-next,05/19] " Andrew Lunn
2018-10-10  7:54         ` [PATCH net-next 05/19] " Igor Russkikh
2018-10-10  7:54           ` [net-next,05/19] " Igor Russkikh
2018-10-08 13:52   ` [PATCH net-next 05/19] " Oliver Neukum
2018-10-08 13:52     ` [net-next,05/19] " Oliver Neukum
2018-10-08 14:10     ` [PATCH net-next 05/19] " Igor Russkikh
2018-10-08 14:10       ` [net-next,05/19] " Igor Russkikh
2018-10-08 14:24       ` [PATCH net-next 05/19] " Oliver Neukum
2018-10-08 14:24         ` [net-next,05/19] " Oliver Neukum
2018-10-05 10:24 ` [PATCH net-next 06/19] net: usb: aqc111: Introduce link management Igor Russkikh
2018-10-05 10:24   ` [net-next,06/19] " Igor Russkikh
2018-10-05 17:11   ` [PATCH net-next 06/19] " Andrew Lunn
2018-10-05 17:11     ` [net-next,06/19] " Andrew Lunn
2018-10-08 13:22     ` [PATCH net-next 06/19] " Igor Russkikh
2018-10-08 13:22       ` [net-next,06/19] " Igor Russkikh
2018-10-05 17:46   ` [PATCH net-next 06/19] " David Miller
2018-10-05 17:46     ` [net-next,06/19] " David Miller
2018-10-06 17:35   ` [PATCH net-next 06/19] " Andrew Lunn
2018-10-06 17:35     ` [net-next,06/19] " Andrew Lunn
2018-10-08  9:29     ` [PATCH net-next 06/19] " Igor Russkikh
2018-10-08  9:29       ` [net-next,06/19] " Igor Russkikh
2018-10-08 12:12       ` [PATCH net-next 06/19] " Andrew Lunn
2018-10-08 12:12         ` [net-next,06/19] " Andrew Lunn
2018-10-08 13:59   ` [PATCH net-next 06/19] " Oliver Neukum
2018-10-08 13:59     ` [net-next,06/19] " Oliver Neukum
2018-10-05 10:24 ` [PATCH net-next 07/19] net: usb: aqc111: Add support for getting and setting of MAC address Igor Russkikh
2018-10-05 10:24   ` [net-next,07/19] " Igor Russkikh
2018-10-06  1:03   ` [PATCH net-next 07/19] " Andrew Lunn
2018-10-06  1:03     ` [net-next,07/19] " Andrew Lunn
2018-10-09 14:34     ` [PATCH net-next 07/19] " Igor Russkikh
2018-10-09 14:34       ` [net-next,07/19] " Igor Russkikh
2018-10-09 14:46       ` [PATCH net-next 07/19] " Andrew Lunn
2018-10-09 14:46         ` [net-next,07/19] " Andrew Lunn
2018-10-05 10:25 ` [PATCH net-next 08/19] net: usb: aqc111: Implement TX data path Igor Russkikh
2018-10-05 10:25   ` [net-next,08/19] " Igor Russkikh
2018-10-06  1:13   ` [PATCH net-next 08/19] " Andrew Lunn
2018-10-06  1:13     ` [net-next,08/19] " Andrew Lunn
2018-10-08 13:43     ` [PATCH net-next 08/19] " Igor Russkikh
2018-10-08 13:43       ` [net-next,08/19] " Igor Russkikh
2018-10-08 14:07       ` [PATCH net-next 08/19] " Oliver Neukum
2018-10-08 14:07         ` [net-next,08/19] " Oliver Neukum
2018-10-09 13:50   ` [PATCH net-next 08/19] " Bjørn Mork
2018-10-09 13:50     ` [net-next,08/19] " Bjørn Mork
2018-10-05 10:25 ` [PATCH net-next 09/19] net: usb: aqc111: Implement RX " Igor Russkikh
2018-10-05 10:25   ` [net-next,09/19] " Igor Russkikh
2018-10-06  1:18   ` [PATCH net-next 09/19] " Andrew Lunn
2018-10-06  1:18     ` [net-next,09/19] " Andrew Lunn
2018-10-09 13:39   ` [PATCH net-next 09/19] " Bjørn Mork
2018-10-09 13:39     ` [net-next,09/19] " Bjørn Mork
2018-10-05 10:25 ` [PATCH net-next 10/19] net: usb: aqc111: Add checksum offload support Igor Russkikh
2018-10-05 10:25   ` [net-next,10/19] " Igor Russkikh
2018-10-05 10:25 ` [PATCH net-next 11/19] net: usb: aqc111: Add support for changing MTU Igor Russkikh
2018-10-05 10:25   ` [net-next,11/19] " Igor Russkikh
2018-10-06 16:56   ` [PATCH net-next 11/19] " Andrew Lunn
2018-10-06 16:56     ` [net-next,11/19] " Andrew Lunn
2018-10-05 10:25 ` [PATCH net-next 12/19] net: usb: aqc111: Add support for enable/disable checksum offload Igor Russkikh
2018-10-05 10:25   ` [net-next,12/19] " Igor Russkikh
2018-10-05 10:25 ` [PATCH net-next 13/19] net: usb: aqc111: Add support for TSO Igor Russkikh
2018-10-05 10:25   ` [net-next,13/19] " Igor Russkikh
2018-10-08 14:12   ` [PATCH net-next 13/19] " Oliver Neukum
2018-10-08 14:12     ` [net-next,13/19] " Oliver Neukum
2018-10-05 10:25 ` [PATCH net-next 14/19] net: usb: aqc111: Implement set_rx_mode callback Igor Russkikh
2018-10-05 10:25   ` [net-next,14/19] " Igor Russkikh
2018-10-06 17:03   ` [PATCH net-next 14/19] " Andrew Lunn
2018-10-06 17:03     ` [net-next,14/19] " Andrew Lunn
2018-10-08 13:49     ` [PATCH net-next 14/19] " Igor Russkikh
2018-10-08 13:49       ` [net-next,14/19] " Igor Russkikh
2018-10-05 10:25 ` [PATCH net-next 15/19] net: usb: aqc111: Add support for VLAN_CTAG_TX/RX offload Igor Russkikh
2018-10-05 10:25   ` [net-next,15/19] " Igor Russkikh
2018-10-08 14:14   ` [PATCH net-next 15/19] " Oliver Neukum
2018-10-08 14:14     ` [net-next,15/19] " Oliver Neukum
2018-10-05 10:25 ` [PATCH net-next 16/19] net: usb: aqc111: Add RX VLAN filtering support Igor Russkikh
2018-10-05 10:25   ` [net-next,16/19] " Igor Russkikh
2018-10-06 17:05   ` [PATCH net-next 16/19] " Andrew Lunn
2018-10-06 17:05     ` [net-next,16/19] " Andrew Lunn
2018-10-05 10:25 ` [PATCH net-next 17/19] net: usb: aqc111: Initialize ethtool_ops structure Igor Russkikh
2018-10-05 10:25   ` [net-next,17/19] " Igor Russkikh
2018-10-06 17:08   ` [PATCH net-next 17/19] " Andrew Lunn
2018-10-06 17:08     ` [net-next,17/19] " Andrew Lunn
2018-10-05 10:25 ` [PATCH net-next 18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks Igor Russkikh
2018-10-05 10:25   ` [net-next,18/19] " Igor Russkikh
2018-10-06 17:38   ` [PATCH net-next 18/19] " Andrew Lunn
2018-10-06 17:38     ` [net-next,18/19] " Andrew Lunn
2018-10-08 14:18   ` [PATCH net-next 18/19] " Oliver Neukum
2018-10-08 14:18     ` [net-next,18/19] " Oliver Neukum
2018-10-05 10:25 ` [PATCH net-next 19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet Igor Russkikh
2018-10-05 10:25   ` [net-next,19/19] " Igor Russkikh
2018-10-06 17:49   ` [PATCH net-next 19/19] " Andrew Lunn
2018-10-06 17:49     ` [net-next,19/19] " Andrew Lunn
2018-10-08 14:12     ` [PATCH net-next 19/19] " Igor Russkikh
2018-10-08 14:12       ` [net-next,19/19] " Igor Russkikh
2018-10-08 14:47       ` [PATCH net-next 19/19] " Andrew Lunn
2018-10-08 14:47         ` [net-next,19/19] " Andrew Lunn
2018-10-06 17:51 ` [PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices Andrew Lunn
2018-10-08  7:58   ` Igor Russkikh
2018-10-08 14:21 ` Oliver Neukum
2018-10-08 14:52   ` Igor Russkikh

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.