diff options
Diffstat (limited to 'drivers/net/usb')
| -rw-r--r-- | drivers/net/usb/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/net/usb/Makefile | 2 | ||||
| -rw-r--r-- | drivers/net/usb/ax88179_178a.c | 22 | ||||
| -rw-r--r-- | drivers/net/usb/cdc_ether.c | 37 | ||||
| -rw-r--r-- | drivers/net/usb/cdc_mbim.c | 4 | ||||
| -rw-r--r-- | drivers/net/usb/hso.c | 15 | ||||
| -rw-r--r-- | drivers/net/usb/ipheth.c | 5 | ||||
| -rw-r--r-- | drivers/net/usb/kalmia.c | 45 | ||||
| -rw-r--r-- | drivers/net/usb/qmi_wwan.c | 13 | ||||
| -rw-r--r-- | drivers/net/usb/r8152.c | 143 | ||||
| -rw-r--r-- | drivers/net/usb/r815x.c | 256 | ||||
| -rw-r--r-- | drivers/net/usb/smsc75xx.c | 12 | ||||
| -rw-r--r-- | drivers/net/usb/usbnet.c | 45 |
13 files changed, 453 insertions, 150 deletions
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 287cc624b90b..d84bfd4109a4 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -67,7 +67,6 @@ config USB_KAWETH config USB_PEGASUS tristate "USB Pegasus/Pegasus-II based ethernet device support" - select NET_CORE select MII ---help--- Say Y here if you know you have Pegasus or Pegasus-II based adapter. @@ -83,7 +82,6 @@ config USB_PEGASUS config USB_RTL8150 tristate "USB RTL8150 based ethernet device support" - select NET_CORE select MII help Say Y here if you have RTL8150 based usb-ethernet adapter. @@ -95,7 +93,6 @@ config USB_RTL8150 config USB_RTL8152 tristate "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" - select NET_CORE select MII help This option adds support for Realtek RTL8152 based USB 2.0 @@ -106,7 +103,6 @@ config USB_RTL8152 config USB_USBNET tristate "Multi-purpose USB Networking Framework" - select NET_CORE select MII ---help--- This driver supports several kinds of network links over USB, diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 9ab5c9d4b45a..e8171784529d 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o asix-y := asix_devices.o asix_common.o ax88172a.o obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o -obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o +obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index bd8758fa38c1..4233c05a3e32 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1028,11 +1028,19 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.phy_id = 0x03; dev->mii.supports_gmii = 1; + if (usb_device_no_sg_constraint(dev->udev)) + dev->can_dma_sg = 1; + dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; + + if (dev->can_dma_sg) { + dev->net->features |= NETIF_F_SG | NETIF_F_TSO; + dev->net->hw_features |= NETIF_F_SG | NETIF_F_TSO; + } /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | @@ -1173,7 +1181,6 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) if (((skb->len + 8) % frame_size) == 0) tx_hdr2 |= 0x80008000; /* Enable padding */ - skb_linearize(skb); headroom = skb_headroom(skb); tailroom = skb_tailroom(skb); @@ -1317,10 +1324,10 @@ static int ax88179_reset(struct usbnet *dev) 1, 1, tmp); dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; + NETIF_F_RXCSUM; /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | @@ -1371,7 +1378,7 @@ static int ax88179_stop(struct usbnet *dev) } static const struct driver_info ax88179_info = { - .description = "ASIX AX88179 USB 3.0 Gigibit Ethernet", + .description = "ASIX AX88179 USB 3.0 Gigabit Ethernet", .bind = ax88179_bind, .unbind = ax88179_unbind, .status = ax88179_status, @@ -1384,7 +1391,7 @@ static const struct driver_info ax88179_info = { }; static const struct driver_info ax88178a_info = { - .description = "ASIX AX88178A USB 2.0 Gigibit Ethernet", + .description = "ASIX AX88178A USB 2.0 Gigabit Ethernet", .bind = ax88179_bind, .unbind = ax88179_unbind, .status = ax88179_status, @@ -1433,6 +1440,7 @@ static struct usb_driver ax88179_178a_driver = { .probe = usbnet_probe, .suspend = ax88179_suspend, .resume = ax88179_resume, + .reset_resume = ax88179_resume, .disconnect = usbnet_disconnect, .supports_autosuspend = 1, .disable_hub_initiated_lpm = 1, diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 078795fe6e31..03ad4dc293aa 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -215,6 +215,10 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) goto bad_desc; } + /* some devices merge these - skip class check */ + if (info->control == info->data) + goto next_desc; + /* a data interface altsetting does the real i/o */ d = &info->data->cur_altsetting->desc; if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { @@ -304,19 +308,23 @@ next_desc: /* claim data interface and set it up ... with side effects. * network traffic can't flow until an altsetting is enabled. */ - status = usb_driver_claim_interface(driver, info->data, dev); - if (status < 0) - return status; + if (info->data != info->control) { + status = usb_driver_claim_interface(driver, info->data, dev); + if (status < 0) + return status; + } status = usbnet_get_endpoints(dev, info->data); if (status < 0) { /* ensure immediate exit from usbnet_disconnect */ usb_set_intfdata(info->data, NULL); - usb_driver_release_interface(driver, info->data); + if (info->data != info->control) + usb_driver_release_interface(driver, info->data); return status; } /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ - dev->status = NULL; + if (info->data != info->control) + dev->status = NULL; if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { struct usb_endpoint_descriptor *desc; @@ -349,6 +357,10 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) struct cdc_state *info = (void *) &dev->data; struct usb_driver *driver = driver_of(intf); + /* combined interface - nothing to do */ + if (info->data == info->control) + return; + /* disconnect master --> disconnect slave */ if (intf == info->control && info->data) { /* ensure immediate exit from usbnet_disconnect */ @@ -627,14 +639,25 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, +/* Huawei E1820 - handled by qmi_wwan */ +{ + USB_DEVICE_INTERFACE_NUMBER(HUAWEI_VENDOR_ID, 0x14ac, 1), + .driver_info = 0, +}, + /* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */ -#if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE) { USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = 0, }, -#endif + +/* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */ +{ + USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, /* * WHITELIST!!! diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 872819851aef..25ba7eca9a13 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -400,6 +400,10 @@ static const struct usb_device_id mbim_devs[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&cdc_mbim_info_zlp, }, + /* HP hs2434 Mobile Broadband Module needs ZLPs */ + { USB_DEVICE_AND_INTERFACE_INFO(0x3f0, 0x4b1d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&cdc_mbim_info_zlp, + }, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&cdc_mbim_info, }, diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index cba1d46e672e..86292e6aaf49 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2816,13 +2816,16 @@ exit: static int hso_get_config_data(struct usb_interface *interface) { struct usb_device *usbdev = interface_to_usbdev(interface); - u8 config_data[17]; + u8 *config_data = kmalloc(17, GFP_KERNEL); u32 if_num = interface->altsetting->desc.bInterfaceNumber; s32 result; + if (!config_data) + return -ENOMEM; if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x86, 0xC0, 0, 0, config_data, 17, USB_CTRL_SET_TIMEOUT) != 0x11) { + kfree(config_data); return -EIO; } @@ -2873,6 +2876,7 @@ static int hso_get_config_data(struct usb_interface *interface) if (config_data[16] & 0x1) result |= HSO_INFO_CRC_BUG; + kfree(config_data); return result; } @@ -2886,6 +2890,11 @@ static int hso_probe(struct usb_interface *interface, struct hso_shared_int *shared_int; struct hso_device *tmp_dev = NULL; + if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) { + dev_err(&interface->dev, "Not our interface\n"); + return -ENODEV; + } + if_num = interface->altsetting->desc.bInterfaceNumber; /* Get the interface/port specification from either driver_info or from @@ -2895,10 +2904,6 @@ static int hso_probe(struct usb_interface *interface, else port_spec = hso_get_config_data(interface); - if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) { - dev_err(&interface->dev, "Not our interface\n"); - return -ENODEV; - } /* Check if we need to switch to alt interfaces prior to port * configuration */ if (interface->num_altsetting > 1) diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 534d8becbbdc..ff8594d8dd2d 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -60,6 +60,7 @@ #define USB_PRODUCT_IPHONE_3GS 0x1294 #define USB_PRODUCT_IPHONE_4 0x1297 #define USB_PRODUCT_IPAD 0x129a +#define USB_PRODUCT_IPAD_MINI 0x12ab #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 #define USB_PRODUCT_IPHONE_5 0x12a8 @@ -107,6 +108,10 @@ static struct usb_device_id ipheth_table[] = { IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPAD_MINI, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c index 0192073e53a3..6866eae3e388 100644 --- a/drivers/net/usb/kalmia.c +++ b/drivers/net/usb/kalmia.c @@ -221,12 +221,9 @@ done: memset(skb_put(skb, padlen), 0, padlen); } - netdev_dbg( - dev->net, - "Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.", - content_len, padlen, header_start[0], header_start[1], - header_start[2], header_start[3], header_start[4], - header_start[5]); + netdev_dbg(dev->net, + "Sending package with length %i and padding %i. Header: %6phC.", + content_len, padlen, header_start); return skb; } @@ -263,32 +260,23 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp( header_start, EXPECTED_UNKNOWN_HEADER_2, sizeof(EXPECTED_UNKNOWN_HEADER_2))) { - netdev_dbg( - dev->net, - "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], - header_start[2], header_start[3], - header_start[4], header_start[5], + netdev_dbg(dev->net, + "Received expected unknown frame header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); } else { - netdev_err( - dev->net, - "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], - header_start[2], header_start[3], - header_start[4], header_start[5], + netdev_err(dev->net, + "Received unknown frame header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); return 0; } } else - netdev_dbg( - dev->net, - "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], header_start[2], - header_start[3], header_start[4], header_start[5], - skb->len - KALMIA_HEADER_LENGTH); + netdev_dbg(dev->net, + "Received header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); /* subtract start header and end header */ usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); @@ -310,12 +298,9 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) sizeof(HEADER_END_OF_USB_PACKET)) == 0); if (!is_last) { header_start = skb->data + ether_packet_length; - netdev_dbg( - dev->net, - "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], - header_start[2], header_start[3], - header_start[4], header_start[5], + netdev_dbg(dev->net, + "End header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); } } diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 86adfa0a912e..606eba2872bd 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -519,9 +519,11 @@ static const struct usb_device_id products[] = { /* 3. Combined interface devices matching on interface number */ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ + {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */ {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0019, 3)}, /* ONDA MT689DC */ {QMI_FIXED_INTF(0x19d2, 0x0021, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0025, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0031, 4)}, @@ -581,6 +583,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ + {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x1e2d, 0x12d1, 4)}, /* Cinterion PLxx */ @@ -589,7 +592,13 @@ static const struct usb_device_id products[] = { {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ - {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel/Verizon USB-1000 */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa002)}, /* Novatel Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa003)}, /* Novatel Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa004)}, /* Novatel Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa005)}, /* Novatel Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa006)}, /* Novatel Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa007)}, /* Novatel Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ @@ -611,6 +620,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ + {QMI_GOBI_DEVICE(0x0af0, 0x8120)}, /* Option GTM681W */ {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ @@ -624,7 +634,6 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */ - {QMI_FIXED_INTF(0x1199, 0x9011, 5)}, /* alternate interface number!? */ {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 14e519888631..11c51f275366 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -11,7 +11,6 @@ #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/mii.h> @@ -345,17 +344,41 @@ static const int multicast_filter_limit = 32; static int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) { - return usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0), + int ret; + void *tmp; + + tmp = kmalloc(size, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0), RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, - value, index, data, size, 500); + value, index, tmp, size, 500); + + memcpy(data, tmp, size); + kfree(tmp); + + return ret; } static int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) { - return usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), + int ret; + void *tmp; + + tmp = kmalloc(size, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + memcpy(tmp, data, size); + + ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, - value, index, data, size, 500); + value, index, tmp, size, 500); + + kfree(tmp); + return ret; } static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size, @@ -491,37 +514,31 @@ int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data) static u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index) { - u32 data; + __le32 data; - if (type == MCU_TYPE_PLA) - pla_ocp_read(tp, index, sizeof(data), &data); - else - usb_ocp_read(tp, index, sizeof(data), &data); + generic_ocp_read(tp, index, sizeof(data), &data, type); return __le32_to_cpu(data); } static void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data) { - if (type == MCU_TYPE_PLA) - pla_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(data), &data); - else - usb_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(data), &data); + __le32 tmp = __cpu_to_le32(data); + + generic_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(tmp), &tmp, type); } static u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index) { u32 data; + __le32 tmp; u8 shift = index & 2; index &= ~3; - if (type == MCU_TYPE_PLA) - pla_ocp_read(tp, index, sizeof(data), &data); - else - usb_ocp_read(tp, index, sizeof(data), &data); + generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); - data = __le32_to_cpu(data); + data = __le32_to_cpu(tmp); data >>= (shift * 8); data &= 0xffff; @@ -530,7 +547,8 @@ static u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index) static void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data) { - u32 tmp, mask = 0xffff; + u32 mask = 0xffff; + __le32 tmp; u16 byen = BYTE_EN_WORD; u8 shift = index & 2; @@ -543,34 +561,25 @@ static void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data) index &= ~3; } - if (type == MCU_TYPE_PLA) - pla_ocp_read(tp, index, sizeof(tmp), &tmp); - else - usb_ocp_read(tp, index, sizeof(tmp), &tmp); + generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); - tmp = __le32_to_cpu(tmp) & ~mask; - tmp |= data; - tmp = __cpu_to_le32(tmp); + data |= __le32_to_cpu(tmp) & ~mask; + tmp = __cpu_to_le32(data); - if (type == MCU_TYPE_PLA) - pla_ocp_write(tp, index, byen, sizeof(tmp), &tmp); - else - usb_ocp_write(tp, index, byen, sizeof(tmp), &tmp); + generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type); } static u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index) { u32 data; + __le32 tmp; u8 shift = index & 3; index &= ~3; - if (type == MCU_TYPE_PLA) - pla_ocp_read(tp, index, sizeof(data), &data); - else - usb_ocp_read(tp, index, sizeof(data), &data); + generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); - data = __le32_to_cpu(data); + data = __le32_to_cpu(tmp); data >>= (shift * 8); data &= 0xff; @@ -579,7 +588,8 @@ static u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index) static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data) { - u32 tmp, mask = 0xff; + u32 mask = 0xff; + __le32 tmp; u16 byen = BYTE_EN_BYTE; u8 shift = index & 3; @@ -592,19 +602,12 @@ static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data) index &= ~3; } - if (type == MCU_TYPE_PLA) - pla_ocp_read(tp, index, sizeof(tmp), &tmp); - else - usb_ocp_read(tp, index, sizeof(tmp), &tmp); + generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); - tmp = __le32_to_cpu(tmp) & ~mask; - tmp |= data; - tmp = __cpu_to_le32(tmp); + data |= __le32_to_cpu(tmp) & ~mask; + tmp = __cpu_to_le32(data); - if (type == MCU_TYPE_PLA) - pla_ocp_write(tp, index, byen, sizeof(tmp), &tmp); - else - usb_ocp_write(tp, index, byen, sizeof(tmp), &tmp); + generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type); } static void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value) @@ -686,21 +689,14 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data) static inline void set_ethernet_addr(struct r8152 *tp) { struct net_device *dev = tp->netdev; - u8 *node_id; - - node_id = kmalloc(sizeof(u8) * 8, GFP_KERNEL); - if (!node_id) { - netif_err(tp, probe, dev, "out of memory"); - return; - } + u8 node_id[8] = {0}; - if (pla_ocp_read(tp, PLA_IDR, sizeof(u8) * 8, node_id) < 0) + if (pla_ocp_read(tp, PLA_IDR, sizeof(node_id), node_id) < 0) netif_notice(tp, probe, dev, "inet addr fail\n"); else { memcpy(dev->dev_addr, node_id, dev->addr_len); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); } - kfree(node_id); } static int rtl8152_set_mac_address(struct net_device *netdev, void *p) @@ -883,15 +879,10 @@ static void rtl8152_set_rx_mode(struct net_device *netdev) static void _rtl8152_set_rx_mode(struct net_device *netdev) { struct r8152 *tp = netdev_priv(netdev); - u32 tmp, *mc_filter; /* Multicast hash filter */ + u32 mc_filter[2]; /* Multicast hash filter */ + __le32 tmp[2]; u32 ocp_data; - mc_filter = kmalloc(sizeof(u32) * 2, GFP_KERNEL); - if (!mc_filter) { - netif_err(tp, link, netdev, "out of memory"); - return; - } - clear_bit(RTL8152_SET_RX_MODE, &tp->flags); netif_stop_queue(netdev); ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); @@ -919,14 +910,12 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev) } } - tmp = mc_filter[0]; - mc_filter[0] = __cpu_to_le32(swab32(mc_filter[1])); - mc_filter[1] = __cpu_to_le32(swab32(tmp)); + tmp[0] = __cpu_to_le32(swab32(mc_filter[1])); + tmp[1] = __cpu_to_le32(swab32(mc_filter[0])); - pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(u32) * 2, mc_filter); + pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(tmp), tmp); ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); netif_wake_queue(netdev); - kfree(mc_filter); } static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, @@ -935,7 +924,8 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, struct r8152 *tp = netdev_priv(netdev); struct net_device_stats *stats = rtl8152_get_stats(netdev); struct tx_desc *tx_desc; - int len, res; + unsigned int len; + int res; netif_stop_queue(netdev); len = skb->len; @@ -1749,18 +1739,7 @@ static struct usb_driver rtl8152_driver = { .resume = rtl8152_resume }; -static int __init usb_rtl8152_init(void) -{ - return usb_register(&rtl8152_driver); -} - -static void __exit usb_rtl8152_exit(void) -{ - usb_deregister(&rtl8152_driver); -} - -module_init(usb_rtl8152_init); -module_exit(usb_rtl8152_exit); +module_usb_driver(rtl8152_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/net/usb/r815x.c b/drivers/net/usb/r815x.c new file mode 100644 index 000000000000..2df2f4fb42a7 --- /dev/null +++ b/drivers/net/usb/r815x.c @@ -0,0 +1,256 @@ +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/mii.h> +#include <linux/usb.h> +#include <linux/usb/cdc.h> +#include <linux/usb/usbnet.h> + +#define RTL815x_REQT_READ 0xc0 +#define RTL815x_REQT_WRITE 0x40 +#define RTL815x_REQ_GET_REGS 0x05 +#define RTL815x_REQ_SET_REGS 0x05 + +#define MCU_TYPE_PLA 0x0100 +#define OCP_BASE 0xe86c +#define BASE_MII 0xa400 + +#define BYTE_EN_DWORD 0xff +#define BYTE_EN_WORD 0x33 +#define BYTE_EN_BYTE 0x11 + +#define R815x_PHY_ID 32 +#define REALTEK_VENDOR_ID 0x0bda + + +static int pla_read_word(struct usb_device *udev, u16 index) +{ + int ret; + u8 shift = index & 2; + __le32 *tmp; + + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + index &= ~3; + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, + index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); + if (ret < 0) + goto out2; + + ret = __le32_to_cpu(*tmp); + ret >>= (shift * 8); + ret &= 0xffff; + +out2: + kfree(tmp); + return ret; +} + +static int pla_write_word(struct usb_device *udev, u16 index, u32 data) +{ + __le32 *tmp; + u32 mask = 0xffff; + u16 byen = BYTE_EN_WORD; + u8 shift = index & 2; + int ret; + + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + data &= mask; + + if (shift) { + byen <<= shift; + mask <<= (shift * 8); + data <<= (shift * 8); + index &= ~3; + } + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, + index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); + if (ret < 0) + goto out3; + + data |= __le32_to_cpu(*tmp) & ~mask; + *tmp = __cpu_to_le32(data); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, + index, MCU_TYPE_PLA | byen, tmp, sizeof(*tmp), + 500); + +out3: + kfree(tmp); + return ret; +} + +static int ocp_reg_read(struct usbnet *dev, u16 addr) +{ + u16 ocp_base, ocp_index; + int ret; + + ocp_base = addr & 0xf000; + ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); + if (ret < 0) + goto out; + + ocp_index = (addr & 0x0fff) | 0xb000; + ret = pla_read_word(dev->udev, ocp_index); + +out: + return ret; +} + +static int ocp_reg_write(struct usbnet *dev, u16 addr, u16 data) +{ + u16 ocp_base, ocp_index; + int ret; + + ocp_base = addr & 0xf000; + ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); + if (ret < 0) + goto out1; + + ocp_index = (addr & 0x0fff) | 0xb000; + ret = pla_write_word(dev->udev, ocp_index, data); + +out1: + return ret; +} + +static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg) +{ + struct usbnet *dev = netdev_priv(netdev); + int ret; + + if (phy_id != R815x_PHY_ID) + return -EINVAL; + + if (usb_autopm_get_interface(dev->intf) < 0) + return -ENODEV; + + ret = ocp_reg_read(dev, BASE_MII + reg * 2); + + usb_autopm_put_interface(dev->intf); + return ret; +} + +static +void r815x_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) +{ + struct usbnet *dev = netdev_priv(netdev); + + if (phy_id != R815x_PHY_ID) + return; + + if (usb_autopm_get_interface(dev->intf) < 0) + return; + + ocp_reg_write(dev, BASE_MII + reg * 2, val); + + usb_autopm_put_interface(dev->intf); +} + +static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status; + + status = usbnet_cdc_bind(dev, intf); + if (status < 0) + return status; + + dev->mii.dev = dev->net; + dev->mii.mdio_read = r815x_mdio_read; + dev->mii.mdio_write = r815x_mdio_write; + dev->mii.phy_id_mask = 0x3f; + dev->mii.reg_num_mask = 0x1f; + dev->mii.phy_id = R815x_PHY_ID; + dev->mii.supports_gmii = 1; + + return status; +} + +static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status; + + status = usbnet_cdc_bind(dev, intf); + if (status < 0) + return status; + + dev->mii.dev = dev->net; + dev->mii.mdio_read = r815x_mdio_read; + dev->mii.mdio_write = r815x_mdio_write; + dev->mii.phy_id_mask = 0x3f; + dev->mii.reg_num_mask = 0x1f; + dev->mii.phy_id = R815x_PHY_ID; + dev->mii.supports_gmii = 0; + + return status; +} + +static const struct driver_info r8152_info = { + .description = "RTL8152 ECM Device", + .flags = FLAG_ETHER | FLAG_POINTTOPOINT, + .bind = r8152_bind, + .unbind = usbnet_cdc_unbind, + .status = usbnet_cdc_status, + .manage_power = usbnet_manage_power, +}; + +static const struct driver_info r8153_info = { + .description = "RTL8153 ECM Device", + .flags = FLAG_ETHER | FLAG_POINTTOPOINT, + .bind = r8153_bind, + .unbind = usbnet_cdc_unbind, + .status = usbnet_cdc_status, + .manage_power = usbnet_manage_power, +}; + +static const struct usb_device_id products[] = { +{ + USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +#if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE) + .driver_info = 0, +#else + .driver_info = (unsigned long) &r8152_info, +#endif +}, + +{ + USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +#if defined(CONFIG_USB_RTL8153) || defined(CONFIG_USB_RTL8153_MODULE) + .driver_info = 0, +#else + .driver_info = (unsigned long) &r8153_info, +#endif +}, + + { }, /* END */ +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver r815x_driver = { + .name = "r815x", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, + .reset_resume = usbnet_resume, + .supports_autosuspend = 1, + .disable_hub_initiated_lpm = 1, +}; + +module_usb_driver(r815x_driver); + +MODULE_AUTHOR("Hayes Wang"); +MODULE_DESCRIPTION("Realtek USB ECM device"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 75409748c774..66ebbacf066f 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -45,7 +45,6 @@ #define EEPROM_MAC_OFFSET (0x01) #define DEFAULT_TX_CSUM_ENABLE (true) #define DEFAULT_RX_CSUM_ENABLE (true) -#define DEFAULT_TSO_ENABLE (true) #define SMSC75XX_INTERNAL_PHY_ID (1) #define SMSC75XX_TX_OVERHEAD (8) #define MAX_RX_FIFO_SIZE (20 * 1024) @@ -1410,17 +1409,14 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write); - if (DEFAULT_TX_CSUM_ENABLE) { + if (DEFAULT_TX_CSUM_ENABLE) dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - if (DEFAULT_TSO_ENABLE) - dev->net->features |= NETIF_F_SG | - NETIF_F_TSO | NETIF_F_TSO6; - } + if (DEFAULT_RX_CSUM_ENABLE) dev->net->features |= NETIF_F_RXCSUM; dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM; + NETIF_F_RXCSUM; ret = smsc75xx_wait_ready(dev, 0); if (ret < 0) { @@ -2200,8 +2196,6 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev, { u32 tx_cmd_a, tx_cmd_b; - skb_linearize(skb); - if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { struct sk_buff *skb2 = skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 06ee82f557d4..27a00b006033 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1197,6 +1197,37 @@ EXPORT_SYMBOL_GPL(usbnet_tx_timeout); /*-------------------------------------------------------------------------*/ +static int build_dma_sg(const struct sk_buff *skb, struct urb *urb) +{ + unsigned num_sgs, total_len = 0; + int i, s = 0; + + num_sgs = skb_shinfo(skb)->nr_frags + 1; + if (num_sgs == 1) + return 0; + + urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), GFP_ATOMIC); + if (!urb->sg) + return -ENOMEM; + + urb->num_sgs = num_sgs; + sg_init_table(urb->sg, urb->num_sgs); + + sg_set_buf(&urb->sg[s++], skb->data, skb_headlen(skb)); + total_len += skb_headlen(skb); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + struct skb_frag_struct *f = &skb_shinfo(skb)->frags[i]; + + total_len += skb_frag_size(f); + sg_set_page(&urb->sg[i + s], f->page.p, f->size, + f->page_offset); + } + urb->transfer_buffer_length = total_len; + + return 1; +} + netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) { @@ -1223,7 +1254,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, goto drop; } } - length = skb->len; if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) { netif_dbg(dev, tx_err, dev->net, "no urb\n"); @@ -1233,10 +1263,14 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, entry = (struct skb_data *) skb->cb; entry->urb = urb; entry->dev = dev; - entry->length = length; usb_fill_bulk_urb (urb, dev->udev, dev->out, skb->data, skb->len, tx_complete, skb); + if (dev->can_dma_sg) { + if (build_dma_sg(skb, urb) < 0) + goto drop; + } + entry->length = length = urb->transfer_buffer_length; /* don't assume the hardware handles USB_ZERO_PACKET * NOTE: strictly conforming cdc-ether devices should expect @@ -1305,7 +1339,10 @@ drop: not_drop: if (skb) dev_kfree_skb_any (skb); - usb_free_urb (urb); + if (urb) { + kfree(urb->sg); + usb_free_urb(urb); + } } else netif_dbg(dev, tx_queued, dev->net, "> tx, len %d, type 0x%x\n", length, skb->protocol); @@ -1356,6 +1393,7 @@ static void usbnet_bh (unsigned long param) rx_process (dev, skb); continue; case tx_done: + kfree(entry->urb->sg); case rx_cleanup: usb_free_urb (entry->urb); dev_kfree_skb (skb); @@ -1689,6 +1727,7 @@ int usbnet_resume (struct usb_interface *intf) retval = usb_submit_urb(res, GFP_ATOMIC); if (retval < 0) { dev_kfree_skb_any(skb); + kfree(res->sg); usb_free_urb(res); usb_autopm_put_interface_async(dev->intf); } else { |
