This is due to a bug in the driver affecting kernel versions from <3.4.
In case anyone wants a working driver here is the patch for version 1.6.0 of
ax88179_178a -
https://launchpad.net/~qji/+archive/ax88179/+files/ax88179_1.9.0-0.tar.gz has
the 1.6.0 driver
---
ax88179_178a1.9/ax88179-1.9.0-0/content/usr/share/ax88179/src/AX88179_178A_LINUX_DRIVER_v1.6.0_SOURCE/ax88179_178a.c
2013-09-10 00:33:30.000000000 +0100
+++ ax88179_178a/ax88179_178a.c 2014-04-08 15:01:53.000000000 +0100
@@ -20,7 +20,8 @@
*/
/* debug messages, extra info */
-/* #define DEBUG */
+#define DEBUG
+#define VERBOSE
#include <linux/version.h>
/*#include <linux/config.h>*/
@@ -74,6 +75,8 @@
u16 size, void *data, int in_pm)
{
int ret;
+ void *buf = kmalloc(size, GFP_ATOMIC);
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
@@ -85,7 +88,7 @@
fn = usbnet_read_cmd_nopm;
ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR |
- USB_RECIP_DEVICE, value, index, data, size);
+ USB_RECIP_DEVICE, value, index, buf, size);
if (unlikely(ret < 0))
netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n",
@@ -98,17 +101,27 @@
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
- data,
+ buf,
size,
USB_CTRL_GET_TIMEOUT);
#endif
+
+ memcpy(data, buf, size);
+
+ kfree(buf);
+
return ret;
}
static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16
index,
u16 size, void *data, int in_pm)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+ //printk(KERN_DEBUG "&data : %p, misalignment: %x, size: %x \n", data,
((uintptr_t)data & 3), size);
+
int ret;
+ void *buf = kmemdup(data, size, GFP_ATOMIC);
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
@@ -120,7 +133,7 @@
fn = usbnet_write_cmd_nopm;
ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
- USB_RECIP_DEVICE, value, index, data, size);
+ USB_RECIP_DEVICE, value, index, buf, size);
if (unlikely(ret < 0))
netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n",
@@ -133,17 +146,20 @@
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
- data,
+ buf,
size,
USB_CTRL_SET_TIMEOUT);
#endif
+ kfree(buf);
return ret;
}
static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
u16 index, u16 size, void *data, int eflag)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
int ret;
if (eflag && (2 == size)) {
@@ -166,17 +182,17 @@
static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
u16 index, u16 size, void *data)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
int ret;
if (2 == size) {
u16 buf;
buf = *((u16 *)data);
cpu_to_le16s(&buf);
- ret = __ax88179_write_cmd(dev, cmd, value, index,
- size, &buf, 1);
+ ret = __ax88179_write_cmd(dev, cmd, value, index, size, &buf,
1);
} else {
- ret = __ax88179_write_cmd(dev, cmd, value, index,
- size, data, 1);
+ ret = __ax88179_write_cmd(dev, cmd, value, index, size, data,
1);
}
return ret;
@@ -185,19 +201,21 @@
static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data, int eflag)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
int ret;
if (eflag && (2 == size)) {
- u16 buf;
- ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
- le16_to_cpus(&buf);
- *((u16 *)data) = buf;
+ u16 buf_le;
+ ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf_le,
0);
+ le16_to_cpus(&buf_le);
+ *((u16 *)data) = buf_le;
} else if (eflag && (4 == size)) {
- u32 buf;
- ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
- le32_to_cpus(&buf);
- *((u32 *)data) = buf;
+ u32 buf_le;
+ ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf_le,
0);
+ le32_to_cpus(&buf_le);
+ *((u32 *)data) = buf_le;
} else {
ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0);
}
@@ -208,17 +226,17 @@
static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
int ret;
if (2 == size) {
u16 buf;
buf = *((u16 *)data);
cpu_to_le16s(&buf);
- ret = __ax88179_write_cmd(dev, cmd, value, index,
- size, &buf, 0);
+ ret = __ax88179_write_cmd(dev, cmd, value, index, size, &buf,
0);
} else {
- ret = __ax88179_write_cmd(dev, cmd, value, index,
- size, data, 0);
+ ret = __ax88179_write_cmd(dev, cmd, value, index, size, data,
0);
}
return ret;
@@ -228,6 +246,8 @@
static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
u16 index, u16 size, void *data)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
if (2 == size) {
u16 buf;
buf = *((u16 *)data);
@@ -247,11 +267,12 @@
static void ax88179_async_cmd_callback(struct urb *urb)
#endif
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
if (urb->status < 0)
- printk(KERN_ERR "ax88179_async_cmd_callback() failed with %d",
- urb->status);
+ printk(KERN_ERR "ax88179_async_cmd_callback() failed with %d",
urb->status);
kfree(req);
usb_free_urb(urb);
}
@@ -260,6 +281,8 @@
ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usb_ctrlrequest *req;
int status;
struct urb *urb;
@@ -373,6 +396,8 @@
static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(netdev);
u16 res;
@@ -383,6 +408,8 @@
static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc,
int val)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(netdev);
u16 res = (u16)val;
@@ -396,6 +423,8 @@
u32 message)
#endif
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = usb_get_intfdata(intf);
u16 tmp16;
u8 tmp8;
@@ -429,6 +458,8 @@
static int ax88179_resume(struct usb_interface *intf)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = usb_get_intfdata(intf);
u16 tmp16;
u8 tmp8;
@@ -470,6 +501,7 @@
static void
ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
struct usbnet *dev = netdev_priv(net);
u8 *opt;
@@ -498,6 +530,8 @@
static int
ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
u8 *opt;
@@ -526,6 +560,8 @@
static int ax88179_get_eeprom_len(struct net_device *net)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
return AX_EEPROM_LEN;
}
@@ -533,6 +569,8 @@
ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
u8 *data)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
u16 *eeprom_buff;
int first_word, last_word;
@@ -567,6 +605,8 @@
static void ax88179_get_drvinfo(struct net_device *net,
struct ethtool_drvinfo *info)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
/* Inherit standard device info */
usbnet_get_drvinfo(net, info);
info->eedump_len = 0x3e;
@@ -574,18 +614,24 @@
static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd
*cmd)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
return mii_ethtool_gset(&dev->mii, cmd);
}
static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd
*cmd)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
return mii_ethtool_sset(&dev->mii, cmd);
}
static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
}
@@ -593,6 +639,8 @@
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 28)
static int ax88179_netdev_stop(struct net_device *net)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
u16 tmp16;
@@ -609,6 +657,8 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
static int ax88179_set_csums(struct usbnet *dev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
u8 checksum;
@@ -631,6 +681,8 @@
static u32 ax88179_get_tx_csum(struct net_device *netdev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(netdev);
struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
return ax179_data->checksum & AX_TX_CHECKSUM;
@@ -638,6 +690,8 @@
static u32 ax88179_get_rx_csum(struct net_device *netdev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(netdev);
struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
return ax179_data->checksum & AX_RX_CHECKSUM;
@@ -645,6 +699,8 @@
static int ax88179_set_rx_csum(struct net_device *netdev, u32 val)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(netdev);
struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
@@ -657,6 +713,8 @@
static int ax88179_set_tx_csum(struct net_device *netdev, u32 val)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(netdev);
struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
@@ -672,6 +730,8 @@
static int ax88179_set_tso(struct net_device *netdev, u32 data)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
if (data)
netdev->features |= NETIF_F_TSO;
else
@@ -705,6 +765,8 @@
static void ax88179_set_multicast(struct net_device *net)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
struct ax88179_data *data = (struct ax88179_data *)&dev->data;
u8 *m_filter = ((u8 *)dev->data) + 12;
@@ -813,6 +875,8 @@
static int ax88179_change_mtu(struct net_device *net, int new_mtu)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
u16 tmp16;
@@ -841,6 +905,8 @@
static int ax88179_set_mac_addr(struct net_device *net, void *p)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct usbnet *dev = netdev_priv(net);
struct sockaddr *addr = p;
@@ -880,6 +946,8 @@
static int ax88179_check_eeprom(struct usbnet *dev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u8 i;
u8 buf[2];
u8 eeprom[20];
@@ -927,6 +995,8 @@
static int ax88179_check_efuse(struct usbnet *dev, void *ledmode)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u8 i;
u8 efuse[64] = {0x00};
u16 csum = 0;
@@ -953,6 +1023,8 @@
static int ax88179_convert_old_led(struct usbnet *dev, u8 efuse, void
*ledvalue)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u8 ledmode;
u16 tmp;
u16 led;
@@ -1005,6 +1077,8 @@
static int ax88179_led_setting(struct usbnet *dev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u8 ledfd, value = 0;
u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10;
unsigned long jtimeout;
@@ -1146,6 +1220,8 @@
static int ax88179_AutoDetach(struct usbnet *dev, int in_pm)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u16 tmp16;
u8 tmp8;
int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *, int);
@@ -1180,6 +1256,8 @@
static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
void *buf;
u16 *tmp16;
u8 *tmp;
@@ -1338,6 +1416,8 @@
static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u16 tmp16;
u8 tmp8;
struct ax88179_data *ax179_data = (struct ax88179_data *) dev->data;
@@ -1362,6 +1442,8 @@
static void
ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
skb->ip_summed = CHECKSUM_NONE;
/* checksum error bit is set */
@@ -1377,6 +1459,8 @@
static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct sk_buff *ax_skb;
int pkt_cnt;
u32 rx_hdr;
@@ -1448,11 +1532,14 @@
static struct sk_buff *
ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u32 tx_hdr1, tx_hdr2;
int frame_size = dev->maxpacket;
int mss = skb_shinfo(skb)->gso_size;
int headroom;
int tailroom;
+ int data_align, head_align, need_room;
tx_hdr1 = skb->len;
tx_hdr2 = mss;
@@ -1466,10 +1553,18 @@
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);
+
+ /* 2 tx_hdr headers need 4+4 bytes plus the misalignment correction
space 3 bytes */
+ need_room = 8 + 3;
+
+ if ((headroom + tailroom) >= need_room) {
+ if (headroom < need_room) {
+ /* skb->data should be 4-byte aligned, calculate the
misalignment */
+ head_align = (4 - ((uintptr_t)skb->head & 3)) % 4;
+ /* calculate room needed, so data will be aligned */
+ need_room = 8 + head_align;
+
+ skb->data = memmove(skb->head + need_room, skb->data,
skb->len);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
skb->tail = skb->data + skb->len;
#else
@@ -1478,13 +1573,24 @@
}
} else {
struct sk_buff *skb2;
- skb2 = skb_copy_expand(skb, 8, 0, flags);
+ skb2 = skb_copy_expand(skb, need_room, 0, flags);
dev_kfree_skb_any(skb);
skb = skb2;
if (!skb)
return NULL;
}
+ /* align skb->data to the left 4-byte boundary, if needed */
+ data_align = (uintptr_t)skb->data & 3;
+ if (data_align > 0) {
+ skb->data = memmove(skb->data - data_align, 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
+ }
+
skb_push(skb, 4);
cpu_to_le32s(&tx_hdr2);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
@@ -1506,6 +1612,8 @@
static int ax88179_link_reset(struct usbnet *dev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
struct ax88179_data *data = (struct ax88179_data *)&dev->data;
u8 tmp[5], link_sts;
u16 mode, tmp16, delay = HZ/10;
@@ -1592,6 +1700,8 @@
static int ax88179_reset(struct usbnet *dev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
void *buf;
u16 *tmp16;
u8 *tmp;
@@ -1714,6 +1824,8 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
static int ax88179_stop(struct usbnet *dev)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
u16 tmp16;
ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
@@ -1839,12 +1951,16 @@
static int __init asix_init(void)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
return usb_register(&asix_driver);
}
module_init(asix_init);
static void __exit asix_exit(void)
{
+ //printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
+
usb_deregister(&asix_driver);
}
module_exit(asix_exit);
@@ -1852,4 +1968,3 @@
MODULE_AUTHOR("David Hollis");
MODULE_DESCRIPTION("ASIX AX88179_178A based USB 2.0/3.0 Gigabit Ethernet
Devices");
MODULE_LICENSE("GPL");
-
> I pulled down the latest kernel and re-compiled and now my errors are looking
> like this. I would really like to have a stable wired connection, and ideas?
>
>
> [ 340.210000] ------------[ cut here ]------------
> <4>WARNING: at net/ipv4/tcp.c:1508 tcp_recvmsg+0x7c0/0x844()
> [ 340.240000] WARNING: at net/ipv4/tcp.c:1508 tcp_recvmsg+0x7c0/0x844()
> recvmsg bug 2: copied BEDFF3EB seq BEDFF3EB rcvnxt BEE303B7 fl 0
> [ 340.270000] recvmsg bug 2: copied BEDFF3EB seq BEDFF3EB rcvnxt BEE303B7 fl > 0
--
You received this message because you are subscribed to the Google Groups
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.