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> 1217364b80SDmitry Bezrukov #include <linux/mii.h> 1317364b80SDmitry Bezrukov #include <linux/usb.h> 14*59b04eeaSDmitry Bezrukov #include <linux/crc32.h> 15df2d59a2SDmitry Bezrukov #include <linux/if_vlan.h> 1617364b80SDmitry Bezrukov #include <linux/usb/cdc.h> 1717364b80SDmitry Bezrukov #include <linux/usb/usbnet.h> 1817364b80SDmitry Bezrukov 19619fcb44SDmitry Bezrukov #include "aqc111.h" 20619fcb44SDmitry Bezrukov 21619fcb44SDmitry Bezrukov static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 22619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 23619fcb44SDmitry Bezrukov { 24619fcb44SDmitry Bezrukov int ret; 25619fcb44SDmitry Bezrukov 26619fcb44SDmitry Bezrukov ret = usbnet_read_cmd_nopm(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | 27619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, size); 28619fcb44SDmitry Bezrukov 29619fcb44SDmitry Bezrukov if (unlikely(ret < 0)) 30619fcb44SDmitry Bezrukov netdev_warn(dev->net, 31619fcb44SDmitry Bezrukov "Failed to read(0x%x) reg index 0x%04x: %d\n", 32619fcb44SDmitry Bezrukov cmd, index, ret); 33619fcb44SDmitry Bezrukov 34619fcb44SDmitry Bezrukov return ret; 35619fcb44SDmitry Bezrukov } 36619fcb44SDmitry Bezrukov 37619fcb44SDmitry Bezrukov static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value, 38619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 39619fcb44SDmitry Bezrukov { 40619fcb44SDmitry Bezrukov int ret; 41619fcb44SDmitry Bezrukov 42619fcb44SDmitry Bezrukov ret = usbnet_read_cmd(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | 43619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, size); 44619fcb44SDmitry Bezrukov 45619fcb44SDmitry Bezrukov if (unlikely(ret < 0)) 46619fcb44SDmitry Bezrukov netdev_warn(dev->net, 47619fcb44SDmitry Bezrukov "Failed to read(0x%x) reg index 0x%04x: %d\n", 48619fcb44SDmitry Bezrukov cmd, index, ret); 49619fcb44SDmitry Bezrukov 50619fcb44SDmitry Bezrukov return ret; 51619fcb44SDmitry Bezrukov } 52619fcb44SDmitry Bezrukov 53f3aa095aSDmitry Bezrukov static int aqc111_read16_cmd(struct usbnet *dev, u8 cmd, u16 value, 54f3aa095aSDmitry Bezrukov u16 index, u16 *data) 55f3aa095aSDmitry Bezrukov { 56f3aa095aSDmitry Bezrukov int ret = 0; 57f3aa095aSDmitry Bezrukov 58f3aa095aSDmitry Bezrukov ret = aqc111_read_cmd(dev, cmd, value, index, sizeof(*data), data); 59f3aa095aSDmitry Bezrukov le16_to_cpus(data); 60f3aa095aSDmitry Bezrukov 61f3aa095aSDmitry Bezrukov return ret; 62f3aa095aSDmitry Bezrukov } 63f3aa095aSDmitry Bezrukov 64619fcb44SDmitry Bezrukov static int __aqc111_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, 65619fcb44SDmitry Bezrukov u16 value, u16 index, u16 size, const void *data) 66619fcb44SDmitry Bezrukov { 67619fcb44SDmitry Bezrukov int err = -ENOMEM; 68619fcb44SDmitry Bezrukov void *buf = NULL; 69619fcb44SDmitry Bezrukov 70619fcb44SDmitry Bezrukov netdev_dbg(dev->net, 71619fcb44SDmitry Bezrukov "%s cmd=%#x reqtype=%#x value=%#x index=%#x size=%d\n", 72619fcb44SDmitry Bezrukov __func__, cmd, reqtype, value, index, size); 73619fcb44SDmitry Bezrukov 74619fcb44SDmitry Bezrukov if (data) { 75619fcb44SDmitry Bezrukov buf = kmemdup(data, size, GFP_KERNEL); 76619fcb44SDmitry Bezrukov if (!buf) 77619fcb44SDmitry Bezrukov goto out; 78619fcb44SDmitry Bezrukov } 79619fcb44SDmitry Bezrukov 80619fcb44SDmitry Bezrukov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 81619fcb44SDmitry Bezrukov cmd, reqtype, value, index, buf, size, 82619fcb44SDmitry Bezrukov (cmd == AQ_PHY_POWER) ? AQ_USB_PHY_SET_TIMEOUT : 83619fcb44SDmitry Bezrukov AQ_USB_SET_TIMEOUT); 84619fcb44SDmitry Bezrukov 85619fcb44SDmitry Bezrukov if (unlikely(err < 0)) 86619fcb44SDmitry Bezrukov netdev_warn(dev->net, 87619fcb44SDmitry Bezrukov "Failed to write(0x%x) reg index 0x%04x: %d\n", 88619fcb44SDmitry Bezrukov cmd, index, err); 89619fcb44SDmitry Bezrukov kfree(buf); 90619fcb44SDmitry Bezrukov 91619fcb44SDmitry Bezrukov out: 92619fcb44SDmitry Bezrukov return err; 93619fcb44SDmitry Bezrukov } 94619fcb44SDmitry Bezrukov 95619fcb44SDmitry Bezrukov static int aqc111_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 96619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 97619fcb44SDmitry Bezrukov { 98619fcb44SDmitry Bezrukov int ret; 99619fcb44SDmitry Bezrukov 100619fcb44SDmitry Bezrukov ret = __aqc111_write_cmd(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 101619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, size, data); 102619fcb44SDmitry Bezrukov 103619fcb44SDmitry Bezrukov return ret; 104619fcb44SDmitry Bezrukov } 105619fcb44SDmitry Bezrukov 106619fcb44SDmitry Bezrukov static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value, 107619fcb44SDmitry Bezrukov u16 index, u16 size, void *data) 108619fcb44SDmitry Bezrukov { 109619fcb44SDmitry Bezrukov int ret; 110619fcb44SDmitry Bezrukov 111619fcb44SDmitry Bezrukov if (usb_autopm_get_interface(dev->intf) < 0) 112619fcb44SDmitry Bezrukov return -ENODEV; 113619fcb44SDmitry Bezrukov 114619fcb44SDmitry Bezrukov ret = __aqc111_write_cmd(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 115619fcb44SDmitry Bezrukov USB_RECIP_DEVICE, value, index, size, data); 116619fcb44SDmitry Bezrukov 117619fcb44SDmitry Bezrukov usb_autopm_put_interface(dev->intf); 118619fcb44SDmitry Bezrukov 119619fcb44SDmitry Bezrukov return ret; 120619fcb44SDmitry Bezrukov } 121619fcb44SDmitry Bezrukov 122f3aa095aSDmitry Bezrukov static int aqc111_write16_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 123f3aa095aSDmitry Bezrukov u16 index, u16 *data) 124f3aa095aSDmitry Bezrukov { 125f3aa095aSDmitry Bezrukov u16 tmp = *data; 126f3aa095aSDmitry Bezrukov 127f3aa095aSDmitry Bezrukov cpu_to_le16s(&tmp); 128f3aa095aSDmitry Bezrukov 129f3aa095aSDmitry Bezrukov return aqc111_write_cmd_nopm(dev, cmd, value, index, sizeof(tmp), &tmp); 130f3aa095aSDmitry Bezrukov } 131f3aa095aSDmitry Bezrukov 132f3aa095aSDmitry Bezrukov static int aqc111_write16_cmd(struct usbnet *dev, u8 cmd, u16 value, 133f3aa095aSDmitry Bezrukov u16 index, u16 *data) 134f3aa095aSDmitry Bezrukov { 135f3aa095aSDmitry Bezrukov u16 tmp = *data; 136f3aa095aSDmitry Bezrukov 137f3aa095aSDmitry Bezrukov cpu_to_le16s(&tmp); 138f3aa095aSDmitry Bezrukov 139f3aa095aSDmitry Bezrukov return aqc111_write_cmd(dev, cmd, value, index, sizeof(tmp), &tmp); 140f3aa095aSDmitry Bezrukov } 141f3aa095aSDmitry Bezrukov 14233cd597fSDmitry Bezrukov static int aqc111_write32_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, 14333cd597fSDmitry Bezrukov u16 index, u32 *data) 14433cd597fSDmitry Bezrukov { 14533cd597fSDmitry Bezrukov u32 tmp = *data; 14633cd597fSDmitry Bezrukov 14733cd597fSDmitry Bezrukov cpu_to_le32s(&tmp); 14833cd597fSDmitry Bezrukov 14933cd597fSDmitry Bezrukov return aqc111_write_cmd_nopm(dev, cmd, value, index, sizeof(tmp), &tmp); 15033cd597fSDmitry Bezrukov } 15133cd597fSDmitry Bezrukov 15233cd597fSDmitry Bezrukov static int aqc111_write32_cmd(struct usbnet *dev, u8 cmd, u16 value, 15333cd597fSDmitry Bezrukov u16 index, u32 *data) 15433cd597fSDmitry Bezrukov { 15533cd597fSDmitry Bezrukov u32 tmp = *data; 15633cd597fSDmitry Bezrukov 15733cd597fSDmitry Bezrukov cpu_to_le32s(&tmp); 15833cd597fSDmitry Bezrukov 15933cd597fSDmitry Bezrukov return aqc111_write_cmd(dev, cmd, value, index, sizeof(tmp), &tmp); 16033cd597fSDmitry Bezrukov } 16133cd597fSDmitry Bezrukov 162*59b04eeaSDmitry Bezrukov static int aqc111_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, 163*59b04eeaSDmitry Bezrukov u16 index, u16 size, void *data) 164*59b04eeaSDmitry Bezrukov { 165*59b04eeaSDmitry Bezrukov return usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | 166*59b04eeaSDmitry Bezrukov USB_RECIP_DEVICE, value, index, data, 167*59b04eeaSDmitry Bezrukov size); 168*59b04eeaSDmitry Bezrukov } 169*59b04eeaSDmitry Bezrukov 170*59b04eeaSDmitry Bezrukov static int aqc111_write16_cmd_async(struct usbnet *dev, u8 cmd, u16 value, 171*59b04eeaSDmitry Bezrukov u16 index, u16 *data) 172*59b04eeaSDmitry Bezrukov { 173*59b04eeaSDmitry Bezrukov u16 tmp = *data; 174*59b04eeaSDmitry Bezrukov 175*59b04eeaSDmitry Bezrukov cpu_to_le16s(&tmp); 176*59b04eeaSDmitry Bezrukov 177*59b04eeaSDmitry Bezrukov return aqc111_write_cmd_async(dev, cmd, value, index, 178*59b04eeaSDmitry Bezrukov sizeof(tmp), &tmp); 179*59b04eeaSDmitry Bezrukov } 180*59b04eeaSDmitry Bezrukov 1817b8b0654SDmitry Bezrukov static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed) 1827b8b0654SDmitry Bezrukov { 1837b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 1847b8b0654SDmitry Bezrukov 1857b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_ADV_MASK; 1867b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_PAUSE; 1877b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ASYM_PAUSE; 1887b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_DOWNSHIFT; 1897b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_DSH_RETRIES_MASK; 1907b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= (3 << AQ_DSH_RETRIES_SHIFT) & 1917b8b0654SDmitry Bezrukov AQ_DSH_RETRIES_MASK; 1927b8b0654SDmitry Bezrukov 1937b8b0654SDmitry Bezrukov if (autoneg == AUTONEG_ENABLE) { 1947b8b0654SDmitry Bezrukov switch (speed) { 1957b8b0654SDmitry Bezrukov case SPEED_5000: 1967b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_5G; 1977b8b0654SDmitry Bezrukov /* fall-through */ 1987b8b0654SDmitry Bezrukov case SPEED_2500: 1997b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_2G5; 2007b8b0654SDmitry Bezrukov /* fall-through */ 2017b8b0654SDmitry Bezrukov case SPEED_1000: 2027b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_1G; 2037b8b0654SDmitry Bezrukov /* fall-through */ 2047b8b0654SDmitry Bezrukov case SPEED_100: 2057b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_100M; 2067b8b0654SDmitry Bezrukov /* fall-through */ 2077b8b0654SDmitry Bezrukov } 2087b8b0654SDmitry Bezrukov } else { 2097b8b0654SDmitry Bezrukov switch (speed) { 2107b8b0654SDmitry Bezrukov case SPEED_5000: 2117b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_5G; 2127b8b0654SDmitry Bezrukov break; 2137b8b0654SDmitry Bezrukov case SPEED_2500: 2147b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_2G5; 2157b8b0654SDmitry Bezrukov break; 2167b8b0654SDmitry Bezrukov case SPEED_1000: 2177b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_1G; 2187b8b0654SDmitry Bezrukov break; 2197b8b0654SDmitry Bezrukov case SPEED_100: 2207b8b0654SDmitry Bezrukov aqc111_data->phy_cfg |= AQ_ADV_100M; 2217b8b0654SDmitry Bezrukov break; 2227b8b0654SDmitry Bezrukov } 2237b8b0654SDmitry Bezrukov } 2247b8b0654SDmitry Bezrukov 2257b8b0654SDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, &aqc111_data->phy_cfg); 2267b8b0654SDmitry Bezrukov } 2277b8b0654SDmitry Bezrukov 228a4017cc2SDmitry Bezrukov static int aqc111_change_mtu(struct net_device *net, int new_mtu) 229a4017cc2SDmitry Bezrukov { 230a4017cc2SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 231a4017cc2SDmitry Bezrukov u16 reg16 = 0; 232a4017cc2SDmitry Bezrukov u8 buf[5]; 233a4017cc2SDmitry Bezrukov 234a4017cc2SDmitry Bezrukov net->mtu = new_mtu; 235a4017cc2SDmitry Bezrukov dev->hard_mtu = net->mtu + net->hard_header_len; 236a4017cc2SDmitry Bezrukov 237a4017cc2SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 238a4017cc2SDmitry Bezrukov 2, ®16); 239a4017cc2SDmitry Bezrukov if (net->mtu > 1500) 240a4017cc2SDmitry Bezrukov reg16 |= SFR_MEDIUM_JUMBO_EN; 241a4017cc2SDmitry Bezrukov else 242a4017cc2SDmitry Bezrukov reg16 &= ~SFR_MEDIUM_JUMBO_EN; 243a4017cc2SDmitry Bezrukov 244a4017cc2SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 245a4017cc2SDmitry Bezrukov 2, ®16); 246a4017cc2SDmitry Bezrukov 247a4017cc2SDmitry Bezrukov if (dev->net->mtu > 12500 && dev->net->mtu <= 16334) { 248a4017cc2SDmitry Bezrukov memcpy(buf, &AQC111_BULKIN_SIZE[2], 5); 249a4017cc2SDmitry Bezrukov /* RX bulk configuration */ 250a4017cc2SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 251a4017cc2SDmitry Bezrukov 5, 5, buf); 252a4017cc2SDmitry Bezrukov } 253a4017cc2SDmitry Bezrukov 254a4017cc2SDmitry Bezrukov /* Set high low water level */ 255a4017cc2SDmitry Bezrukov if (dev->net->mtu <= 4500) 256a4017cc2SDmitry Bezrukov reg16 = 0x0810; 257a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 9500) 258a4017cc2SDmitry Bezrukov reg16 = 0x1020; 259a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 12500) 260a4017cc2SDmitry Bezrukov reg16 = 0x1420; 261a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 16334) 262a4017cc2SDmitry Bezrukov reg16 = 0x1A20; 263a4017cc2SDmitry Bezrukov 264a4017cc2SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW, 265a4017cc2SDmitry Bezrukov 2, ®16); 266a4017cc2SDmitry Bezrukov 267a4017cc2SDmitry Bezrukov return 0; 268a4017cc2SDmitry Bezrukov } 269a4017cc2SDmitry Bezrukov 270df2d59a2SDmitry Bezrukov static int aqc111_set_mac_addr(struct net_device *net, void *p) 271df2d59a2SDmitry Bezrukov { 272df2d59a2SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 273df2d59a2SDmitry Bezrukov int ret = 0; 274df2d59a2SDmitry Bezrukov 275df2d59a2SDmitry Bezrukov ret = eth_mac_addr(net, p); 276df2d59a2SDmitry Bezrukov if (ret < 0) 277df2d59a2SDmitry Bezrukov return ret; 278df2d59a2SDmitry Bezrukov 279df2d59a2SDmitry Bezrukov /* Set the MAC address */ 280df2d59a2SDmitry Bezrukov return aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN, 281df2d59a2SDmitry Bezrukov ETH_ALEN, net->dev_addr); 282df2d59a2SDmitry Bezrukov } 283df2d59a2SDmitry Bezrukov 284*59b04eeaSDmitry Bezrukov static void aqc111_set_rx_mode(struct net_device *net) 285*59b04eeaSDmitry Bezrukov { 286*59b04eeaSDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 287*59b04eeaSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 288*59b04eeaSDmitry Bezrukov int mc_count = 0; 289*59b04eeaSDmitry Bezrukov 290*59b04eeaSDmitry Bezrukov mc_count = netdev_mc_count(net); 291*59b04eeaSDmitry Bezrukov 292*59b04eeaSDmitry Bezrukov aqc111_data->rxctl &= ~(SFR_RX_CTL_PRO | SFR_RX_CTL_AMALL | 293*59b04eeaSDmitry Bezrukov SFR_RX_CTL_AM); 294*59b04eeaSDmitry Bezrukov 295*59b04eeaSDmitry Bezrukov if (net->flags & IFF_PROMISC) { 296*59b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_PRO; 297*59b04eeaSDmitry Bezrukov } else if ((net->flags & IFF_ALLMULTI) || mc_count > AQ_MAX_MCAST) { 298*59b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_AMALL; 299*59b04eeaSDmitry Bezrukov } else if (!netdev_mc_empty(net)) { 300*59b04eeaSDmitry Bezrukov u8 m_filter[AQ_MCAST_FILTER_SIZE] = { 0 }; 301*59b04eeaSDmitry Bezrukov struct netdev_hw_addr *ha = NULL; 302*59b04eeaSDmitry Bezrukov u32 crc_bits = 0; 303*59b04eeaSDmitry Bezrukov 304*59b04eeaSDmitry Bezrukov netdev_for_each_mc_addr(ha, net) { 305*59b04eeaSDmitry Bezrukov crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; 306*59b04eeaSDmitry Bezrukov m_filter[crc_bits >> 3] |= BIT(crc_bits & 7); 307*59b04eeaSDmitry Bezrukov } 308*59b04eeaSDmitry Bezrukov 309*59b04eeaSDmitry Bezrukov aqc111_write_cmd_async(dev, AQ_ACCESS_MAC, 310*59b04eeaSDmitry Bezrukov SFR_MULTI_FILTER_ARRY, 311*59b04eeaSDmitry Bezrukov AQ_MCAST_FILTER_SIZE, 312*59b04eeaSDmitry Bezrukov AQ_MCAST_FILTER_SIZE, m_filter); 313*59b04eeaSDmitry Bezrukov 314*59b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_AM; 315*59b04eeaSDmitry Bezrukov } 316*59b04eeaSDmitry Bezrukov 317*59b04eeaSDmitry Bezrukov aqc111_write16_cmd_async(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 318*59b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 319*59b04eeaSDmitry Bezrukov } 320*59b04eeaSDmitry Bezrukov 3216649d2a6SDmitry Bezrukov static int aqc111_set_features(struct net_device *net, 3226649d2a6SDmitry Bezrukov netdev_features_t features) 3236649d2a6SDmitry Bezrukov { 3246649d2a6SDmitry Bezrukov struct usbnet *dev = netdev_priv(net); 3256649d2a6SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 3266649d2a6SDmitry Bezrukov netdev_features_t changed = net->features ^ features; 3276649d2a6SDmitry Bezrukov u8 reg8 = 0; 3286649d2a6SDmitry Bezrukov 3296649d2a6SDmitry Bezrukov if (changed & NETIF_F_IP_CSUM) { 3306649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 3316649d2a6SDmitry Bezrukov reg8 ^= SFR_TXCOE_TCP | SFR_TXCOE_UDP; 3326649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 3336649d2a6SDmitry Bezrukov 1, 1, ®8); 3346649d2a6SDmitry Bezrukov } 3356649d2a6SDmitry Bezrukov 3366649d2a6SDmitry Bezrukov if (changed & NETIF_F_IPV6_CSUM) { 3376649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 3386649d2a6SDmitry Bezrukov reg8 ^= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6; 3396649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 3406649d2a6SDmitry Bezrukov 1, 1, ®8); 3416649d2a6SDmitry Bezrukov } 3426649d2a6SDmitry Bezrukov 3436649d2a6SDmitry Bezrukov if (changed & NETIF_F_RXCSUM) { 3446649d2a6SDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8); 3456649d2a6SDmitry Bezrukov if (features & NETIF_F_RXCSUM) { 3466649d2a6SDmitry Bezrukov aqc111_data->rx_checksum = 1; 3476649d2a6SDmitry Bezrukov reg8 &= ~(SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 3486649d2a6SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6); 3496649d2a6SDmitry Bezrukov } else { 3506649d2a6SDmitry Bezrukov aqc111_data->rx_checksum = 0; 3516649d2a6SDmitry Bezrukov reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 3526649d2a6SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6; 3536649d2a6SDmitry Bezrukov } 3546649d2a6SDmitry Bezrukov 3556649d2a6SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 3566649d2a6SDmitry Bezrukov 1, 1, ®8); 3576649d2a6SDmitry Bezrukov } 3586649d2a6SDmitry Bezrukov return 0; 3596649d2a6SDmitry Bezrukov } 3606649d2a6SDmitry Bezrukov 3617cea2d40SDmitry Bezrukov static const struct net_device_ops aqc111_netdev_ops = { 3627cea2d40SDmitry Bezrukov .ndo_open = usbnet_open, 3637cea2d40SDmitry Bezrukov .ndo_stop = usbnet_stop, 3644a3576d2SDmitry Bezrukov .ndo_start_xmit = usbnet_start_xmit, 3654a3576d2SDmitry Bezrukov .ndo_tx_timeout = usbnet_tx_timeout, 3664a3576d2SDmitry Bezrukov .ndo_get_stats64 = usbnet_get_stats64, 367a4017cc2SDmitry Bezrukov .ndo_change_mtu = aqc111_change_mtu, 368df2d59a2SDmitry Bezrukov .ndo_set_mac_address = aqc111_set_mac_addr, 369df2d59a2SDmitry Bezrukov .ndo_validate_addr = eth_validate_addr, 370*59b04eeaSDmitry Bezrukov .ndo_set_rx_mode = aqc111_set_rx_mode, 3716649d2a6SDmitry Bezrukov .ndo_set_features = aqc111_set_features, 3727cea2d40SDmitry Bezrukov }; 3737cea2d40SDmitry Bezrukov 374df2d59a2SDmitry Bezrukov static int aqc111_read_perm_mac(struct usbnet *dev) 375df2d59a2SDmitry Bezrukov { 376df2d59a2SDmitry Bezrukov u8 buf[ETH_ALEN]; 377df2d59a2SDmitry Bezrukov int ret; 378df2d59a2SDmitry Bezrukov 379df2d59a2SDmitry Bezrukov ret = aqc111_read_cmd(dev, AQ_FLASH_PARAMETERS, 0, 0, ETH_ALEN, buf); 380df2d59a2SDmitry Bezrukov if (ret < 0) 381df2d59a2SDmitry Bezrukov goto out; 382df2d59a2SDmitry Bezrukov 383df2d59a2SDmitry Bezrukov ether_addr_copy(dev->net->perm_addr, buf); 384df2d59a2SDmitry Bezrukov 385df2d59a2SDmitry Bezrukov return 0; 386df2d59a2SDmitry Bezrukov out: 387df2d59a2SDmitry Bezrukov return ret; 388df2d59a2SDmitry Bezrukov } 389df2d59a2SDmitry Bezrukov 39033cd597fSDmitry Bezrukov static void aqc111_read_fw_version(struct usbnet *dev, 39133cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data) 39233cd597fSDmitry Bezrukov { 39333cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MAJOR, 39433cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.major); 39533cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_MINOR, 39633cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.minor); 39733cd597fSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, AQ_FW_VER_REV, 39833cd597fSDmitry Bezrukov 1, 1, &aqc111_data->fw_ver.rev); 39933cd597fSDmitry Bezrukov 40033cd597fSDmitry Bezrukov if (aqc111_data->fw_ver.major & 0x80) 40133cd597fSDmitry Bezrukov aqc111_data->fw_ver.major &= ~0x80; 40233cd597fSDmitry Bezrukov } 40333cd597fSDmitry Bezrukov 4047cea2d40SDmitry Bezrukov static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf) 4057cea2d40SDmitry Bezrukov { 4067cea2d40SDmitry Bezrukov struct usb_device *udev = interface_to_usbdev(intf); 4077b8b0654SDmitry Bezrukov enum usb_device_speed usb_speed = udev->speed; 40833cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data; 4097cea2d40SDmitry Bezrukov int ret; 4107cea2d40SDmitry Bezrukov 4117cea2d40SDmitry Bezrukov /* Check if vendor configuration */ 4127cea2d40SDmitry Bezrukov if (udev->actconfig->desc.bConfigurationValue != 1) { 4137cea2d40SDmitry Bezrukov usb_driver_set_configuration(udev, 1); 4147cea2d40SDmitry Bezrukov return -ENODEV; 4157cea2d40SDmitry Bezrukov } 4167cea2d40SDmitry Bezrukov 4177cea2d40SDmitry Bezrukov usb_reset_configuration(dev->udev); 4187cea2d40SDmitry Bezrukov 4197cea2d40SDmitry Bezrukov ret = usbnet_get_endpoints(dev, intf); 4207cea2d40SDmitry Bezrukov if (ret < 0) { 4217cea2d40SDmitry Bezrukov netdev_dbg(dev->net, "usbnet_get_endpoints failed"); 4227cea2d40SDmitry Bezrukov return ret; 4237cea2d40SDmitry Bezrukov } 4247cea2d40SDmitry Bezrukov 42533cd597fSDmitry Bezrukov aqc111_data = kzalloc(sizeof(*aqc111_data), GFP_KERNEL); 42633cd597fSDmitry Bezrukov if (!aqc111_data) 42733cd597fSDmitry Bezrukov return -ENOMEM; 42833cd597fSDmitry Bezrukov 42933cd597fSDmitry Bezrukov /* store aqc111_data pointer in device data field */ 43033cd597fSDmitry Bezrukov dev->driver_priv = aqc111_data; 43133cd597fSDmitry Bezrukov 432df2d59a2SDmitry Bezrukov /* Init the MAC address */ 433df2d59a2SDmitry Bezrukov ret = aqc111_read_perm_mac(dev); 434df2d59a2SDmitry Bezrukov if (ret) 435df2d59a2SDmitry Bezrukov goto out; 436df2d59a2SDmitry Bezrukov 437df2d59a2SDmitry Bezrukov ether_addr_copy(dev->net->dev_addr, dev->net->perm_addr); 4384a3576d2SDmitry Bezrukov 439361459cdSDmitry Bezrukov /* Set Rx urb size */ 440361459cdSDmitry Bezrukov dev->rx_urb_size = URB_SIZE; 441361459cdSDmitry Bezrukov 4424a3576d2SDmitry Bezrukov /* Set TX needed headroom & tailroom */ 4434a3576d2SDmitry Bezrukov dev->net->needed_headroom += sizeof(u64); 4444a3576d2SDmitry Bezrukov dev->net->needed_tailroom += sizeof(u64); 4454a3576d2SDmitry Bezrukov 446a4017cc2SDmitry Bezrukov dev->net->max_mtu = 16334; 447a4017cc2SDmitry Bezrukov 4487cea2d40SDmitry Bezrukov dev->net->netdev_ops = &aqc111_netdev_ops; 4497cea2d40SDmitry Bezrukov 4504a3576d2SDmitry Bezrukov if (usb_device_no_sg_constraint(dev->udev)) 4514a3576d2SDmitry Bezrukov dev->can_dma_sg = 1; 4524a3576d2SDmitry Bezrukov 4534a3576d2SDmitry Bezrukov dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE; 4544a3576d2SDmitry Bezrukov dev->net->features |= AQ_SUPPORT_FEATURE; 4554a3576d2SDmitry Bezrukov 456de074e7aSDmitry Bezrukov netif_set_gso_max_size(dev->net, 65535); 457de074e7aSDmitry Bezrukov 45833cd597fSDmitry Bezrukov aqc111_read_fw_version(dev, aqc111_data); 4597b8b0654SDmitry Bezrukov aqc111_data->autoneg = AUTONEG_ENABLE; 4607b8b0654SDmitry Bezrukov aqc111_data->advertised_speed = (usb_speed == USB_SPEED_SUPER) ? 4617b8b0654SDmitry Bezrukov SPEED_5000 : SPEED_1000; 46233cd597fSDmitry Bezrukov 4637cea2d40SDmitry Bezrukov return 0; 464df2d59a2SDmitry Bezrukov 465df2d59a2SDmitry Bezrukov out: 466df2d59a2SDmitry Bezrukov kfree(aqc111_data); 467df2d59a2SDmitry Bezrukov return ret; 4687cea2d40SDmitry Bezrukov } 4697cea2d40SDmitry Bezrukov 4707cea2d40SDmitry Bezrukov static void aqc111_unbind(struct usbnet *dev, struct usb_interface *intf) 4717cea2d40SDmitry Bezrukov { 47233cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 473f3aa095aSDmitry Bezrukov u16 reg16; 474f3aa095aSDmitry Bezrukov 475f3aa095aSDmitry Bezrukov /* Force bz */ 476f3aa095aSDmitry Bezrukov reg16 = SFR_PHYPWR_RSTCTL_BZ; 477f3aa095aSDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 478f3aa095aSDmitry Bezrukov 2, ®16); 479f3aa095aSDmitry Bezrukov reg16 = 0; 480f3aa095aSDmitry Bezrukov aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL, 481f3aa095aSDmitry Bezrukov 2, ®16); 48233cd597fSDmitry Bezrukov 48333cd597fSDmitry Bezrukov /* Power down ethernet PHY */ 4847b8b0654SDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_ADV_MASK; 48533cd597fSDmitry Bezrukov aqc111_data->phy_cfg |= AQ_LOW_POWER; 48633cd597fSDmitry Bezrukov aqc111_data->phy_cfg &= ~AQ_PHY_POWER_EN; 48733cd597fSDmitry Bezrukov aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, 48833cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 48933cd597fSDmitry Bezrukov 49033cd597fSDmitry Bezrukov kfree(aqc111_data); 491f3aa095aSDmitry Bezrukov } 492f3aa095aSDmitry Bezrukov 4937b8b0654SDmitry Bezrukov static void aqc111_status(struct usbnet *dev, struct urb *urb) 4947b8b0654SDmitry Bezrukov { 4957b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 4967b8b0654SDmitry Bezrukov u64 *event_data = NULL; 4977b8b0654SDmitry Bezrukov int link = 0; 4987b8b0654SDmitry Bezrukov 4997b8b0654SDmitry Bezrukov if (urb->actual_length < sizeof(*event_data)) 5007b8b0654SDmitry Bezrukov return; 5017b8b0654SDmitry Bezrukov 5027b8b0654SDmitry Bezrukov event_data = urb->transfer_buffer; 5037b8b0654SDmitry Bezrukov le64_to_cpus(event_data); 5047b8b0654SDmitry Bezrukov 5057b8b0654SDmitry Bezrukov if (*event_data & AQ_LS_MASK) 5067b8b0654SDmitry Bezrukov link = 1; 5077b8b0654SDmitry Bezrukov else 5087b8b0654SDmitry Bezrukov link = 0; 5097b8b0654SDmitry Bezrukov 5107b8b0654SDmitry Bezrukov aqc111_data->link_speed = (*event_data & AQ_SPEED_MASK) >> 5117b8b0654SDmitry Bezrukov AQ_SPEED_SHIFT; 5127b8b0654SDmitry Bezrukov aqc111_data->link = link; 5137b8b0654SDmitry Bezrukov 5147b8b0654SDmitry Bezrukov if (netif_carrier_ok(dev->net) != link) 5157b8b0654SDmitry Bezrukov usbnet_defer_kevent(dev, EVENT_LINK_RESET); 5167b8b0654SDmitry Bezrukov } 5177b8b0654SDmitry Bezrukov 5187b8b0654SDmitry Bezrukov static void aqc111_configure_rx(struct usbnet *dev, 5197b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data) 5207b8b0654SDmitry Bezrukov { 5217b8b0654SDmitry Bezrukov enum usb_device_speed usb_speed = dev->udev->speed; 5227b8b0654SDmitry Bezrukov u16 link_speed = 0, usb_host = 0; 5237b8b0654SDmitry Bezrukov u8 buf[5] = { 0 }; 5247b8b0654SDmitry Bezrukov u8 queue_num = 0; 5257b8b0654SDmitry Bezrukov u16 reg16 = 0; 5267b8b0654SDmitry Bezrukov u8 reg8 = 0; 5277b8b0654SDmitry Bezrukov 5287b8b0654SDmitry Bezrukov buf[0] = 0x00; 5297b8b0654SDmitry Bezrukov buf[1] = 0xF8; 5307b8b0654SDmitry Bezrukov buf[2] = 0x07; 5317b8b0654SDmitry Bezrukov switch (aqc111_data->link_speed) { 5327b8b0654SDmitry Bezrukov case AQ_INT_SPEED_5G: 5337b8b0654SDmitry Bezrukov link_speed = 5000; 5347b8b0654SDmitry Bezrukov reg8 = 0x05; 5357b8b0654SDmitry Bezrukov reg16 = 0x001F; 5367b8b0654SDmitry Bezrukov break; 5377b8b0654SDmitry Bezrukov case AQ_INT_SPEED_2_5G: 5387b8b0654SDmitry Bezrukov link_speed = 2500; 5397b8b0654SDmitry Bezrukov reg16 = 0x003F; 5407b8b0654SDmitry Bezrukov break; 5417b8b0654SDmitry Bezrukov case AQ_INT_SPEED_1G: 5427b8b0654SDmitry Bezrukov link_speed = 1000; 5437b8b0654SDmitry Bezrukov reg16 = 0x009F; 5447b8b0654SDmitry Bezrukov break; 5457b8b0654SDmitry Bezrukov case AQ_INT_SPEED_100M: 5467b8b0654SDmitry Bezrukov link_speed = 100; 5477b8b0654SDmitry Bezrukov queue_num = 1; 5487b8b0654SDmitry Bezrukov reg16 = 0x063F; 5497b8b0654SDmitry Bezrukov buf[1] = 0xFB; 5507b8b0654SDmitry Bezrukov buf[2] = 0x4; 5517b8b0654SDmitry Bezrukov break; 5527b8b0654SDmitry Bezrukov } 5537b8b0654SDmitry Bezrukov 5547b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_INTER_PACKET_GAP_0, 5557b8b0654SDmitry Bezrukov 1, 1, ®8); 5567b8b0654SDmitry Bezrukov 5577b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TX_PAUSE_RESEND_T, 3, 3, buf); 5587b8b0654SDmitry Bezrukov 5597b8b0654SDmitry Bezrukov switch (usb_speed) { 5607b8b0654SDmitry Bezrukov case USB_SPEED_SUPER: 5617b8b0654SDmitry Bezrukov usb_host = 3; 5627b8b0654SDmitry Bezrukov break; 5637b8b0654SDmitry Bezrukov case USB_SPEED_HIGH: 5647b8b0654SDmitry Bezrukov usb_host = 2; 5657b8b0654SDmitry Bezrukov break; 5667b8b0654SDmitry Bezrukov case USB_SPEED_FULL: 5677b8b0654SDmitry Bezrukov case USB_SPEED_LOW: 5687b8b0654SDmitry Bezrukov usb_host = 1; 5697b8b0654SDmitry Bezrukov queue_num = 0; 5707b8b0654SDmitry Bezrukov break; 5717b8b0654SDmitry Bezrukov default: 5727b8b0654SDmitry Bezrukov usb_host = 0; 5737b8b0654SDmitry Bezrukov break; 5747b8b0654SDmitry Bezrukov } 5757b8b0654SDmitry Bezrukov 576a4017cc2SDmitry Bezrukov if (dev->net->mtu > 12500 && dev->net->mtu <= 16334) 577a4017cc2SDmitry Bezrukov queue_num = 2; /* For Jumbo packet 16KB */ 578a4017cc2SDmitry Bezrukov 5797b8b0654SDmitry Bezrukov memcpy(buf, &AQC111_BULKIN_SIZE[queue_num], 5); 5807b8b0654SDmitry Bezrukov /* RX bulk configuration */ 5817b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL, 5, 5, buf); 5827b8b0654SDmitry Bezrukov 5837b8b0654SDmitry Bezrukov /* Set high low water level */ 584a4017cc2SDmitry Bezrukov if (dev->net->mtu <= 4500) 5857b8b0654SDmitry Bezrukov reg16 = 0x0810; 586a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 9500) 587a4017cc2SDmitry Bezrukov reg16 = 0x1020; 588a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 12500) 589a4017cc2SDmitry Bezrukov reg16 = 0x1420; 590a4017cc2SDmitry Bezrukov else if (dev->net->mtu <= 16334) 591a4017cc2SDmitry Bezrukov reg16 = 0x1A20; 5927b8b0654SDmitry Bezrukov 5937b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_PAUSE_WATERLVL_LOW, 5947b8b0654SDmitry Bezrukov 2, ®16); 5957b8b0654SDmitry Bezrukov netdev_info(dev->net, "Link Speed %d, USB %d", link_speed, usb_host); 5967b8b0654SDmitry Bezrukov } 5977b8b0654SDmitry Bezrukov 59802031466SDmitry Bezrukov static void aqc111_configure_csum_offload(struct usbnet *dev) 59902031466SDmitry Bezrukov { 60002031466SDmitry Bezrukov u8 reg8 = 0; 60102031466SDmitry Bezrukov 60202031466SDmitry Bezrukov if (dev->net->features & NETIF_F_RXCSUM) { 60302031466SDmitry Bezrukov reg8 |= SFR_RXCOE_IP | SFR_RXCOE_TCP | SFR_RXCOE_UDP | 60402031466SDmitry Bezrukov SFR_RXCOE_TCPV6 | SFR_RXCOE_UDPV6; 60502031466SDmitry Bezrukov } 60602031466SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_RXCOE_CTL, 1, 1, ®8); 60702031466SDmitry Bezrukov 60802031466SDmitry Bezrukov reg8 = 0; 60902031466SDmitry Bezrukov if (dev->net->features & NETIF_F_IP_CSUM) 61002031466SDmitry Bezrukov reg8 |= SFR_TXCOE_IP | SFR_TXCOE_TCP | SFR_TXCOE_UDP; 61102031466SDmitry Bezrukov 61202031466SDmitry Bezrukov if (dev->net->features & NETIF_F_IPV6_CSUM) 61302031466SDmitry Bezrukov reg8 |= SFR_TXCOE_TCPV6 | SFR_TXCOE_UDPV6; 61402031466SDmitry Bezrukov 61502031466SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_TXCOE_CTL, 1, 1, ®8); 61602031466SDmitry Bezrukov } 61702031466SDmitry Bezrukov 6187b8b0654SDmitry Bezrukov static int aqc111_link_reset(struct usbnet *dev) 6197b8b0654SDmitry Bezrukov { 6207b8b0654SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 6217b8b0654SDmitry Bezrukov u16 reg16 = 0; 6227b8b0654SDmitry Bezrukov u8 reg8 = 0; 6237b8b0654SDmitry Bezrukov 6247b8b0654SDmitry Bezrukov if (aqc111_data->link == 1) { /* Link up */ 6257b8b0654SDmitry Bezrukov aqc111_configure_rx(dev, aqc111_data); 6267b8b0654SDmitry Bezrukov 6277b8b0654SDmitry Bezrukov /* Vlan Tag Filter */ 6287b8b0654SDmitry Bezrukov reg8 = SFR_VLAN_CONTROL_VSO; 6297b8b0654SDmitry Bezrukov 6307b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_VLAN_ID_CONTROL, 6317b8b0654SDmitry Bezrukov 1, 1, ®8); 6327b8b0654SDmitry Bezrukov 6337b8b0654SDmitry Bezrukov reg8 = 0x0; 6347b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 6357b8b0654SDmitry Bezrukov 1, 1, ®8); 6367b8b0654SDmitry Bezrukov 6377b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMTX_DMA_CONTROL, 6387b8b0654SDmitry Bezrukov 1, 1, ®8); 6397b8b0654SDmitry Bezrukov 6407b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ARC_CTRL, 1, 1, ®8); 6417b8b0654SDmitry Bezrukov 6427b8b0654SDmitry Bezrukov reg16 = SFR_RX_CTL_IPE | SFR_RX_CTL_AB; 643*59b04eeaSDmitry Bezrukov aqc111_data->rxctl = reg16; 6447b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 6457b8b0654SDmitry Bezrukov 6467b8b0654SDmitry Bezrukov reg8 = SFR_RX_PATH_READY; 6477b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH, 6487b8b0654SDmitry Bezrukov 1, 1, ®8); 6497b8b0654SDmitry Bezrukov 6507b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_EFF_EN; 6517b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 6527b8b0654SDmitry Bezrukov 1, 1, ®8); 6537b8b0654SDmitry Bezrukov 6547b8b0654SDmitry Bezrukov reg16 = 0; 6557b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 6567b8b0654SDmitry Bezrukov 2, ®16); 6577b8b0654SDmitry Bezrukov 6587b8b0654SDmitry Bezrukov reg16 = SFR_MEDIUM_XGMIIMODE | SFR_MEDIUM_FULL_DUPLEX; 6597b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 6607b8b0654SDmitry Bezrukov 2, ®16); 6617b8b0654SDmitry Bezrukov 66202031466SDmitry Bezrukov aqc111_configure_csum_offload(dev); 66302031466SDmitry Bezrukov 664*59b04eeaSDmitry Bezrukov aqc111_set_rx_mode(dev->net); 665*59b04eeaSDmitry Bezrukov 6667b8b0654SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 6677b8b0654SDmitry Bezrukov 2, ®16); 6687b8b0654SDmitry Bezrukov 669a4017cc2SDmitry Bezrukov if (dev->net->mtu > 1500) 670a4017cc2SDmitry Bezrukov reg16 |= SFR_MEDIUM_JUMBO_EN; 671a4017cc2SDmitry Bezrukov 6727b8b0654SDmitry Bezrukov reg16 |= SFR_MEDIUM_RECEIVE_EN | SFR_MEDIUM_RXFLOW_CTRLEN | 6737b8b0654SDmitry Bezrukov SFR_MEDIUM_TXFLOW_CTRLEN; 6747b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 6757b8b0654SDmitry Bezrukov 2, ®16); 6767b8b0654SDmitry Bezrukov 677*59b04eeaSDmitry Bezrukov aqc111_data->rxctl |= SFR_RX_CTL_START; 678*59b04eeaSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 679*59b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 6807b8b0654SDmitry Bezrukov 6817b8b0654SDmitry Bezrukov netif_carrier_on(dev->net); 6827b8b0654SDmitry Bezrukov } else { 6837b8b0654SDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 6847b8b0654SDmitry Bezrukov 2, ®16); 6857b8b0654SDmitry Bezrukov reg16 &= ~SFR_MEDIUM_RECEIVE_EN; 6867b8b0654SDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 6877b8b0654SDmitry Bezrukov 2, ®16); 6887b8b0654SDmitry Bezrukov 689*59b04eeaSDmitry Bezrukov aqc111_data->rxctl &= ~SFR_RX_CTL_START; 690*59b04eeaSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 691*59b04eeaSDmitry Bezrukov 2, &aqc111_data->rxctl); 6927b8b0654SDmitry Bezrukov 6937b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_FLUSH_EN | SFR_BULK_OUT_EFF_EN; 6947b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 6957b8b0654SDmitry Bezrukov 1, 1, ®8); 6967b8b0654SDmitry Bezrukov reg8 = SFR_BULK_OUT_EFF_EN; 6977b8b0654SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL, 6987b8b0654SDmitry Bezrukov 1, 1, ®8); 6997b8b0654SDmitry Bezrukov 7007b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 7017b8b0654SDmitry Bezrukov } 7027b8b0654SDmitry Bezrukov return 0; 7037b8b0654SDmitry Bezrukov } 7047b8b0654SDmitry Bezrukov 705f3aa095aSDmitry Bezrukov static int aqc111_reset(struct usbnet *dev) 706f3aa095aSDmitry Bezrukov { 70733cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 708f3aa095aSDmitry Bezrukov u8 reg8 = 0; 709f3aa095aSDmitry Bezrukov 710361459cdSDmitry Bezrukov dev->rx_urb_size = URB_SIZE; 711361459cdSDmitry Bezrukov 7124a3576d2SDmitry Bezrukov if (usb_device_no_sg_constraint(dev->udev)) 7134a3576d2SDmitry Bezrukov dev->can_dma_sg = 1; 7144a3576d2SDmitry Bezrukov 7154a3576d2SDmitry Bezrukov dev->net->hw_features |= AQ_SUPPORT_HW_FEATURE; 7164a3576d2SDmitry Bezrukov dev->net->features |= AQ_SUPPORT_FEATURE; 7174a3576d2SDmitry Bezrukov 71833cd597fSDmitry Bezrukov /* Power up ethernet PHY */ 71933cd597fSDmitry Bezrukov aqc111_data->phy_cfg = AQ_PHY_POWER_EN; 72033cd597fSDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 72133cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 72233cd597fSDmitry Bezrukov 723df2d59a2SDmitry Bezrukov /* Set the MAC address */ 724df2d59a2SDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_NODE_ID, ETH_ALEN, 725df2d59a2SDmitry Bezrukov ETH_ALEN, dev->net->dev_addr); 726df2d59a2SDmitry Bezrukov 727f3aa095aSDmitry Bezrukov reg8 = 0xFF; 728f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK, 1, 1, ®8); 729f3aa095aSDmitry Bezrukov 730f3aa095aSDmitry Bezrukov reg8 = 0x0; 731f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_SWP_CTRL, 1, 1, ®8); 732f3aa095aSDmitry Bezrukov 733f3aa095aSDmitry Bezrukov aqc111_read_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8); 734f3aa095aSDmitry Bezrukov reg8 &= ~(SFR_MONITOR_MODE_EPHYRW | SFR_MONITOR_MODE_RWLC | 735f3aa095aSDmitry Bezrukov SFR_MONITOR_MODE_RWMP | SFR_MONITOR_MODE_RWWF | 736f3aa095aSDmitry Bezrukov SFR_MONITOR_MODE_RW_FLAG); 737f3aa095aSDmitry Bezrukov aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_MONITOR_MODE, 1, 1, ®8); 738f3aa095aSDmitry Bezrukov 7397b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 7407b8b0654SDmitry Bezrukov 7417b8b0654SDmitry Bezrukov /* Phy advertise */ 7427b8b0654SDmitry Bezrukov aqc111_set_phy_speed(dev, aqc111_data->autoneg, 7437b8b0654SDmitry Bezrukov aqc111_data->advertised_speed); 7447b8b0654SDmitry Bezrukov 745f3aa095aSDmitry Bezrukov return 0; 746f3aa095aSDmitry Bezrukov } 747f3aa095aSDmitry Bezrukov 748f3aa095aSDmitry Bezrukov static int aqc111_stop(struct usbnet *dev) 749f3aa095aSDmitry Bezrukov { 75033cd597fSDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 751f3aa095aSDmitry Bezrukov u16 reg16 = 0; 752f3aa095aSDmitry Bezrukov 753f3aa095aSDmitry Bezrukov aqc111_read16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 754f3aa095aSDmitry Bezrukov 2, ®16); 755f3aa095aSDmitry Bezrukov reg16 &= ~SFR_MEDIUM_RECEIVE_EN; 756f3aa095aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE, 757f3aa095aSDmitry Bezrukov 2, ®16); 758f3aa095aSDmitry Bezrukov reg16 = 0; 759f3aa095aSDmitry Bezrukov aqc111_write16_cmd(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16); 760f3aa095aSDmitry Bezrukov 76133cd597fSDmitry Bezrukov /* Put PHY to low power*/ 76233cd597fSDmitry Bezrukov aqc111_data->phy_cfg |= AQ_LOW_POWER; 76333cd597fSDmitry Bezrukov aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, 76433cd597fSDmitry Bezrukov &aqc111_data->phy_cfg); 76533cd597fSDmitry Bezrukov 7667b8b0654SDmitry Bezrukov netif_carrier_off(dev->net); 7677b8b0654SDmitry Bezrukov 768f3aa095aSDmitry Bezrukov return 0; 7697cea2d40SDmitry Bezrukov } 7707cea2d40SDmitry Bezrukov 77102031466SDmitry Bezrukov static void aqc111_rx_checksum(struct sk_buff *skb, u64 pkt_desc) 77202031466SDmitry Bezrukov { 77302031466SDmitry Bezrukov u32 pkt_type = 0; 77402031466SDmitry Bezrukov 77502031466SDmitry Bezrukov skb->ip_summed = CHECKSUM_NONE; 77602031466SDmitry Bezrukov /* checksum error bit is set */ 77702031466SDmitry Bezrukov if (pkt_desc & AQ_RX_PD_L4_ERR || pkt_desc & AQ_RX_PD_L3_ERR) 77802031466SDmitry Bezrukov return; 77902031466SDmitry Bezrukov 78002031466SDmitry Bezrukov pkt_type = pkt_desc & AQ_RX_PD_L4_TYPE_MASK; 78102031466SDmitry Bezrukov /* It must be a TCP or UDP packet with a valid checksum */ 78202031466SDmitry Bezrukov if (pkt_type == AQ_RX_PD_L4_TCP || pkt_type == AQ_RX_PD_L4_UDP) 78302031466SDmitry Bezrukov skb->ip_summed = CHECKSUM_UNNECESSARY; 78402031466SDmitry Bezrukov } 78502031466SDmitry Bezrukov 786361459cdSDmitry Bezrukov static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 787361459cdSDmitry Bezrukov { 7886649d2a6SDmitry Bezrukov struct aqc111_data *aqc111_data = dev->driver_priv; 789361459cdSDmitry Bezrukov struct sk_buff *new_skb = NULL; 790361459cdSDmitry Bezrukov u32 pkt_total_offset = 0; 791361459cdSDmitry Bezrukov u64 *pkt_desc_ptr = NULL; 792361459cdSDmitry Bezrukov u32 start_of_descs = 0; 793361459cdSDmitry Bezrukov u32 desc_offset = 0; /*RX Header Offset*/ 794361459cdSDmitry Bezrukov u16 pkt_count = 0; 795361459cdSDmitry Bezrukov u64 desc_hdr = 0; 796361459cdSDmitry Bezrukov u32 skb_len = 0; 797361459cdSDmitry Bezrukov 798361459cdSDmitry Bezrukov if (!skb) 799361459cdSDmitry Bezrukov goto err; 800361459cdSDmitry Bezrukov 801361459cdSDmitry Bezrukov if (skb->len == 0) 802361459cdSDmitry Bezrukov goto err; 803361459cdSDmitry Bezrukov 804361459cdSDmitry Bezrukov skb_len = skb->len; 805361459cdSDmitry Bezrukov /* RX Descriptor Header */ 806361459cdSDmitry Bezrukov skb_trim(skb, skb->len - sizeof(desc_hdr)); 807361459cdSDmitry Bezrukov desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb)); 808361459cdSDmitry Bezrukov 809361459cdSDmitry Bezrukov /* Check these packets */ 810361459cdSDmitry Bezrukov desc_offset = (desc_hdr & AQ_RX_DH_DESC_OFFSET_MASK) >> 811361459cdSDmitry Bezrukov AQ_RX_DH_DESC_OFFSET_SHIFT; 812361459cdSDmitry Bezrukov pkt_count = desc_hdr & AQ_RX_DH_PKT_CNT_MASK; 813361459cdSDmitry Bezrukov start_of_descs = skb_len - ((pkt_count + 1) * sizeof(desc_hdr)); 814361459cdSDmitry Bezrukov 815361459cdSDmitry Bezrukov /* self check descs position */ 816361459cdSDmitry Bezrukov if (start_of_descs != desc_offset) 817361459cdSDmitry Bezrukov goto err; 818361459cdSDmitry Bezrukov 819361459cdSDmitry Bezrukov /* self check desc_offset from header*/ 820361459cdSDmitry Bezrukov if (desc_offset >= skb_len) 821361459cdSDmitry Bezrukov goto err; 822361459cdSDmitry Bezrukov 823361459cdSDmitry Bezrukov if (pkt_count == 0) 824361459cdSDmitry Bezrukov goto err; 825361459cdSDmitry Bezrukov 826361459cdSDmitry Bezrukov /* Get the first RX packet descriptor */ 827361459cdSDmitry Bezrukov pkt_desc_ptr = (u64 *)(skb->data + desc_offset); 828361459cdSDmitry Bezrukov 829361459cdSDmitry Bezrukov while (pkt_count--) { 830361459cdSDmitry Bezrukov u64 pkt_desc = le64_to_cpup(pkt_desc_ptr); 831361459cdSDmitry Bezrukov u32 pkt_len_with_padd = 0; 832361459cdSDmitry Bezrukov u32 pkt_len = 0; 833361459cdSDmitry Bezrukov 834361459cdSDmitry Bezrukov pkt_len = (u32)((pkt_desc & AQ_RX_PD_LEN_MASK) >> 835361459cdSDmitry Bezrukov AQ_RX_PD_LEN_SHIFT); 836361459cdSDmitry Bezrukov pkt_len_with_padd = ((pkt_len + 7) & 0x7FFF8); 837361459cdSDmitry Bezrukov 838361459cdSDmitry Bezrukov pkt_total_offset += pkt_len_with_padd; 839361459cdSDmitry Bezrukov if (pkt_total_offset > desc_offset || 840361459cdSDmitry Bezrukov (pkt_count == 0 && pkt_total_offset != desc_offset)) { 841361459cdSDmitry Bezrukov goto err; 842361459cdSDmitry Bezrukov } 843361459cdSDmitry Bezrukov 844361459cdSDmitry Bezrukov if (pkt_desc & AQ_RX_PD_DROP || 845361459cdSDmitry Bezrukov !(pkt_desc & AQ_RX_PD_RX_OK) || 846361459cdSDmitry Bezrukov pkt_len > (dev->hard_mtu + AQ_RX_HW_PAD)) { 847361459cdSDmitry Bezrukov skb_pull(skb, pkt_len_with_padd); 848361459cdSDmitry Bezrukov /* Next RX Packet Descriptor */ 849361459cdSDmitry Bezrukov pkt_desc_ptr++; 850361459cdSDmitry Bezrukov continue; 851361459cdSDmitry Bezrukov } 852361459cdSDmitry Bezrukov 853361459cdSDmitry Bezrukov /* Clone SKB */ 854361459cdSDmitry Bezrukov new_skb = skb_clone(skb, GFP_ATOMIC); 855361459cdSDmitry Bezrukov 856361459cdSDmitry Bezrukov if (!new_skb) 857361459cdSDmitry Bezrukov goto err; 858361459cdSDmitry Bezrukov 859361459cdSDmitry Bezrukov new_skb->len = pkt_len; 860361459cdSDmitry Bezrukov skb_pull(new_skb, AQ_RX_HW_PAD); 861361459cdSDmitry Bezrukov skb_set_tail_pointer(new_skb, new_skb->len); 862361459cdSDmitry Bezrukov 863361459cdSDmitry Bezrukov new_skb->truesize = SKB_TRUESIZE(new_skb->len); 8646649d2a6SDmitry Bezrukov if (aqc111_data->rx_checksum) 86502031466SDmitry Bezrukov aqc111_rx_checksum(new_skb, pkt_desc); 866361459cdSDmitry Bezrukov 867361459cdSDmitry Bezrukov usbnet_skb_return(dev, new_skb); 868361459cdSDmitry Bezrukov if (pkt_count == 0) 869361459cdSDmitry Bezrukov break; 870361459cdSDmitry Bezrukov 871361459cdSDmitry Bezrukov skb_pull(skb, pkt_len_with_padd); 872361459cdSDmitry Bezrukov 873361459cdSDmitry Bezrukov /* Next RX Packet Header */ 874361459cdSDmitry Bezrukov pkt_desc_ptr++; 875361459cdSDmitry Bezrukov 876361459cdSDmitry Bezrukov new_skb = NULL; 877361459cdSDmitry Bezrukov } 878361459cdSDmitry Bezrukov 879361459cdSDmitry Bezrukov return 1; 880361459cdSDmitry Bezrukov 881361459cdSDmitry Bezrukov err: 882361459cdSDmitry Bezrukov return 0; 883361459cdSDmitry Bezrukov } 884361459cdSDmitry Bezrukov 8854a3576d2SDmitry Bezrukov static struct sk_buff *aqc111_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 8864a3576d2SDmitry Bezrukov gfp_t flags) 8874a3576d2SDmitry Bezrukov { 8884a3576d2SDmitry Bezrukov int frame_size = dev->maxpacket; 8894a3576d2SDmitry Bezrukov struct sk_buff *new_skb = NULL; 8904a3576d2SDmitry Bezrukov u64 *tx_desc_ptr = NULL; 8914a3576d2SDmitry Bezrukov int padding_size = 0; 8924a3576d2SDmitry Bezrukov int headroom = 0; 8934a3576d2SDmitry Bezrukov int tailroom = 0; 8944a3576d2SDmitry Bezrukov u64 tx_desc = 0; 8954a3576d2SDmitry Bezrukov 8964a3576d2SDmitry Bezrukov /*Length of actual data*/ 8974a3576d2SDmitry Bezrukov tx_desc |= skb->len & AQ_TX_DESC_LEN_MASK; 8984a3576d2SDmitry Bezrukov 899de074e7aSDmitry Bezrukov /* TSO MSS */ 900de074e7aSDmitry Bezrukov tx_desc |= ((u64)(skb_shinfo(skb)->gso_size & AQ_TX_DESC_MSS_MASK)) << 901de074e7aSDmitry Bezrukov AQ_TX_DESC_MSS_SHIFT; 902de074e7aSDmitry Bezrukov 9034a3576d2SDmitry Bezrukov headroom = (skb->len + sizeof(tx_desc)) % 8; 9044a3576d2SDmitry Bezrukov if (headroom != 0) 9054a3576d2SDmitry Bezrukov padding_size = 8 - headroom; 9064a3576d2SDmitry Bezrukov 9074a3576d2SDmitry Bezrukov if (((skb->len + sizeof(tx_desc) + padding_size) % frame_size) == 0) { 9084a3576d2SDmitry Bezrukov padding_size += 8; 9094a3576d2SDmitry Bezrukov tx_desc |= AQ_TX_DESC_DROP_PADD; 9104a3576d2SDmitry Bezrukov } 9114a3576d2SDmitry Bezrukov 9124a3576d2SDmitry Bezrukov if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) && 9134a3576d2SDmitry Bezrukov skb_linearize(skb)) 9144a3576d2SDmitry Bezrukov return NULL; 9154a3576d2SDmitry Bezrukov 9164a3576d2SDmitry Bezrukov headroom = skb_headroom(skb); 9174a3576d2SDmitry Bezrukov tailroom = skb_tailroom(skb); 9184a3576d2SDmitry Bezrukov 9194a3576d2SDmitry Bezrukov if (!(headroom >= sizeof(tx_desc) && tailroom >= padding_size)) { 9204a3576d2SDmitry Bezrukov new_skb = skb_copy_expand(skb, sizeof(tx_desc), 9214a3576d2SDmitry Bezrukov padding_size, flags); 9224a3576d2SDmitry Bezrukov dev_kfree_skb_any(skb); 9234a3576d2SDmitry Bezrukov skb = new_skb; 9244a3576d2SDmitry Bezrukov if (!skb) 9254a3576d2SDmitry Bezrukov return NULL; 9264a3576d2SDmitry Bezrukov } 9274a3576d2SDmitry Bezrukov if (padding_size != 0) 9284a3576d2SDmitry Bezrukov skb_put_zero(skb, padding_size); 9294a3576d2SDmitry Bezrukov /* Copy TX header */ 9304a3576d2SDmitry Bezrukov tx_desc_ptr = skb_push(skb, sizeof(tx_desc)); 9314a3576d2SDmitry Bezrukov *tx_desc_ptr = cpu_to_le64(tx_desc); 9324a3576d2SDmitry Bezrukov 9334a3576d2SDmitry Bezrukov usbnet_set_skb_tx_stats(skb, 1, 0); 9344a3576d2SDmitry Bezrukov 9354a3576d2SDmitry Bezrukov return skb; 9364a3576d2SDmitry Bezrukov } 9374a3576d2SDmitry Bezrukov 93817364b80SDmitry Bezrukov static const struct driver_info aqc111_info = { 93917364b80SDmitry Bezrukov .description = "Aquantia AQtion USB to 5GbE Controller", 9407cea2d40SDmitry Bezrukov .bind = aqc111_bind, 9417cea2d40SDmitry Bezrukov .unbind = aqc111_unbind, 9427b8b0654SDmitry Bezrukov .status = aqc111_status, 9437b8b0654SDmitry Bezrukov .link_reset = aqc111_link_reset, 944f3aa095aSDmitry Bezrukov .reset = aqc111_reset, 945f3aa095aSDmitry Bezrukov .stop = aqc111_stop, 9464a3576d2SDmitry Bezrukov .flags = FLAG_ETHER | FLAG_FRAMING_AX | 9474a3576d2SDmitry Bezrukov FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET, 948361459cdSDmitry Bezrukov .rx_fixup = aqc111_rx_fixup, 9494a3576d2SDmitry Bezrukov .tx_fixup = aqc111_tx_fixup, 95017364b80SDmitry Bezrukov }; 95117364b80SDmitry Bezrukov 95217364b80SDmitry Bezrukov #define AQC111_USB_ETH_DEV(vid, pid, table) \ 95317364b80SDmitry Bezrukov USB_DEVICE_INTERFACE_CLASS((vid), (pid), USB_CLASS_VENDOR_SPEC), \ 95417364b80SDmitry Bezrukov .driver_info = (unsigned long)&(table) \ 95517364b80SDmitry Bezrukov }, \ 95617364b80SDmitry Bezrukov { \ 95717364b80SDmitry Bezrukov USB_DEVICE_AND_INTERFACE_INFO((vid), (pid), \ 95817364b80SDmitry Bezrukov USB_CLASS_COMM, \ 95917364b80SDmitry Bezrukov USB_CDC_SUBCLASS_ETHERNET, \ 96017364b80SDmitry Bezrukov USB_CDC_PROTO_NONE), \ 96117364b80SDmitry Bezrukov .driver_info = (unsigned long)&(table), 96217364b80SDmitry Bezrukov 96317364b80SDmitry Bezrukov static const struct usb_device_id products[] = { 96417364b80SDmitry Bezrukov {AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)}, 96517364b80SDmitry Bezrukov { },/* END */ 96617364b80SDmitry Bezrukov }; 96717364b80SDmitry Bezrukov MODULE_DEVICE_TABLE(usb, products); 96817364b80SDmitry Bezrukov 96917364b80SDmitry Bezrukov static struct usb_driver aq_driver = { 97017364b80SDmitry Bezrukov .name = "aqc111", 97117364b80SDmitry Bezrukov .id_table = products, 97217364b80SDmitry Bezrukov .probe = usbnet_probe, 97317364b80SDmitry Bezrukov .disconnect = usbnet_disconnect, 97417364b80SDmitry Bezrukov }; 97517364b80SDmitry Bezrukov 97617364b80SDmitry Bezrukov module_usb_driver(aq_driver); 97717364b80SDmitry Bezrukov 97817364b80SDmitry Bezrukov MODULE_DESCRIPTION("Aquantia AQtion USB to 5/2.5GbE Controllers"); 97917364b80SDmitry Bezrukov MODULE_LICENSE("GPL"); 980