[GIT PULL] USB for v4.20 merge window

2018-10-05 Thread Felipe Balbi

Hi Greg,

Here's my pull request for v4.20 merge window. Most of the changes are
on the UVC gadget driver. Seems like we'll have a calm merge window for
USB folks this time around.

Let me know if you want anything to be changed.

The following changes since commit 17b57b1883c1285f3d0dc2266e8f79286a7bef38:

  Linux 4.19-rc6 (2018-09-30 07:15:35 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git tags/usb-for-v4.20

for you to fetch changes up to 3b766f45355775fc5c404b7ff88f3fd3e9d77f86:

  USB: net2280: Remove ->disconnect() callback from net2280_pullup() 
(2018-10-05 10:50:23 +0300)


USB for v4.20

With 63 non-merge commits, this is not a large merge window for USB
peripheral. The largest changes go to the UVC gadget driver which a
few folks have been improving.

Apart from UVC changes, we have a few more devices being added to
Renesas USB3 and DWC3 controller drivers and a couple minor bug fixes
on other drivers.


Alan Stern (2):
  USB: gadget core: Issue ->disconnect() callback from 
usb_gadget_disconnect()
  USB: net2280: Remove ->disconnect() callback from net2280_pullup()

Alexandre Belloni (1):
  usb: gadget: udc: atmel: handle at91sam9rl PMC

Andreas Pape (1):
  usb: gadget: f_uac2: disable IN/OUT ep if unused

Arnd Bergmann (1):
  usb: dwc3: add EXTCON dependency for qcom

Chunfeng Yun (1):
  usb: mtu3: disable vbus rise/fall interrupts of ltssm

Colin Ian King (2):
  usb: gadget: fix spelling mistakeis "[En]queing" -> "[En]queuing"
  usb: phy: mxs: fix spelling mistake "stardard" -> "standard"

Fabrice Gasnier (4):
  usb: dwc2: get optional vbus-supply regulator once
  usb: dwc2: fix a race with external vbus supply
  usb: dwc2: fix call to vbus supply exit routine, call it unlocked
  usb: dwc2: fix unbalanced use of external vbus-supply

Fabrizio Castro (1):
  usb: gadget: udc: renesas_usb3: Add r8a774a1 support

Faisal Mehmood (1):
  usb: dwc3: Fix spelling of 'optimizations'

Felipe Balbi (1):
  Merge tag 'uvcg-20180925' of git://linuxtv.org/pinchartl/media into 
testing/next

Grigor Tovmasyan (9):
  usb: dwc2: Update registers definitions to support service interval
  usb: dwc2: Add core parameter for service interval support
  usb: dwc2: Add dwc2_gadget_dec_frame_num_by_one() function
  usb: dwc2: Update target (u)frame calculation
  usb: dwc2: Add definitions for new registers
  usb: dwc2: gadget: Add parameters for GREFCLK register
  usb: dwc2: gadget: Program GREFCLK register
  usb: dwc2: gadget: enable WKUP_ALERT interrupt
  usb: dwc2: gadget: Add handler for WkupAlert interrupt

Jia-Ju Bai (1):
  usb: gadget: udc: fotg210-udc: Fix a sleep-in-atomic-context bug in 
fotg210_get_status()

Joel Pepper (2):
  usb: gadget: uvc: configfs: Add bFrameIndex attributes
  usb: gadget: uvc: configfs: Prevent format changes after linking header

Josh Abraham (1):
  usb: dwc2: remove set but unused variable

Laurent Pinchart (14):
  usb: gadget: uvc: configfs: Don't wrap groups unnecessarily
  usb: gadget: uvc: configfs: Add section header comments
  usb: gadget: uvc: configfs: Drop leaked references to config items
  usb: gadget: uvc: configfs: Allocate groups dynamically
  usb: gadget: uvc: configfs: Add interface number attributes
  usb: gadget: uvc: configfs: Add bFormatIndex attributes
  usb: gadget: uvc: Factor out video USB request queueing
  usb: gadget: uvc: Only halt video streaming endpoint in bulk mode
  usb: gadget: uvc: Replace plain printk() with dev_*()
  usb: gadget: uvc: Remove uvc_set_trace_param() function
  usb: video: Fix endianness mismatches in descriptor structures
  usb: gadget: uvc: configfs: Fix operation on big endian platforms
  usb: gadget: uvc: configfs: Simplify attributes macros
  usb: gadget: uvc: configfs: Use %u to print unsigned int values

Marek Szyprowski (3):
  usb: dwc3: exynos: Remove dead code
  usb: dwc3: exynos: Rework clock handling and prepare for new variants
  usb: dwc3: exynos: Add support for Exynos5433 variant with all clocks

Minas Harutyunyan (1):
  usb: dwc2: Disable all EP's on disconnect

Nathan Chancellor (1):
  usb: gadget: udc: Remove unnecessary parentheses

Nicholas Mc Guire (2):
  usb: gadget: fsl_udc_core: check allocation return value and cleanup on 
failure
  usb: gadget: fsl_udc_core: fixup struct_udc_setup documentation

Paul Elder (1):
  usb: gadget: uvc: configfs: Sort frame intervals upon writing

Rob Herring (1):
  usb: gadget: atmel: remove pointless retrieval of DT name property

SolidHal (1):
  usb: dwc2: disable power_down on rockchip devices

Thinh Nguyen (1):
  usb: dwc3: gadget: Check ENBLSLPM before sending ep command

Yoshihir

Re: [PATCH v2 -next] USB: cypress_m8: remove set but not used variables 'iflag'

2018-10-05 Thread Johan Hovold
On Thu, Oct 04, 2018 at 07:09:53AM +, YueHaibing wrote:
> Fixes gcc '-Wunused-but-set-variable' warning:
> 
> drivers/usb/serial/cypress_m8.c: In function 'cypress_set_termios':
> drivers/usb/serial/cypress_m8.c:866:18: warning:
>  variable 'iflag' set but not used [-Wunused-but-set-variable]
> 
> Signed-off-by: YueHaibing 
> ---
> v2: only fix 'iflag' warning

Now applied, thanks.

Johan


Re: [GIT PULL] USB for v4.20 merge window

2018-10-05 Thread Greg Kroah-Hartman
On Fri, Oct 05, 2018 at 11:07:31AM +0300, Felipe Balbi wrote:
> 
> Hi Greg,
> 
> Here's my pull request for v4.20 merge window. Most of the changes are
> on the UVC gadget driver. Seems like we'll have a calm merge window for
> USB folks this time around.

Now pulled and pushed out, thanks.

greg k-h


USB mass storage device inaccessible, freezes lsusb

2018-10-05 Thread Christoph Groth
Dear Linux USB experts,

I noticed that a device (Garmin Foretrex 601, firmware version 2.80)
that is supposed to present itself as USB mass storage, does not work on
Linux.  After being connected, the device does show up in the output of
lsusb (ID 091e:0003):

$ lsusb
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
(...)
Bus 001 Device 003: ID 17ef:100a Lenovo ThinkPad Mini Dock Plus Series 3
Bus 001 Device 008: ID 091e:0003 Garmin International GPS (various models)
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

But it does not become available for mounting as USB mass storage
devices normally.  Moreover, the device itself freezes completely.  It
is not even possible to switch it off, so that the batteries must be
removed.

I verified that this problem exists on several machines from different
manufacturers running different Linux versions, including my main
machine, a Thinkpad X220

$ uname -a
Linux abc 4.17.0-3-amd64 #1 SMP Debian 4.17.17-1 (2018-08-18) x86_64 GNU/Linux

However, the same device was accessible as USB mass storage one MacOS
and one Windows machine that I tried.  Moreover, if I plug it into my
machine before Linux boots (for example while Grub runs), the device
does not freeze.  So it seems to me that the problem could be specific
to the Linux USB stack.

Another symptom that I noticed is that 'lsusb -v' freezes, with the last
line it outputs being

Bus 001 Device 008: ID 091e:0003 Garmin International GPS (various models)

Even 'killall -9 lsusb' does not terminate it.

The kernel module garmin_usb that sometimes causes problems is
blacklisted and not loaded.

Are such problems (USB mass storage devices not working) known or even
common?  I can well imagine that the culprit is the Garmin device, but
it seems that there might be also a problem at the Linux side, since the
freezing of lsusb probably should not happen even with a malfunctioning
device.

I would be grateful for hints on how solve or further debug this
problem.

Christoph


[PATCH -next] usb/early: remove set but not used variable 'remain_length'

2018-10-05 Thread YueHaibing
Fixes gcc '-Wunused-but-set-variable' warning:

drivers/usb/early/xhci-dbc.c: In function 'xdbc_handle_tx_event':
drivers/usb/early/xhci-dbc.c:720:9: warning:
 variable 'remain_length' set but not used [-Wunused-but-set-variable]

It never be used since introduction in 
commit aeb9dd1de98c ("usb/early: Add driver for xhci debug capability")

Signed-off-by: YueHaibing 
---
 drivers/usb/early/xhci-dbc.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
index 9d4ee88..d2652dc 100644
--- a/drivers/usb/early/xhci-dbc.c
+++ b/drivers/usb/early/xhci-dbc.c
@@ -717,17 +717,14 @@ static void xdbc_handle_port_status(struct xdbc_trb 
*evt_trb)
 
 static void xdbc_handle_tx_event(struct xdbc_trb *evt_trb)
 {
-   size_t remain_length;
u32 comp_code;
int ep_id;
 
comp_code   = GET_COMP_CODE(le32_to_cpu(evt_trb->field[2]));
-   remain_length   = EVENT_TRB_LEN(le32_to_cpu(evt_trb->field[2]));
ep_id   = TRB_TO_EP_ID(le32_to_cpu(evt_trb->field[3]));
 
switch (comp_code) {
case COMP_SUCCESS:
-   remain_length = 0;
case COMP_SHORT_PACKET:
break;
case COMP_TRB_ERROR:



[PATCH net-next 02/19] net: usb: aqc111: Add bind and empty unbind callbacks

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Initialize net_device_ops structure

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 
 #include 
 
+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



[PATCH net-next 01/19] net: usb: aqc111: Driver skeleton for Aquantia AQtion USB to 5GbE

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Initialize usb_driver structure skeleton

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 ..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 
+ * Copyright (C) 2005 Phil Chang 
+ * Copyright (C) 2002-2003 TiVo Inc.
+ * Copyright (C) 2017-2018 ASIX
+ * Copyright (C) 2018 Aquantia Corp.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+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



[PATCH net-next 00/19] Add support for Aquantia AQtion USB to 5/2.5GbE devices

2018-10-05 Thread 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



[PATCH net-next 08/19] net: usb: aqc111: Implement TX data path

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 & 0x1F);
+
+   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 1
 #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_1G0x11

[PATCH net-next 17/19] net: usb: aqc111: Initialize ethtool_ops structure

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Implement get_drvinfo, set/get_msglevel, get_link callbacks

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -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



[PATCH net-next 03/19] net: usb: aqc111: Add implementation of read and write commands

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Read/write command register defines and functions

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 
 #include 
 
+#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 ..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

[PATCH net-next 07/19] net: usb: aqc111: Add support for getting and setting of MAC address

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -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_PARAMETERS0x20
 #define AQ_PHY_POWER   0x31
 #define AQ_PHY_CMD 0x32
 #define AQ_PHY_OPS 0x61
-- 
2.7.4



[PATCH net-next 13/19] net: usb: aqc111: Add support for TSO

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 & 0x1F);
 
+   /* 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..9cf35df9 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



[PATCH net-next 16/19] net: usb: aqc111: Add RX VLAN filtering support

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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_a

[PATCH net-next 06/19] net: usb: aqc111: Introduce link management

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Add full hardware initialization sequence and link configuration logic

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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_u

[PATCH net-next 18/19] net: usb: aqc111: Implement get/set_link_ksettings callbacks

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 &&
+

[PATCH net-next 19/19] net: usb: aqc111: Add support for wake on LAN by MAGIC packet

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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_ACC

[PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

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 
Signed-off-by: Igor Russkikh 
---
 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_AD

[PATCH net-next 15/19] net: usb: aqc111: Add support for VLAN_CTAG_TX/RX offload

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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



[PATCH net-next 12/19] net: usb: aqc111: Add support for enable/disable checksum offload

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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



[PATCH net-next 09/19] net: usb: aqc111: Implement RX data path

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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_PARAMETERS0x20
 #define AQ_PHY_POWER   0x31
@@ -228,6 +230,8 @@ struct aqc111_int_data {
 #define AQ_INT_SPEED_1G0x11
 #define AQ_INT_SPEED_100M  0x13
 
+#def

[PATCH net-next 14/19] net: usb: aqc111: Implement set_rx_mode callback

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -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(de

[PATCH net-next 10/19] net: usb: aqc111: Add checksum offload support

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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_1G0x11
 #define AQ_INT_SPEED_100M  0x13
 
+#define AQ_RXHDR_L4_ERRBIT(8)
+#define AQ_RXHDR_L3_ERRBIT(9)
+
+#define AQ_RXHDR_L4_TYPE_ICMP  0x02
+#define AQ_RXHDR_L4_TYPE_IGMP  0x03
+#define AQ_RXHDR_L4_TYPE_TCMPV60x05
+
+#define AQ_RXHDR_L3_TYPE_IP0x01
+#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_ERR0x02
+#define AQ_RXHDR_L4CSUM_ERR0x01
+
 #define AQ_RX_HW_PAD   0x02
 
 struct aq_tx_packet_desc {
-- 
2.7.4



[PATCH net-next 11/19] net: usb: aqc111: Add support for changing MTU

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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



[PATCH net-next 04/19] net: usb: aqc111: Various callbacks implementation

2018-10-05 Thread Igor Russkikh
From: Dmitry Bezrukov 

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

Signed-off-by: Dmitry Bezrukov 
Signed-off-by: Igor Russkikh 
---
 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 1
 #define AQ_USB_SET_TIMEOUT 4000
 
+/* SFR Reg. /
+
+#define SFR_GENERAL_STATUS 0x03
+#define SFR_CHIP_STATUS0x05
+#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_START0x0080
+   #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_AMALL0x0002
+   #define SFR_RX_CTL_PRO  0x0001
+   #define SFR_RX_CTL_STOP 0x
+#define SFR_INTER_PACKET_GAP_0 0x0D
+#define SFR_NODE_ID0x10
+#define SFR_MULTI_FILTER_ARRY  0x16
+#define SFR_MEDIUM_STATUS_MODE 0x22
+   #define SFR_MEDIUM_XGMIIMODE0x0001
+   #define SFR_MEDIUM_FULL_DUPLEX  0x0002
+   #define SFR_MEDIUM_RXFLOW_CTRLEN0x0010
+   #define SFR_MEDIUM_TXFLOW_CTRLEN0x0020
+   #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_FLAG0x10
+   #define SFR_MONITOR_MODE_PMEPOL 0x20
+   #define SFR_MONITOR_MODE_PMETYPE0x40
+#define SFR_PHYPWR_RSTCTL  0x26
+   #define SFR_PHYPWR_RSTCTL_BZ0x0010
+   #define SFR_PHYPWR_RSTCTL_IPRL  0x0020
+#define SFR_VLAN_ID_ADDRESS0x2A
+#define SFR_VLAN_ID_CONTROL0x2B
+   #define SFR_VLAN_CONTROL_WE 0x0001
+   #define SFR_VLAN_CONTROL_RD 0x00

Re: [PATCH 0/2] USB: serial: gpio line-name fix and FT232R CBUS gpio support

2018-10-05 Thread Johan Hovold
On Mon, Oct 01, 2018 at 11:43:55AM +0200, Linus Walleij wrote:
> On Sun, Sep 30, 2018 at 2:29 PM Johan Hovold  wrote:

> > Linus, we finally got around to adding gpio support for FTDI devices;
> > see commit
> >
> > ba93cc7da896 ("USB: serial: ftdi_sio: implement GPIO support for 
> > FT-X devices")
> >
> > in my usb-next branch (and linux-next).
> 
> This is good news, I think it's a pretty neat way for people to get
> a few inexpensive GPIOs from their serial adapters.
> 
> > The gpiolib warnings and inability to use the legacy sysfs interface
> > prevents us from setting the line names however as someone is bound to
> > plugin more than one of these devices at some point. I think we
> > discussed this issue with the name space and hotpluggable devices a few
> > years ago, but looks like this topic may need to be revisited.
> 
> Hm I guess the right long-term fix is to allow per-gpiochip unique
> names rather than enforcing globally unique names.

Indeed.

> The idea is to make it possible for userspace to look up a GPIO
> on a chip by name, so if the gpiochip has a unique name,
> and the line name is unique on that chip it should be good
> enough.

I haven't really had time do dig into this again, but is this also an
issue with the chardev interface? I thought this was one of the things
you wanted to get right with the new interface, so hopefully that's
already taken care of.

If the flat name space is only an issue with the legacy interface we
might get away with simply not using the line names in sysfs when a new
chip flag is set (unless we can resue .can_sleep, but there seems to be
some i2c devices already using line names).

Thanks,
Johan


Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management

2018-10-05 Thread Andrew Lunn
On Fri, Oct 05, 2018 at 10:24:55AM +, Igor Russkikh wrote:
> From: Dmitry Bezrukov 
> 
> 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


Re: [PATCH net-next 02/19] net: usb: aqc111: Add bind and empty unbind callbacks

2018-10-05 Thread David Miller
From: Igor Russkikh 
Date: Fri, 5 Oct 2018 10:24:42 +

> +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).


Re: [PATCH net-next 03/19] net: usb: aqc111: Add implementation of read and write commands

2018-10-05 Thread David Miller
From: Igor Russkikh 
Date: Fri, 5 Oct 2018 10:24:44 +

> +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.


Re: [PATCH net-next 06/19] net: usb: aqc111: Introduce link management

2018-10-05 Thread David Miller
From: Igor Russkikh 
Date: Fri, 5 Oct 2018 10:24:55 +

> + 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.


Re: [PATCH] usbnet: smsc95xx: simplify tx_fixup code

2018-10-05 Thread David Miller
From: Ben Dooks 
Date: Tue,  2 Oct 2018 17:56:02 +0100

> - memcpy(skb->data, &tx_cmd_a, 4);
> + ptr = skb_push(skb, 8);
> + tx_cmd_a = cpu_to_le32(tx_cmd_a);
> + tx_cmd_b = cpu_to_le32(tx_cmd_b);
> + memcpy(ptr, &tx_cmd_a, 4);
> + memcpy(ptr+4, &tx_cmd_b, 4);

Even a memcpy() through a void pointer does not guarantee that gcc will
not emit word sized loads and stores.

You must use the get_unaligned()/put_unaligned() facilities to do this
properly.

I also agree that making a proper type and structure instead of using
a void pointer would be better.


Re: [PATCH net-next 05/19] net: usb: aqc111: Introduce PHY access

2018-10-05 Thread Andrew Lunn
On Fri, Oct 05, 2018 at 10:24:53AM +, Igor Russkikh wrote:
> From: Dmitry Bezrukov 
> 
> 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


[PATCH] selftests: usbip: add wait after attach and before checking port status

2018-10-05 Thread Shuah Khan (Samsung OSG)
Add sleep between attach and "usbip port" check to make sure status is
updated. Running attach and query back shows incorrect status.

Signed-off-by: Shuah Khan (Samsung OSG) 
---
 tools/testing/selftests/drivers/usb/usbip/usbip_test.sh | 4 
 1 file changed, 4 insertions(+)

diff --git a/tools/testing/selftests/drivers/usb/usbip/usbip_test.sh 
b/tools/testing/selftests/drivers/usb/usbip/usbip_test.sh
index a72df93cf1f8..128f0ab24307 100755
--- a/tools/testing/selftests/drivers/usb/usbip/usbip_test.sh
+++ b/tools/testing/selftests/drivers/usb/usbip/usbip_test.sh
@@ -141,6 +141,10 @@ echo "Import devices from localhost - should work"
 src/usbip attach -r localhost -b $busid;
 echo "=="
 
+# Wait for sysfs file to be updated. Without this sleep, usbip port
+# shows no imported devices.
+sleep 3;
+
 echo "List imported devices - expect to see imported devices";
 src/usbip port;
 echo "=="
-- 
2.17.0



[PATCH] usb: usbip: Fix BUG: KASAN: slab-out-of-bounds in vhci_hub_control()

2018-10-05 Thread Shuah Khan (Samsung OSG)
vhci_hub_control() accesses port_status array with out of bounds port
value. Fix it to reference port_status[] only with a valid rhport value
when invalid_rhport flag is true.

The invalid_rhport flag is set early on after detecting in port value
is within the bounds or not.

The following is used reproduce the problem and verify the fix:
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=14ed8ab640

Reported-by: syzbot+bccc1fe10b70fadc7...@syzkaller.appspotmail.com
Signed-off-by: Shuah Khan (Samsung OSG) 
---
 drivers/usb/usbip/vhci_hcd.c | 57 ++--
 1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index d11f3f8dad40..1e592ec94ba4 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -318,8 +318,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 
typeReq, u16 wValue,
struct vhci_hcd *vhci_hcd;
struct vhci *vhci;
int retval = 0;
-   int rhport;
+   int rhport = -1;
unsigned long   flags;
+   bool invalid_rhport = false;
 
u32 prev_port_status[VHCI_HC_PORTS];
 
@@ -334,9 +335,19 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 
typeReq, u16 wValue,
usbip_dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue,
  wIndex);
 
-   if (wIndex > VHCI_HC_PORTS)
-   pr_err("invalid port number %d\n", wIndex);
-   rhport = wIndex - 1;
+   /*
+* wIndex can be 0 for some request types (typeReq). rhport is
+* in valid range when wIndex >= 1 and < VHCI_HC_PORTS.
+*
+* Reference port_status[] only with valid rhport when
+* invalid_rhport is false.
+*/
+   if (wIndex < 1 || wIndex > VHCI_HC_PORTS) {
+   invalid_rhport = true;
+   if (wIndex > VHCI_HC_PORTS)
+   pr_err("invalid port number %d\n", wIndex);
+   } else
+   rhport = wIndex - 1;
 
vhci_hcd = hcd_to_vhci_hcd(hcd);
vhci = vhci_hcd->vhci;
@@ -345,8 +356,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 
typeReq, u16 wValue,
 
/* store old status and compare now and old later */
if (usbip_dbg_flag_vhci_rh) {
-   memcpy(prev_port_status, vhci_hcd->port_status,
-   sizeof(prev_port_status));
+   if (!invalid_rhport)
+   memcpy(prev_port_status, vhci_hcd->port_status,
+   sizeof(prev_port_status));
}
 
switch (typeReq) {
@@ -354,8 +366,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 
typeReq, u16 wValue,
usbip_dbg_vhci_rh(" ClearHubFeature\n");
break;
case ClearPortFeature:
-   if (rhport < 0)
+   if (invalid_rhport) {
+   pr_err("invalid port number %d\n", wIndex);
goto error;
+   }
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
if (hcd->speed == HCD_USB3) {
@@ -415,9 +429,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 
typeReq, u16 wValue,
break;
case GetPortStatus:
usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
-   if (wIndex < 1) {
+   if (invalid_rhport) {
pr_err("invalid port number %d\n", wIndex);
retval = -EPIPE;
+   goto error;
}
 
/* we do not care about resume. */
@@ -513,16 +528,20 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 
typeReq, u16 wValue,
goto error;
}
 
-   if (rhport < 0)
+   if (invalid_rhport) {
+   pr_err("invalid port number %d\n", wIndex);
goto error;
+   }
 
vhci_hcd->port_status[rhport] |= USB_PORT_STAT_SUSPEND;
break;
case USB_PORT_FEAT_POWER:
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_POWER\n");
-   if (rhport < 0)
+   if (invalid_rhport) {
+   pr_err("invalid port number %d\n", wIndex);
goto error;
+   }
if (hcd->speed == HCD_USB3)
vhci_hcd->port_status[rhport] |= 
USB_SS_PORT_STAT_POWER;
else
@@ -531,8 +550,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 
typeReq, u16 wValue,
case USB_PORT_FEAT_BH_PORT_RESET:
usbip_dbg_vhci_rh(
   

Re: [PATCH net-next 07/19] net: usb: aqc111: Add support for getting and setting of MAC address

2018-10-05 Thread Andrew Lunn
On Fri, Oct 05, 2018 at 10:24:58AM +, Igor Russkikh wrote:
> From: Dmitry Bezrukov 
> 
> Signed-off-by: Dmitry Bezrukov 
> Signed-off-by: Igor Russkikh 
> ---
>  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 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  
> @@ -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


Re: [PATCH net-next 08/19] net: usb: aqc111: Implement TX data path

2018-10-05 Thread Andrew Lunn
> +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 & 0x1F);
> +
> + 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


Re: [PATCH net-next 09/19] net: usb: aqc111: Implement RX data path

2018-10-05 Thread Andrew Lunn
> +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