117364b80SDmitry Bezrukov // SPDX-License-Identifier: GPL-2.0-or-later 217364b80SDmitry Bezrukov /* Aquantia Corp. Aquantia AQtion USB to 5GbE Controller 317364b80SDmitry Bezrukov * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> 417364b80SDmitry Bezrukov * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net> 517364b80SDmitry Bezrukov * Copyright (C) 2002-2003 TiVo Inc. 617364b80SDmitry Bezrukov * Copyright (C) 2017-2018 ASIX 717364b80SDmitry Bezrukov * Copyright (C) 2018 Aquantia Corp. 817364b80SDmitry Bezrukov */ 917364b80SDmitry Bezrukov 1017364b80SDmitry Bezrukov #include <linux/module.h> 1117364b80SDmitry Bezrukov #include <linux/netdevice.h> 12027e6f78SDmitry Bezrukov #include <linux/ethtool.h> 1317364b80SDmitry Bezrukov #include <linux/mii.h> 1417364b80SDmitry Bezrukov #include <linux/usb.h> 1559b04eeaSDmitry Bezrukov #include <linux/crc32.h> 16df2d59a2SDmitry Bezrukov #include <linux/if_vlan.h> 1717364b80SDmitry Bezrukov #include <linux/usb/cdc.h> 1817364b80SDmitry Bezrukov #include <linux/usb/usbnet.h> 19*abbd8e7dSDmitry Bezrukov #include <linux/linkmode.h> 2017364b80SDmitry Bezrukov 21619fcb44SDmitry Bezrukov #include "aqc111.h" 22619fcb44SDmitry Bezrukov 23027e6f78SDmitry Bezrukov #define DRIVER_NAME "aqc111" 24027e6f78SDmitry Bezrukov 25619fcb44SDmitry Bezrukov static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 26619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 27619fcb44SDmitry Bezrukov { 28619fcb44SDmitry Bezrukov int ret; 29619fcb44SDmitry Bezrukov 30619fcb44SDmitry Bezrukov ret = usbnet_read_cmd_nopm(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | 31619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, size); 32619fcb44SDmitry Bezrukov 33619fcb44SDmitry Bezrukov if (unlikely(ret < 0)) 34619fcb44SDmitry Bezrukov netdev_warn(dev->net, 35619fcb44SDmitry Bezrukov "Failed to read(0x%x) reg index 0x%04x: %d\n", 36619fcb44SDmitry Bezrukov cmd, index, ret); 37619fcb44SDmitry Bezrukov 38619fcb44SDmitry Bezrukov return ret; 39619fcb44SDmitry Bezrukov } 40619fcb44SDmitry Bezrukov 41619fcb44SDmitry Bezrukov static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value, 42619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 43619fcb44SDmitry Bezrukov { 44619fcb44SDmitry Bezrukov int ret; 45619fcb44SDmitry Bezrukov 46619fcb44SDmitry Bezrukov ret = usbnet_read_cmd(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | 47619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, size); 48619fcb44SDmitry Bezrukov 49619fcb44SDmitry Bezrukov if (unlikely(ret < 0)) 50619fcb44SDmitry Bezrukov netdev_warn(dev->net, 51619fcb44SDmitry Bezrukov "Failed to read(0x%x) reg index 0x%04x: %d\n", 52619fcb44SDmitry Bezrukov cmd, index, ret); 53619fcb44SDmitry Bezrukov 54619fcb44SDmitry Bezrukov return ret; 55619fcb44SDmitry Bezrukov } 56619fcb44SDmitry Bezrukov 57f3aa095aSDmitry Bezrukov static int aqc111_read16_cmd(struct usbnet *dev, u8 cmd, u16 value, 58f3aa095aSDmitry Bezrukov u16 index, u16 *data) 59f3aa095aSDmitry Bezrukov { 60f3aa095aSDmitry Bezrukov int ret = 0; 61f3aa095aSDmitry Bezrukov 62f3aa095aSDmitry Bezrukov ret = aqc111_read_cmd(dev, cmd, value, index, sizeof(*data), data); 63f3aa095aSDmitry Bezrukov le16_to_cpus(data); 64f3aa095aSDmitry Bezrukov 65f3aa095aSDmitry Bezrukov return ret; 66f3aa095aSDmitry Bezrukov } 67f3aa095aSDmitry Bezrukov 68619fcb44SDmitry Bezrukov static int __aqc111_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, 69619fcb44SDmitry Bezrukov u16 value, u16 index, u16 size, const void *data) 70619fcb44SDmitry Bezrukov { 71619fcb44SDmitry Bezrukov int err = -ENOMEM; 72619fcb44SDmitry Bezrukov void *buf = NULL; 73619fcb44SDmitry Bezrukov 74619fcb44SDmitry Bezrukov netdev_dbg(dev->net, 75619fcb44SDmitry Bezrukov "%s cmd=%#x reqtype=%#x value=%#x index=%#x size=%d\n", 76619fcb44SDmitry Bezrukov __func__, cmd, reqtype, value, index, size); 77619fcb44SDmitry Bezrukov 78619fcb44SDmitry Bezrukov if (data) { 79619fcb44SDmitry Bezrukov buf = kmemdup(data, size, GFP_KERNEL); 80619fcb44SDmitry Bezrukov if (!buf) 81619fcb44SDmitry Bezrukov goto out; 82619fcb44SDmitry Bezrukov } 83619fcb44SDmitry Bezrukov 84619fcb44SDmitry Bezrukov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 85619fcb44SDmitry Bezrukov cmd, reqtype, value, index, buf, size, 86619fcb44SDmitry Bezrukov (cmd == AQ_PHY_POWER) ? AQ_USB_PHY_SET_TIMEOUT : 87619fcb44SDmitry Bezrukov AQ_USB_SET_TIMEOUT); 88619fcb44SDmitry Bezrukov 89619fcb44SDmitry Bezrukov if (unlikely(err < 0)) 90619fcb44SDmitry Bezrukov netdev_warn(dev->net, 91619fcb44SDmitry Bezrukov "Failed to write(0x%x) reg index 0x%04x: %d\n", 92619fcb44SDmitry Bezrukov cmd, index, err); 93619fcb44SDmitry Bezrukov kfree(buf); 94619fcb44SDmitry Bezrukov 95619fcb44SDmitry Bezrukov out: 96619fcb44SDmitry Bezrukov return err; 97619fcb44SDmitry Bezrukov } 98619fcb44SDmitry Bezrukov 99619fcb44SDmitry Bezrukov static int aqc111_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 100619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 101619fcb44SDmitry Bezrukov { 102619fcb44SDmitry Bezrukov int ret; 103619fcb44SDmitry Bezrukov 104619fcb44SDmitry Bezrukov ret = __aqc111_write_cmd(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 105619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, size, data); 106619fcb44SDmitry Bezrukov 107619fcb44SDmitry Bezrukov return ret; 108619fcb44SDmitry Bezrukov } 109619fcb44SDmitry Bezrukov 110619fcb44SDmitry Bezrukov static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value, 111619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 112619fcb44SDmitry Bezrukov { 113619fcb44SDmitry Bezrukov int ret; 114619fcb44SDmitry Bezrukov 115619fcb44SDmitry Bezrukov if (usb_autopm_get_interface(dev->intf) < 0) 116619fcb44SDmitry Bezrukov return -ENODEV; 117619fcb44SDmitry Bezrukov 118619fcb44SDmitry Bezrukov ret = __aqc111_write_cmd(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 119619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, size, data); 120619fcb44SDmitry Bezrukov 121619fcb44SDmitry Bezrukov usb_autopm_put_interface(dev->intf); 122619fcb44SDmitry Bezrukov 123619fcb44SDmitry Bezrukov return ret; 124619fcb44SDmitry Bezrukov } 125619fcb44SDmitry Bezrukov 126f3aa095aSDmitry Bezrukov static int aqc111_write16_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 127f3aa095aSDmitry Bezrukov u16 index, u16 *data) 128f3aa095aSDmitry Bezrukov { 129f3aa095aSDmitry Bezrukov u16 tmp = *data; 130f3aa095aSDmitry Bezrukov 131f3aa095aSDmitry Bezrukov cpu_to_le16s(&tmp); 132f3aa095aSDmitry Bezrukov 133f3aa095aSDmitry Bezrukov return aqc111_write_cmd_nopm(dev, cmd, value, index, sizeof(tmp), &tmp); 134f3aa095aSDmitry Bezrukov } 135f3aa095aSDmitry Bezrukov 136f3aa095aSDmitry Bezrukov static int aqc111_write16_cmd(struct usbnet *dev, u8 cmd, u16 value, 137f3aa095aSDmitry Bezrukov u16 index, u16 *data) 138f3aa095aSDmitry Bezrukov { 139f3aa095aSDmitry Bezrukov u16 tmp = *data; 140f3aa095aSDmitry Bezrukov 141f3aa095aSDmitry Bezrukov cpu_to_le16s(&tmp); 142f3aa095aSDmitry Bezrukov 143f3aa095aSDmitry Bezrukov return aqc111_write_cmd(dev, cmd, value, index, sizeof(tmp), &tmp); 144f3aa095aSDmitry Bezrukov } 145f3aa095aSDmitry Bezrukov 14633cd597fSDmitry Bezrukov static int aqc111_write32_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 14733cd597fSDmitry Bezrukov u16 index, u32 *data) 14833cd597fSDmitry Bezrukov { 14933cd597fSDmitry Bezrukov u32 tmp = *data; 15033cd597fSDmitry Bezrukov 15133cd597fSDmitry Bezrukov cpu_to_le32s(&tmp); 15233cd597fSDmitry Bezrukov 15333cd597fSDmitry Bezrukov return aqc111_write_cmd_nopm(dev, cmd, value, index, sizeof(tmp), &tmp); 15433cd597fSDmitry Bezrukov } 15533cd597fSDmitry Bezrukov 15633cd597fSDmitry Bezrukov static int aqc111_write32_cmd(struct usbnet *dev, u8 cmd, u16 value, 15733cd597fSDmitry Bezrukov u16 index, u32 *data) 15833cd597fSDmitry Bezrukov { 15933cd597fSDmitry Bezrukov u32 tmp = *data; 16033cd597fSDmitry Bezrukov 16133cd597fSDmitry Bezrukov cpu_to_le32s(&tmp); 16233cd597fSDmitry Bezrukov 16333cd597fSDmitry Bezrukov return aqc111_write_cmd(dev, cmd, value, index, sizeof(tmp), &tmp); 16433cd597fSDmitry Bezrukov } 16533cd597fSDmitry Bezrukov 16659b04eeaSDmitry Bezrukov static int aqc111_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, 16759b04eeaSDmitry Bezrukov u16 index, u16 size, void *data) 16859b04eeaSDmitry Bezrukov { 16959b04eeaSDmitry Bezrukov return usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 17059b04eeaSDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, 17159b04eeaSDmitry Bezrukov size); 17259b04eeaSDmitry Bezrukov } 17359b04eeaSDmitry Bezrukov 17459b04eeaSDmitry Bezrukov static int aqc111_write16_cmd_async(struct usbnet *dev, u8 cmd, u16 value, 17559b04eeaSDmitry Bezrukov u16 index, u16 *data) 17659b04eeaSDmitry Bezrukov { 17759b04eeaSDmitry Bezrukov u16 tmp = *data; 17859b04eeaSDmitry Bezrukov 17959b04eeaSDmitry Bezrukov cpu_to_le16s(&tmp); 18059b04eeaSDmitry Bezrukov 18159b04eeaSDmitry Bezrukov return aqc111_write_cmd_async(dev, cmd, value, index, 18259b04eeaSDmitry Bezrukov sizeof(tmp), &tmp); 18359b04eeaSDmitry Bezrukov } 18459b04eeaSDmitry Bezrukov 185027e6f78SDmitry Bezrukov static void aqc111_get_drvinfo(struct net_device *net, 186027e6f78SDmitry Bezrukov struct ethtool_drvinfo *info) 187027e6f78SDmitry Bezrukov { 188027e6f78SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 189027e6f78SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 190027e6f78SDmitry Bezrukov 191027e6f78SDmitry Bezrukov /* Inherit standard device info */ 192027e6f78SDmitry Bezrukov usbnet_get_drvinfo(net, info); 193027e6f78SDmitry Bezrukov strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver)); 194027e6f78SDmitry Bezrukov snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u", 195027e6f78SDmitry Bezrukov aqc111_data->fw_ver.major, 196027e6f78SDmitry Bezrukov aqc111_data->fw_ver.minor, 197027e6f78SDmitry Bezrukov aqc111_data->fw_ver.rev); 198027e6f78SDmitry Bezrukov info->eedump_len = 0x00; 199027e6f78SDmitry Bezrukov info->regdump_len = 0x00; 200027e6f78SDmitry Bezrukov } 201027e6f78SDmitry Bezrukov 202*abbd8e7dSDmitry Bezrukov static void aqc111_speed_to_link_mode(u32 speed, 203*abbd8e7dSDmitry Bezrukov struct ethtool_link_ksettings *elk) 204*abbd8e7dSDmitry Bezrukov { 205*abbd8e7dSDmitry Bezrukov switch (speed) { 206*abbd8e7dSDmitry Bezrukov case SPEED_5000: 207*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 208*abbd8e7dSDmitry Bezrukov 5000baseT_Full); 209*abbd8e7dSDmitry Bezrukov break; 210*abbd8e7dSDmitry Bezrukov case SPEED_2500: 211*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 212*abbd8e7dSDmitry Bezrukov 2500baseT_Full); 213*abbd8e7dSDmitry Bezrukov break; 214*abbd8e7dSDmitry Bezrukov case SPEED_1000: 215*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 216*abbd8e7dSDmitry Bezrukov 1000baseT_Full); 217*abbd8e7dSDmitry Bezrukov break; 218*abbd8e7dSDmitry Bezrukov case SPEED_100: 219*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, advertising, 220*abbd8e7dSDmitry Bezrukov 100baseT_Full); 221*abbd8e7dSDmitry Bezrukov break; 222*abbd8e7dSDmitry Bezrukov } 223*abbd8e7dSDmitry Bezrukov } 224*abbd8e7dSDmitry Bezrukov 225*abbd8e7dSDmitry Bezrukov static int aqc111_get_link_ksettings(struct net_device *net, 226*abbd8e7dSDmitry Bezrukov struct ethtool_link_ksettings *elk) 227*abbd8e7dSDmitry Bezrukov { 228*abbd8e7dSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 229*abbd8e7dSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 230*abbd8e7dSDmitry Bezrukov enum usb_device_speed usb_speed = dev->udev->speed; 231*abbd8e7dSDmitry Bezrukov u32 speed = SPEED_UNKNOWN; 232*abbd8e7dSDmitry Bezrukov 233*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_zero_link_mode(elk, supported); 234*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 235*abbd8e7dSDmitry Bezrukov 100baseT_Full); 236*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 237*abbd8e7dSDmitry Bezrukov 1000baseT_Full); 238*abbd8e7dSDmitry Bezrukov if (usb_speed == USB_SPEED_SUPER) { 239*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 240*abbd8e7dSDmitry Bezrukov 2500baseT_Full); 241*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, 242*abbd8e7dSDmitry Bezrukov 5000baseT_Full); 243*abbd8e7dSDmitry Bezrukov } 244*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, TP); 245*abbd8e7dSDmitry Bezrukov ethtool_link_ksettings_add_link_mode(elk, supported, Autoneg); 246*abbd8e7dSDmitry Bezrukov 247*abbd8e7dSDmitry Bezrukov elk->base.port = PORT_TP; 248*abbd8e7dSDmitry Bezrukov elk->base.transceiver = XCVR_INTERNAL; 249*abbd8e7dSDmitry Bezrukov 250*abbd8e7dSDmitry Bezrukov elk->base.mdio_support = 0x00; /*Not supported*/ 251*abbd8e7dSDmitry Bezrukov 252*abbd8e7dSDmitry Bezrukov if (aqc111_data->autoneg) 253*abbd8e7dSDmitry Bezrukov linkmode_copy(elk->link_modes.advertising, 254*abbd8e7dSDmitry Bezrukov elk->link_modes.supported); 255*abbd8e7dSDmitry Bezrukov else 256*abbd8e7dSDmitry Bezrukov aqc111_speed_to_link_mode(aqc111_data->advertised_speed, elk); 257*abbd8e7dSDmitry Bezrukov 258*abbd8e7dSDmitry Bezrukov elk->base.autoneg = aqc111_data->autoneg; 259*abbd8e7dSDmitry Bezrukov 260*abbd8e7dSDmitry Bezrukov switch (aqc111_data->link_speed) { 261*abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_5G: 262*abbd8e7dSDmitry Bezrukov speed = SPEED_5000; 263*abbd8e7dSDmitry Bezrukov break; 264*abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_2_5G: 265*abbd8e7dSDmitry Bezrukov speed = SPEED_2500; 266*abbd8e7dSDmitry Bezrukov break; 267*abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_1G: 268*abbd8e7dSDmitry Bezrukov speed = SPEED_1000; 269*abbd8e7dSDmitry Bezrukov break; 270*abbd8e7dSDmitry Bezrukov case AQ_INT_SPEED_100M: 271*abbd8e7dSDmitry Bezrukov speed = SPEED_100; 272*abbd8e7dSDmitry Bezrukov break; 273*abbd8e7dSDmitry Bezrukov } 274*abbd8e7dSDmitry Bezrukov elk->base.duplex = DUPLEX_FULL; 275*abbd8e7dSDmitry Bezrukov elk->base.speed = speed; 276*abbd8e7dSDmitry Bezrukov 277*abbd8e7dSDmitry Bezrukov return 0; 278*abbd8e7dSDmitry Bezrukov } 279*abbd8e7dSDmitry Bezrukov 2807b8b0654SDmitry Bezrukov static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed) 2817b8b0654SDmitry Bezrukov { 2827b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 2837b8b0654SDmitry Bezrukov 2847b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_ADV_MASK; 2857b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_PAUSE; 2867b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ASYM_PAUSE; 2877b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_DOWNSHIFT; 2887b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_DSH_RETRIES_MASK; 2897b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= (3 << AQ_DSH_RETRIES_SHIFT) & 2907b8b0654SDmitry Bezrukov AQ_DSH_RETRIES_MASK; 2917b8b0654SDmitry Bezrukov 2927b8b0654SDmitry Bezrukov if (autoneg == AUTONEG_ENABLE) { 2937b8b0654SDmitry Bezrukov switch (speed) { 2947b8b0654SDmitry Bezrukov case SPEED_5000: 2957b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_5G; 2967b8b0654SDmitry Bezrukov /* fall-through */ 2977b8b0654SDmitry Bezrukov case SPEED_2500: 2987b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_2G5; 2997b8b0654SDmitry Bezrukov /* fall-through */ 3007b8b0654SDmitry Bezrukov case SPEED_1000: 3017b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_1G; 3027b8b0654SDmitry Bezrukov /* fall-through */ 3037b8b0654SDmitry Bezrukov case SPEED_100: 3047b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_100M; 3057b8b0654SDmitry Bezrukov /* fall-through */ 3067b8b0654SDmitry Bezrukov } 3077b8b0654SDmitry Bezrukov } else { 3087b8b0654SDmitry Bezrukov switch (speed) { 3097b8b0654SDmitry Bezrukov case SPEED_5000: 3107b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_5G; 3117b8b0654SDmitry Bezrukov break; 3127b8b0654SDmitry Bezrukov case SPEED_2500: 3137b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_2G5; 3147b8b0654SDmitry Bezrukov break; 3157b8b0654SDmitry Bezrukov case SPEED_1000: 3167b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_1G; 3177b8b0654SDmitry Bezrukov break; 3187b8b0654SDmitry Bezrukov case SPEED_100: 3197b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_100M; 3207b8b0654SDmitry Bezrukov break; 3217b8b0654SDmitry Bezrukov } 3227b8b0654SDmitry Bezrukov } 3237b8b0654SDmitry Bezrukov 3247b8b0654SDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, &aqc111_data->phy_cfg); 3257b8b0654SDmitry Bezrukov } 3267b8b0654SDmitry Bezrukov 327*abbd8e7dSDmitry Bezrukov static int aqc111_set_link_ksettings(struct net_device *net, 328*abbd8e7dSDmitry Bezrukov const struct ethtool_link_ksettings *elk) 329*abbd8e7dSDmitry Bezrukov { 330*abbd8e7dSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 331*abbd8e7dSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 332*abbd8e7dSDmitry Bezrukov enum usb_device_speed usb_speed = dev->udev->speed; 333*abbd8e7dSDmitry Bezrukov u8 autoneg = elk->base.autoneg; 334*abbd8e7dSDmitry Bezrukov u32 speed = elk->base.speed; 335*abbd8e7dSDmitry Bezrukov 336*abbd8e7dSDmitry Bezrukov if (autoneg == AUTONEG_ENABLE) { 337*abbd8e7dSDmitry Bezrukov if (aqc111_data->autoneg != AUTONEG_ENABLE) { 338*abbd8e7dSDmitry Bezrukov aqc111_data->autoneg = AUTONEG_ENABLE; 339*abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed = 340*abbd8e7dSDmitry Bezrukov (usb_speed == USB_SPEED_SUPER) ? 341*abbd8e7dSDmitry Bezrukov SPEED_5000 : SPEED_1000; 342*abbd8e7dSDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 343*abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed); 344*abbd8e7dSDmitry Bezrukov } 345*abbd8e7dSDmitry Bezrukov } else { 346*abbd8e7dSDmitry Bezrukov if (speed != SPEED_100 && 347*abbd8e7dSDmitry Bezrukov speed != SPEED_1000 && 348*abbd8e7dSDmitry Bezrukov speed != SPEED_2500 && 349*abbd8e7dSDmitry Bezrukov speed != SPEED_5000 && 350*abbd8e7dSDmitry Bezrukov speed != SPEED_UNKNOWN) 351*abbd8e7dSDmitry Bezrukov return -EINVAL; 352*abbd8e7dSDmitry Bezrukov 353*abbd8e7dSDmitry Bezrukov if (elk->base.duplex != DUPLEX_FULL) 354*abbd8e7dSDmitry Bezrukov return -EINVAL; 355*abbd8e7dSDmitry Bezrukov 356*abbd8e7dSDmitry Bezrukov if (usb_speed != USB_SPEED_SUPER && speed > SPEED_1000) 357*abbd8e7dSDmitry Bezrukov return -EINVAL; 358*abbd8e7dSDmitry Bezrukov 359*abbd8e7dSDmitry Bezrukov aqc111_data->autoneg = AUTONEG_DISABLE; 360*abbd8e7dSDmitry Bezrukov if (speed != SPEED_UNKNOWN) 361*abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed = speed; 362*abbd8e7dSDmitry Bezrukov 363*abbd8e7dSDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 364*abbd8e7dSDmitry Bezrukov aqc111_data->advertised_speed); 365*abbd8e7dSDmitry Bezrukov } 366*abbd8e7dSDmitry Bezrukov 367*abbd8e7dSDmitry Bezrukov return 0; 368*abbd8e7dSDmitry Bezrukov } 369*abbd8e7dSDmitry Bezrukov 370027e6f78SDmitry Bezrukov static const struct ethtool_ops aqc111_ethtool_ops = { 371027e6f78SDmitry Bezrukov .get_drvinfo = aqc111_get_drvinfo, 372027e6f78SDmitry Bezrukov .get_msglevel = usbnet_get_msglevel, 373027e6f78SDmitry Bezrukov .set_msglevel = usbnet_set_msglevel, 374027e6f78SDmitry Bezrukov .get_link = ethtool_op_get_link, 375*abbd8e7dSDmitry Bezrukov .get_link_ksettings = aqc111_get_link_ksettings, 376*abbd8e7dSDmitry Bezrukov .set_link_ksettings = aqc111_set_link_ksettings 377027e6f78SDmitry Bezrukov }; 378027e6f78SDmitry Bezrukov 379a4017cc2SDmitry Bezrukov static int aqc111_change_mtu(struct net_device *net, int new_mtu) 380a4017cc2SDmitry Bezrukov { 381a4017cc2SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 382a4017cc2SDmitry Bezrukov u16 reg16 = 0; 383a4017cc2SDmitry Bezrukov u8 buf[5]; 384a4017cc2SDmitry Bezrukov 385a4017cc2SDmitry Bezrukov net->mtu = new_mtu; 386a4017cc2SDmitry Bezrukov dev->hard_mtu = net->mtu + net->hard_header_len; 387a4017cc2SDmitry Bezrukov 388a4017cc2SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 389a4017cc2SDmitry Bezrukov 2, ®16); 390a4017cc2SDmitry Bezrukov if (net->mtu > 1500) 391a4017cc2SDmitry Bezrukov reg16 |= SFR_MEDIUM_JUMBO_EN; 392a4017cc2SDmitry Bezrukov else 393a4017cc2SDmitry Bezrukov reg16 &= ~SFR_MEDIUM_JUMBO_EN; 394a4017cc2SDmitry Bezrukov 395a4017cc2SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 396a4017cc2SDmitry Bezrukov 2, ®16); 397a4017cc2SDmitry Bezrukov 398a4017cc2SDmitry Bezrukov if (dev->net->mtu > 12500 && dev->net->mtu <= 16334) { 399a4017cc2SDmitry Bezrukov memcpy(buf, &AQC111_BULKIN_SIZE[2], 5); 400a4017cc2SDmitry Bezrukov /* RX bulk configuration */ 401a4017cc2SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 402a4017cc2SDmitry Bezrukov 5, 5, buf); 403a4017cc2SDmitry Bezrukov } 404a4017cc2SDmitry Bezrukov 405a4017cc2SDmitry Bezrukov /* Set high low water level */ 406a4017cc2SDmitry Bezrukov if (dev->net->mtu <= 4500) 407a4017cc2SDmitry Bezrukov reg16 = 0x0810; 408a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 9500) 409a4017cc2SDmitry Bezrukov reg16 = 0x1020; 410a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 12500) 411a4017cc2SDmitry Bezrukov reg16 = 0x1420; 412a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 16334) 413a4017cc2SDmitry Bezrukov reg16 = 0x1A20; 414a4017cc2SDmitry Bezrukov 415a4017cc2SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW, 416a4017cc2SDmitry Bezrukov 2, ®16); 417a4017cc2SDmitry Bezrukov 418a4017cc2SDmitry Bezrukov return 0; 419a4017cc2SDmitry Bezrukov } 420a4017cc2SDmitry Bezrukov 421df2d59a2SDmitry Bezrukov static int aqc111_set_mac_addr(struct net_device *net, void *p) 422df2d59a2SDmitry Bezrukov { 423df2d59a2SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 424df2d59a2SDmitry Bezrukov int ret = 0; 425df2d59a2SDmitry Bezrukov 426df2d59a2SDmitry Bezrukov ret = eth_mac_addr(net, p); 427df2d59a2SDmitry Bezrukov if (ret < 0) 428df2d59a2SDmitry Bezrukov return ret; 429df2d59a2SDmitry Bezrukov 430df2d59a2SDmitry Bezrukov /* Set the MAC address */ 431df2d59a2SDmitry Bezrukov return aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN, 432df2d59a2SDmitry Bezrukov ETH_ALEN, net->dev_addr); 433df2d59a2SDmitry Bezrukov } 434df2d59a2SDmitry Bezrukov 4354189673aSDmitry Bezrukov static int aqc111_vlan_rx_kill_vid(struct net_device *net, 4364189673aSDmitry Bezrukov __be16 proto, u16 vid) 4374189673aSDmitry Bezrukov { 4384189673aSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 4394189673aSDmitry Bezrukov u8 vlan_ctrl = 0; 4404189673aSDmitry Bezrukov u16 reg16 = 0; 4414189673aSDmitry Bezrukov u8 reg8 = 0; 4424189673aSDmitry Bezrukov 4434189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4444189673aSDmitry Bezrukov vlan_ctrl = reg8; 4454189673aSDmitry Bezrukov 4464189673aSDmitry Bezrukov /* Address */ 4474189673aSDmitry Bezrukov reg8 = (vid / 16); 4484189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8); 4494189673aSDmitry Bezrukov /* Data */ 4504189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD; 4514189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4524189673aSDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 4534189673aSDmitry Bezrukov reg16 &= ~(1 << (vid % 16)); 4544189673aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 4554189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE; 4564189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4574189673aSDmitry Bezrukov 4584189673aSDmitry Bezrukov return 0; 4594189673aSDmitry Bezrukov } 4604189673aSDmitry Bezrukov 4614189673aSDmitry Bezrukov static int aqc111_vlan_rx_add_vid(struct net_device *net, __be16 proto, u16 vid) 4624189673aSDmitry Bezrukov { 4634189673aSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 4644189673aSDmitry Bezrukov u8 vlan_ctrl = 0; 4654189673aSDmitry Bezrukov u16 reg16 = 0; 4664189673aSDmitry Bezrukov u8 reg8 = 0; 4674189673aSDmitry Bezrukov 4684189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4694189673aSDmitry Bezrukov vlan_ctrl = reg8; 4704189673aSDmitry Bezrukov 4714189673aSDmitry Bezrukov /* Address */ 4724189673aSDmitry Bezrukov reg8 = (vid / 16); 4734189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_ADDRESS, 1, 1, ®8); 4744189673aSDmitry Bezrukov /* Data */ 4754189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_RD; 4764189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4774189673aSDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 4784189673aSDmitry Bezrukov reg16 |= (1 << (vid % 16)); 4794189673aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_DATA0, 2, ®16); 4804189673aSDmitry Bezrukov reg8 = vlan_ctrl | SFR_VLAN_CONTROL_WE; 4814189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 1, 1, ®8); 4824189673aSDmitry Bezrukov 4834189673aSDmitry Bezrukov return 0; 4844189673aSDmitry Bezrukov } 4854189673aSDmitry Bezrukov 48659b04eeaSDmitry Bezrukov static void aqc111_set_rx_mode(struct net_device *net) 48759b04eeaSDmitry Bezrukov { 48859b04eeaSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 48959b04eeaSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 49059b04eeaSDmitry Bezrukov int mc_count = 0; 49159b04eeaSDmitry Bezrukov 49259b04eeaSDmitry Bezrukov mc_count = netdev_mc_count(net); 49359b04eeaSDmitry Bezrukov 49459b04eeaSDmitry Bezrukov aqc111_data->rxctl &= ~(SFR_RX_CTL_PRO | SFR_RX_CTL_AMALL | 49559b04eeaSDmitry Bezrukov SFR_RX_CTL_AM); 49659b04eeaSDmitry Bezrukov 49759b04eeaSDmitry Bezrukov if (net->flags & IFF_PROMISC) { 49859b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_PRO; 49959b04eeaSDmitry Bezrukov } else if ((net->flags & IFF_ALLMULTI) || mc_count > AQ_MAX_MCAST) { 50059b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_AMALL; 50159b04eeaSDmitry Bezrukov } else if (!netdev_mc_empty(net)) { 50259b04eeaSDmitry Bezrukov u8 m_filter[AQ_MCAST_FILTER_SIZE] = { 0 }; 50359b04eeaSDmitry Bezrukov struct netdev_hw_addr *ha = NULL; 50459b04eeaSDmitry Bezrukov u32 crc_bits = 0; 50559b04eeaSDmitry Bezrukov 50659b04eeaSDmitry Bezrukov netdev_for_each_mc_addr(ha, net) { 50759b04eeaSDmitry Bezrukov crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; 50859b04eeaSDmitry Bezrukov m_filter[crc_bits >> 3] |= BIT(crc_bits & 7); 50959b04eeaSDmitry Bezrukov } 51059b04eeaSDmitry Bezrukov 51159b04eeaSDmitry Bezrukov aqc111_write_cmd_async(dev, AQ_ACCESS_MAC, 51259b04eeaSDmitry Bezrukov SFR_MULTI_FILTER_ARRY, 51359b04eeaSDmitry Bezrukov AQ_MCAST_FILTER_SIZE, 51459b04eeaSDmitry Bezrukov AQ_MCAST_FILTER_SIZE, m_filter); 51559b04eeaSDmitry Bezrukov 51659b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_AM; 51759b04eeaSDmitry Bezrukov } 51859b04eeaSDmitry Bezrukov 51959b04eeaSDmitry Bezrukov aqc111_write16_cmd_async(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 52059b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 52159b04eeaSDmitry Bezrukov } 52259b04eeaSDmitry Bezrukov 5236649d2a6SDmitry Bezrukov static int aqc111_set_features(struct net_device *net, 5246649d2a6SDmitry Bezrukov netdev_features_t features) 5256649d2a6SDmitry Bezrukov { 5266649d2a6SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 5276649d2a6SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 5286649d2a6SDmitry Bezrukov netdev_features_t changed = net->features ^ features; 5294189673aSDmitry Bezrukov u16 reg16 = 0; 5306649d2a6SDmitry Bezrukov u8 reg8 = 0; 5316649d2a6SDmitry Bezrukov 5326649d2a6SDmitry Bezrukov if (changed & NETIF_F_IP_CSUM) { 5336649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 5346649d2a6SDmitry Bezrukov reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP; 5356649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 5366649d2a6SDmitry Bezrukov 1, 1, ®8); 5376649d2a6SDmitry Bezrukov } 5386649d2a6SDmitry Bezrukov 5396649d2a6SDmitry Bezrukov if (changed & NETIF_F_IPV6_CSUM) { 5406649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 5416649d2a6SDmitry Bezrukov reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6; 5426649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 5436649d2a6SDmitry Bezrukov 1, 1, ®8); 5446649d2a6SDmitry Bezrukov } 5456649d2a6SDmitry Bezrukov 5466649d2a6SDmitry Bezrukov if (changed & NETIF_F_RXCSUM) { 5476649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8); 5486649d2a6SDmitry Bezrukov if (features & NETIF_F_RXCSUM) { 5496649d2a6SDmitry Bezrukov aqc111_data->rx_checksum = 1; 5506649d2a6SDmitry Bezrukov reg8 &= ~(SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 5516649d2a6SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6); 5526649d2a6SDmitry Bezrukov } else { 5536649d2a6SDmitry Bezrukov aqc111_data->rx_checksum = 0; 5546649d2a6SDmitry Bezrukov reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 5556649d2a6SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6; 5566649d2a6SDmitry Bezrukov } 5576649d2a6SDmitry Bezrukov 5586649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 5596649d2a6SDmitry Bezrukov 1, 1, ®8); 5606649d2a6SDmitry Bezrukov } 5614189673aSDmitry Bezrukov if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) { 5624189673aSDmitry Bezrukov if (features & NETIF_F_HW_VLAN_CTAG_FILTER) { 5634189673aSDmitry Bezrukov u16 i = 0; 5644189673aSDmitry Bezrukov 5654189673aSDmitry Bezrukov for (i = 0; i < 256; i++) { 5664189673aSDmitry Bezrukov /* Address */ 5674189673aSDmitry Bezrukov reg8 = i; 5684189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 5694189673aSDmitry Bezrukov SFR_VLAN_ID_ADDRESS, 5704189673aSDmitry Bezrukov 1, 1, ®8); 5714189673aSDmitry Bezrukov /* Data */ 5724189673aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, 5734189673aSDmitry Bezrukov SFR_VLAN_ID_DATA0, 5744189673aSDmitry Bezrukov 2, ®16); 5754189673aSDmitry Bezrukov reg8 = SFR_VLAN_CONTROL_WE; 5764189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 5774189673aSDmitry Bezrukov SFR_VLAN_ID_CONTROL, 5784189673aSDmitry Bezrukov 1, 1, ®8); 5794189673aSDmitry Bezrukov } 5804189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 5814189673aSDmitry Bezrukov 1, 1, ®8); 5824189673aSDmitry Bezrukov reg8 |= SFR_VLAN_CONTROL_VFE; 5834189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 5844189673aSDmitry Bezrukov SFR_VLAN_ID_CONTROL, 1, 1, ®8); 5854189673aSDmitry Bezrukov } else { 5864189673aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 5874189673aSDmitry Bezrukov 1, 1, ®8); 5884189673aSDmitry Bezrukov reg8 &= ~SFR_VLAN_CONTROL_VFE; 5894189673aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, 5904189673aSDmitry Bezrukov SFR_VLAN_ID_CONTROL, 1, 1, ®8); 5914189673aSDmitry Bezrukov } 5924189673aSDmitry Bezrukov } 5934189673aSDmitry Bezrukov 5946649d2a6SDmitry Bezrukov return 0; 5956649d2a6SDmitry Bezrukov } 5966649d2a6SDmitry Bezrukov 5977cea2d40SDmitry Bezrukov static const struct net_device_ops aqc111_netdev_ops = { 5987cea2d40SDmitry Bezrukov .ndo_open = usbnet_open, 5997cea2d40SDmitry Bezrukov .ndo_stop = usbnet_stop, 6004a3576d2SDmitry Bezrukov .ndo_start_xmit = usbnet_start_xmit, 6014a3576d2SDmitry Bezrukov .ndo_tx_timeout = usbnet_tx_timeout, 6024a3576d2SDmitry Bezrukov .ndo_get_stats64 = usbnet_get_stats64, 603a4017cc2SDmitry Bezrukov .ndo_change_mtu = aqc111_change_mtu, 604df2d59a2SDmitry Bezrukov .ndo_set_mac_address = aqc111_set_mac_addr, 605df2d59a2SDmitry Bezrukov .ndo_validate_addr = eth_validate_addr, 6064189673aSDmitry Bezrukov .ndo_vlan_rx_add_vid = aqc111_vlan_rx_add_vid, 6074189673aSDmitry Bezrukov .ndo_vlan_rx_kill_vid = aqc111_vlan_rx_kill_vid, 60859b04eeaSDmitry Bezrukov .ndo_set_rx_mode = aqc111_set_rx_mode, 6096649d2a6SDmitry Bezrukov .ndo_set_features = aqc111_set_features, 6107cea2d40SDmitry Bezrukov }; 6117cea2d40SDmitry Bezrukov 612df2d59a2SDmitry Bezrukov static int aqc111_read_perm_mac(struct usbnet *dev) 613df2d59a2SDmitry Bezrukov { 614df2d59a2SDmitry Bezrukov u8 buf[ETH_ALEN]; 615df2d59a2SDmitry Bezrukov int ret; 616df2d59a2SDmitry Bezrukov 617df2d59a2SDmitry Bezrukov ret = aqc111_read_cmd(dev, AQ_FLASH_PARAMETERS, 0, 0, ETH_ALEN, buf); 618df2d59a2SDmitry Bezrukov if (ret < 0) 619df2d59a2SDmitry Bezrukov goto out; 620df2d59a2SDmitry Bezrukov 621df2d59a2SDmitry Bezrukov ether_addr_copy(dev->net->perm_addr, buf); 622df2d59a2SDmitry Bezrukov 623df2d59a2SDmitry Bezrukov return 0; 624df2d59a2SDmitry Bezrukov out: 625df2d59a2SDmitry Bezrukov return ret; 626df2d59a2SDmitry Bezrukov } 627df2d59a2SDmitry Bezrukov 62833cd597fSDmitry Bezrukov static void aqc111_read_fw_version(struct usbnet *dev, 62933cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data) 63033cd597fSDmitry Bezrukov { 63133cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR, 63233cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.major); 63333cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR, 63433cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.minor); 63533cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV, 63633cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.rev); 63733cd597fSDmitry Bezrukov 63833cd597fSDmitry Bezrukov if (aqc111_data->fw_ver.major & 0x80) 63933cd597fSDmitry Bezrukov aqc111_data->fw_ver.major &= ~0x80; 64033cd597fSDmitry Bezrukov } 64133cd597fSDmitry Bezrukov 6427cea2d40SDmitry Bezrukov static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf) 6437cea2d40SDmitry Bezrukov { 6447cea2d40SDmitry Bezrukov struct usb_device *udev = interface_to_usbdev(intf); 6457b8b0654SDmitry Bezrukov enum usb_device_speed usb_speed = udev->speed; 64633cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data; 6477cea2d40SDmitry Bezrukov int ret; 6487cea2d40SDmitry Bezrukov 6497cea2d40SDmitry Bezrukov /* Check if vendor configuration */ 6507cea2d40SDmitry Bezrukov if (udev->actconfig->desc.bConfigurationValue != 1) { 6517cea2d40SDmitry Bezrukov usb_driver_set_configuration(udev, 1); 6527cea2d40SDmitry Bezrukov return -ENODEV; 6537cea2d40SDmitry Bezrukov } 6547cea2d40SDmitry Bezrukov 6557cea2d40SDmitry Bezrukov usb_reset_configuration(dev->udev); 6567cea2d40SDmitry Bezrukov 6577cea2d40SDmitry Bezrukov ret = usbnet_get_endpoints(dev, intf); 6587cea2d40SDmitry Bezrukov if (ret < 0) { 6597cea2d40SDmitry Bezrukov netdev_dbg(dev->net, "usbnet_get_endpoints failed"); 6607cea2d40SDmitry Bezrukov return ret; 6617cea2d40SDmitry Bezrukov } 6627cea2d40SDmitry Bezrukov 66333cd597fSDmitry Bezrukov aqc111_data = kzalloc(sizeof(*aqc111_data), GFP_KERNEL); 66433cd597fSDmitry Bezrukov if (!aqc111_data) 66533cd597fSDmitry Bezrukov return -ENOMEM; 66633cd597fSDmitry Bezrukov 66733cd597fSDmitry Bezrukov /* store aqc111_data pointer in device data field */ 66833cd597fSDmitry Bezrukov dev->driver_priv = aqc111_data; 66933cd597fSDmitry Bezrukov 670df2d59a2SDmitry Bezrukov /* Init the MAC address */ 671df2d59a2SDmitry Bezrukov ret = aqc111_read_perm_mac(dev); 672df2d59a2SDmitry Bezrukov if (ret) 673df2d59a2SDmitry Bezrukov goto out; 674df2d59a2SDmitry Bezrukov 675df2d59a2SDmitry Bezrukov ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr); 6764a3576d2SDmitry Bezrukov 677361459cdSDmitry Bezrukov /* Set Rx urb size */ 678361459cdSDmitry Bezrukov dev->rx_urb_size = URB_SIZE; 679361459cdSDmitry Bezrukov 6804a3576d2SDmitry Bezrukov /* Set TX needed headroom & tailroom */ 6814a3576d2SDmitry Bezrukov dev->net->needed_headroom += sizeof(u64); 6824a3576d2SDmitry Bezrukov dev->net->needed_tailroom += sizeof(u64); 6834a3576d2SDmitry Bezrukov 684a4017cc2SDmitry Bezrukov dev->net->max_mtu = 16334; 685a4017cc2SDmitry Bezrukov 6867cea2d40SDmitry Bezrukov dev->net->netdev_ops = &aqc111_netdev_ops; 687027e6f78SDmitry Bezrukov dev->net->ethtool_ops = &aqc111_ethtool_ops; 6887cea2d40SDmitry Bezrukov 6894a3576d2SDmitry Bezrukov if (usb_device_no_sg_constraint(dev->udev)) 6904a3576d2SDmitry Bezrukov dev->can_dma_sg = 1; 6914a3576d2SDmitry Bezrukov 6924a3576d2SDmitry Bezrukov dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE; 6934a3576d2SDmitry Bezrukov dev->net->features |= AQ_SUPPORT_FEATURE; 6947afa6c98SDmitry Bezrukov dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE; 6954a3576d2SDmitry Bezrukov 696de074e7aSDmitry Bezrukov netif_set_gso_max_size(dev->net, 65535); 697de074e7aSDmitry Bezrukov 69833cd597fSDmitry Bezrukov aqc111_read_fw_version(dev, aqc111_data); 6997b8b0654SDmitry Bezrukov aqc111_data->autoneg = AUTONEG_ENABLE; 7007b8b0654SDmitry Bezrukov aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ? 7017b8b0654SDmitry Bezrukov SPEED_5000 : SPEED_1000; 70233cd597fSDmitry Bezrukov 7037cea2d40SDmitry Bezrukov return 0; 704df2d59a2SDmitry Bezrukov 705df2d59a2SDmitry Bezrukov out: 706df2d59a2SDmitry Bezrukov kfree(aqc111_data); 707df2d59a2SDmitry Bezrukov return ret; 7087cea2d40SDmitry Bezrukov } 7097cea2d40SDmitry Bezrukov 7107cea2d40SDmitry Bezrukov static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf) 7117cea2d40SDmitry Bezrukov { 71233cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 713f3aa095aSDmitry Bezrukov u16 reg16; 714f3aa095aSDmitry Bezrukov 715f3aa095aSDmitry Bezrukov /* Force bz */ 716f3aa095aSDmitry Bezrukov reg16 = SFR_PHYPWR_RSTCTL_BZ; 717f3aa095aSDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 718f3aa095aSDmitry Bezrukov 2, ®16); 719f3aa095aSDmitry Bezrukov reg16 = 0; 720f3aa095aSDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 721f3aa095aSDmitry Bezrukov 2, ®16); 72233cd597fSDmitry Bezrukov 72333cd597fSDmitry Bezrukov /* Power down ethernet PHY */ 7247b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_ADV_MASK; 72533cd597fSDmitry Bezrukov aqc111_data->phy_cfg |= AQ_LOW_POWER; 72633cd597fSDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_PHY_POWER_EN; 72733cd597fSDmitry Bezrukov aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, 72833cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 72933cd597fSDmitry Bezrukov 73033cd597fSDmitry Bezrukov kfree(aqc111_data); 731f3aa095aSDmitry Bezrukov } 732f3aa095aSDmitry Bezrukov 7337b8b0654SDmitry Bezrukov static void aqc111_status(struct usbnet *dev, struct urb *urb) 7347b8b0654SDmitry Bezrukov { 7357b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 7367b8b0654SDmitry Bezrukov u64 *event_data = NULL; 7377b8b0654SDmitry Bezrukov int link = 0; 7387b8b0654SDmitry Bezrukov 7397b8b0654SDmitry Bezrukov if (urb->actual_length < sizeof(*event_data)) 7407b8b0654SDmitry Bezrukov return; 7417b8b0654SDmitry Bezrukov 7427b8b0654SDmitry Bezrukov event_data = urb->transfer_buffer; 7437b8b0654SDmitry Bezrukov le64_to_cpus(event_data); 7447b8b0654SDmitry Bezrukov 7457b8b0654SDmitry Bezrukov if (*event_data & AQ_LS_MASK) 7467b8b0654SDmitry Bezrukov link = 1; 7477b8b0654SDmitry Bezrukov else 7487b8b0654SDmitry Bezrukov link = 0; 7497b8b0654SDmitry Bezrukov 7507b8b0654SDmitry Bezrukov aqc111_data->link_speed = (*event_data & AQ_SPEED_MASK) >> 7517b8b0654SDmitry Bezrukov AQ_SPEED_SHIFT; 7527b8b0654SDmitry Bezrukov aqc111_data->link = link; 7537b8b0654SDmitry Bezrukov 7547b8b0654SDmitry Bezrukov if (netif_carrier_ok(dev->net) != link) 7557b8b0654SDmitry Bezrukov usbnet_defer_kevent(dev, EVENT_LINK_RESET); 7567b8b0654SDmitry Bezrukov } 7577b8b0654SDmitry Bezrukov 7587b8b0654SDmitry Bezrukov static void aqc111_configure_rx(struct usbnet *dev, 7597b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data) 7607b8b0654SDmitry Bezrukov { 7617b8b0654SDmitry Bezrukov enum usb_device_speed usb_speed = dev->udev->speed; 7627b8b0654SDmitry Bezrukov u16 link_speed = 0, usb_host = 0; 7637b8b0654SDmitry Bezrukov u8 buf[5] = { 0 }; 7647b8b0654SDmitry Bezrukov u8 queue_num = 0; 7657b8b0654SDmitry Bezrukov u16 reg16 = 0; 7667b8b0654SDmitry Bezrukov u8 reg8 = 0; 7677b8b0654SDmitry Bezrukov 7687b8b0654SDmitry Bezrukov buf[0] = 0x00; 7697b8b0654SDmitry Bezrukov buf[1] = 0xF8; 7707b8b0654SDmitry Bezrukov buf[2] = 0x07; 7717b8b0654SDmitry Bezrukov switch (aqc111_data->link_speed) { 7727b8b0654SDmitry Bezrukov case AQ_INT_SPEED_5G: 7737b8b0654SDmitry Bezrukov link_speed = 5000; 7747b8b0654SDmitry Bezrukov reg8 = 0x05; 7757b8b0654SDmitry Bezrukov reg16 = 0x001F; 7767b8b0654SDmitry Bezrukov break; 7777b8b0654SDmitry Bezrukov case AQ_INT_SPEED_2_5G: 7787b8b0654SDmitry Bezrukov link_speed = 2500; 7797b8b0654SDmitry Bezrukov reg16 = 0x003F; 7807b8b0654SDmitry Bezrukov break; 7817b8b0654SDmitry Bezrukov case AQ_INT_SPEED_1G: 7827b8b0654SDmitry Bezrukov link_speed = 1000; 7837b8b0654SDmitry Bezrukov reg16 = 0x009F; 7847b8b0654SDmitry Bezrukov break; 7857b8b0654SDmitry Bezrukov case AQ_INT_SPEED_100M: 7867b8b0654SDmitry Bezrukov link_speed = 100; 7877b8b0654SDmitry Bezrukov queue_num = 1; 7887b8b0654SDmitry Bezrukov reg16 = 0x063F; 7897b8b0654SDmitry Bezrukov buf[1] = 0xFB; 7907b8b0654SDmitry Bezrukov buf[2] = 0x4; 7917b8b0654SDmitry Bezrukov break; 7927b8b0654SDmitry Bezrukov } 7937b8b0654SDmitry Bezrukov 7947b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0, 7957b8b0654SDmitry Bezrukov 1, 1, ®8); 7967b8b0654SDmitry Bezrukov 7977b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TX_PAUSE_RESEND_T, 3, 3, buf); 7987b8b0654SDmitry Bezrukov 7997b8b0654SDmitry Bezrukov switch (usb_speed) { 8007b8b0654SDmitry Bezrukov case USB_SPEED_SUPER: 8017b8b0654SDmitry Bezrukov usb_host = 3; 8027b8b0654SDmitry Bezrukov break; 8037b8b0654SDmitry Bezrukov case USB_SPEED_HIGH: 8047b8b0654SDmitry Bezrukov usb_host = 2; 8057b8b0654SDmitry Bezrukov break; 8067b8b0654SDmitry Bezrukov case USB_SPEED_FULL: 8077b8b0654SDmitry Bezrukov case USB_SPEED_LOW: 8087b8b0654SDmitry Bezrukov usb_host = 1; 8097b8b0654SDmitry Bezrukov queue_num = 0; 8107b8b0654SDmitry Bezrukov break; 8117b8b0654SDmitry Bezrukov default: 8127b8b0654SDmitry Bezrukov usb_host = 0; 8137b8b0654SDmitry Bezrukov break; 8147b8b0654SDmitry Bezrukov } 8157b8b0654SDmitry Bezrukov 816a4017cc2SDmitry Bezrukov if (dev->net->mtu > 12500 && dev->net->mtu <= 16334) 817a4017cc2SDmitry Bezrukov queue_num = 2; /* For Jumbo packet 16KB */ 818a4017cc2SDmitry Bezrukov 8197b8b0654SDmitry Bezrukov memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5); 8207b8b0654SDmitry Bezrukov /* RX bulk configuration */ 8217b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf); 8227b8b0654SDmitry Bezrukov 8237b8b0654SDmitry Bezrukov /* Set high low water level */ 824a4017cc2SDmitry Bezrukov if (dev->net->mtu <= 4500) 8257b8b0654SDmitry Bezrukov reg16 = 0x0810; 826a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 9500) 827a4017cc2SDmitry Bezrukov reg16 = 0x1020; 828a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 12500) 829a4017cc2SDmitry Bezrukov reg16 = 0x1420; 830a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 16334) 831a4017cc2SDmitry Bezrukov reg16 = 0x1A20; 8327b8b0654SDmitry Bezrukov 8337b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW, 8347b8b0654SDmitry Bezrukov 2, ®16); 8357b8b0654SDmitry Bezrukov netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host); 8367b8b0654SDmitry Bezrukov } 8377b8b0654SDmitry Bezrukov 83802031466SDmitry Bezrukov static void aqc111_configure_csum_offload(struct usbnet *dev) 83902031466SDmitry Bezrukov { 84002031466SDmitry Bezrukov u8 reg8 = 0; 84102031466SDmitry Bezrukov 84202031466SDmitry Bezrukov if (dev->net->features & NETIF_F_RXCSUM) { 84302031466SDmitry Bezrukov reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 84402031466SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6; 84502031466SDmitry Bezrukov } 84602031466SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8); 84702031466SDmitry Bezrukov 84802031466SDmitry Bezrukov reg8 = 0; 84902031466SDmitry Bezrukov if (dev->net->features & NETIF_F_IP_CSUM) 85002031466SDmitry Bezrukov reg8 |= SFR_TXCOE_IP | SFR_TXCOE_TCP | SFR_TXCOE_UDP; 85102031466SDmitry Bezrukov 85202031466SDmitry Bezrukov if (dev->net->features & NETIF_F_IPV6_CSUM) 85302031466SDmitry Bezrukov reg8 |= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6; 85402031466SDmitry Bezrukov 85502031466SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 85602031466SDmitry Bezrukov } 85702031466SDmitry Bezrukov 8587b8b0654SDmitry Bezrukov static int aqc111_link_reset(struct usbnet *dev) 8597b8b0654SDmitry Bezrukov { 8607b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 8617b8b0654SDmitry Bezrukov u16 reg16 = 0; 8627b8b0654SDmitry Bezrukov u8 reg8 = 0; 8637b8b0654SDmitry Bezrukov 8647b8b0654SDmitry Bezrukov if (aqc111_data->link == 1) { /* Link up */ 8657b8b0654SDmitry Bezrukov aqc111_configure_rx(dev, aqc111_data); 8667b8b0654SDmitry Bezrukov 8677b8b0654SDmitry Bezrukov /* Vlan Tag Filter */ 8687b8b0654SDmitry Bezrukov reg8 = SFR_VLAN_CONTROL_VSO; 8694189673aSDmitry Bezrukov if (dev->net->features & NETIF_F_HW_VLAN_CTAG_FILTER) 8704189673aSDmitry Bezrukov reg8 |= SFR_VLAN_CONTROL_VFE; 8717b8b0654SDmitry Bezrukov 8727b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 8737b8b0654SDmitry Bezrukov 1, 1, ®8); 8747b8b0654SDmitry Bezrukov 8757b8b0654SDmitry Bezrukov reg8 = 0x0; 8767b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 8777b8b0654SDmitry Bezrukov 1, 1, ®8); 8787b8b0654SDmitry Bezrukov 8797b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMTX_DMA_CONTROL, 8807b8b0654SDmitry Bezrukov 1, 1, ®8); 8817b8b0654SDmitry Bezrukov 8827b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, ®8); 8837b8b0654SDmitry Bezrukov 8847b8b0654SDmitry Bezrukov reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB; 88559b04eeaSDmitry Bezrukov aqc111_data->rxctl = reg16; 8867b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 8877b8b0654SDmitry Bezrukov 8887b8b0654SDmitry Bezrukov reg8 = SFR_RX_PATH_READY; 8897b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH, 8907b8b0654SDmitry Bezrukov 1, 1, ®8); 8917b8b0654SDmitry Bezrukov 8927b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_EFF_EN; 8937b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 8947b8b0654SDmitry Bezrukov 1, 1, ®8); 8957b8b0654SDmitry Bezrukov 8967b8b0654SDmitry Bezrukov reg16 = 0; 8977b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 8987b8b0654SDmitry Bezrukov 2, ®16); 8997b8b0654SDmitry Bezrukov 9007b8b0654SDmitry Bezrukov reg16 = SFR_MEDIUM_XGMIIMODE | SFR_MEDIUM_FULL_DUPLEX; 9017b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9027b8b0654SDmitry Bezrukov 2, ®16); 9037b8b0654SDmitry Bezrukov 90402031466SDmitry Bezrukov aqc111_configure_csum_offload(dev); 90502031466SDmitry Bezrukov 90659b04eeaSDmitry Bezrukov aqc111_set_rx_mode(dev->net); 90759b04eeaSDmitry Bezrukov 9087b8b0654SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9097b8b0654SDmitry Bezrukov 2, ®16); 9107b8b0654SDmitry Bezrukov 911a4017cc2SDmitry Bezrukov if (dev->net->mtu > 1500) 912a4017cc2SDmitry Bezrukov reg16 |= SFR_MEDIUM_JUMBO_EN; 913a4017cc2SDmitry Bezrukov 9147b8b0654SDmitry Bezrukov reg16 |= SFR_MEDIUM_RECEIVE_EN | SFR_MEDIUM_RXFLOW_CTRLEN | 9157b8b0654SDmitry Bezrukov SFR_MEDIUM_TXFLOW_CTRLEN; 9167b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9177b8b0654SDmitry Bezrukov 2, ®16); 9187b8b0654SDmitry Bezrukov 91959b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_START; 92059b04eeaSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 92159b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 9227b8b0654SDmitry Bezrukov 9237b8b0654SDmitry Bezrukov netif_carrier_on(dev->net); 9247b8b0654SDmitry Bezrukov } else { 9257b8b0654SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9267b8b0654SDmitry Bezrukov 2, ®16); 9277b8b0654SDmitry Bezrukov reg16 &= ~SFR_MEDIUM_RECEIVE_EN; 9287b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 9297b8b0654SDmitry Bezrukov 2, ®16); 9307b8b0654SDmitry Bezrukov 93159b04eeaSDmitry Bezrukov aqc111_data->rxctl &= ~SFR_RX_CTL_START; 93259b04eeaSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 93359b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 9347b8b0654SDmitry Bezrukov 9357b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN; 9367b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 9377b8b0654SDmitry Bezrukov 1, 1, ®8); 9387b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_EFF_EN; 9397b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 9407b8b0654SDmitry Bezrukov 1, 1, ®8); 9417b8b0654SDmitry Bezrukov 9427b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 9437b8b0654SDmitry Bezrukov } 9447b8b0654SDmitry Bezrukov return 0; 9457b8b0654SDmitry Bezrukov } 9467b8b0654SDmitry Bezrukov 947f3aa095aSDmitry Bezrukov static int aqc111_reset(struct usbnet *dev) 948f3aa095aSDmitry Bezrukov { 94933cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 950f3aa095aSDmitry Bezrukov u8 reg8 = 0; 951f3aa095aSDmitry Bezrukov 952361459cdSDmitry Bezrukov dev->rx_urb_size = URB_SIZE; 953361459cdSDmitry Bezrukov 9544a3576d2SDmitry Bezrukov if (usb_device_no_sg_constraint(dev->udev)) 9554a3576d2SDmitry Bezrukov dev->can_dma_sg = 1; 9564a3576d2SDmitry Bezrukov 9574a3576d2SDmitry Bezrukov dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE; 9584a3576d2SDmitry Bezrukov dev->net->features |= AQ_SUPPORT_FEATURE; 9597afa6c98SDmitry Bezrukov dev->net->vlan_features |= AQ_SUPPORT_VLAN_FEATURE; 9604a3576d2SDmitry Bezrukov 96133cd597fSDmitry Bezrukov /* Power up ethernet PHY */ 96233cd597fSDmitry Bezrukov aqc111_data->phy_cfg = AQ_PHY_POWER_EN; 96333cd597fSDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 96433cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 96533cd597fSDmitry Bezrukov 966df2d59a2SDmitry Bezrukov /* Set the MAC address */ 967df2d59a2SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN, 968df2d59a2SDmitry Bezrukov ETH_ALEN, dev->net->dev_addr); 969df2d59a2SDmitry Bezrukov 970f3aa095aSDmitry Bezrukov reg8 = 0xFF; 971f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, ®8); 972f3aa095aSDmitry Bezrukov 973f3aa095aSDmitry Bezrukov reg8 = 0x0; 974f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_SWP_CTRL, 1, 1, ®8); 975f3aa095aSDmitry Bezrukov 976f3aa095aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8); 977f3aa095aSDmitry Bezrukov reg8 &= ~(SFR_MONITOR_MODE_EPHYRW | SFR_MONITOR_MODE_RWLC | 978f3aa095aSDmitry Bezrukov SFR_MONITOR_MODE_RWMP | SFR_MONITOR_MODE_RWWF | 979f3aa095aSDmitry Bezrukov SFR_MONITOR_MODE_RW_FLAG); 980f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8); 981f3aa095aSDmitry Bezrukov 9827b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 9837b8b0654SDmitry Bezrukov 9847b8b0654SDmitry Bezrukov /* Phy advertise */ 9857b8b0654SDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 9867b8b0654SDmitry Bezrukov aqc111_data->advertised_speed); 9877b8b0654SDmitry Bezrukov 988f3aa095aSDmitry Bezrukov return 0; 989f3aa095aSDmitry Bezrukov } 990f3aa095aSDmitry Bezrukov 991f3aa095aSDmitry Bezrukov static int aqc111_stop(struct usbnet *dev) 992f3aa095aSDmitry Bezrukov { 99333cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 994f3aa095aSDmitry Bezrukov u16 reg16 = 0; 995f3aa095aSDmitry Bezrukov 996f3aa095aSDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 997f3aa095aSDmitry Bezrukov 2, ®16); 998f3aa095aSDmitry Bezrukov reg16 &= ~SFR_MEDIUM_RECEIVE_EN; 999f3aa095aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 1000f3aa095aSDmitry Bezrukov 2, ®16); 1001f3aa095aSDmitry Bezrukov reg16 = 0; 1002f3aa095aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 1003f3aa095aSDmitry Bezrukov 100433cd597fSDmitry Bezrukov /* Put PHY to low power*/ 100533cd597fSDmitry Bezrukov aqc111_data->phy_cfg |= AQ_LOW_POWER; 100633cd597fSDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 100733cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 100833cd597fSDmitry Bezrukov 10097b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 10107b8b0654SDmitry Bezrukov 1011f3aa095aSDmitry Bezrukov return 0; 10127cea2d40SDmitry Bezrukov } 10137cea2d40SDmitry Bezrukov 101402031466SDmitry Bezrukov static void aqc111_rx_checksum(struct sk_buff *skb, u64 pkt_desc) 101502031466SDmitry Bezrukov { 101602031466SDmitry Bezrukov u32 pkt_type = 0; 101702031466SDmitry Bezrukov 101802031466SDmitry Bezrukov skb->ip_summed = CHECKSUM_NONE; 101902031466SDmitry Bezrukov /* checksum error bit is set */ 102002031466SDmitry Bezrukov if (pkt_desc & AQ_RX_PD_L4_ERR || pkt_desc & AQ_RX_PD_L3_ERR) 102102031466SDmitry Bezrukov return; 102202031466SDmitry Bezrukov 102302031466SDmitry Bezrukov pkt_type = pkt_desc & AQ_RX_PD_L4_TYPE_MASK; 102402031466SDmitry Bezrukov /* It must be a TCP or UDP packet with a valid checksum */ 102502031466SDmitry Bezrukov if (pkt_type == AQ_RX_PD_L4_TCP || pkt_type == AQ_RX_PD_L4_UDP) 102602031466SDmitry Bezrukov skb->ip_summed = CHECKSUM_UNNECESSARY; 102702031466SDmitry Bezrukov } 102802031466SDmitry Bezrukov 1029361459cdSDmitry Bezrukov static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 1030361459cdSDmitry Bezrukov { 10316649d2a6SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 1032361459cdSDmitry Bezrukov struct sk_buff *new_skb = NULL; 1033361459cdSDmitry Bezrukov u32 pkt_total_offset = 0; 1034361459cdSDmitry Bezrukov u64 *pkt_desc_ptr = NULL; 1035361459cdSDmitry Bezrukov u32 start_of_descs = 0; 1036361459cdSDmitry Bezrukov u32 desc_offset = 0; /*RX Header Offset*/ 1037361459cdSDmitry Bezrukov u16 pkt_count = 0; 1038361459cdSDmitry Bezrukov u64 desc_hdr = 0; 10397afa6c98SDmitry Bezrukov u16 vlan_tag = 0; 1040361459cdSDmitry Bezrukov u32 skb_len = 0; 1041361459cdSDmitry Bezrukov 1042361459cdSDmitry Bezrukov if (!skb) 1043361459cdSDmitry Bezrukov goto err; 1044361459cdSDmitry Bezrukov 1045361459cdSDmitry Bezrukov if (skb->len == 0) 1046361459cdSDmitry Bezrukov goto err; 1047361459cdSDmitry Bezrukov 1048361459cdSDmitry Bezrukov skb_len = skb->len; 1049361459cdSDmitry Bezrukov /* RX Descriptor Header */ 1050361459cdSDmitry Bezrukov skb_trim(skb, skb->len - sizeof(desc_hdr)); 1051361459cdSDmitry Bezrukov desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb)); 1052361459cdSDmitry Bezrukov 1053361459cdSDmitry Bezrukov /* Check these packets */ 1054361459cdSDmitry Bezrukov desc_offset = (desc_hdr & AQ_RX_DH_DESC_OFFSET_MASK) >> 1055361459cdSDmitry Bezrukov AQ_RX_DH_DESC_OFFSET_SHIFT; 1056361459cdSDmitry Bezrukov pkt_count = desc_hdr & AQ_RX_DH_PKT_CNT_MASK; 1057361459cdSDmitry Bezrukov start_of_descs = skb_len - ((pkt_count + 1) * sizeof(desc_hdr)); 1058361459cdSDmitry Bezrukov 1059361459cdSDmitry Bezrukov /* self check descs position */ 1060361459cdSDmitry Bezrukov if (start_of_descs != desc_offset) 1061361459cdSDmitry Bezrukov goto err; 1062361459cdSDmitry Bezrukov 1063361459cdSDmitry Bezrukov /* self check desc_offset from header*/ 1064361459cdSDmitry Bezrukov if (desc_offset >= skb_len) 1065361459cdSDmitry Bezrukov goto err; 1066361459cdSDmitry Bezrukov 1067361459cdSDmitry Bezrukov if (pkt_count == 0) 1068361459cdSDmitry Bezrukov goto err; 1069361459cdSDmitry Bezrukov 1070361459cdSDmitry Bezrukov /* Get the first RX packet descriptor */ 1071361459cdSDmitry Bezrukov pkt_desc_ptr = (u64 *)(skb->data + desc_offset); 1072361459cdSDmitry Bezrukov 1073361459cdSDmitry Bezrukov while (pkt_count--) { 1074361459cdSDmitry Bezrukov u64 pkt_desc = le64_to_cpup(pkt_desc_ptr); 1075361459cdSDmitry Bezrukov u32 pkt_len_with_padd = 0; 1076361459cdSDmitry Bezrukov u32 pkt_len = 0; 1077361459cdSDmitry Bezrukov 1078361459cdSDmitry Bezrukov pkt_len = (u32)((pkt_desc & AQ_RX_PD_LEN_MASK) >> 1079361459cdSDmitry Bezrukov AQ_RX_PD_LEN_SHIFT); 1080361459cdSDmitry Bezrukov pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8); 1081361459cdSDmitry Bezrukov 1082361459cdSDmitry Bezrukov pkt_total_offset += pkt_len_with_padd; 1083361459cdSDmitry Bezrukov if (pkt_total_offset > desc_offset || 1084361459cdSDmitry Bezrukov (pkt_count == 0 && pkt_total_offset != desc_offset)) { 1085361459cdSDmitry Bezrukov goto err; 1086361459cdSDmitry Bezrukov } 1087361459cdSDmitry Bezrukov 1088361459cdSDmitry Bezrukov if (pkt_desc & AQ_RX_PD_DROP || 1089361459cdSDmitry Bezrukov !(pkt_desc & AQ_RX_PD_RX_OK) || 1090361459cdSDmitry Bezrukov pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) { 1091361459cdSDmitry Bezrukov skb_pull(skb, pkt_len_with_padd); 1092361459cdSDmitry Bezrukov /* Next RX Packet Descriptor */ 1093361459cdSDmitry Bezrukov pkt_desc_ptr++; 1094361459cdSDmitry Bezrukov continue; 1095361459cdSDmitry Bezrukov } 1096361459cdSDmitry Bezrukov 1097361459cdSDmitry Bezrukov /* Clone SKB */ 1098361459cdSDmitry Bezrukov new_skb = skb_clone(skb, GFP_ATOMIC); 1099361459cdSDmitry Bezrukov 1100361459cdSDmitry Bezrukov if (!new_skb) 1101361459cdSDmitry Bezrukov goto err; 1102361459cdSDmitry Bezrukov 1103361459cdSDmitry Bezrukov new_skb->len = pkt_len; 1104361459cdSDmitry Bezrukov skb_pull(new_skb, AQ_RX_HW_PAD); 1105361459cdSDmitry Bezrukov skb_set_tail_pointer(new_skb, new_skb->len); 1106361459cdSDmitry Bezrukov 1107361459cdSDmitry Bezrukov new_skb->truesize = SKB_TRUESIZE(new_skb->len); 11086649d2a6SDmitry Bezrukov if (aqc111_data->rx_checksum) 110902031466SDmitry Bezrukov aqc111_rx_checksum(new_skb, pkt_desc); 1110361459cdSDmitry Bezrukov 11117afa6c98SDmitry Bezrukov if (pkt_desc & AQ_RX_PD_VLAN) { 11127afa6c98SDmitry Bezrukov vlan_tag = pkt_desc >> AQ_RX_PD_VLAN_SHIFT; 11137afa6c98SDmitry Bezrukov __vlan_hwaccel_put_tag(new_skb, htons(ETH_P_8021Q), 11147afa6c98SDmitry Bezrukov vlan_tag & VLAN_VID_MASK); 11157afa6c98SDmitry Bezrukov } 11167afa6c98SDmitry Bezrukov 1117361459cdSDmitry Bezrukov usbnet_skb_return(dev, new_skb); 1118361459cdSDmitry Bezrukov if (pkt_count == 0) 1119361459cdSDmitry Bezrukov break; 1120361459cdSDmitry Bezrukov 1121361459cdSDmitry Bezrukov skb_pull(skb, pkt_len_with_padd); 1122361459cdSDmitry Bezrukov 1123361459cdSDmitry Bezrukov /* Next RX Packet Header */ 1124361459cdSDmitry Bezrukov pkt_desc_ptr++; 1125361459cdSDmitry Bezrukov 1126361459cdSDmitry Bezrukov new_skb = NULL; 1127361459cdSDmitry Bezrukov } 1128361459cdSDmitry Bezrukov 1129361459cdSDmitry Bezrukov return 1; 1130361459cdSDmitry Bezrukov 1131361459cdSDmitry Bezrukov err: 1132361459cdSDmitry Bezrukov return 0; 1133361459cdSDmitry Bezrukov } 1134361459cdSDmitry Bezrukov 11354a3576d2SDmitry Bezrukov static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 11364a3576d2SDmitry Bezrukov gfp_t flags) 11374a3576d2SDmitry Bezrukov { 11384a3576d2SDmitry Bezrukov int frame_size = dev->maxpacket; 11394a3576d2SDmitry Bezrukov struct sk_buff *new_skb = NULL; 11404a3576d2SDmitry Bezrukov u64 *tx_desc_ptr = NULL; 11414a3576d2SDmitry Bezrukov int padding_size = 0; 11424a3576d2SDmitry Bezrukov int headroom = 0; 11434a3576d2SDmitry Bezrukov int tailroom = 0; 11444a3576d2SDmitry Bezrukov u64 tx_desc = 0; 11457afa6c98SDmitry Bezrukov u16 tci = 0; 11464a3576d2SDmitry Bezrukov 11474a3576d2SDmitry Bezrukov /*Length of actual data*/ 11484a3576d2SDmitry Bezrukov tx_desc |= skb->len & AQ_TX_DESC_LEN_MASK; 11494a3576d2SDmitry Bezrukov 1150de074e7aSDmitry Bezrukov /* TSO MSS */ 1151de074e7aSDmitry Bezrukov tx_desc |= ((u64)(skb_shinfo(skb)->gso_size & AQ_TX_DESC_MSS_MASK)) << 1152de074e7aSDmitry Bezrukov AQ_TX_DESC_MSS_SHIFT; 1153de074e7aSDmitry Bezrukov 11544a3576d2SDmitry Bezrukov headroom = (skb->len + sizeof(tx_desc)) % 8; 11554a3576d2SDmitry Bezrukov if (headroom != 0) 11564a3576d2SDmitry Bezrukov padding_size = 8 - headroom; 11574a3576d2SDmitry Bezrukov 11584a3576d2SDmitry Bezrukov if (((skb->len + sizeof(tx_desc) + padding_size) % frame_size) == 0) { 11594a3576d2SDmitry Bezrukov padding_size += 8; 11604a3576d2SDmitry Bezrukov tx_desc |= AQ_TX_DESC_DROP_PADD; 11614a3576d2SDmitry Bezrukov } 11624a3576d2SDmitry Bezrukov 11637afa6c98SDmitry Bezrukov /* Vlan Tag */ 11647afa6c98SDmitry Bezrukov if (vlan_get_tag(skb, &tci) >= 0) { 11657afa6c98SDmitry Bezrukov tx_desc |= AQ_TX_DESC_VLAN; 11667afa6c98SDmitry Bezrukov tx_desc |= ((u64)tci & AQ_TX_DESC_VLAN_MASK) << 11677afa6c98SDmitry Bezrukov AQ_TX_DESC_VLAN_SHIFT; 11687afa6c98SDmitry Bezrukov } 11697afa6c98SDmitry Bezrukov 11704a3576d2SDmitry Bezrukov if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) && 11714a3576d2SDmitry Bezrukov skb_linearize(skb)) 11724a3576d2SDmitry Bezrukov return NULL; 11734a3576d2SDmitry Bezrukov 11744a3576d2SDmitry Bezrukov headroom = skb_headroom(skb); 11754a3576d2SDmitry Bezrukov tailroom = skb_tailroom(skb); 11764a3576d2SDmitry Bezrukov 11774a3576d2SDmitry Bezrukov if (!(headroom >= sizeof(tx_desc) && tailroom >= padding_size)) { 11784a3576d2SDmitry Bezrukov new_skb = skb_copy_expand(skb, sizeof(tx_desc), 11794a3576d2SDmitry Bezrukov padding_size, flags); 11804a3576d2SDmitry Bezrukov dev_kfree_skb_any(skb); 11814a3576d2SDmitry Bezrukov skb = new_skb; 11824a3576d2SDmitry Bezrukov if (!skb) 11834a3576d2SDmitry Bezrukov return NULL; 11844a3576d2SDmitry Bezrukov } 11854a3576d2SDmitry Bezrukov if (padding_size != 0) 11864a3576d2SDmitry Bezrukov skb_put_zero(skb, padding_size); 11874a3576d2SDmitry Bezrukov /* Copy TX header */ 11884a3576d2SDmitry Bezrukov tx_desc_ptr = skb_push(skb, sizeof(tx_desc)); 11894a3576d2SDmitry Bezrukov *tx_desc_ptr = cpu_to_le64(tx_desc); 11904a3576d2SDmitry Bezrukov 11914a3576d2SDmitry Bezrukov usbnet_set_skb_tx_stats(skb, 1, 0); 11924a3576d2SDmitry Bezrukov 11934a3576d2SDmitry Bezrukov return skb; 11944a3576d2SDmitry Bezrukov } 11954a3576d2SDmitry Bezrukov 119617364b80SDmitry Bezrukov static const struct driver_info aqc111_info = { 119717364b80SDmitry Bezrukov .description = "Aquantia AQtion USB to 5GbE Controller", 11987cea2d40SDmitry Bezrukov .bind = aqc111_bind, 11997cea2d40SDmitry Bezrukov .unbind = aqc111_unbind, 12007b8b0654SDmitry Bezrukov .status = aqc111_status, 12017b8b0654SDmitry Bezrukov .link_reset = aqc111_link_reset, 1202f3aa095aSDmitry Bezrukov .reset = aqc111_reset, 1203f3aa095aSDmitry Bezrukov .stop = aqc111_stop, 12044a3576d2SDmitry Bezrukov .flags = FLAG_ETHER | FLAG_FRAMING_AX | 12054a3576d2SDmitry Bezrukov FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, 1206361459cdSDmitry Bezrukov .rx_fixup = aqc111_rx_fixup, 12074a3576d2SDmitry Bezrukov .tx_fixup = aqc111_tx_fixup, 120817364b80SDmitry Bezrukov }; 120917364b80SDmitry Bezrukov 121017364b80SDmitry Bezrukov #define AQC111_USB_ETH_DEV(vid, pid, table) \ 121117364b80SDmitry Bezrukov USB_DEVICE_INTERFACE_CLASS((vid), (pid), USB_CLASS_VENDOR_SPEC), \ 121217364b80SDmitry Bezrukov .driver_info = (unsigned long)&(table) \ 121317364b80SDmitry Bezrukov }, \ 121417364b80SDmitry Bezrukov { \ 121517364b80SDmitry Bezrukov USB_DEVICE_AND_INTERFACE_INFO((vid), (pid), \ 121617364b80SDmitry Bezrukov USB_CLASS_COMM, \ 121717364b80SDmitry Bezrukov USB_CDC_SUBCLASS_ETHERNET, \ 121817364b80SDmitry Bezrukov USB_CDC_PROTO_NONE), \ 121917364b80SDmitry Bezrukov .driver_info = (unsigned long)&(table), 122017364b80SDmitry Bezrukov 122117364b80SDmitry Bezrukov static const struct usb_device_id products[] = { 122217364b80SDmitry Bezrukov {AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)}, 122317364b80SDmitry Bezrukov { },/* END */ 122417364b80SDmitry Bezrukov }; 122517364b80SDmitry Bezrukov MODULE_DEVICE_TABLE(usb, products); 122617364b80SDmitry Bezrukov 122717364b80SDmitry Bezrukov static struct usb_driver aq_driver = { 122817364b80SDmitry Bezrukov .name = "aqc111", 122917364b80SDmitry Bezrukov .id_table = products, 123017364b80SDmitry Bezrukov .probe = usbnet_probe, 123117364b80SDmitry Bezrukov .disconnect = usbnet_disconnect, 123217364b80SDmitry Bezrukov }; 123317364b80SDmitry Bezrukov 123417364b80SDmitry Bezrukov module_usb_driver(aq_driver); 123517364b80SDmitry Bezrukov 123617364b80SDmitry Bezrukov MODULE_DESCRIPTION("Aquantia AQtion USB to 5/2.5GbE Controllers"); 123717364b80SDmitry Bezrukov MODULE_LICENSE("GPL"); 1238