* [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, ®16);
+ reg16 = 0;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, 2, ®16);
+}
+
+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, ®8);
+
+ reg8 = 0x0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_SWP_CTRL, 1, 1, ®8);
+
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8);
+ 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, ®8);
+
+ 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, ®16);
+ reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+ reg16 = 0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+ 2, 2, ®16);
+
+ 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, ®16);
+ reg16 = 0;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, 2, ®16);
+}
+
+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, ®8);
+
+ reg8 = 0x0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_SWP_CTRL, 1, 1, ®8);
+
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8);
+ 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, ®8);
+
+ 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, ®16);
+ reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+ reg16 = 0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+ 2, 2, ®16);
+
+ 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, ®16);
+
+ /* Power down ethernet PHY */
+ if (aqc111_data->dpa) {
+ reg8 = 0x00;
+ aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
+ 0, 1, ®8);
+ } 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, ®8);
+ if (reg8 == 0x00) {
+ reg8 = 0x02;
+ aqc111_write_cmd(dev, AQ_PHY_POWER, 0, 0, 1, ®8);
+ msleep(200);
+ }
+
+ aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+ 2, ®16);
+ 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, ®16);
+ }
+ } 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, ®8);
@@ -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, ®16);
@@ -214,6 +296,17 @@ static int aqc111_stop(struct usbnet *dev)
aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
2, 2, ®16);
+ /* 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, ®16);
+ } 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, ®16);
+
+ /* Power down ethernet PHY */
+ if (aqc111_data->dpa) {
+ reg8 = 0x00;
+ aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
+ 0, 1, ®8);
+ } 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, ®8);
+ if (reg8 == 0x00) {
+ reg8 = 0x02;
+ aqc111_write_cmd(dev, AQ_PHY_POWER, 0, 0, 1, ®8);
+ msleep(200);
+ }
+
+ aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+ 2, ®16);
+ 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, ®16);
+ }
+ } 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, ®8);
@@ -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, ®16);
@@ -214,6 +296,17 @@ static int aqc111_stop(struct usbnet *dev)
aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
2, 2, ®16);
+ /* 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, ®16);
+ } 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, ®16_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, ®16_1);
+ aq_mdio_write_cmd(dev, AQ_AUTONEG_10GT_CTRL_REG,
+ AQ_PHY_AUTONEG_ADDR, 2, ®16_2);
+
+ aq_mdio_read_cmd(dev, AQ_AUTONEG_ADV_REG, AQ_PHY_AUTONEG_ADDR,
+ 2, ®16_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, ®16_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, ®16_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, ®8);
} 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, ®16);
+ aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
+ AQ_PHY_AUTONEG_ADDR, 2, ®16);
+ }
+
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
+ 1, 1, ®8);
+
+ 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, ®16);
+ 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, ®8);
+
+ reg8 = 0x0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+ 1, 1, ®8);
+
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMTX_DMA_CONTROL,
+ 1, 1, ®8);
+
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, ®8);
+
+ reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+
+ reg8 = SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+
+ reg16 = 0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ reg16 = SFR_MEDIUM_XGMIIMODE | SFR_MEDIUM_FULL_DUPLEX;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ 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, ®16);
+
+ 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, ®16);
+
+ netif_carrier_on(dev->net);
+ } else {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+ reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+ reg16 &= ~SFR_RX_CTL_START;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+
+ reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+ reg8 = SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+
+ 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, ®8);
+ 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, ®16_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, ®16_1);
+ aq_mdio_write_cmd(dev, AQ_AUTONEG_10GT_CTRL_REG,
+ AQ_PHY_AUTONEG_ADDR, 2, ®16_2);
+
+ aq_mdio_read_cmd(dev, AQ_AUTONEG_ADV_REG, AQ_PHY_AUTONEG_ADDR,
+ 2, ®16_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, ®16_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, ®16_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, ®8);
} 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, ®16);
+ aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
+ AQ_PHY_AUTONEG_ADDR, 2, ®16);
+ }
+
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
+ 1, 1, ®8);
+
+ 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, ®16);
+ 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, ®8);
+
+ reg8 = 0x0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+ 1, 1, ®8);
+
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMTX_DMA_CONTROL,
+ 1, 1, ®8);
+
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, ®8);
+
+ reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+
+ reg8 = SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+
+ reg16 = 0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ reg16 = SFR_MEDIUM_XGMIIMODE | SFR_MEDIUM_FULL_DUPLEX;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ 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, ®16);
+
+ 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, ®16);
+
+ netif_carrier_on(dev->net);
+ } else {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+ reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+ reg16 &= ~SFR_RX_CTL_START;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+
+ reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+ reg8 = SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+
+ 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, ®8);
+ 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, ®8);
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, ®8);
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, ®8);
+
+ 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, ®8);
+}
+
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, ®16);
+ aqc111_configure_csum_offload(dev);
+
aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
2, 2, ®16);
@@ -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, ®8);
+
+ 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, ®8);
+}
+
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, ®16);
+ aqc111_configure_csum_offload(dev);
+
aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
2, 2, ®16);
@@ -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, ®16);
+ 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, ®16);
+
+ 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, ®16);
+
+ 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, ®16);
@@ -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, ®16);
+ 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, ®16);
+ 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, ®16);
+
+ 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, ®16);
+
+ 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, ®16);
@@ -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, ®16);
+ 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, ®8);
+ reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+ 1, 1, ®8);
+ }
+
+ if (changed & NETIF_F_IPV6_CSUM) {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8);
+ reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+ 1, 1, ®8);
+ }
+
+ if (changed & NETIF_F_RXCSUM) {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8);
+ 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, ®8);
+ }
+ 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, ®8);
+ reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+ 1, 1, ®8);
+ }
+
+ if (changed & NETIF_F_IPV6_CSUM) {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8);
+ reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL,
+ 1, 1, ®8);
+ }
+
+ if (changed & NETIF_F_RXCSUM) {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8);
+ 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, ®8);
+ }
+ 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, ®8);
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, ®16);
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, ®16);
@@ -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, ®16);
- 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, ®16);
+ 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, ®16);
- aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
- reg16 &= ~SFR_RX_CTL_START;
- aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+ 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, ®8);
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, ®16);
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, ®16);
@@ -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, ®16);
- 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, ®16);
+ 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, ®16);
- aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
- reg16 &= ~SFR_RX_CTL_START;
- aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+ 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, ®8);
+ vlan_ctrl = reg8;
+
+ /* Address */
+ reg8 = (vid / 16);
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8);
+ /* Data */
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg16 &= ~(1 << (vid % 16));
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+
+ 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, ®8);
+ vlan_ctrl = reg8;
+
+ /* Address */
+ reg8 = (vid / 16);
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8);
+ /* Data */
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg16 |= (1 << (vid % 16));
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+
+ 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, ®8);
}
+ 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, ®8);
+ /* Data */
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_DATA0,
+ 2, 2, ®16);
+ reg8 = SFR_VLAN_CONTROL_WE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_CONTROL,
+ 1, 1, ®8);
+ }
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+ 1, 1, ®8);
+ reg8 |= SFR_VLAN_CONTROL_VFE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ } else {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+ 1, 1, ®8);
+ reg8 &= ~SFR_VLAN_CONTROL_VFE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ }
+ }
+
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, ®8);
@@ -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, ®8);
+ vlan_ctrl = reg8;
+
+ /* Address */
+ reg8 = (vid / 16);
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8);
+ /* Data */
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg16 &= ~(1 << (vid % 16));
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+
+ 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, ®8);
+ vlan_ctrl = reg8;
+
+ /* Address */
+ reg8 = (vid / 16);
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8);
+ /* Data */
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg16 |= (1 << (vid % 16));
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, 2, ®16);
+ reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+
+ 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, ®8);
}
+ 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, ®8);
+ /* Data */
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_DATA0,
+ 2, 2, ®16);
+ reg8 = SFR_VLAN_CONTROL_WE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_CONTROL,
+ 1, 1, ®8);
+ }
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+ 1, 1, ®8);
+ reg8 |= SFR_VLAN_CONTROL_VFE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ } else {
+ aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL,
+ 1, 1, ®8);
+ reg8 &= ~SFR_VLAN_CONTROL_VFE;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC,
+ SFR_VLAN_ID_CONTROL, 1, 1, ®8);
+ }
+ }
+
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, ®8);
@@ -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, ®16);
+ 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, ®16);
+ /* Force bz */
+ aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, 2, ®16);
+ reg16 |= SFR_PHYPWR_RSTCTL_BZ;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, 2, ®16);
+
+ reg8 = SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+
+ 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, ®8);
+
+ 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, ®8);
+ } 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, ®8);
+ reg8 = SFR_BMRX_DMA_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+ 1, 1, ®8);
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+ reg8 = 0x07;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL,
+ 1, 1, ®8);
+ reg8 = 0x00;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_RX_BULKIN_QTIMR_LOW, 1, 1, ®8);
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_RX_BULKIN_QTIMR_HIGH, 1, 1, ®8);
+ reg8 = 0xFF;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QSIZE,
+ 1, 1, ®8);
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QIFG,
+ 1, 1, ®8);
+
+ aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+ reg16 |= SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+
+ 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, ®16);
+ }
+
+ /* Disable RX path */
+ aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+ reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+ }
+
+ 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, ®8);
+ if (reg8 == 0x00) {
+ reg8 = 0x02;
+ aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
+ 1, ®8);
+ msleep(200);
+ }
+
+ aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+ 2, ®16);
+ 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, ®16);
+ }
+ }
+
+ reg8 = 0xFF;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+ 1, 1, ®8);
+ /* 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, ®16);
+
+ reg16 |= SFR_RX_CTL_START;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+
+ 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, ®16);
+ reg16 |= SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+ reg8 = 0x0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 1, 1, ®8);
+
+ 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, ®16);
+ 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, ®16);
+ /* Force bz */
+ aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, 2, ®16);
+ reg16 |= SFR_PHYPWR_RSTCTL_BZ;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, 2, ®16);
+
+ reg8 = SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+
+ 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, ®8);
+
+ 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, ®8);
+ } 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, ®8);
+ reg8 = SFR_BMRX_DMA_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+ 1, 1, ®8);
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+ reg8 = 0x07;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL,
+ 1, 1, ®8);
+ reg8 = 0x00;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_RX_BULKIN_QTIMR_LOW, 1, 1, ®8);
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_RX_BULKIN_QTIMR_HIGH, 1, 1, ®8);
+ reg8 = 0xFF;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QSIZE,
+ 1, 1, ®8);
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QIFG,
+ 1, 1, ®8);
+
+ aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, 2, ®16);
+ reg16 |= SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+
+ 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, ®16);
+ }
+
+ /* Disable RX path */
+ aqc111_read_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+ reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+ }
+
+ 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, ®8);
+ if (reg8 == 0x00) {
+ reg8 = 0x02;
+ aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
+ 1, ®8);
+ msleep(200);
+ }
+
+ aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
+ 2, ®16);
+ 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, ®16);
+ }
+ }
+
+ reg8 = 0xFF;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+ 1, 1, ®8);
+ /* 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, ®16);
+
+ reg16 |= SFR_RX_CTL_START;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
+
+ 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, ®16);
+ reg16 |= SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, 2, ®16);
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+ reg8 = 0x0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 1, 1, ®8);
+
+ 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, ®16);
> +
> + /* Power down ethernet PHY */
> + if (aqc111_data->dpa) {
> + reg8 = 0x00;
> + aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
> + 0, 1, ®8);
> + } 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, ®16);
> +
> + /* Power down ethernet PHY */
> + if (aqc111_data->dpa) {
> + reg8 = 0x00;
> + aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0,
> + 0, 1, ®8);
> + } 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, ®8);
> + if (reg8 == 0x00) {
> + reg8 = 0x02;
> + aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
> + 1, ®8);
> + msleep(200);
> + }
> +
> + aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
> + 2, ®16);
> + 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, ®16);
> + }
> + }
> +
> + reg8 = 0xFF;
> + aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
> + 1, 1, ®8);
> + /* 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, ®16);
> +
> + reg16 |= SFR_RX_CTL_START;
> + aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
> +
> + 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, ®8);
> + if (reg8 == 0x00) {
> + reg8 = 0x02;
> + aqc111_write_cmd_nopm(dev, AQ_PHY_POWER, 0, 0,
> + 1, ®8);
> + msleep(200);
> + }
> +
> + aq_mdio_read_cmd(dev, AQ_GLB_STD_CTRL_REG, AQ_PHY_GLOBAL_ADDR,
> + 2, ®16);
> + 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, ®16);
> + }
> + }
> +
> + reg8 = 0xFF;
> + aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
> + 1, 1, ®8);
> + /* 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, ®16);
> +
> + reg16 |= SFR_RX_CTL_START;
> + aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, 2, ®16);
> +
> + 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, ®16);
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, ®16);
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, ®16);
> + aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
> + AQ_PHY_AUTONEG_ADDR, 2, ®16);
> + }
> +
> + aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
> + 1, 1, ®8);
> +
> + 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, ®16);
> + 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, ®16);
> + aq_mdio_write_cmd(dev, AQ_GLB_EGR_PAUSE_CTRL_REG,
> + AQ_PHY_AUTONEG_ADDR, 2, ®16);
> + }
> +
> + aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0,
> + 1, 1, ®8);
> +
> + 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, ®16);
> + 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, ®16);
>
> 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, ®16);
>
> 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, ®16);
> >
> > 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, ®16);
> >
> > 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.