diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 05e8bd7b3e0f96..2e6bfd4ff5a2da 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -766,6 +766,9 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu) dev->hard_mtu = net->mtu + net->hard_header_len; ax88178_set_mfb(dev); + /* max qlen depend on hard_mtu and rx_urb_size */ + usbnet_update_max_qlen(dev); + return 0; } diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c old mode 100755 new mode 100644 index e59d1751527bd0..e6338c16081a5d --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1,13 +1,12 @@ /* - * ASIX AX88179 based USB 3.0 Ethernet Devices - * Copyright (C) 2003-2005 David Hollis - * Copyright (C) 2005 Phil Chang - * Copyright (c) 2002-2003 TiVo Inc. + * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices + * + * Copyright (C) 2011-2013 ASIX * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,75 +14,192 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program; if not, see . */ -/* debug messages, extra info */ -/* #define DEBUG */ - -#include -/*#include */ -#ifdef CONFIG_USB_DEBUG -#define DEBUG -#endif #include -#include -#include -#include -#include #include -#include -#include #include #include #include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) #include -#else -#include <../drivers/usb/net/usbnet.h> -#endif - -#include "ax88179_178a.h" - -#define DRV_VERSION "1.13.0" - -static char version[] = -KERN_INFO "ASIX USB Ethernet Adapter:v" DRV_VERSION - " " __TIME__ " " __DATE__ "\n" -" http://www.asix.com.tw\n"; - -static int msg_enable; -module_param(msg_enable, int, 0); -MODULE_PARM_DESC(msg_enable, "usbnet msg_enable"); - -static int bsize = -1; -module_param(bsize, int, 0); -MODULE_PARM_DESC(bsize, "RX Bulk IN Queue Size"); - -static int ifg = -1; -module_param(ifg, int, 0); -MODULE_PARM_DESC(ifg, "RX Bulk IN Inter Frame Gap"); - +#include +#include + +#define AX88179_PHY_ID 0x03 +#define AX_EEPROM_LEN 0x100 +#define AX88179_EEPROM_MAGIC 0x17900b95 +#define AX_MCAST_FLTSIZE 8 +#define AX_MAX_MCAST 64 +#define AX_INT_PPLS_LINK ((u32)BIT(16)) +#define AX_RXHDR_L4_TYPE_MASK 0x1c +#define AX_RXHDR_L4_TYPE_UDP 4 +#define AX_RXHDR_L4_TYPE_TCP 16 +#define AX_RXHDR_L3CSUM_ERR 2 +#define AX_RXHDR_L4CSUM_ERR 1 +#define AX_RXHDR_CRC_ERR ((u32)BIT(29)) +#define AX_RXHDR_DROP_ERR ((u32)BIT(31)) +#define AX_ACCESS_MAC 0x01 +#define AX_ACCESS_PHY 0x02 +#define AX_ACCESS_EEPROM 0x04 +#define AX_ACCESS_EFUS 0x05 +#define AX_PAUSE_WATERLVL_HIGH 0x54 +#define AX_PAUSE_WATERLVL_LOW 0x55 + +#define PHYSICAL_LINK_STATUS 0x02 + #define AX_USB_SS 0x04 + #define AX_USB_HS 0x02 + +#define GENERAL_STATUS 0x03 +/* Check AX88179 version. UA1:Bit2 = 0, UA2:Bit2 = 1 */ + #define AX_SECLD 0x04 + +#define AX_SROM_ADDR 0x07 +#define AX_SROM_CMD 0x0a + #define EEP_RD 0x04 + #define EEP_BUSY 0x10 + +#define AX_SROM_DATA_LOW 0x08 +#define AX_SROM_DATA_HIGH 0x09 + +#define AX_RX_CTL 0x0b + #define AX_RX_CTL_DROPCRCERR 0x0100 + #define AX_RX_CTL_IPE 0x0200 + #define AX_RX_CTL_START 0x0080 + #define AX_RX_CTL_AP 0x0020 + #define AX_RX_CTL_AM 0x0010 + #define AX_RX_CTL_AB 0x0008 + #define AX_RX_CTL_AMALL 0x0002 + #define AX_RX_CTL_PRO 0x0001 + #define AX_RX_CTL_STOP 0x0000 + +#define AX_NODE_ID 0x10 +#define AX_MULFLTARY 0x16 + +#define AX_MEDIUM_STATUS_MODE 0x22 + #define AX_MEDIUM_GIGAMODE 0x01 + #define AX_MEDIUM_FULL_DUPLEX 0x02 + #define AX_MEDIUM_EN_125MHZ 0x08 + #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 + #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 + #define AX_MEDIUM_RECEIVE_EN 0x100 + #define AX_MEDIUM_PS 0x200 + #define AX_MEDIUM_JUMBO_EN 0x8040 + +#define AX_MONITOR_MOD 0x24 + #define AX_MONITOR_MODE_RWLC 0x02 + #define AX_MONITOR_MODE_RWMP 0x04 + #define AX_MONITOR_MODE_PMEPOL 0x20 + #define AX_MONITOR_MODE_PMETYPE 0x40 + +#define AX_GPIO_CTRL 0x25 + #define AX_GPIO_CTRL_GPIO3EN 0x80 + #define AX_GPIO_CTRL_GPIO2EN 0x40 + #define AX_GPIO_CTRL_GPIO1EN 0x20 + +#define AX_PHYPWR_RSTCTL 0x26 + #define AX_PHYPWR_RSTCTL_BZ 0x0010 + #define AX_PHYPWR_RSTCTL_IPRL 0x0020 + #define AX_PHYPWR_RSTCTL_AT 0x1000 + +#define AX_RX_BULKIN_QCTRL 0x2e +#define AX_CLK_SELECT 0x33 + #define AX_CLK_SELECT_BCS 0x01 + #define AX_CLK_SELECT_ACS 0x02 + #define AX_CLK_SELECT_ULR 0x08 + +#define AX_RXCOE_CTL 0x34 + #define AX_RXCOE_IP 0x01 + #define AX_RXCOE_TCP 0x02 + #define AX_RXCOE_UDP 0x04 + #define AX_RXCOE_TCPV6 0x20 + #define AX_RXCOE_UDPV6 0x40 + +#define AX_TXCOE_CTL 0x35 + #define AX_TXCOE_IP 0x01 + #define AX_TXCOE_TCP 0x02 + #define AX_TXCOE_UDP 0x04 + #define AX_TXCOE_TCPV6 0x20 + #define AX_TXCOE_UDPV6 0x40 + +#define AX_LEDCTRL 0x73 + +#define GMII_PHY_PHYSR 0x11 + #define GMII_PHY_PHYSR_SMASK 0xc000 + #define GMII_PHY_PHYSR_GIGA 0x8000 + #define GMII_PHY_PHYSR_100 0x4000 + #define GMII_PHY_PHYSR_FULL 0x2000 + #define GMII_PHY_PHYSR_LINK 0x400 + +#define GMII_LED_ACT 0x1a + #define GMII_LED_ACTIVE_MASK 0xff8f + #define GMII_LED0_ACTIVE BIT(4) + #define GMII_LED1_ACTIVE BIT(5) + #define GMII_LED2_ACTIVE BIT(6) + +#define GMII_LED_LINK 0x1c + #define GMII_LED_LINK_MASK 0xf888 + #define GMII_LED0_LINK_10 BIT(0) + #define GMII_LED0_LINK_100 BIT(1) + #define GMII_LED0_LINK_1000 BIT(2) + #define GMII_LED1_LINK_10 BIT(4) + #define GMII_LED1_LINK_100 BIT(5) + #define GMII_LED1_LINK_1000 BIT(6) + #define GMII_LED2_LINK_10 BIT(8) + #define GMII_LED2_LINK_100 BIT(9) + #define GMII_LED2_LINK_1000 BIT(10) + #define LED0_ACTIVE BIT(0) + #define LED0_LINK_10 BIT(1) + #define LED0_LINK_100 BIT(2) + #define LED0_LINK_1000 BIT(3) + #define LED0_FD BIT(4) + #define LED0_USB3_MASK 0x001f + #define LED1_ACTIVE BIT(5) + #define LED1_LINK_10 BIT(6) + #define LED1_LINK_100 BIT(7) + #define LED1_LINK_1000 BIT(8) + #define LED1_FD BIT(9) + #define LED1_USB3_MASK 0x03e0 + #define LED2_ACTIVE BIT(10) + #define LED2_LINK_1000 BIT(13) + #define LED2_LINK_100 BIT(12) + #define LED2_LINK_10 BIT(11) + #define LED2_FD BIT(14) + #define LED_VALID BIT(15) + #define LED2_USB3_MASK 0x7c00 + +#define GMII_PHYPAGE 0x1e +#define GMII_PHY_PAGE_SELECT 0x1f + #define GMII_PHY_PGSEL_EXT 0x0007 + #define GMII_PHY_PGSEL_PAGE0 0x0000 + #define GMII_PHY_PGSEL_PAGE3 0x0003 + #define GMII_PHY_PGSEL_PAGE5 0x0005 + +struct ax88179_data { + u8 eee_enabled; + u8 eee_active; + u16 rxctl; + u16 reserved; +}; -/* EEE advertisement is disabled in default setting */ -static int bEEE = 0; -module_param(bEEE, int, 0); -MODULE_PARM_DESC(bEEE, "EEE advertisement configuration"); +struct ax88179_int_data { + __le32 intdata1; + __le32 intdata2; +}; -/* Green ethernet advertisement is disabled in default setting */ -static int bGETH = 0; -module_param(bGETH, int, 0); -MODULE_PARM_DESC(bGETH, "Green ethernet configuration"); -/* ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices */ +static const struct { + unsigned char ctrl, timer_l, timer_h, size, ifg; +} AX88179_BULKIN_SIZE[] = { + {7, 0x4f, 0, 0x12, 0xff}, + {7, 0x20, 3, 0x16, 0xff}, + {7, 0xae, 7, 0x18, 0xff}, + {7, 0xcc, 0x4c, 0x18, 8}, +}; static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16 size, void *data, int in_pm) { int ret; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); BUG_ON(!dev); @@ -93,24 +209,13 @@ static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, else fn = usbnet_read_cmd_nopm; - ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, data, size); + ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, data, size); if (unlikely(ret < 0)) netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", index, ret); -#else - ret = usb_control_msg( - dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - cmd, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - data, - size, - USB_CTRL_GET_TIMEOUT); -#endif + return ret; } @@ -118,7 +223,6 @@ static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16 size, void *data, int in_pm) { int ret; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); BUG_ON(!dev); @@ -128,40 +232,46 @@ static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, else fn = usbnet_write_cmd_nopm; - ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, data, size); + ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, data, size); if (unlikely(ret < 0)) netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", index, ret); -#else - ret = usb_control_msg( - dev->udev, - usb_sndctrlpipe(dev->udev, 0), - cmd, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - data, - size, - USB_CTRL_SET_TIMEOUT); - -#endif + return ret; } +static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, + u16 index, u16 size, void *data) +{ + u16 buf; + + if (2 == size) { + buf = *((u16 *)data); + cpu_to_le16s(&buf); + usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, &buf, + size); + } else { + usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, data, + size); + } +} + static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data, int eflag) + u16 index, u16 size, void *data) { int ret; - if (eflag && (2 == size)) { - u16 buf = 0; + if (2 == size) { + u16 buf; ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); le16_to_cpus(&buf); *((u16 *)data) = buf; - } else if (eflag && (4 == size)) { - u32 buf = 0; + } else if (4 == size) { + u32 buf; ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); le32_to_cpus(&buf); *((u32 *)data) = buf; @@ -178,7 +288,7 @@ static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, int ret; if (2 == size) { - u16 buf = 0; + u16 buf; buf = *((u16 *)data); cpu_to_le16s(&buf); ret = __ax88179_write_cmd(dev, cmd, value, index, @@ -192,18 +302,17 @@ static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, } static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data, int eflag) + u16 size, void *data) { - int ret; - if (eflag && (2 == size)) { - u16 buf = 0; + if (2 == size) { + u16 buf; ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); le16_to_cpus(&buf); *((u16 *)data) = buf; - } else if (eflag && (4 == size)) { - u32 buf = 0; + } else if (4 == size) { + u32 buf; ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); le32_to_cpus(&buf); *((u32 *)data) = buf; @@ -220,7 +329,7 @@ static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, int ret; if (2 == size) { - u16 buf = 0; + u16 buf; buf = *((u16 *)data); cpu_to_le16s(&buf); ret = __ax88179_write_cmd(dev, cmd, value, index, @@ -233,138 +342,31 @@ static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, return ret; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -static void ax88179_async_cmd_callback(struct urb *urb, struct pt_regs *regs) -#else -static void ax88179_async_cmd_callback(struct urb *urb) -#endif -{ - struct ax88179_async_handle *asyncdata = (struct ax88179_async_handle *)urb->context; - - if (urb->status < 0) - printk(KERN_ERR "ax88179_async_cmd_callback() failed with %d", - urb->status); - - kfree(asyncdata->req); - kfree(asyncdata); - usb_free_urb(urb); - -} - -static void -ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - struct usb_ctrlrequest *req = NULL; - int status = 0; - struct urb *urb = NULL; - void *buf = NULL; - struct ax88179_async_handle *asyncdata = NULL; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (urb == NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Error allocating URB in write_cmd_async!"); -#else - deverr(dev, "Error allocating URB in write_cmd_async!"); -#endif - return; - } - - req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); - if (req == NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Failed to allocate memory for control request"); -#else - deverr(dev, "Failed to allocate memory for control request"); -#endif - usb_free_urb(urb); - return; - } - - asyncdata = (struct ax88179_async_handle*) - kmalloc(sizeof(struct ax88179_async_handle), GFP_ATOMIC); - if (asyncdata == NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Failed to allocate memory for async data"); -#else - deverr(dev, "Failed to allocate memory for async data"); -#endif - kfree(req); - usb_free_urb(urb); - return; - } - - asyncdata->req = req; - - if (size == 2) { - asyncdata->rxctl = *((u16 *)data); - cpu_to_le16s(&asyncdata->rxctl); - buf = &asyncdata->rxctl; - } else { - memcpy(asyncdata->m_filter, data, size); - buf = asyncdata->m_filter; - } - - req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - req->bRequest = cmd; - req->wValue = cpu_to_le16(value); - req->wIndex = cpu_to_le16(index); - req->wLength = cpu_to_le16(size); - - usb_fill_control_urb(urb, dev->udev, - usb_sndctrlpipe(dev->udev, 0), - (void *)req, buf, size, - ax88179_async_cmd_callback, asyncdata); - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status < 0) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Error submitting the control message: status=%d", - status); -#else - deverr(dev, "Error submitting the control message: status=%d", - status); -#endif - kfree(req); - kfree(asyncdata); - usb_free_urb(urb); - } -} - static void ax88179_status(struct usbnet *dev, struct urb *urb) { - struct ax88179_int_data *event = NULL; - int link = 0; + struct ax88179_int_data *event; + u32 link; if (urb->actual_length < 8) return; event = urb->transfer_buffer; - link = event->link & AX_INT_PPLS_LINK; + le32_to_cpus((void *)&event->intdata1); + + link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; if (netif_carrier_ok(dev->net) != link) { - if (link) { - netif_carrier_on(dev->net); - usbnet_defer_kevent(dev, EVENT_LINK_RESET); - } - else - netif_carrier_off(dev->net); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_info(dev->net, "ax88179_178a - Link status is: %d\n", - link); -#else - devinfo(dev, "ax88179_178a - Link status is: %d\n", link); -#endif + usbnet_link_change(dev, link, 1); + netdev_info(dev->net, "ax88179 - Link status is: %d\n", link); } } static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc) { struct usbnet *dev = netdev_priv(netdev); - u16 res = 0; + u16 res; - ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res, 1); + ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); return res; } @@ -372,34 +374,84 @@ static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) { struct usbnet *dev = netdev_priv(netdev); - u16 res = (u16)val; + u16 res = (u16) val; ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); } -static int ax88179_suspend(struct usb_interface *intf, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10) - pm_message_t message) -#else - u32 message) -#endif +static inline int ax88179_phy_mmd_indirect(struct usbnet *dev, u16 prtad, + u16 devad) +{ + u16 tmp16; + int ret; + + tmp16 = devad; + ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_CTRL, 2, &tmp16); + + tmp16 = prtad; + ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_DATA, 2, &tmp16); + + tmp16 = devad | MII_MMD_CTRL_NOINCR; + ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_CTRL, 2, &tmp16); + + return ret; +} + +static int +ax88179_phy_read_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad) +{ + int ret; + u16 tmp16; + + ax88179_phy_mmd_indirect(dev, prtad, devad); + + ret = ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_DATA, 2, &tmp16); + if (ret < 0) + return ret; + + return tmp16; +} + +static int +ax88179_phy_write_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad, + u16 data) +{ + int ret; + + ax88179_phy_mmd_indirect(dev, prtad, devad); + + ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_DATA, 2, &data); + + if (ret < 0) + return ret; + + return 0; +} + +static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); - u16 tmp16 = 0; - u8 tmp8 = 0; + u16 tmp16; + u8 tmp8; usbnet_suspend(intf, message); /* Disable RX path */ ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16, 1); + 2, 2, &tmp16); tmp16 &= ~AX_MEDIUM_RECEIVE_EN; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &tmp16); - /* Force bz */ + /* Force bulk-in zero length */ ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16, 1); + 2, 2, &tmp16); + tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL; ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); @@ -415,127 +467,73 @@ static int ax88179_suspend(struct usb_interface *intf, return 0; } - -static void ax88179_EEE_setting(struct usbnet *dev) +/* This function is used to enable the autodetach function. */ +/* This function is determined by offset 0x43 of EEPROM */ +static int ax88179_auto_detach(struct usbnet *dev, int in_pm) { u16 tmp16; - - if (bEEE) { - // Enable EEE - tmp16 = 0x07; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MACR, 2, &tmp16); - - tmp16 = 0x3c; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MAADR, 2, &tmp16); - - tmp16 = 0x4007; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MACR, 2, &tmp16); - - tmp16 = 0x06; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MAADR, 2, &tmp16); + u8 tmp8; + int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *); + int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *); + + if (!in_pm) { + fnr = ax88179_read_cmd; + fnw = ax88179_write_cmd; } else { - // Disable EEE - tmp16 = 0x07; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MACR, 2, &tmp16); - - tmp16 = 0x3c; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MAADR, 2, &tmp16); - - tmp16 = 0x4007; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MACR, 2, &tmp16); - - tmp16 = 0x00; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_MAADR, 2, &tmp16); + fnr = ax88179_read_cmd_nopm; + fnw = ax88179_write_cmd_nopm; } -} - -static void ax88179_Gether_setting(struct usbnet *dev) -{ - u16 tmp16; - - if (bGETH) { - // Enable Green Ethernet - tmp16 = 0x03; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 31, 2, &tmp16); + if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0) + return 0; - tmp16 = 0x3247; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 25, 2, &tmp16); + if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100))) + return 0; - tmp16 = 0x05; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 31, 2, &tmp16); + /* Enable Auto Detach bit */ + tmp8 = 0; + fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); + tmp8 |= AX_CLK_SELECT_ULR; + fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - tmp16 = 0x0680; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 1, 2, &tmp16); + fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); + tmp16 |= AX_PHYPWR_RSTCTL_AT; + fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); - tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 31, 2, &tmp16); - } else { - // Disable Green Ethernet - tmp16 = 0x03; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 31, 2, &tmp16); - - tmp16 = 0x3246; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 25, 2, &tmp16); - - tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - 31, 2, &tmp16); - } + return 0; } static int ax88179_resume(struct usb_interface *intf) { struct usbnet *dev = usb_get_intfdata(intf); - u16 tmp16 = 0; - u8 tmp8 = 0; + u16 tmp16; + u8 tmp8; - netif_carrier_off(dev->net); + usbnet_link_change(dev, 0, 0); /* Power up ethernet PHY */ tmp16 = 0; ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) - usleep_range(1000, 2000); -#else - msleep(1); -#endif + udelay(1000); + tmp16 = AX_PHYPWR_RSTCTL_IPRL; ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); msleep(200); /* Ethernet PHY Auto Detach*/ - ax88179_AutoDetach(dev, 1); + ax88179_auto_detach(dev, 1); - /* change clock */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, - 1, 1, &tmp8, 0); + /* Enable clock */ + ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); msleep(100); /* Configure RX control register => start operation */ - tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_START | AX_RX_CTL_AP | - AX_RX_CTL_AMALL | AX_RX_CTL_AB; - if (NET_IP_ALIGN == 0) - tmp16 |= AX_RX_CTL_IPE; + tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | + AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); return usbnet_resume(intf); @@ -544,57 +542,38 @@ static int ax88179_resume(struct usb_interface *intf) static void ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { - struct usbnet *dev = netdev_priv(net); - u8 *opt = NULL; + u8 opt; - opt = kmalloc(1, GFP_KERNEL); - if (!opt) - return; - - if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MODE, - 1, 1, opt, 0) < 0) { + if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, + 1, 1, &opt) < 0) { wolinfo->supported = 0; wolinfo->wolopts = 0; - kfree(opt); return; } wolinfo->supported = WAKE_PHY | WAKE_MAGIC; - - if (*opt & AX_MONITOR_MODE_RWLC) + wolinfo->wolopts = 0; + if (opt & AX_MONITOR_MODE_RWLC) wolinfo->wolopts |= WAKE_PHY; - if (*opt & AX_MONITOR_MODE_RWMP) + if (opt & AX_MONITOR_MODE_RWMP) wolinfo->wolopts |= WAKE_MAGIC; - - kfree(opt); } static int ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { struct usbnet *dev = netdev_priv(net); - u8 *opt = NULL; - - opt = kmalloc(1, GFP_KERNEL); - if (!opt) - return -ENOMEM; - - *opt = 0; + u8 opt = 0; if (wolinfo->wolopts & WAKE_PHY) - *opt |= AX_MONITOR_MODE_RWLC; - else - *opt &= ~AX_MONITOR_MODE_RWLC; - + opt |= AX_MONITOR_MODE_RWLC; if (wolinfo->wolopts & WAKE_MAGIC) - *opt |= AX_MONITOR_MODE_RWMP; - else - *opt &= ~AX_MONITOR_MODE_RWMP; - - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, opt); + opt |= AX_MONITOR_MODE_RWMP; - kfree(opt); + if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, + 1, 1, &opt) < 0) + return -EINVAL; return 0; } @@ -609,9 +588,9 @@ ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, u8 *data) { struct usbnet *dev = netdev_priv(net); - u16 *eeprom_buff = NULL; - int first_word = 0, last_word = 0; - int i = 0; + u16 *eeprom_buff; + int first_word, last_word; + int i, ret; if (eeprom->len == 0) return -EINVAL; @@ -627,8 +606,10 @@ ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, /* ax88179/178A returns 2 bytes from eeprom on read */ for (i = first_word; i <= last_word; i++) { - if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &(eeprom_buff[i - first_word]), 0) < 0) { + ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, + &eeprom_buff[i - first_word], + 0); + if (ret < 0) { kfree(eeprom_buff); return -EIO; } @@ -639,14 +620,6 @@ ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, return 0; } -static void ax88179_get_drvinfo(struct net_device *net, - struct ethtool_drvinfo *info) -{ - /* Inherit standard device info */ - usbnet_get_drvinfo(net, info); - info->eedump_len = 0x3e; -} - static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd *cmd) { struct usbnet *dev = netdev_priv(net); @@ -659,105 +632,193 @@ static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd *cmd) return mii_ethtool_sset(&dev->mii, cmd); } -static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd) +static int +ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data) { - struct usbnet *dev = netdev_priv(net); - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); + int val; + + /* Get Supported EEE */ + val = ax88179_phy_read_mmd_indirect(dev, MDIO_PCS_EEE_ABLE, + MDIO_MMD_PCS); + if (val < 0) + return val; + data->supported = mmd_eee_cap_to_ethtool_sup_t(val); + + /* Get advertisement EEE */ + val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV, + MDIO_MMD_AN); + if (val < 0) + return val; + data->advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Get LP advertisement EEE */ + val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_LPABLE, + MDIO_MMD_AN); + if (val < 0) + return val; + data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + return 0; } -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 28) -static int ax88179_netdev_stop(struct net_device *net) +static int +ax88179_ethtool_set_eee(struct usbnet *dev, struct ethtool_eee *data) { - struct usbnet *dev = netdev_priv(net); - u16 tmp16 = 0; + u16 tmp16 = ethtool_adv_to_mmd_eee_adv_t(data->advertised); - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16, 1); - tmp16 &= ~AX_MEDIUM_RECEIVE_EN; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); - return 0; + return ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV, + MDIO_MMD_AN, tmp16); } -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) -static int ax88179_set_csums(struct usbnet *dev) +static int ax88179_chk_eee(struct usbnet *dev) { - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - u8 checksum = 0; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; + struct ax88179_data *priv = (struct ax88179_data *)dev->data; - if (ax179_data->checksum & AX_RX_CHECKSUM) - checksum = AX_RXCOE_DEF_CSUM; - else - checksum = 0; + mii_ethtool_gset(&dev->mii, &ecmd); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &checksum); + if (ecmd.duplex & DUPLEX_FULL) { + int eee_lp, eee_cap, eee_adv; + u32 lp, cap, adv, supported = 0; - if (ax179_data->checksum & AX_TX_CHECKSUM) - checksum = AX_TXCOE_DEF_CSUM; - else - checksum = 0; + eee_cap = ax88179_phy_read_mmd_indirect(dev, + MDIO_PCS_EEE_ABLE, + MDIO_MMD_PCS); + if (eee_cap < 0) { + priv->eee_active = 0; + return false; + } - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &checksum); + cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap); + if (!cap) { + priv->eee_active = 0; + return false; + } - return 0; + eee_lp = ax88179_phy_read_mmd_indirect(dev, + MDIO_AN_EEE_LPABLE, + MDIO_MMD_AN); + if (eee_lp < 0) { + priv->eee_active = 0; + return false; + } + + eee_adv = ax88179_phy_read_mmd_indirect(dev, + MDIO_AN_EEE_ADV, + MDIO_MMD_AN); + + if (eee_adv < 0) { + priv->eee_active = 0; + return false; + } + + adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv); + lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp); + supported = (ecmd.speed == SPEED_1000) ? + SUPPORTED_1000baseT_Full : + SUPPORTED_100baseT_Full; + + if (!(lp & adv & supported)) { + priv->eee_active = 0; + return false; + } + + priv->eee_active = 1; + return true; + } + + priv->eee_active = 0; + return false; } -static u32 ax88179_get_tx_csum(struct net_device *netdev) +static void ax88179_disable_eee(struct usbnet *dev) { - struct usbnet *dev = netdev_priv(netdev); - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - return ax179_data->checksum & AX_TX_CHECKSUM; + u16 tmp16; + + tmp16 = GMII_PHY_PGSEL_PAGE3; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PAGE_SELECT, 2, &tmp16); + + tmp16 = 0x3246; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_PHYADDR, 2, &tmp16); + + tmp16 = GMII_PHY_PGSEL_PAGE0; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PAGE_SELECT, 2, &tmp16); } -static u32 ax88179_get_rx_csum(struct net_device *netdev) +static void ax88179_enable_eee(struct usbnet *dev) { - struct usbnet *dev = netdev_priv(netdev); - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; - return ax179_data->checksum & AX_RX_CHECKSUM; + u16 tmp16; + + tmp16 = GMII_PHY_PGSEL_PAGE3; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PAGE_SELECT, 2, &tmp16); + + tmp16 = 0x3247; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_PHYADDR, 2, &tmp16); + + tmp16 = GMII_PHY_PGSEL_PAGE5; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PAGE_SELECT, 2, &tmp16); + + tmp16 = 0x0680; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_BMSR, 2, &tmp16); + + tmp16 = GMII_PHY_PGSEL_PAGE0; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PAGE_SELECT, 2, &tmp16); } -static int ax88179_set_rx_csum(struct net_device *netdev, u32 val) +static int ax88179_get_eee(struct net_device *net, struct ethtool_eee *edata) { - struct usbnet *dev = netdev_priv(netdev); - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; + struct usbnet *dev = netdev_priv(net); + struct ax88179_data *priv = (struct ax88179_data *)dev->data; - if (val) - ax179_data->checksum |= AX_RX_CHECKSUM; - else - ax179_data->checksum &= ~AX_RX_CHECKSUM; - return ax88179_set_csums(dev); + edata->eee_enabled = priv->eee_enabled; + edata->eee_active = priv->eee_active; + + return ax88179_ethtool_get_eee(dev, edata); } -static int ax88179_set_tx_csum(struct net_device *netdev, u32 val) +static int ax88179_set_eee(struct net_device *net, struct ethtool_eee *edata) { - struct usbnet *dev = netdev_priv(netdev); - struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; + struct usbnet *dev = netdev_priv(net); + struct ax88179_data *priv = (struct ax88179_data *)dev->data; + int ret = -EOPNOTSUPP; - if (val) - ax179_data->checksum |= AX_TX_CHECKSUM; - else - ax179_data->checksum &= ~AX_TX_CHECKSUM; + priv->eee_enabled = edata->eee_enabled; + if (!priv->eee_enabled) { + ax88179_disable_eee(dev); + } else { + priv->eee_enabled = ax88179_chk_eee(dev); + if (!priv->eee_enabled) + return -EOPNOTSUPP; - ethtool_op_set_tx_csum(netdev, val); + ax88179_enable_eee(dev); + } - return ax88179_set_csums(dev); + ret = ax88179_ethtool_set_eee(dev, edata); + if (ret) + return ret; + + mii_nway_restart(&dev->mii); + + usbnet_link_change(dev, 0, 0); + + return ret; } -static int ax88179_set_tso(struct net_device *netdev, u32 data) +static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd) { - if (data) - netdev->features |= NETIF_F_TSO; - else - netdev->features &= ~NETIF_F_TSO; - - return 0; + struct usbnet *dev = netdev_priv(net); + return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } -#endif -static struct ethtool_ops ax88179_ethtool_ops = { - .get_drvinfo = ax88179_get_drvinfo, +static const struct ethtool_ops ax88179_ethtool_ops = { .get_link = ethtool_op_get_link, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, @@ -767,77 +828,43 @@ static struct ethtool_ops ax88179_ethtool_ops = { .get_eeprom = ax88179_get_eeprom, .get_settings = ax88179_get_settings, .set_settings = ax88179_set_settings, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) - .set_tx_csum = ax88179_set_tx_csum, - .get_tx_csum = ax88179_get_tx_csum, - .get_rx_csum = ax88179_get_rx_csum, - .set_rx_csum = ax88179_set_rx_csum, - .get_tso = ethtool_op_get_tso, - .set_tso = ax88179_set_tso, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg -#endif + .get_eee = ax88179_get_eee, + .set_eee = ax88179_set_eee, + .nway_reset = usbnet_nway_reset, }; static void ax88179_set_multicast(struct net_device *net) { struct usbnet *dev = netdev_priv(net); - struct ax88179_data *data = (struct ax88179_data *)&dev->data; + struct ax88179_data *data = (struct ax88179_data *)dev->data; u8 *m_filter = ((u8 *)dev->data) + 12; - int mc_count = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) - mc_count = net->mc_count; -#else - mc_count = netdev_mc_count(net); -#endif - - data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB); - if (NET_IP_ALIGN == 0) - data->rxctl |= AX_RX_CTL_IPE; + data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); if (net->flags & IFF_PROMISC) { data->rxctl |= AX_RX_CTL_PRO; - } else if (net->flags & IFF_ALLMULTI - || mc_count > AX_MAX_MCAST) { + } else if (net->flags & IFF_ALLMULTI || + netdev_mc_count(net) > AX_MAX_MCAST) { data->rxctl |= AX_RX_CTL_AMALL; - } else if (mc_count == 0) { + } else if (netdev_mc_empty(net)) { /* just broadcast and directed */ } else { - /* We use the 20 byte dev->data - * for our 8 byte filter buffer - * to avoid allocating memory that - * is tricky to free later */ - u32 crc_bits = 0; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) - struct dev_mc_list *mc_list = net->mc_list; - int i = 0; - - memset(m_filter, 0, AX_MCAST_FILTER_SIZE); - - /* Build the multicast hash filter. */ - for (i = 0; i < net->mc_count; i++) { - crc_bits = - ether_crc(ETH_ALEN, - mc_list->dmi_addr) >> 26; - *(m_filter + (crc_bits >> 3)) |= - 1 << (crc_bits & 7); - mc_list = mc_list->next; - } -#else - struct netdev_hw_addr *ha = NULL; - memset(m_filter, 0, AX_MCAST_FILTER_SIZE); + /* We use the 20 byte dev->data for our 8 byte filter buffer + * to avoid allocating memory that is tricky to free later + */ + u32 crc_bits; + struct netdev_hw_addr *ha; + + memset(m_filter, 0, AX_MCAST_FLTSIZE); + netdev_for_each_mc_addr(ha, net) { crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; - *(m_filter + (crc_bits >> 3)) |= - 1 << (crc_bits & 7); + *(m_filter + (crc_bits >> 3)) |= (1 << (crc_bits & 7)); } -#endif - ax88179_write_cmd_async(dev, AX_ACCESS_MAC, - AX_MULTI_FILTER_ARRY, - AX_MCAST_FILTER_SIZE, - AX_MCAST_FILTER_SIZE, m_filter); + + ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY, + AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE, + m_filter); data->rxctl |= AX_RX_CTL_AM; } @@ -846,40 +873,27 @@ static void ax88179_set_multicast(struct net_device *net) 2, 2, &data->rxctl); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) ax88179_set_features(struct net_device *net, netdev_features_t features) -#else -ax88179_set_features(struct net_device *net, u32 features) -#endif - { - u8 tmp = 0; + u8 tmp; struct usbnet *dev = netdev_priv(net); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) netdev_features_t changed = net->features ^ features; -#else - u32 changed = net->features ^ features; -#endif if (changed & NETIF_F_IP_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, - 1, 1, &tmp, 0); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); } if (changed & NETIF_F_IPV6_CSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, - 1, 1, &tmp, 0); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); } if (changed & NETIF_F_RXCSUM) { - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, - 1, 1, &tmp, 0); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); @@ -887,12 +901,11 @@ ax88179_set_features(struct net_device *net, u32 features) return 0; } -#endif static int ax88179_change_mtu(struct net_device *net, int new_mtu) { struct usbnet *dev = netdev_priv(net); - u16 tmp16 = 0; + u16 tmp16; if (new_mtu <= 0 || new_mtu > 4088) return -EINVAL; @@ -902,18 +915,21 @@ static int ax88179_change_mtu(struct net_device *net, int new_mtu) if (net->mtu > 1500) { ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16, 1); + 2, 2, &tmp16); tmp16 |= AX_MEDIUM_JUMBO_EN; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &tmp16); } else { ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16, 1); + 2, 2, &tmp16); tmp16 &= ~AX_MEDIUM_JUMBO_EN; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &tmp16); } + /* max qlen depend on hard_mtu and rx_urb_size */ + usbnet_update_max_qlen(dev); + return 0; } @@ -921,6 +937,7 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p) { struct usbnet *dev = netdev_priv(net); struct sockaddr *addr = p; + int ret; if (netif_running(net)) return -EBUSY; @@ -930,64 +947,57 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p) memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); /* Set the MAC address */ - return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, net->dev_addr); + if (ret < 0) + return ret; + return 0; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29) static const struct net_device_ops ax88179_netdev_ops = { .ndo_open = usbnet_open, .ndo_stop = usbnet_stop, .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, .ndo_change_mtu = ax88179_change_mtu, - .ndo_do_ioctl = ax88179_ioctl, .ndo_set_mac_address = ax88179_set_mac_addr, .ndo_validate_addr = eth_validate_addr, -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 2, 0) - .ndo_set_multicast_list = ax88179_set_multicast, -#else + .ndo_do_ioctl = ax88179_ioctl, .ndo_set_rx_mode = ax88179_set_multicast, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) .ndo_set_features = ax88179_set_features, -#endif }; -#endif static int ax88179_check_eeprom(struct usbnet *dev) { - u8 i = 0; - u8 buf[2] = {0}; - u8 eeprom[20] = {0}; - u16 csum = 0, delay = HZ / 10; - unsigned long jtimeout = 0; + u8 i, buf, eeprom[20]; + u16 csum, delay = HZ / 10; + unsigned long jtimeout; /* Read EEPROM content */ - for (i = 0 ; i < 6; i++) { - - buf[0] = i; + for (i = 0; i < 6; i++) { + buf = i; if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, - 1, 1, buf) < 0) + 1, 1, &buf) < 0) return -EINVAL; - buf[0] = EEP_RD; + buf = EEP_RD; if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, buf) < 0) + 1, 1, &buf) < 0) return -EINVAL; jtimeout = jiffies + delay; do { ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, buf, 0); + 1, 1, &buf); if (time_after(jiffies, jtimeout)) return -EINVAL; - } while (buf[0] & EEP_BUSY); - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, - 2, 2, &eeprom[i * 2], 0); + } while (buf & EEP_BUSY); + + __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, + 2, 2, &eeprom[i * 2], 0); if ((i == 0) && (eeprom[0] == 0xFF)) return -EINVAL; @@ -995,23 +1005,22 @@ static int ax88179_check_eeprom(struct usbnet *dev) csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9]; csum = (csum >> 8) + (csum & 0xff); - - if ((csum + eeprom[10]) == 0xff) - return AX_EEP_EFUSE_CORRECT; - else + if ((csum + eeprom[10]) != 0xff) return -EINVAL; + + return 0; } -static int ax88179_check_efuse(struct usbnet *dev, void *ledmode) +static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode) { - u8 i = 0; - u8 efuse[64] = {0x00}; + u8 i; + u8 efuse[64]; u16 csum = 0; - if (ax88179_read_cmd(dev, AX_ACCESS_EFUSE, 0, 64, 64, efuse, 0) < 0) + if (ax88179_read_cmd(dev, AX_ACCESS_EFUS, 0, 64, 64, efuse) < 0) return -EINVAL; - if (efuse[0] == 0xFF) + if (*efuse == 0xFF) return -EINVAL; for (i = 0; i < 64; i++) @@ -1020,38 +1029,24 @@ static int ax88179_check_efuse(struct usbnet *dev, void *ledmode) while (csum > 255) csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF); - if (csum == 0xFF) { - memcpy((u8 *)ledmode, &efuse[51], 2); - return AX_EEP_EFUSE_CORRECT; - } else { + if (csum != 0xFF) return -EINVAL; - } + + *ledmode = (efuse[51] << 8) | efuse[52]; + + return 0; } -static int ax88179_convert_old_led(struct usbnet *dev, u8 efuse, void *ledvalue) +static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue) { - u8 ledmode = 0; - u16 tmp = 0; - u16 led = 0; - - /* loaded the old eFuse LED Mode */ - if (efuse) { - if (ax88179_read_cmd(dev, AX_ACCESS_EFUSE, 0x18, - 1, 2, &tmp, 1) < 0) - return -EINVAL; - ledmode = (u8)(tmp & 0xFF); - } else { /* loaded the old EEprom LED Mode */ - if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, - 1, 2, &tmp, 1) < 0) - return -EINVAL; - ledmode = (u8) (tmp >> 8); - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_dbg(dev->net, "Old LED Mode = %02X\n", ledmode); -#else - devdbg(dev, "Old LED Mode = %02X\n", ledmode); -#endif - switch (ledmode) { + u16 led; + + /* Loaded the old eFuse LED Mode */ + if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0) + return -EINVAL; + + led >>= 8; + switch (led) { case 0xFF: led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | @@ -1075,22 +1070,21 @@ static int ax88179_convert_old_led(struct usbnet *dev, u8 efuse, void *ledvalue) break; } - memcpy((u8 *)ledvalue, &led, 2); + *ledvalue = led; return 0; } static int ax88179_led_setting(struct usbnet *dev) { - u8 ledfd = 0, value = 0; - u16 tmp = 0, ledact = 0, ledlink = 0, ledvalue = 0, delay = HZ / 10; - unsigned long jtimeout = 0; + u8 ledfd, value = 0; + u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10; + unsigned long jtimeout; - /* Check AX88179 version. UA1 or UA2 */ - ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value, 0); + /* Check AX88179 version. UA1 or UA2*/ + ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value); - /* UA1 */ - if (!(value & AX_SECLD)) { + if (!(value & AX_SECLD)) { /* UA1 */ value = AX_GPIO_CTRL_GPIO3EN | AX_GPIO_CTRL_GPIO2EN | AX_GPIO_CTRL_GPIO1EN; if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_GPIO_CTRL, @@ -1098,8 +1092,8 @@ static int ax88179_led_setting(struct usbnet *dev) return -EINVAL; } - /* check EEprom */ - if (ax88179_check_eeprom(dev) == AX_EEP_EFUSE_CORRECT) { + /* Check EEPROM */ + if (!ax88179_check_eeprom(dev)) { value = 0x42; if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, 1, 1, &value) < 0) @@ -1113,35 +1107,33 @@ static int ax88179_led_setting(struct usbnet *dev) jtimeout = jiffies + delay; do { ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &value, 0); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, - 1, 1, &value, 0); + 1, 1, &value); if (time_after(jiffies, jtimeout)) return -EINVAL; + } while (value & EEP_BUSY); ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH, - 1, 1, &value, 0); + 1, 1, &value); ledvalue = (value << 8); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, - 1, 1, &value, 0); + 1, 1, &value); ledvalue |= value; /* load internal ROM for defaule setting */ if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) - ax88179_convert_old_led(dev, 0, &ledvalue); + ax88179_convert_old_led(dev, &ledvalue); - } else if (ax88179_check_efuse(dev, &ledvalue) == - AX_EEP_EFUSE_CORRECT) { /* check efuse */ + } else if (!ax88179_check_efuse(dev, &ledvalue)) { if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) - ax88179_convert_old_led(dev, 0, &ledvalue); + ax88179_convert_old_led(dev, &ledvalue); } else { - ax88179_convert_old_led(dev, 0, &ledvalue); + ax88179_convert_old_led(dev, &ledvalue); } - tmp = GMII_PHY_PAGE_SELECT_EXT; + tmp = GMII_PHY_PGSEL_EXT; ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_PAGE_SELECT, 2, &tmp); @@ -1150,51 +1142,59 @@ static int ax88179_led_setting(struct usbnet *dev) GMII_PHYPAGE, 2, &tmp); ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_ACTIVE, 2, &ledact, 1); + GMII_LED_ACT, 2, &ledact); ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_LINK, 2, &ledlink, 1); + GMII_LED_LINK, 2, &ledlink); ledact &= GMII_LED_ACTIVE_MASK; ledlink &= GMII_LED_LINK_MASK; if (ledvalue & LED0_ACTIVE) ledact |= GMII_LED0_ACTIVE; + if (ledvalue & LED1_ACTIVE) ledact |= GMII_LED1_ACTIVE; + if (ledvalue & LED2_ACTIVE) ledact |= GMII_LED2_ACTIVE; if (ledvalue & LED0_LINK_10) ledlink |= GMII_LED0_LINK_10; + if (ledvalue & LED1_LINK_10) ledlink |= GMII_LED1_LINK_10; + if (ledvalue & LED2_LINK_10) ledlink |= GMII_LED2_LINK_10; if (ledvalue & LED0_LINK_100) ledlink |= GMII_LED0_LINK_100; + if (ledvalue & LED1_LINK_100) ledlink |= GMII_LED1_LINK_100; + if (ledvalue & LED2_LINK_100) ledlink |= GMII_LED2_LINK_100; if (ledvalue & LED0_LINK_1000) ledlink |= GMII_LED0_LINK_1000; + if (ledvalue & LED1_LINK_1000) ledlink |= GMII_LED1_LINK_1000; + if (ledvalue & LED2_LINK_1000) ledlink |= GMII_LED2_LINK_1000; tmp = ledact; ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_LED_ACTIVE, 2, &tmp); + GMII_LED_ACT, 2, &tmp); tmp = ledlink; ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_LED_LINK, 2, &tmp); - tmp = GMII_PHY_PAGE_SELECT_PAGE0; + tmp = GMII_PHY_PGSEL_PAGE0; ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, GMII_PHY_PAGE_SELECT, 2, &tmp); @@ -1205,215 +1205,31 @@ static int ax88179_led_setting(struct usbnet *dev) else if ((ledvalue & LED0_USB3_MASK) == 0) ledfd |= 0x02; - if (ledvalue & LED1_FD) ledfd |= 0x04; else if ((ledvalue & LED1_USB3_MASK) == 0) ledfd |= 0x08; - if (ledvalue & LED2_FD) /* LED2_FD */ + if (ledvalue & LED2_FD) ledfd |= 0x10; - else if ((ledvalue & LED2_USB3_MASK) == 0) /* LED2_USB3 */ + else if ((ledvalue & LED2_USB3_MASK) == 0) ledfd |= 0x20; - ax88179_write_cmd(dev, AX_ACCESS_MAC, 0x73, 1, 1, &ledfd); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_LEDCTRL, 1, 1, &ledfd); return 0; } -static int ax88179_AutoDetach(struct usbnet *dev, int in_pm) -{ - u16 tmp16 = 0; - u8 tmp8 = 0; - int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *, int); - int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *); - - if (!in_pm) { - fnr = ax88179_read_cmd; - fnw = ax88179_write_cmd; - } else { - fnr = ax88179_read_cmd_nopm; - fnw = ax88179_write_cmd_nopm; - } - - if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16, 1) < 0) - return 0; - - if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100))) - return 0; - - /* Enable Auto Detach bit */ - tmp8 = 0; - fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8, 0); - tmp8 |= AX_CLK_SELECT_ULR; - fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - - fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16, 1); - tmp16 |= AX_PHYPWR_RSTCTL_AUTODETACH; - fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); - - return 0; -} - -static int access_eeprom_mac(struct usbnet *dev, u8 *buf, u8 offset, bool wflag) -{ - int ret = 0, i; - u16* tmp = (u16*)buf; - - for (i = 0; i < (ETH_ALEN >> 1); i++) { - if (wflag) { - u16 wd = cpu_to_le16(*(tmp + i)); - ret = ax88179_write_cmd(dev, AX_ACCESS_EEPROM, - offset + i, 1, 2, &wd); - if (ret < 0) - break; - - mdelay(15); - } - else { - ret = ax88179_read_cmd(dev, AX_ACCESS_EEPROM, - offset + i, 1, 2, tmp + i, 0); - if (ret < 0) - break; - } - } - - if (!wflag) { - if (ret < 0) { - netdev_dbg(dev->net, "Failed to read MAC address from EEPROM: %d\n", ret); - return ret; - } - memcpy(dev->net->dev_addr, buf, ETH_ALEN); - } - else { - /* reload eeprom data */ - ret = ax88179_write_cmd(dev, AX_RELOAD_EEPROM_EFUSE, 0, 0, 0, 0); - if (ret < 0) - return ret; - } - - return 0; -} - -static int ax88179_check_ether_addr(struct usbnet *dev) -{ - unsigned char *tmp = (unsigned char*)dev->net->dev_addr; - u8 default_mac[6] = {0, 0x0e, 0xc6, 0x81, 0x79, 0x01}; - - if (((*((u8*)tmp) == 0) && (*((u8*)tmp + 1) == 0) && (*((u8*)tmp + 2) == 0)) || - !is_valid_ether_addr((u8*)tmp) || - !memcmp(dev->net->dev_addr, default_mac, ETH_ALEN)) { - int i; - - printk("Found invalid EEPROM MAC address value "); - - for (i = 0; i < ETH_ALEN; i++) { - printk("%02X", *((u8*)tmp + i)); - if (i != 5) - printk("-"); - } - printk("\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) - eth_hw_addr_random(dev->net); -#else - dev->net->addr_assign_type |= NET_ADDR_RANDOM; - random_ether_addr(dev->net->dev_addr); -#endif - *tmp = 0; - *(tmp + 1) = 0x0E; - *(tmp + 2) = 0xC6; - *(tmp + 3) = 0x8E; - - return -EADDRNOTAVAIL; - } - return 0; -} - -static int ax88179_get_mac(struct usbnet *dev, u8* buf) -{ - int ret, i; - - ret = access_eeprom_mac(dev, buf, 0x0, 0); - if (ret < 0) - goto out; - - if (ax88179_check_ether_addr(dev)) { - ret = access_eeprom_mac(dev, dev->net->dev_addr, 0x0, 1); - if (ret < 0) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Failed to write MAC to EEPROM: %d", ret); -#else - deverr(dev, "Failed to write MAC to EEPROM: %d", ret); -#endif - goto out; - } - - msleep(5); - - ret = ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, - ETH_ALEN, ETH_ALEN, buf, 0); - if (ret < 0) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Failed to read MAC address: %d", ret); -#else - deverr(dev, "Failed to read MAC address: %d", ret); -#endif - goto out; - } - - for (i = 0; i < ETH_ALEN; i++) - if (*(dev->net->dev_addr + i) != *((u8*)buf + i)) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_warn(dev->net, "Found invalid EEPROM part or non-EEPROM"); -#else - devwarn(dev, "Found invalid EEPROM part or non-EEPROM"); -#endif - break; - } - } - - memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); - - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, dev->net->dev_addr); - - if (ret < 0) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Failed to write MAC address: %d", ret); -#else - deverr(dev, "Failed to write MAC address: %d", ret); -#endif - goto out; - } - - return 0; -out: - return ret; -} - static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) { - void *buf = NULL; - u16 *tmp16 = NULL; - u8 *tmp = NULL; - int ret; - + u8 buf[5]; + u16 *tmp16; + u8 *tmp; struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; + struct ethtool_eee eee_data; usbnet_get_endpoints(dev, intf); - if (msg_enable != 0) - dev->msg_enable = msg_enable; - - buf = kmalloc(6, GFP_KERNEL); - if (!buf) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Cannot allocate memory for buffer"); -#else - deverr(dev, "Cannot allocate memory for buffer"); -#endif - return -ENOMEM; - } tmp16 = (u16 *)buf; tmp = (u8 *)buf; @@ -1430,53 +1246,26 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); msleep(100); - /* Get the MAC address */ - memset(buf, 0, ETH_ALEN); - ret = ax88179_get_mac(dev, buf); - if (ret) - goto out; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_dbg(dev->net, "MAC [%02x-%02x-%02x-%02x-%02x-%02x]\n", - dev->net->dev_addr[0], dev->net->dev_addr[1], - dev->net->dev_addr[2], dev->net->dev_addr[3], - dev->net->dev_addr[4], dev->net->dev_addr[5]); -#else - devdbg(dev, "MAC [%02x-%02x-%02x-%02x-%02x-%02x]\n", - dev->net->dev_addr[0], dev->net->dev_addr[1], - dev->net->dev_addr[2], dev->net->dev_addr[3], - dev->net->dev_addr[4], dev->net->dev_addr[5]); -#endif - - /* RX bulk configuration, default for USB3.0 to Giga*/ + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, dev->net->dev_addr); + memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); + + /* RX bulk configuration */ memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); dev->rx_urb_size = 1024 * 20; - tmp[0] = 0x34; + *tmp = 0x34; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); - tmp[0] = 0x52; + *tmp = 0x52; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, 1, 1, tmp); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) - dev->net->do_ioctl = ax88179_ioctl; - dev->net->set_multicast_list = ax88179_set_multicast; - dev->net->set_mac_address = ax88179_set_mac_addr; - dev->net->change_mtu = ax88179_change_mtu; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 28) - dev->net->stop = ax88179_netdev_stop; -#endif -#else dev->net->netdev_ops = &ax88179_netdev_ops; -#endif - dev->net->ethtool_ops = &ax88179_ethtool_ops; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) dev->net->needed_headroom = 8; -#endif /* Initialize MII structure */ dev->mii.dev = dev->net; @@ -1487,21 +1276,11 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.phy_id = 0x03; dev->mii.supports_gmii = 1; - dev->net->features |= NETIF_F_IP_CSUM; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) - dev->net->features |= NETIF_F_IPV6_CSUM; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) - if (usb_device_no_sg_constraint(dev->udev)) - dev->can_dma_sg = 1; - dev->net->features |= NETIF_F_SG | NETIF_F_TSO; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) - dev->net->hw_features |= NETIF_F_IP_CSUM; - dev->net->hw_features |= NETIF_F_IPV6_CSUM; - dev->net->hw_features |= NETIF_F_SG | NETIF_F_TSO; -#endif + dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + + dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | @@ -1512,80 +1291,55 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); - ax179_data->checksum |= AX_RX_CHECKSUM | AX_TX_CHECKSUM; - /* Configure RX control register => start operation */ - *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_START | AX_RX_CTL_AP | - AX_RX_CTL_AMALL | AX_RX_CTL_AB; - if (NET_IP_ALIGN == 0) - *tmp16 |= AX_RX_CTL_IPE; + *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | + AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | - AX_MONITOR_MODE_RWMP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, tmp); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, tmp, 0); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_dbg(dev->net, "Monitor mode = 0x%02x\n", *tmp); -#else - devdbg(dev, "Monitor mode = 0x%02x\n", *tmp); -#endif + AX_MONITOR_MODE_RWMP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); + /* Configure default medium type => giga */ - *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | + *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | + AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, tmp16); ax88179_led_setting(dev); - ax88179_EEE_setting(dev); + ax179_data->eee_enabled = 0; + ax179_data->eee_active = 0; + + ax88179_disable_eee(dev); - ax88179_Gether_setting(dev); + ax88179_ethtool_get_eee(dev, &eee_data); + eee_data.advertised = 0; + ax88179_ethtool_set_eee(dev, &eee_data); /* Restart autoneg */ mii_nway_restart(&dev->mii); - netif_carrier_off(dev->net); + usbnet_link_change(dev, 0, 0); - kfree(buf); - printk(version); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_info(dev->net, "mtu %d\n", dev->net->mtu); -#else - devinfo(dev, "mtu %d\n", dev->net->mtu); -#endif return 0; - -out: - kfree(buf); - return ret; - } static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf) { - u16 tmp16 = 0; - u8 tmp8 = 0; - struct ax88179_data *ax179_data = (struct ax88179_data *) dev->data; - - if (ax179_data) { - /* Configure RX control register => stop operation */ - tmp16 = AX_RX_CTL_STOP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); - - tmp8 = 0x0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, - 1, 1, &tmp8); - - /* Power down ethernet PHY */ - tmp16 = AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); - msleep(200); - } + u16 tmp16; + + /* Configure RX control register => stop operation */ + tmp16 = AX_RX_CTL_STOP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + + tmp16 = 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp16); + + /* Power down ethernet PHY */ + tmp16 = 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); } static void @@ -1606,18 +1360,18 @@ ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr) static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { - struct sk_buff *ax_skb = NULL; - int pkt_cnt = 0; - u32 rx_hdr = 0; - u16 hdr_off = 0; - u32 *pkt_hdr = NULL; + struct sk_buff *ax_skb; + int pkt_cnt; + u32 rx_hdr; + u16 hdr_off; + u32 *pkt_hdr; + + /* This check is no longer done by usbnet */ + if (skb->len < dev->net->hard_header_len) + return 0; skb_trim(skb, skb->len - 4); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) - memcpy(&rx_hdr, skb_tail_pointer(skb), sizeof(rx_hdr)); -#else - memcpy(&rx_hdr, skb->tail, sizeof(rx_hdr)); -#endif + memcpy(&rx_hdr, skb_tail_pointer(skb), 4); le32_to_cpus(&rx_hdr); pkt_cnt = (u16)rx_hdr; @@ -1638,53 +1392,22 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) continue; } - if (pkt_cnt == 0) { - skb->len = pkt_len; - + if (pkt_cnt == 0) { /* Skip IP alignment psudo header */ - if (NET_IP_ALIGN == 0) - skb_pull(skb, 2); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - skb->tail = skb->data + skb->len; -#else - skb_set_tail_pointer(skb, skb->len); -#endif - skb->truesize = skb->len + sizeof(struct sk_buff); + skb_pull(skb, 2); + skb->len = pkt_len; + skb_set_tail_pointer(skb, pkt_len); + skb->truesize = pkt_len + sizeof(struct sk_buff); ax88179_rx_checksum(skb, pkt_hdr); - return 1; } -#ifndef RX_SKB_COPY ax_skb = skb_clone(skb, GFP_ATOMIC); -#else - ax_skb = alloc_skb(pkt_len + NET_IP_ALIGN, GFP_ATOMIC); - skb_reserve(ax_skb, NET_IP_ALIGN); -#endif - if (ax_skb) { -#ifndef RX_SKB_COPY ax_skb->len = pkt_len; - - /* Skip IP alignment psudo header */ - if (NET_IP_ALIGN == 0) - skb_pull(ax_skb, 2); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - ax_skb->tail = ax_skb->data + ax_skb->len; -#else - skb_set_tail_pointer(ax_skb, ax_skb->len); -#endif - -#else - skb_put(ax_skb, pkt_len); - memcpy(ax_skb->data, skb->data, pkt_len); - - if (NET_IP_ALIGN == 0) - skb_pull(ax_skb, 2); -#endif - ax_skb->truesize = ax_skb->len + sizeof(struct sk_buff); + ax_skb->data = skb->data + 2; + skb_set_tail_pointer(ax_skb, pkt_len); + ax_skb->truesize = pkt_len + sizeof(struct sk_buff); ax88179_rx_checksum(ax_skb, pkt_hdr); usbnet_skb_return(dev, ax_skb); } else { @@ -1700,100 +1423,69 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) static struct sk_buff * ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { - u32 tx_hdr1 = 0, tx_hdr2 = 0; + u32 tx_hdr1, tx_hdr2; int frame_size = dev->maxpacket; int mss = skb_shinfo(skb)->gso_size; - int headroom = 0; - int tailroom = 0; + int headroom; tx_hdr1 = skb->len; tx_hdr2 = mss; if (((skb->len + 8) % frame_size) == 0) tx_hdr2 |= 0x80008000; /* Enable padding */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) - if (!dev->can_dma_sg && (dev->net->features & NETIF_F_SG) && - skb_linearize(skb)) - return NULL; -#else - if ((dev->net->features & NETIF_F_SG) && skb_linearize(skb)) - return NULL; -#endif - - headroom = skb_headroom(skb); - tailroom = skb_tailroom(skb); - - if ((headroom + tailroom) >= 8) { - if (headroom < 8) { - skb->data = memmove(skb->head + 8, skb->data, skb->len); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - skb->tail = skb->data + skb->len; -#else - skb_set_tail_pointer(skb, skb->len); -#endif - } - } else { - struct sk_buff *skb2 = NULL; - skb2 = skb_copy_expand(skb, 8, 0, flags); + headroom = skb_headroom(skb) - 8; + + if ((skb_header_cloned(skb) || headroom < 0) && + pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) { dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return NULL; + return NULL; } skb_push(skb, 4); cpu_to_le32s(&tx_hdr2); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - memcpy(skb->data, &tx_hdr2, 4); -#else skb_copy_to_linear_data(skb, &tx_hdr2, 4); -#endif skb_push(skb, 4); cpu_to_le32s(&tx_hdr1); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - memcpy(skb->data, &tx_hdr1, 4); -#else skb_copy_to_linear_data(skb, &tx_hdr1, 4); -#endif return skb; } static int ax88179_link_reset(struct usbnet *dev) { - struct ax88179_data *data = (struct ax88179_data *)&dev->data; - u8 tmp[5] = {0}, link_sts = 0; - u16 mode = 0, tmp16 = 0, delay = HZ/10; + struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; + u8 tmp[5], link_sts; + u16 mode, tmp16, delay = HZ / 10; u32 tmp32 = 0x40000000; - unsigned long jtimeout = 0; + unsigned long jtimeout; jtimeout = jiffies + delay; - while (tmp32 & 0x40000000) { mode = 0; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mode); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, - 2, 2, &data->rxctl); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, + &ax179_data->rxctl); - /* link up, check the usb device control TX FIFO full or empty*/ - ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32, 1); + /*link up, check the usb device control TX FIFO full or empty*/ + ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32); if (time_after(jiffies, jtimeout)) return 0; } - mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN; + mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | + AX_MEDIUM_RXFLOW_CTRLEN; ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, - 1, 1, &link_sts, 0); + 1, 1, &link_sts); + ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PHYSR, 2, &tmp16, 1); + GMII_PHY_PHYSR, 2, &tmp16); - if (!(tmp16 & GMII_PHY_PHYSR_LINK)) + if (!(tmp16 & GMII_PHY_PHYSR_LINK)) { return 0; - else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) { + } else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) { mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ; if (dev->net->mtu > 1500) mode |= AX_MEDIUM_JUMBO_EN; @@ -1805,69 +1497,40 @@ static int ax88179_link_reset(struct usbnet *dev) else memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); } else if (GMII_PHY_PHYSR_100 == (tmp16 & GMII_PHY_PHYSR_SMASK)) { - mode |= AX_MEDIUM_PS; /* Bit 9 : PS */ + mode |= AX_MEDIUM_PS; + if (link_sts & (AX_USB_SS | AX_USB_HS)) memcpy(tmp, &AX88179_BULKIN_SIZE[2], 5); else memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - } else + } else { memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); - - if (bsize != -1) { - if (bsize > 24) - bsize = 24; - - else if (bsize == 0) { - tmp[1] = 0; - tmp[2] = 0; - } - - tmp[3] = (u8)bsize; - } - - if (ifg != -1) { - if (ifg > 255) - ifg = 255; - tmp[4] = (u8)ifg; } /* RX bulk configuration */ ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); - if (tmp16 & GMII_PHY_PHYSR_FULL) - mode |= AX_MEDIUM_FULL_DUPLEX; /* Bit 1 : FD */ - dev->rx_urb_size = (1024 * (tmp[3] + 2)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_info(dev->net, "Write medium type: 0x%04x\n", mode); -#else - devinfo(dev, "Write medium type: 0x%04x\n", mode); -#endif - /* Configure default medium type => giga */ + if (tmp16 & GMII_PHY_PHYSR_FULL) + mode |= AX_MEDIUM_FULL_DUPLEX; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &mode); - mii_check_media(&dev->mii, 1, 1); + + ax179_data->eee_enabled = ax88179_chk_eee(dev); + + netif_carrier_on(dev->net); return 0; } static int ax88179_reset(struct usbnet *dev) { - void *buf = NULL; - u16 *tmp16 = NULL; - u8 *tmp = NULL; - struct ax88179_data *ax179_data = (struct ax88179_data *) dev->data; - buf = kmalloc(6, GFP_KERNEL); - - if (!buf) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_err(dev->net, "Cannot allocate memory for buffer"); -#else - deverr(dev, "Cannot allocate memory for buffer"); -#endif - return -ENOMEM; - } + u8 buf[5]; + u16 *tmp16; + u8 *tmp; + struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; + struct ethtool_eee eee_data; tmp16 = (u16 *)buf; tmp = (u8 *)buf; @@ -1875,6 +1538,7 @@ static int ax88179_reset(struct usbnet *dev) /* Power up ethernet PHY */ *tmp16 = 0; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); + *tmp16 = AX_PHYPWR_RSTCTL_IPRL; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); msleep(200); @@ -1884,23 +1548,11 @@ static int ax88179_reset(struct usbnet *dev) msleep(100); /* Ethernet PHY Auto Detach*/ - ax88179_AutoDetach(dev, 0); + ax88179_auto_detach(dev, 0); - /* Set the MAC address */ - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, - ETH_ALEN, dev->net->dev_addr); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_dbg(dev->net, "MAC [%02x-%02x-%02x-%02x-%02x-%02x]\n", - dev->net->dev_addr[0], dev->net->dev_addr[1], - dev->net->dev_addr[2], dev->net->dev_addr[3], - dev->net->dev_addr[4], dev->net->dev_addr[5]); -#else - devdbg(dev, "MAC [%02x-%02x-%02x-%02x-%02x-%02x]\n", - dev->net->dev_addr[0], dev->net->dev_addr[1], - dev->net->dev_addr[2], dev->net->dev_addr[3], - dev->net->dev_addr[4], dev->net->dev_addr[5]); -#endif + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, + dev->net->dev_addr); + memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); /* RX bulk configuration */ memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); @@ -1908,33 +1560,18 @@ static int ax88179_reset(struct usbnet *dev) dev->rx_urb_size = 1024 * 20; - tmp[0] = 0x34; + *tmp = 0x34; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); - tmp[0] = 0x52; + *tmp = 0x52; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, 1, 1, tmp); - dev->net->features |= NETIF_F_IP_CSUM; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) - dev->net->features |= NETIF_F_IPV6_CSUM; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) - if (usb_device_no_sg_constraint(dev->udev)) - dev->can_dma_sg = 1; - dev->net->features |= NETIF_F_SG | NETIF_F_TSO; -#endif - -#if defined(CONFIG_MACH_ODROIDXU3) - /* Hack to set such features by default on driver is loaded */ - dev->net->features |= NETIF_F_SG | NETIF_F_TSO; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) - dev->net->hw_features |= NETIF_F_IP_CSUM; - dev->net->hw_features |= NETIF_F_IPV6_CSUM; - dev->net->hw_features |= NETIF_F_SG | NETIF_F_TSO; -#endif + dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + + dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | @@ -1945,226 +1582,175 @@ static int ax88179_reset(struct usbnet *dev) AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); - ax179_data->checksum |= AX_RX_CHECKSUM | AX_TX_CHECKSUM; - /* Configure RX control register => start operation */ - *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_START | AX_RX_CTL_AP | - AX_RX_CTL_AMALL | AX_RX_CTL_AB; - if (NET_IP_ALIGN == 0) - *tmp16 |= AX_RX_CTL_IPE; + *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | + AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | - AX_MONITOR_MODE_RWMP; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, tmp); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MODE, 1, 1, tmp, 0); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_dbg(dev->net, "Monitor mode = 0x%02x\n", *tmp); -#else - devdbg(dev, "Monitor mode = 0x%02x\n", *tmp); -#endif + AX_MONITOR_MODE_RWMP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); /* Configure default medium type => giga */ - *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | + *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | + AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, tmp16); ax88179_led_setting(dev); - ax88179_EEE_setting(dev); + ax179_data->eee_enabled = 0; + ax179_data->eee_active = 0; - ax88179_Gether_setting(dev); + ax88179_disable_eee(dev); + + ax88179_ethtool_get_eee(dev, &eee_data); + eee_data.advertised = 0; + ax88179_ethtool_set_eee(dev, &eee_data); /* Restart autoneg */ mii_nway_restart(&dev->mii); - netif_carrier_off(dev->net); - - kfree(buf); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) - netdev_dbg(dev->net, "mtu %d\n", dev->net->mtu); -#else - devdbg(dev, "mtu %d\n", dev->net->mtu); -#endif + usbnet_link_change(dev, 0, 0); return 0; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) static int ax88179_stop(struct usbnet *dev) { - u16 tmp16 = 0; + u16 tmp16; ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16, 1); + 2, 2, &tmp16); tmp16 &= ~AX_MEDIUM_RECEIVE_EN; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &tmp16); + return 0; } -#endif static const struct driver_info ax88179_info = { .description = "ASIX AX88179 USB 3.0 Gigabit Ethernet", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, + .bind = ax88179_bind, + .unbind = ax88179_unbind, + .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS, -#else - .flags = FLAG_ETHER | FLAG_FRAMING_AX, -#endif + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; - static const struct driver_info ax88178a_info = { .description = "ASIX AX88178A USB 2.0 Gigabit Ethernet", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, + .bind = ax88179_bind, + .unbind = ax88179_unbind, + .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS, -#else - .flags = FLAG_ETHER | FLAG_FRAMING_AX, -#endif + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; -static const struct driver_info sitecom_info = { - .description = "Sitecom USB 3.0 to Gigabit Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, +static const struct driver_info dlink_dub1312_info = { + .description = "D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter", + .bind = ax88179_bind, + .unbind = ax88179_unbind, + .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS, -#else - .flags = FLAG_ETHER | FLAG_FRAMING_AX, -#endif + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; -static const struct driver_info lenovo_info = { - .description = "ThinkPad OneLinkDock USB GigaLAN", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, +static const struct driver_info sitecom_info = { + .description = "Sitecom USB 3.0 to Gigabit Adapter", + .bind = ax88179_bind, + .unbind = ax88179_unbind, + .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS, -#else - .flags = FLAG_ETHER | FLAG_FRAMING_AX, -#endif + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; -static const struct driver_info toshiba_info = { - .description = "Toshiba USB 3.0 to Gigabit LAN Adapter", - .bind = ax88179_bind, - .unbind = ax88179_unbind, - .status = ax88179_status, +static const struct driver_info samsung_info = { + .description = "Samsung USB Ethernet Adapter", + .bind = ax88179_bind, + .unbind = ax88179_unbind, + .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS, -#else - .flags = FLAG_ETHER | FLAG_FRAMING_AX, -#endif + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; -static const struct driver_info samsung_info = { - .description = "Samsung USB Ethernet Adapter", - .bind = ax88179_bind, +static const struct driver_info lenovo_info = { + .description = "Lenovo OneLinkDock Gigabit LAN", + .bind = ax88179_bind, .unbind = ax88179_unbind, .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_AVOID_UNLINK_URBS, -#else - .flags = FLAG_ETHER | FLAG_FRAMING_AX, -#endif + .reset = ax88179_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; -static const struct usb_device_id products[] = { +static const struct usb_device_id products[] = { { /* ASIX AX88179 10/100/1000 */ USB_DEVICE(0x0b95, 0x1790), - .driver_info = (unsigned long) &ax88179_info, + .driver_info = (unsigned long)&ax88179_info, }, { /* ASIX AX88178A 10/100/1000 */ USB_DEVICE(0x0b95, 0x178a), - .driver_info = (unsigned long) &ax88178a_info, + .driver_info = (unsigned long)&ax88178a_info, +}, { + /* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */ + USB_DEVICE(0x2001, 0x4a00), + .driver_info = (unsigned long)&dlink_dub1312_info, }, { /* Sitecom USB 3.0 to Gigabit Adapter */ USB_DEVICE(0x0df6, 0x0072), - .driver_info = (unsigned long) &sitecom_info, -}, { - /* ThinkPad OneLinkDock USB GigaLAN */ - USB_DEVICE(0x17ef, 0x304b), - .driver_info = (unsigned long) &lenovo_info, -}, { - /* Toshiba USB3.0 to Gigabit LAN Adapter */ - USB_DEVICE(0x0930, 0x0a13), - .driver_info = (unsigned long) &toshiba_info, + .driver_info = (unsigned long)&sitecom_info, }, { /* Samsung USB Ethernet Adapter */ USB_DEVICE(0x04e8, 0xa100), - .driver_info = (unsigned long) &samsung_info, + .driver_info = (unsigned long)&samsung_info, +}, { + /* Lenovo OneLinkDock Gigabit LAN */ + USB_DEVICE(0x17ef, 0x304b), + .driver_info = (unsigned long)&lenovo_info, }, - { }, /* END */ + { }, }; MODULE_DEVICE_TABLE(usb, products); -static struct usb_driver asix_driver = { +static struct usb_driver ax88179_178a_driver = { .name = "ax88179_178a", .id_table = products, .probe = usbnet_probe, .suspend = ax88179_suspend, .resume = ax88179_resume, + .reset_resume = ax88179_resume, .disconnect = usbnet_disconnect, + .supports_autosuspend = 1, + .disable_hub_initiated_lpm = 1, }; +module_usb_driver(ax88179_178a_driver); -static int __init asix_init(void) -{ - return usb_register(&asix_driver); -} -module_init(asix_init); - -static void __exit asix_exit(void) -{ - usb_deregister(&asix_driver); -} -module_exit(asix_exit); - -MODULE_AUTHOR("David Hollis"); -MODULE_DESCRIPTION("ASIX AX88179_178A based USB 2.0/3.0 Gigabit Ethernet Devices"); +MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices"); MODULE_LICENSE("GPL"); - diff --git a/drivers/net/usb/ax88179_178a.h b/drivers/net/usb/ax88179_178a.h deleted file mode 100755 index cbe4e9fa6f303a..00000000000000 --- a/drivers/net/usb/ax88179_178a.h +++ /dev/null @@ -1,365 +0,0 @@ -#ifndef __LINUX_USBNET_ASIX_H -#define __LINUX_USBNET_ASIX_H - -//#define RX_SKB_COPY - -#define AX88179_PHY_ID 0x03 -#define AX_MCAST_FILTER_SIZE 8 -#define AX_MAX_MCAST 64 -#define AX_EEPROM_LEN 0x40 -#define AX_RX_CHECKSUM 1 -#define AX_TX_CHECKSUM 2 - -#define AX_BULKIN_24K 0x18; /* 24k */ - -#define AX_ACCESS_MAC 0x01 -#define AX_ACCESS_PHY 0x02 -#define AX_ACCESS_WAKEUP 0x03 -#define AX_ACCESS_EEPROM 0x04 -#define AX_ACCESS_EFUSE 0x05 -#define AX_RELOAD_EEPROM_EFUSE 0x06 -#define AX_WRITE_EFUSE_EN 0x09 -#define AX_WRITE_EFUSE_DIS 0x0A -#define AX_ACCESS_MFAB 0x10 - -#define PHYSICAL_LINK_STATUS 0x02 - #define AX_USB_SS 0x04 - #define AX_USB_HS 0x02 - #define AX_USB_FS 0x01 - -#define GENERAL_STATUS 0x03 -/* Check AX88179 version. UA1:Bit2 = 0, UA2:Bit2 = 1 */ - #define AX_SECLD 0x04 - - - -#define AX_SROM_ADDR 0x07 -#define AX_SROM_CMD 0x0a - #define EEP_RD 0x04 /* EEprom read command */ - #define EEP_WR 0x08 /* EEprom write command */ - #define EEP_BUSY 0x10 /* EEprom access module busy */ - - -#define AX_SROM_DATA_LOW 0x08 -#define AX_SROM_DATA_HIGH 0x09 - -#define AX_RX_CTL 0x0b - #define AX_RX_CTL_DROPCRCERR 0x0100 /* Drop CRC error packet */ - #define AX_RX_CTL_IPE 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */ - #define AX_RX_CTL_TXPADCRC 0x0400 /* checksum value in rx header 3 */ - #define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */ - #define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */ - #define AX_RX_CTL_AM 0x0010 /* Accetp Brocadcast frames*/ - #define AX_RX_CTL_AB 0x0008 /* HW auto-added 8-bytes data when meet USB bulk in transfer boundary (1024/512/64)*/ - #define AX_RX_CTL_HA8B 0x0004 - #define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */ - #define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */ - #define AX_RX_CTL_STOP 0x0000 /* Stop MAC */ - -#define AX_NODE_ID 0x10 -#define AX_MULTI_FILTER_ARRY 0x16 - -#define AX_MEDIUM_STATUS_MODE 0x22 - #define AX_MEDIUM_GIGAMODE 0x01 - #define AX_MEDIUM_FULL_DUPLEX 0x02 -// #define AX_MEDIUM_ALWAYS_ONE 0x04 - #define AX_MEDIUM_EN_125MHZ 0x08 - #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 - #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 - #define AX_MEDIUM_RECEIVE_EN 0x100 - #define AX_MEDIUM_PS 0x200 - #define AX_MEDIUM_JUMBO_EN 0x8040 - -#define AX_MONITOR_MODE 0x24 - #define AX_MONITOR_MODE_RWLC 0x02 - #define AX_MONITOR_MODE_RWMP 0x04 - #define AX_MONITOR_MODE_RWWF 0x08 - #define AX_MONITOR_MODE_RW_FLAG 0x10 - #define AX_MONITOR_MODE_PMEPOL 0x20 - #define AX_MONITOR_MODE_PMETYPE 0x40 - -#define AX_GPIO_CTRL 0x25 - #define AX_GPIO_CTRL_GPIO3EN 0x80 - #define AX_GPIO_CTRL_GPIO2EN 0x40 - #define AX_GPIO_CTRL_GPIO1EN 0x20 - -#define AX_PHYPWR_RSTCTL 0x26 - #define AX_PHYPWR_RSTCTL_BZ 0x0010 - #define AX_PHYPWR_RSTCTL_IPRL 0x0020 - #define AX_PHYPWR_RSTCTL_AUTODETACH 0x1000 - -#define AX_RX_BULKIN_QCTRL 0x2e - #define AX_RX_BULKIN_QCTRL_TIME 0x01 - #define AX_RX_BULKIN_QCTRL_IFG 0x02 - #define AX_RX_BULKIN_QCTRL_SIZE 0x04 - -#define AX_RX_BULKIN_QTIMR_LOW 0x2f -#define AX_RX_BULKIN_QTIMR_HIGH 0x30 -#define AX_RX_BULKIN_QSIZE 0x31 -#define AX_RX_BULKIN_QIFG 0x32 - -#define AX_CLK_SELECT 0x33 - #define AX_CLK_SELECT_BCS 0x01 - #define AX_CLK_SELECT_ACS 0x02 - #define AX_CLK_SELECT_ACSREQ 0x10 - #define AX_CLK_SELECT_ULR 0x08 - -#define AX_RXCOE_CTL 0x34 - #define AX_RXCOE_IP 0x01 - #define AX_RXCOE_TCP 0x02 - #define AX_RXCOE_UDP 0x04 - #define AX_RXCOE_ICMP 0x08 - #define AX_RXCOE_IGMP 0x10 - #define AX_RXCOE_TCPV6 0x20 - #define AX_RXCOE_UDPV6 0x40 - #define AX_RXCOE_ICMV6 0x80 - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) - #define AX_RXCOE_DEF_CSUM (AX_RXCOE_IP | AX_RXCOE_TCP | \ - AX_RXCOE_UDP | AX_RXCOE_ICMV6 | \ - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6) -#else - #define AX_RXCOE_DEF_CSUM (AX_RXCOE_IP | AX_RXCOE_TCP | \ - AX_RXCOE_UDP) -#endif - -#define AX_TXCOE_CTL 0x35 - #define AX_TXCOE_IP 0x01 - #define AX_TXCOE_TCP 0x02 - #define AX_TXCOE_UDP 0x04 - #define AX_TXCOE_ICMP 0x08 - #define AX_TXCOE_IGMP 0x10 - #define AX_TXCOE_TCPV6 0x20 - #define AX_TXCOE_UDPV6 0x40 - #define AX_TXCOE_ICMV6 0x80 -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) - #define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \ - AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6) -#else - #define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP) -#endif - -#define AX_PAUSE_WATERLVL_HIGH 0x54 -#define AX_PAUSE_WATERLVL_LOW 0x55 - - -#define AX_EEP_EFUSE_CORRECT 0x00 -#define AX88179_EEPROM_MAGIC 0x17900b95 - - -/*****************************************************************************/ -/* GMII register definitions */ -#define GMII_PHY_CONTROL 0x00 /* control reg */ - /* Bit definitions: GMII Control */ - #define GMII_CONTROL_RESET 0x8000 /* reset bit in control reg */ - #define GMII_CONTROL_LOOPBACK 0x4000 /* loopback bit in control reg */ - #define GMII_CONTROL_10MB 0x0000 /* 10 Mbit */ - #define GMII_CONTROL_100MB 0x2000 /* 100Mbit */ - #define GMII_CONTROL_1000MB 0x0040 /* 1000Mbit */ - #define GMII_CONTROL_SPEED_BITS 0x2040 /* speed bit mask */ - #define GMII_CONTROL_ENABLE_AUTO 0x1000 /* autonegotiate enable */ - #define GMII_CONTROL_POWER_DOWN 0x0800 - #define GMII_CONTROL_ISOLATE 0x0400 /* islolate bit */ - #define GMII_CONTROL_START_AUTO 0x0200 /* restart autonegotiate */ - #define GMII_CONTROL_FULL_DUPLEX 0x0100 - -#define GMII_PHY_STATUS 0x01 /* status reg */ - /* Bit definitions: GMII Status */ - #define GMII_STATUS_100MB_MASK 0xE000 /* any of these indicate 100 Mbit */ - #define GMII_STATUS_10MB_MASK 0x1800 /* either of these indicate 10 Mbit */ - #define GMII_STATUS_AUTO_DONE 0x0020 /* auto negotiation complete */ - #define GMII_STATUS_AUTO 0x0008 /* auto negotiation is available */ - #define GMII_STATUS_LINK_UP 0x0004 /* link status bit */ - #define GMII_STATUS_EXTENDED 0x0001 /* extended regs exist */ - #define GMII_STATUS_100T4 0x8000 /* capable of 100BT4 */ - #define GMII_STATUS_100TXFD 0x4000 /* capable of 100BTX full duplex */ - #define GMII_STATUS_100TX 0x2000 /* capable of 100BTX */ - #define GMII_STATUS_10TFD 0x1000 /* capable of 10BT full duplex */ - #define GMII_STATUS_10T 0x0800 /* capable of 10BT */ - -#define GMII_PHY_OUI 0x02 /* most of the OUI bits */ -#define GMII_PHY_MODEL 0x03 /* model/rev bits, and rest of OUI */ -#define GMII_PHY_ANAR 0x04 /* AN advertisement reg */ - /* Bit definitions: Auto-Negotiation Advertisement */ - #define GMII_ANAR_ASYM_PAUSE 0x0800 /* support asymetric pause */ - #define GMII_ANAR_PAUSE 0x0400 /* support pause packets */ - #define GMII_ANAR_100T4 0x0200 /* support 100BT4 */ - #define GMII_ANAR_100TXFD 0x0100 /* support 100BTX full duplex */ - #define GMII_ANAR_100TX 0x0080 /* support 100BTX half duplex */ - #define GMII_ANAR_10TFD 0x0040 /* support 10BT full duplex */ - #define GMII_ANAR_10T 0x0020 /* support 10BT half duplex */ - #define GMII_SELECTOR_FIELD 0x001F /* selector field. */ - -#define GMII_PHY_ANLPAR 0x05 /* AN Link Partner */ - /* Bit definitions: Auto-Negotiation Link Partner Ability */ - #define GMII_ANLPAR_100T4 0x0200 /* support 100BT4 */ - #define GMII_ANLPAR_100TXFD 0x0100 /* support 100BTX full duplex */ - #define GMII_ANLPAR_100TX 0x0080 /* support 100BTX half duplex */ - #define GMII_ANLPAR_10TFD 0x0040 /* support 10BT full duplex */ - #define GMII_ANLPAR_10T 0x0020 /* support 10BT half duplex */ - #define GMII_ANLPAR_PAUSE 0x0400 /* support pause packets */ - #define GMII_ANLPAR_ASYM_PAUSE 0x0800 /* support asymetric pause */ - #define GMII_ANLPAR_ACK 0x4000 /* means LCB was successfully rx'd */ - #define GMII_SELECTOR_8023 0x0001; - -#define GMII_PHY_ANER 0x06 /* AN expansion reg */ -#define GMII_PHY_1000BT_CONTROL 0x09 /* control reg for 1000BT */ -#define GMII_PHY_1000BT_STATUS 0x0A /* status reg for 1000BT */ - -#define GMII_PHY_MACR 0x0D -#define GMII_PHY_MAADR 0x0E - -#define GMII_PHY_PHYSR 0x11 /* PHY specific status register */ - #define GMII_PHY_PHYSR_SMASK 0xc000 - #define GMII_PHY_PHYSR_GIGA 0x8000 - #define GMII_PHY_PHYSR_100 0x4000 - #define GMII_PHY_PHYSR_FULL 0x2000 - #define GMII_PHY_PHYSR_LINK 0x400 - -/* Bit definitions: 1000BaseT AUX Control */ -#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000 -#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 /* full duplex capable */ -#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 /* half duplex capable */ - -/* Bit definitions: 1000BaseT AUX Status */ -#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 /* full duplex capable */ -#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 /* half duplex capable */ - -/*Cicada MII Registers */ -#define GMII_AUX_CTRL_STATUS 0x1C -#define GMII_AUX_ANEG_CPLT 0x8000 -#define GMII_AUX_FDX 0x0020 -#define GMII_AUX_SPEED_1000 0x0010 -#define GMII_AUX_SPEED_100 0x0008 - -#define GMII_LED_ACTIVE 0x1a - #define GMII_LED_ACTIVE_MASK 0xff8f - #define GMII_LED0_ACTIVE (1 << 4) - #define GMII_LED1_ACTIVE (1 << 5) - #define GMII_LED2_ACTIVE (1 << 6) - -#define GMII_LED_LINK 0x1c - #define GMII_LED_LINK_MASK 0xf888 - #define GMII_LED0_LINK_10 (1 << 0) - #define GMII_LED0_LINK_100 (1 << 1) - #define GMII_LED0_LINK_1000 (1 << 2) - #define GMII_LED1_LINK_10 (1 << 4) - #define GMII_LED1_LINK_100 (1 << 5) - #define GMII_LED1_LINK_1000 (1 << 6) - #define GMII_LED2_LINK_10 (1 << 8) - #define GMII_LED2_LINK_100 (1 << 9) - #define GMII_LED2_LINK_1000 (1 << 10) - - #define LED_VALID (1 << 15) /* UA2 LED Setting */ - - #define LED0_ACTIVE (1 << 0) - #define LED0_LINK_10 (1 << 1) - #define LED0_LINK_100 (1 << 2) - #define LED0_LINK_1000 (1 << 3) - #define LED0_FD (1 << 4) - #define LED0_USB3_MASK 0x001f - - #define LED1_ACTIVE (1 << 5) - #define LED1_LINK_10 (1 << 6) - #define LED1_LINK_100 (1 << 7) - #define LED1_LINK_1000 (1 << 8) - #define LED1_FD (1 << 9) - #define LED1_USB3_MASK 0x03e0 - - #define LED2_ACTIVE (1 << 10) - #define LED2_LINK_1000 (1 << 13) - #define LED2_LINK_100 (1 << 12) - #define LED2_LINK_10 (1 << 11) - #define LED2_FD (1 << 14) - #define LED2_USB3_MASK 0x7c00 - -#define GMII_PHYPAGE 0x1e - -#define GMII_PHY_PAGE_SELECT 0x1f - #define GMII_PHY_PAGE_SELECT_EXT 0x0007 - #define GMII_PHY_PAGE_SELECT_PAGE0 0X0000 - #define GMII_PHY_PAGE_SELECT_PAGE1 0X0001 - #define GMII_PHY_PAGE_SELECT_PAGE2 0X0002 - #define GMII_PHY_PAGE_SELECT_PAGE3 0X0003 - #define GMII_PHY_PAGE_SELECT_PAGE4 0X0004 - #define GMII_PHY_PAGE_SELECT_PAGE5 0X0005 - #define GMII_PHY_PAGE_SELECT_PAGE6 0X0006 - -/******************************************************************************/ - -struct ax88179_data { - u16 rxctl; - u8 checksum; -} __attribute__ ((packed)); - -struct ax88179_async_handle { - struct usb_ctrlrequest *req; - u8 m_filter[8]; - u16 rxctl; -} __attribute__ ((packed)); - -struct ax88179_int_data { - __le16 res1; -#define AX_INT_PPLS_LINK (1 << 0) -#define AX_INT_SPLS_LINK (1 << 1) -#define AX_INT_CABOFF_UNPLUG (1 << 7) - u8 link; - __le16 res2; - u8 status; - __le16 res3; -} __attribute__ ((packed)); - -#define AX_RXHDR_L4_ERR (1 << 8) -#define AX_RXHDR_L3_ERR (1 << 9) - - -#define AX_RXHDR_L4_TYPE_ICMP 2 -#define AX_RXHDR_L4_TYPE_IGMP 3 -#define AX_RXHDR_L4_TYPE_TCMPV6 5 - -#define AX_RXHDR_L3_TYPE_IP 1 -#define AX_RXHDR_L3_TYPE_IPV6 2 - -#define AX_RXHDR_L4_TYPE_MASK 0x1c -#define AX_RXHDR_L4_TYPE_UDP 4 -#define AX_RXHDR_L4_TYPE_TCP 16 -#define AX_RXHDR_L3CSUM_ERR 2 -#define AX_RXHDR_L4CSUM_ERR 1 -#define AX_RXHDR_CRC_ERR 0x20000000 -#define AX_RXHDR_MII_ERR 0x40000000 -#define AX_RXHDR_DROP_ERR 0x80000000 -#if 0 -struct ax88179_rx_pkt_header { - - u8 l4_csum_err:1, - l3_csum_err:1, - l4_type:3, - l3_type:2, - ce:1; - - u8 vlan_ind:3, - rx_ok:1, - pri:3, - bmc:1; - - u16 len:13, - crc:1, - mii:1, - drop:1; - -} __attribute__ ((packed)); -#endif -static struct {unsigned char ctrl, timer_l, timer_h, size, ifg; } -AX88179_BULKIN_SIZE[] = { - {7, 0x4f, 0, 0x12, 0xff}, - {7, 0x20, 3, 0x16, 0xff}, - {7, 0xae, 7, 0x18, 0xff}, - {7, 0xcc, 0x4c, 0x18, 8}, -}; - -static int ax88179_reset(struct usbnet *dev); -static int ax88179_link_reset(struct usbnet *dev); -static int ax88179_AutoDetach(struct usbnet *dev, int in_pm); - -#endif /* __LINUX_USBNET_ASIX_H */ - diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index fb068ada0c5ad3..4abf8e910c6c01 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -59,15 +59,13 @@ * For high speed, each frame comfortably fits almost 36 max size * Ethernet packets (so queues should be bigger). * - * REVISIT qlens should be members of 'struct usbnet'; the goal is to - * let the USB host controller be busy for 5msec or more before an irq - * is required, under load. Jumbograms change the equation. + * The goal is to let the USB host controller be busy for 5msec or + * more before an irq is required, under load. Jumbograms change + * the equation. */ -#define RX_MAX_QUEUE_MEMORY (60 * 1518) -#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ - (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4) -#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ - (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4) +#define MAX_QUEUE_MEMORY (60 * 1518) +#define RX_QLEN(dev) ((dev)->rx_qlen) +#define TX_QLEN(dev) ((dev)->tx_qlen) // reawaken network queue this soon after stopping; else watchdog barks #define TX_TIMEOUT_JIFFIES (5*HZ) @@ -344,6 +342,31 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(usbnet_skb_return); +/* must be called if hard_mtu or rx_urb_size changed */ +void usbnet_update_max_qlen(struct usbnet *dev) +{ + enum usb_device_speed speed = dev->udev->speed; + + switch (speed) { + case USB_SPEED_HIGH: + dev->rx_qlen = MAX_QUEUE_MEMORY / dev->rx_urb_size; + dev->tx_qlen = MAX_QUEUE_MEMORY / dev->hard_mtu; + break; + case USB_SPEED_SUPER: + /* + * Not take default 5ms qlen for super speed HC to + * save memory, and iperf tests show 2.5ms qlen can + * work well + */ + dev->rx_qlen = 5 * MAX_QUEUE_MEMORY / dev->rx_urb_size; + dev->tx_qlen = 5 * MAX_QUEUE_MEMORY / dev->hard_mtu; + break; + default: + dev->rx_qlen = dev->tx_qlen = 4; + } +} +EXPORT_SYMBOL_GPL(usbnet_update_max_qlen); + /*------------------------------------------------------------------------- * @@ -372,6 +395,9 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu) usbnet_unlink_rx_urbs(dev); } + /* max qlen depend on hard_mtu and rx_urb_size */ + usbnet_update_max_qlen(dev); + return 0; } EXPORT_SYMBOL_GPL(usbnet_change_mtu); @@ -838,6 +864,9 @@ int usbnet_open (struct net_device *net) goto done; } + /* hard_mtu or rx_urb_size may change in reset() */ + usbnet_update_max_qlen(dev); + // insist peer be connected if (info->check_connect && (retval = info->check_connect (dev)) < 0) { netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval); @@ -922,6 +951,9 @@ int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd) if (dev->driver_info->link_reset) dev->driver_info->link_reset(dev); + /* hard_mtu or rx_urb_size may change in link_reset() */ + usbnet_update_max_qlen(dev); + return retval; } @@ -1015,6 +1047,9 @@ static void __handle_link_change(struct usbnet *dev) tasklet_schedule(&dev->bh); } + /* hard_mtu or rx_urb_size may change during link change */ + usbnet_update_max_qlen(dev); + clear_bit(EVENT_LINK_CHANGE, &dev->flags); } @@ -1596,6 +1631,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if ((dev->driver_info->flags & FLAG_WWAN) != 0) SET_NETDEV_DEVTYPE(net, &wwan_type); + /* initialize max rx_qlen and tx_qlen */ + usbnet_update_max_qlen(dev); + status = register_netdev (net); if (status) goto out4; diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 123b21bef1b4d3..185db1d9eda1d3 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -34,6 +34,7 @@ struct usbnet { struct mutex phy_mutex; unsigned char suspend_count; unsigned char pkt_cnt, pkt_err; + unsigned short rx_qlen, tx_qlen; /* i/o info: pipes etc */ unsigned in, out; @@ -253,4 +254,6 @@ extern void usbnet_link_change(struct usbnet *, bool, bool); extern int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags); extern void usbnet_status_stop(struct usbnet *dev); +extern void usbnet_update_max_qlen(struct usbnet *dev); + #endif /* __LINUX_USB_USBNET_H */