diff options
Diffstat (limited to 'drivers/net/usb')
| -rw-r--r-- | drivers/net/usb/Kconfig | 15 | ||||
| -rw-r--r-- | drivers/net/usb/Makefile | 3 | ||||
| -rw-r--r-- | drivers/net/usb/asix_devices.c | 3 | ||||
| -rw-r--r-- | drivers/net/usb/ax88179_178a.c | 46 | ||||
| -rw-r--r-- | drivers/net/usb/cdc_ether.c | 7 | ||||
| -rw-r--r-- | drivers/net/usb/cdc_ncm.c | 48 | ||||
| -rw-r--r-- | drivers/net/usb/gl620a.c | 4 | ||||
| -rw-r--r-- | drivers/net/usb/hso.c | 32 | ||||
| -rw-r--r-- | drivers/net/usb/mcs7830.c | 5 | ||||
| -rw-r--r-- | drivers/net/usb/net1080.c | 4 | ||||
| -rw-r--r-- | drivers/net/usb/qmi_wwan.c | 11 | ||||
| -rw-r--r-- | drivers/net/usb/r8152.c | 32 | ||||
| -rw-r--r-- | drivers/net/usb/r815x.c | 248 | ||||
| -rw-r--r-- | drivers/net/usb/rndis_host.c | 4 | ||||
| -rw-r--r-- | drivers/net/usb/smsc75xx.c | 4 | ||||
| -rw-r--r-- | drivers/net/usb/smsc95xx.c | 4 | ||||
| -rw-r--r-- | drivers/net/usb/sr9800.c | 874 | ||||
| -rw-r--r-- | drivers/net/usb/sr9800.h | 202 | ||||
| -rw-r--r-- | drivers/net/usb/usbnet.c | 25 |
19 files changed, 1231 insertions, 340 deletions
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 6b638a066c1d..7e7269fd3707 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
| @@ -292,6 +292,21 @@ config USB_NET_SR9700 | |||
| 292 | This option adds support for CoreChip-sz SR9700 based USB 1.1 | 292 | This option adds support for CoreChip-sz SR9700 based USB 1.1 |
| 293 | 10/100 Ethernet adapters. | 293 | 10/100 Ethernet adapters. |
| 294 | 294 | ||
| 295 | config USB_NET_SR9800 | ||
| 296 | tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices" | ||
| 297 | depends on USB_USBNET | ||
| 298 | select CRC32 | ||
| 299 | ---help--- | ||
| 300 | Say Y if you want to use one of the following 100Mbps USB Ethernet | ||
| 301 | device based on the CoreChip-sz SR9800 chip. | ||
| 302 | |||
| 303 | This driver makes the adapter appear as a normal Ethernet interface, | ||
| 304 | typically on eth0, if it is the only ethernet device, or perhaps on | ||
| 305 | eth1, if you have a PCI or ISA ethernet card installed. | ||
| 306 | |||
| 307 | To compile this driver as a module, choose M here: the | ||
| 308 | module will be called sr9800. | ||
| 309 | |||
| 295 | config USB_NET_SMSC75XX | 310 | config USB_NET_SMSC75XX |
| 296 | tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices" | 311 | tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices" |
| 297 | depends on USB_USBNET | 312 | depends on USB_USBNET |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index b17b5e88bbaf..e2797f1e1b31 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
| @@ -11,10 +11,11 @@ obj-$(CONFIG_USB_HSO) += hso.o | |||
| 11 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o | 11 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o |
| 12 | asix-y := asix_devices.o asix_common.o ax88172a.o | 12 | asix-y := asix_devices.o asix_common.o ax88172a.o |
| 13 | obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o | 13 | obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o |
| 14 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o | 14 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o |
| 15 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o | 15 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o |
| 16 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o | 16 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o |
| 17 | obj-$(CONFIG_USB_NET_SR9700) += sr9700.o | 17 | obj-$(CONFIG_USB_NET_SR9700) += sr9700.o |
| 18 | obj-$(CONFIG_USB_NET_SR9800) += sr9800.o | ||
| 18 | obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o | 19 | obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o |
| 19 | obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o | 20 | obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o |
| 20 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o | 21 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o |
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 9765a7d4766d..5d194093f3e1 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c | |||
| @@ -917,7 +917,8 @@ static const struct driver_info ax88178_info = { | |||
| 917 | .status = asix_status, | 917 | .status = asix_status, |
| 918 | .link_reset = ax88178_link_reset, | 918 | .link_reset = ax88178_link_reset, |
| 919 | .reset = ax88178_reset, | 919 | .reset = ax88178_reset, |
| 920 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, | 920 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | |
| 921 | FLAG_MULTI_PACKET, | ||
| 921 | .rx_fixup = asix_rx_fixup_common, | 922 | .rx_fixup = asix_rx_fixup_common, |
| 922 | .tx_fixup = asix_tx_fixup, | 923 | .tx_fixup = asix_tx_fixup, |
| 923 | }; | 924 | }; |
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index d6f64dad05bc..054e59ca6946 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c | |||
| @@ -1029,20 +1029,12 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 1029 | dev->mii.phy_id = 0x03; | 1029 | dev->mii.phy_id = 0x03; |
| 1030 | dev->mii.supports_gmii = 1; | 1030 | dev->mii.supports_gmii = 1; |
| 1031 | 1031 | ||
| 1032 | if (usb_device_no_sg_constraint(dev->udev)) | ||
| 1033 | dev->can_dma_sg = 1; | ||
| 1034 | |||
| 1035 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | 1032 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
| 1036 | NETIF_F_RXCSUM; | 1033 | NETIF_F_RXCSUM; |
| 1037 | 1034 | ||
| 1038 | dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | 1035 | dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
| 1039 | NETIF_F_RXCSUM; | 1036 | NETIF_F_RXCSUM; |
| 1040 | 1037 | ||
| 1041 | if (dev->can_dma_sg) { | ||
| 1042 | dev->net->features |= NETIF_F_SG | NETIF_F_TSO; | ||
| 1043 | dev->net->hw_features |= NETIF_F_SG | NETIF_F_TSO; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /* Enable checksum offload */ | 1038 | /* Enable checksum offload */ |
| 1047 | *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | | 1039 | *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | |
| 1048 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; | 1040 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; |
| @@ -1118,6 +1110,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 1118 | u16 hdr_off; | 1110 | u16 hdr_off; |
| 1119 | u32 *pkt_hdr; | 1111 | u32 *pkt_hdr; |
| 1120 | 1112 | ||
| 1113 | /* This check is no longer done by usbnet */ | ||
| 1114 | if (skb->len < dev->net->hard_header_len) | ||
| 1115 | return 0; | ||
| 1116 | |||
| 1121 | skb_trim(skb, skb->len - 4); | 1117 | skb_trim(skb, skb->len - 4); |
| 1122 | memcpy(&rx_hdr, skb_tail_pointer(skb), 4); | 1118 | memcpy(&rx_hdr, skb_tail_pointer(skb), 4); |
| 1123 | le32_to_cpus(&rx_hdr); | 1119 | le32_to_cpus(&rx_hdr); |
| @@ -1391,6 +1387,19 @@ static const struct driver_info ax88178a_info = { | |||
| 1391 | .tx_fixup = ax88179_tx_fixup, | 1387 | .tx_fixup = ax88179_tx_fixup, |
| 1392 | }; | 1388 | }; |
| 1393 | 1389 | ||
| 1390 | static const struct driver_info dlink_dub1312_info = { | ||
| 1391 | .description = "D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter", | ||
| 1392 | .bind = ax88179_bind, | ||
| 1393 | .unbind = ax88179_unbind, | ||
| 1394 | .status = ax88179_status, | ||
| 1395 | .link_reset = ax88179_link_reset, | ||
| 1396 | .reset = ax88179_reset, | ||
| 1397 | .stop = ax88179_stop, | ||
| 1398 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
| 1399 | .rx_fixup = ax88179_rx_fixup, | ||
| 1400 | .tx_fixup = ax88179_tx_fixup, | ||
| 1401 | }; | ||
| 1402 | |||
| 1394 | static const struct driver_info sitecom_info = { | 1403 | static const struct driver_info sitecom_info = { |
| 1395 | .description = "Sitecom USB 3.0 to Gigabit Adapter", | 1404 | .description = "Sitecom USB 3.0 to Gigabit Adapter", |
| 1396 | .bind = ax88179_bind, | 1405 | .bind = ax88179_bind, |
| @@ -1417,6 +1426,19 @@ static const struct driver_info samsung_info = { | |||
| 1417 | .tx_fixup = ax88179_tx_fixup, | 1426 | .tx_fixup = ax88179_tx_fixup, |
| 1418 | }; | 1427 | }; |
| 1419 | 1428 | ||
| 1429 | static const struct driver_info lenovo_info = { | ||
| 1430 | .description = "Lenovo OneLinkDock Gigabit LAN", | ||
| 1431 | .bind = ax88179_bind, | ||
| 1432 | .unbind = ax88179_unbind, | ||
| 1433 | .status = ax88179_status, | ||
| 1434 | .link_reset = ax88179_link_reset, | ||
| 1435 | .reset = ax88179_reset, | ||
| 1436 | .stop = ax88179_stop, | ||
| 1437 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
| 1438 | .rx_fixup = ax88179_rx_fixup, | ||
| 1439 | .tx_fixup = ax88179_tx_fixup, | ||
| 1440 | }; | ||
| 1441 | |||
| 1420 | static const struct usb_device_id products[] = { | 1442 | static const struct usb_device_id products[] = { |
| 1421 | { | 1443 | { |
| 1422 | /* ASIX AX88179 10/100/1000 */ | 1444 | /* ASIX AX88179 10/100/1000 */ |
| @@ -1427,6 +1449,10 @@ static const struct usb_device_id products[] = { | |||
| 1427 | USB_DEVICE(0x0b95, 0x178a), | 1449 | USB_DEVICE(0x0b95, 0x178a), |
| 1428 | .driver_info = (unsigned long)&ax88178a_info, | 1450 | .driver_info = (unsigned long)&ax88178a_info, |
| 1429 | }, { | 1451 | }, { |
| 1452 | /* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */ | ||
| 1453 | USB_DEVICE(0x2001, 0x4a00), | ||
| 1454 | .driver_info = (unsigned long)&dlink_dub1312_info, | ||
| 1455 | }, { | ||
| 1430 | /* Sitecom USB 3.0 to Gigabit Adapter */ | 1456 | /* Sitecom USB 3.0 to Gigabit Adapter */ |
| 1431 | USB_DEVICE(0x0df6, 0x0072), | 1457 | USB_DEVICE(0x0df6, 0x0072), |
| 1432 | .driver_info = (unsigned long)&sitecom_info, | 1458 | .driver_info = (unsigned long)&sitecom_info, |
| @@ -1434,6 +1460,10 @@ static const struct usb_device_id products[] = { | |||
| 1434 | /* Samsung USB Ethernet Adapter */ | 1460 | /* Samsung USB Ethernet Adapter */ |
| 1435 | USB_DEVICE(0x04e8, 0xa100), | 1461 | USB_DEVICE(0x04e8, 0xa100), |
| 1436 | .driver_info = (unsigned long)&samsung_info, | 1462 | .driver_info = (unsigned long)&samsung_info, |
| 1463 | }, { | ||
| 1464 | /* Lenovo OneLinkDock Gigabit LAN */ | ||
| 1465 | USB_DEVICE(0x17ef, 0x304b), | ||
| 1466 | .driver_info = (unsigned long)&lenovo_info, | ||
| 1437 | }, | 1467 | }, |
| 1438 | { }, | 1468 | { }, |
| 1439 | }; | 1469 | }; |
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 42e176912c8e..bd363b27e854 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
| @@ -652,6 +652,13 @@ static const struct usb_device_id products[] = { | |||
| 652 | .driver_info = 0, | 652 | .driver_info = 0, |
| 653 | }, | 653 | }, |
| 654 | 654 | ||
| 655 | /* Samsung USB Ethernet Adapters */ | ||
| 656 | { | ||
| 657 | USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM, | ||
| 658 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), | ||
| 659 | .driver_info = 0, | ||
| 660 | }, | ||
| 661 | |||
| 655 | /* WHITELIST!!! | 662 | /* WHITELIST!!! |
| 656 | * | 663 | * |
| 657 | * CDC Ether uses two interfaces, not necessarily consecutive. | 664 | * CDC Ether uses two interfaces, not necessarily consecutive. |
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index dbff290ed0e4..d350d2795e10 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
| @@ -68,7 +68,6 @@ static struct usb_driver cdc_ncm_driver; | |||
| 68 | static int cdc_ncm_setup(struct usbnet *dev) | 68 | static int cdc_ncm_setup(struct usbnet *dev) |
| 69 | { | 69 | { |
| 70 | struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; | 70 | struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; |
| 71 | struct usb_cdc_ncm_ntb_parameters ncm_parm; | ||
| 72 | u32 val; | 71 | u32 val; |
| 73 | u8 flags; | 72 | u8 flags; |
| 74 | u8 iface_no; | 73 | u8 iface_no; |
| @@ -82,22 +81,22 @@ static int cdc_ncm_setup(struct usbnet *dev) | |||
| 82 | err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS, | 81 | err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS, |
| 83 | USB_TYPE_CLASS | USB_DIR_IN | 82 | USB_TYPE_CLASS | USB_DIR_IN |
| 84 | |USB_RECIP_INTERFACE, | 83 | |USB_RECIP_INTERFACE, |
| 85 | 0, iface_no, &ncm_parm, | 84 | 0, iface_no, &ctx->ncm_parm, |
| 86 | sizeof(ncm_parm)); | 85 | sizeof(ctx->ncm_parm)); |
| 87 | if (err < 0) { | 86 | if (err < 0) { |
| 88 | dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n"); | 87 | dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n"); |
| 89 | return err; /* GET_NTB_PARAMETERS is required */ | 88 | return err; /* GET_NTB_PARAMETERS is required */ |
| 90 | } | 89 | } |
| 91 | 90 | ||
| 92 | /* read correct set of parameters according to device mode */ | 91 | /* read correct set of parameters according to device mode */ |
| 93 | ctx->rx_max = le32_to_cpu(ncm_parm.dwNtbInMaxSize); | 92 | ctx->rx_max = le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize); |
| 94 | ctx->tx_max = le32_to_cpu(ncm_parm.dwNtbOutMaxSize); | 93 | ctx->tx_max = le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize); |
| 95 | ctx->tx_remainder = le16_to_cpu(ncm_parm.wNdpOutPayloadRemainder); | 94 | ctx->tx_remainder = le16_to_cpu(ctx->ncm_parm.wNdpOutPayloadRemainder); |
| 96 | ctx->tx_modulus = le16_to_cpu(ncm_parm.wNdpOutDivisor); | 95 | ctx->tx_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutDivisor); |
| 97 | ctx->tx_ndp_modulus = le16_to_cpu(ncm_parm.wNdpOutAlignment); | 96 | ctx->tx_ndp_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutAlignment); |
| 98 | /* devices prior to NCM Errata shall set this field to zero */ | 97 | /* devices prior to NCM Errata shall set this field to zero */ |
| 99 | ctx->tx_max_datagrams = le16_to_cpu(ncm_parm.wNtbOutMaxDatagrams); | 98 | ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams); |
| 100 | ntb_fmt_supported = le16_to_cpu(ncm_parm.bmNtbFormatsSupported); | 99 | ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported); |
| 101 | 100 | ||
| 102 | /* there are some minor differences in NCM and MBIM defaults */ | 101 | /* there are some minor differences in NCM and MBIM defaults */ |
| 103 | if (cdc_ncm_comm_intf_is_mbim(ctx->control->cur_altsetting)) { | 102 | if (cdc_ncm_comm_intf_is_mbim(ctx->control->cur_altsetting)) { |
| @@ -146,7 +145,7 @@ static int cdc_ncm_setup(struct usbnet *dev) | |||
| 146 | } | 145 | } |
| 147 | 146 | ||
| 148 | /* inform device about NTB input size changes */ | 147 | /* inform device about NTB input size changes */ |
| 149 | if (ctx->rx_max != le32_to_cpu(ncm_parm.dwNtbInMaxSize)) { | 148 | if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) { |
| 150 | __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); | 149 | __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); |
| 151 | 150 | ||
| 152 | err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE, | 151 | err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE, |
| @@ -162,14 +161,6 @@ static int cdc_ncm_setup(struct usbnet *dev) | |||
| 162 | dev_dbg(&dev->intf->dev, "Using default maximum transmit length=%d\n", | 161 | dev_dbg(&dev->intf->dev, "Using default maximum transmit length=%d\n", |
| 163 | CDC_NCM_NTB_MAX_SIZE_TX); | 162 | CDC_NCM_NTB_MAX_SIZE_TX); |
| 164 | ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX; | 163 | ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX; |
| 165 | |||
| 166 | /* Adding a pad byte here simplifies the handling in | ||
| 167 | * cdc_ncm_fill_tx_frame, by making tx_max always | ||
| 168 | * represent the real skb max size. | ||
| 169 | */ | ||
| 170 | if (ctx->tx_max % usb_maxpacket(dev->udev, dev->out, 1) == 0) | ||
| 171 | ctx->tx_max++; | ||
| 172 | |||
| 173 | } | 164 | } |
| 174 | 165 | ||
| 175 | /* | 166 | /* |
| @@ -439,6 +430,10 @@ advance: | |||
| 439 | goto error2; | 430 | goto error2; |
| 440 | } | 431 | } |
| 441 | 432 | ||
| 433 | /* initialize data interface */ | ||
| 434 | if (cdc_ncm_setup(dev)) | ||
| 435 | goto error2; | ||
| 436 | |||
| 442 | /* configure data interface */ | 437 | /* configure data interface */ |
| 443 | temp = usb_set_interface(dev->udev, iface_no, data_altsetting); | 438 | temp = usb_set_interface(dev->udev, iface_no, data_altsetting); |
| 444 | if (temp) { | 439 | if (temp) { |
| @@ -453,12 +448,6 @@ advance: | |||
| 453 | goto error2; | 448 | goto error2; |
| 454 | } | 449 | } |
| 455 | 450 | ||
| 456 | /* initialize data interface */ | ||
| 457 | if (cdc_ncm_setup(dev)) { | ||
| 458 | dev_dbg(&intf->dev, "cdc_ncm_setup() failed\n"); | ||
| 459 | goto error2; | ||
| 460 | } | ||
| 461 | |||
| 462 | usb_set_intfdata(ctx->data, dev); | 451 | usb_set_intfdata(ctx->data, dev); |
| 463 | usb_set_intfdata(ctx->control, dev); | 452 | usb_set_intfdata(ctx->control, dev); |
| 464 | 453 | ||
| @@ -475,6 +464,15 @@ advance: | |||
| 475 | dev->hard_mtu = ctx->tx_max; | 464 | dev->hard_mtu = ctx->tx_max; |
| 476 | dev->rx_urb_size = ctx->rx_max; | 465 | dev->rx_urb_size = ctx->rx_max; |
| 477 | 466 | ||
| 467 | /* cdc_ncm_setup will override dwNtbOutMaxSize if it is | ||
| 468 | * outside the sane range. Adding a pad byte here if necessary | ||
| 469 | * simplifies the handling in cdc_ncm_fill_tx_frame, making | ||
| 470 | * tx_max always represent the real skb max size. | ||
| 471 | */ | ||
| 472 | if (ctx->tx_max != le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) && | ||
| 473 | ctx->tx_max % usb_maxpacket(dev->udev, dev->out, 1) == 0) | ||
| 474 | ctx->tx_max++; | ||
| 475 | |||
| 478 | return 0; | 476 | return 0; |
| 479 | 477 | ||
| 480 | error2: | 478 | error2: |
diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c index e4a8a93fbaf7..1cc24e6f23e2 100644 --- a/drivers/net/usb/gl620a.c +++ b/drivers/net/usb/gl620a.c | |||
| @@ -84,6 +84,10 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 84 | u32 size; | 84 | u32 size; |
| 85 | u32 count; | 85 | u32 count; |
| 86 | 86 | ||
| 87 | /* This check is no longer done by usbnet */ | ||
| 88 | if (skb->len < dev->net->hard_header_len) | ||
| 89 | return 0; | ||
| 90 | |||
| 87 | header = (struct gl_header *) skb->data; | 91 | header = (struct gl_header *) skb->data; |
| 88 | 92 | ||
| 89 | // get the packet count of the received skb | 93 | // get the packet count of the received skb |
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 1a482344b3f5..660bd5ea9fc0 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
| @@ -1201,16 +1201,18 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) | |||
| 1201 | struct hso_serial *serial = urb->context; | 1201 | struct hso_serial *serial = urb->context; |
| 1202 | int status = urb->status; | 1202 | int status = urb->status; |
| 1203 | 1203 | ||
| 1204 | D4("\n--- Got serial_read_bulk callback %02x ---", status); | ||
| 1205 | |||
| 1204 | /* sanity check */ | 1206 | /* sanity check */ |
| 1205 | if (!serial) { | 1207 | if (!serial) { |
| 1206 | D1("serial == NULL"); | 1208 | D1("serial == NULL"); |
| 1207 | return; | 1209 | return; |
| 1208 | } else if (status) { | 1210 | } |
| 1211 | if (status) { | ||
| 1209 | handle_usb_error(status, __func__, serial->parent); | 1212 | handle_usb_error(status, __func__, serial->parent); |
| 1210 | return; | 1213 | return; |
| 1211 | } | 1214 | } |
| 1212 | 1215 | ||
| 1213 | D4("\n--- Got serial_read_bulk callback %02x ---", status); | ||
| 1214 | D1("Actual length = %d\n", urb->actual_length); | 1216 | D1("Actual length = %d\n", urb->actual_length); |
| 1215 | DUMP1(urb->transfer_buffer, urb->actual_length); | 1217 | DUMP1(urb->transfer_buffer, urb->actual_length); |
| 1216 | 1218 | ||
| @@ -1218,25 +1220,13 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) | |||
| 1218 | if (serial->port.count == 0) | 1220 | if (serial->port.count == 0) |
| 1219 | return; | 1221 | return; |
| 1220 | 1222 | ||
| 1221 | if (status == 0) { | 1223 | if (serial->parent->port_spec & HSO_INFO_CRC_BUG) |
| 1222 | if (serial->parent->port_spec & HSO_INFO_CRC_BUG) | 1224 | fix_crc_bug(urb, serial->in_endp->wMaxPacketSize); |
| 1223 | fix_crc_bug(urb, serial->in_endp->wMaxPacketSize); | 1225 | /* Valid data, handle RX data */ |
| 1224 | /* Valid data, handle RX data */ | 1226 | spin_lock(&serial->serial_lock); |
| 1225 | spin_lock(&serial->serial_lock); | 1227 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; |
| 1226 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; | 1228 | put_rxbuf_data_and_resubmit_bulk_urb(serial); |
| 1227 | put_rxbuf_data_and_resubmit_bulk_urb(serial); | 1229 | spin_unlock(&serial->serial_lock); |
| 1228 | spin_unlock(&serial->serial_lock); | ||
| 1229 | } else if (status == -ENOENT || status == -ECONNRESET) { | ||
| 1230 | /* Unlinked - check for throttled port. */ | ||
| 1231 | D2("Port %d, successfully unlinked urb", serial->minor); | ||
| 1232 | spin_lock(&serial->serial_lock); | ||
| 1233 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; | ||
| 1234 | hso_resubmit_rx_bulk_urb(serial, urb); | ||
| 1235 | spin_unlock(&serial->serial_lock); | ||
| 1236 | } else { | ||
| 1237 | D2("Port %d, status = %d for read urb", serial->minor, status); | ||
| 1238 | return; | ||
| 1239 | } | ||
| 1240 | } | 1230 | } |
| 1241 | 1231 | ||
| 1242 | /* | 1232 | /* |
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index a305a7b2dae6..82d844a8ebd0 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c | |||
| @@ -526,8 +526,9 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 526 | { | 526 | { |
| 527 | u8 status; | 527 | u8 status; |
| 528 | 528 | ||
| 529 | if (skb->len == 0) { | 529 | /* This check is no longer done by usbnet */ |
| 530 | dev_err(&dev->udev->dev, "unexpected empty rx frame\n"); | 530 | if (skb->len < dev->net->hard_header_len) { |
| 531 | dev_err(&dev->udev->dev, "unexpected tiny rx frame\n"); | ||
| 531 | return 0; | 532 | return 0; |
| 532 | } | 533 | } |
| 533 | 534 | ||
diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 0a85d9227775..4cbdb1307f3e 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c | |||
| @@ -364,6 +364,10 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 364 | struct nc_trailer *trailer; | 364 | struct nc_trailer *trailer; |
| 365 | u16 hdr_len, packet_len; | 365 | u16 hdr_len, packet_len; |
| 366 | 366 | ||
| 367 | /* This check is no longer done by usbnet */ | ||
| 368 | if (skb->len < dev->net->hard_header_len) | ||
| 369 | return 0; | ||
| 370 | |||
| 367 | if (!(skb->len & 0x01)) { | 371 | if (!(skb->len & 0x01)) { |
| 368 | netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n", | 372 | netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n", |
| 369 | skb->len, dev->net->hard_header_len, dev->hard_mtu, | 373 | skb->len, dev->net->hard_header_len, dev->hard_mtu, |
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 23bdd5b9274d..313cb6cd4848 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
| @@ -80,10 +80,10 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
| 80 | { | 80 | { |
| 81 | __be16 proto; | 81 | __be16 proto; |
| 82 | 82 | ||
| 83 | /* usbnet rx_complete guarantees that skb->len is at least | 83 | /* This check is no longer done by usbnet */ |
| 84 | * hard_header_len, so we can inspect the dest address without | 84 | if (skb->len < dev->net->hard_header_len) |
| 85 | * checking skb->len | 85 | return 0; |
| 86 | */ | 86 | |
| 87 | switch (skb->data[0] & 0xf0) { | 87 | switch (skb->data[0] & 0xf0) { |
| 88 | case 0x40: | 88 | case 0x40: |
| 89 | proto = htons(ETH_P_IP); | 89 | proto = htons(ETH_P_IP); |
| @@ -712,6 +712,7 @@ static const struct usb_device_id products[] = { | |||
| 712 | {QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, | 712 | {QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, |
| 713 | {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, | 713 | {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, |
| 714 | {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, | 714 | {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, |
| 715 | {QMI_FIXED_INTF(0x19d2, 0x1270, 5)}, /* ZTE MF667 */ | ||
| 715 | {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, | 716 | {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, |
| 716 | {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ | 717 | {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ |
| 717 | {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, | 718 | {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, |
| @@ -723,6 +724,7 @@ static const struct usb_device_id products[] = { | |||
| 723 | {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ | 724 | {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ |
| 724 | {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ | 725 | {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ |
| 725 | {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ | 726 | {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ |
| 727 | {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ | ||
| 726 | {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ | 728 | {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ |
| 727 | {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ | 729 | {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ |
| 728 | {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ | 730 | {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ |
| @@ -730,6 +732,7 @@ static const struct usb_device_id products[] = { | |||
| 730 | {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ | 732 | {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ |
| 731 | {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)}, /* Olivetti Olicard 200 */ | 733 | {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)}, /* Olivetti Olicard 200 */ |
| 732 | {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ | 734 | {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ |
| 735 | {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */ | ||
| 733 | 736 | ||
| 734 | /* 4. Gobi 1000 devices */ | 737 | /* 4. Gobi 1000 devices */ |
| 735 | {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ | 738 | {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ |
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index e8fac732c6f1..adb12f349a61 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
| @@ -449,9 +449,6 @@ enum rtl8152_flags { | |||
| 449 | #define MCU_TYPE_PLA 0x0100 | 449 | #define MCU_TYPE_PLA 0x0100 |
| 450 | #define MCU_TYPE_USB 0x0000 | 450 | #define MCU_TYPE_USB 0x0000 |
| 451 | 451 | ||
| 452 | #define REALTEK_USB_DEVICE(vend, prod) \ | ||
| 453 | USB_DEVICE_INTERFACE_CLASS(vend, prod, USB_CLASS_VENDOR_SPEC) | ||
| 454 | |||
| 455 | struct rx_desc { | 452 | struct rx_desc { |
| 456 | __le32 opts1; | 453 | __le32 opts1; |
| 457 | #define RX_LEN_MASK 0x7fff | 454 | #define RX_LEN_MASK 0x7fff |
| @@ -2273,22 +2270,21 @@ static int rtl8152_open(struct net_device *netdev) | |||
| 2273 | struct r8152 *tp = netdev_priv(netdev); | 2270 | struct r8152 *tp = netdev_priv(netdev); |
| 2274 | int res = 0; | 2271 | int res = 0; |
| 2275 | 2272 | ||
| 2273 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | ||
| 2274 | tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, | ||
| 2275 | DUPLEX_FULL); | ||
| 2276 | tp->speed = 0; | ||
| 2277 | netif_carrier_off(netdev); | ||
| 2278 | netif_start_queue(netdev); | ||
| 2279 | set_bit(WORK_ENABLE, &tp->flags); | ||
| 2276 | res = usb_submit_urb(tp->intr_urb, GFP_KERNEL); | 2280 | res = usb_submit_urb(tp->intr_urb, GFP_KERNEL); |
| 2277 | if (res) { | 2281 | if (res) { |
| 2278 | if (res == -ENODEV) | 2282 | if (res == -ENODEV) |
| 2279 | netif_device_detach(tp->netdev); | 2283 | netif_device_detach(tp->netdev); |
| 2280 | netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n", | 2284 | netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n", |
| 2281 | res); | 2285 | res); |
| 2282 | return res; | ||
| 2283 | } | 2286 | } |
| 2284 | 2287 | ||
| 2285 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | ||
| 2286 | tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, | ||
| 2287 | DUPLEX_FULL); | ||
| 2288 | tp->speed = 0; | ||
| 2289 | netif_carrier_off(netdev); | ||
| 2290 | netif_start_queue(netdev); | ||
| 2291 | set_bit(WORK_ENABLE, &tp->flags); | ||
| 2292 | 2288 | ||
| 2293 | return res; | 2289 | return res; |
| 2294 | } | 2290 | } |
| @@ -2298,8 +2294,8 @@ static int rtl8152_close(struct net_device *netdev) | |||
| 2298 | struct r8152 *tp = netdev_priv(netdev); | 2294 | struct r8152 *tp = netdev_priv(netdev); |
| 2299 | int res = 0; | 2295 | int res = 0; |
| 2300 | 2296 | ||
| 2301 | usb_kill_urb(tp->intr_urb); | ||
| 2302 | clear_bit(WORK_ENABLE, &tp->flags); | 2297 | clear_bit(WORK_ENABLE, &tp->flags); |
| 2298 | usb_kill_urb(tp->intr_urb); | ||
| 2303 | cancel_delayed_work_sync(&tp->schedule); | 2299 | cancel_delayed_work_sync(&tp->schedule); |
| 2304 | netif_stop_queue(netdev); | 2300 | netif_stop_queue(netdev); |
| 2305 | tasklet_disable(&tp->tl); | 2301 | tasklet_disable(&tp->tl); |
| @@ -2740,6 +2736,12 @@ static int rtl8152_probe(struct usb_interface *intf, | |||
| 2740 | struct net_device *netdev; | 2736 | struct net_device *netdev; |
| 2741 | int ret; | 2737 | int ret; |
| 2742 | 2738 | ||
| 2739 | if (udev->actconfig->desc.bConfigurationValue != 1) { | ||
| 2740 | usb_driver_set_configuration(udev, 1); | ||
| 2741 | return -ENODEV; | ||
| 2742 | } | ||
| 2743 | |||
| 2744 | usb_reset_device(udev); | ||
| 2743 | netdev = alloc_etherdev(sizeof(struct r8152)); | 2745 | netdev = alloc_etherdev(sizeof(struct r8152)); |
| 2744 | if (!netdev) { | 2746 | if (!netdev) { |
| 2745 | dev_err(&intf->dev, "Out of memory\n"); | 2747 | dev_err(&intf->dev, "Out of memory\n"); |
| @@ -2820,9 +2822,9 @@ static void rtl8152_disconnect(struct usb_interface *intf) | |||
| 2820 | 2822 | ||
| 2821 | /* table of devices that work with this driver */ | 2823 | /* table of devices that work with this driver */ |
| 2822 | static struct usb_device_id rtl8152_table[] = { | 2824 | static struct usb_device_id rtl8152_table[] = { |
| 2823 | {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)}, | 2825 | {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)}, |
| 2824 | {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)}, | 2826 | {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)}, |
| 2825 | {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)}, | 2827 | {USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)}, |
| 2826 | {} | 2828 | {} |
| 2827 | }; | 2829 | }; |
| 2828 | 2830 | ||
diff --git a/drivers/net/usb/r815x.c b/drivers/net/usb/r815x.c deleted file mode 100644 index f0a8791b7636..000000000000 --- a/drivers/net/usb/r815x.c +++ /dev/null | |||
| @@ -1,248 +0,0 @@ | |||
| 1 | #include <linux/module.h> | ||
| 2 | #include <linux/netdevice.h> | ||
| 3 | #include <linux/mii.h> | ||
| 4 | #include <linux/usb.h> | ||
| 5 | #include <linux/usb/cdc.h> | ||
| 6 | #include <linux/usb/usbnet.h> | ||
| 7 | |||
| 8 | #define RTL815x_REQT_READ 0xc0 | ||
| 9 | #define RTL815x_REQT_WRITE 0x40 | ||
| 10 | #define RTL815x_REQ_GET_REGS 0x05 | ||
| 11 | #define RTL815x_REQ_SET_REGS 0x05 | ||
| 12 | |||
| 13 | #define MCU_TYPE_PLA 0x0100 | ||
| 14 | #define OCP_BASE 0xe86c | ||
| 15 | #define BASE_MII 0xa400 | ||
| 16 | |||
| 17 | #define BYTE_EN_DWORD 0xff | ||
| 18 | #define BYTE_EN_WORD 0x33 | ||
| 19 | #define BYTE_EN_BYTE 0x11 | ||
| 20 | |||
| 21 | #define R815x_PHY_ID 32 | ||
| 22 | #define REALTEK_VENDOR_ID 0x0bda | ||
| 23 | |||
| 24 | |||
| 25 | static int pla_read_word(struct usb_device *udev, u16 index) | ||
| 26 | { | ||
| 27 | int ret; | ||
| 28 | u8 shift = index & 2; | ||
| 29 | __le32 *tmp; | ||
| 30 | |||
| 31 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
| 32 | if (!tmp) | ||
| 33 | return -ENOMEM; | ||
| 34 | |||
| 35 | index &= ~3; | ||
| 36 | |||
| 37 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 38 | RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, | ||
| 39 | index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); | ||
| 40 | if (ret < 0) | ||
| 41 | goto out2; | ||
| 42 | |||
| 43 | ret = __le32_to_cpu(*tmp); | ||
| 44 | ret >>= (shift * 8); | ||
| 45 | ret &= 0xffff; | ||
| 46 | |||
| 47 | out2: | ||
| 48 | kfree(tmp); | ||
| 49 | return ret; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int pla_write_word(struct usb_device *udev, u16 index, u32 data) | ||
| 53 | { | ||
| 54 | __le32 *tmp; | ||
| 55 | u32 mask = 0xffff; | ||
| 56 | u16 byen = BYTE_EN_WORD; | ||
| 57 | u8 shift = index & 2; | ||
| 58 | int ret; | ||
| 59 | |||
| 60 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
| 61 | if (!tmp) | ||
| 62 | return -ENOMEM; | ||
| 63 | |||
| 64 | data &= mask; | ||
| 65 | |||
| 66 | if (shift) { | ||
| 67 | byen <<= shift; | ||
| 68 | mask <<= (shift * 8); | ||
| 69 | data <<= (shift * 8); | ||
| 70 | index &= ~3; | ||
| 71 | } | ||
| 72 | |||
| 73 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 74 | RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, | ||
| 75 | index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); | ||
| 76 | if (ret < 0) | ||
| 77 | goto out3; | ||
| 78 | |||
| 79 | data |= __le32_to_cpu(*tmp) & ~mask; | ||
| 80 | *tmp = __cpu_to_le32(data); | ||
| 81 | |||
| 82 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 83 | RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, | ||
| 84 | index, MCU_TYPE_PLA | byen, tmp, sizeof(*tmp), | ||
| 85 | 500); | ||
| 86 | |||
| 87 | out3: | ||
| 88 | kfree(tmp); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int ocp_reg_read(struct usbnet *dev, u16 addr) | ||
| 93 | { | ||
| 94 | u16 ocp_base, ocp_index; | ||
| 95 | int ret; | ||
| 96 | |||
| 97 | ocp_base = addr & 0xf000; | ||
| 98 | ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); | ||
| 99 | if (ret < 0) | ||
| 100 | goto out; | ||
| 101 | |||
| 102 | ocp_index = (addr & 0x0fff) | 0xb000; | ||
| 103 | ret = pla_read_word(dev->udev, ocp_index); | ||
| 104 | |||
| 105 | out: | ||
| 106 | return ret; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int ocp_reg_write(struct usbnet *dev, u16 addr, u16 data) | ||
| 110 | { | ||
| 111 | u16 ocp_base, ocp_index; | ||
| 112 | int ret; | ||
| 113 | |||
| 114 | ocp_base = addr & 0xf000; | ||
| 115 | ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); | ||
| 116 | if (ret < 0) | ||
| 117 | goto out1; | ||
| 118 | |||
| 119 | ocp_index = (addr & 0x0fff) | 0xb000; | ||
| 120 | ret = pla_write_word(dev->udev, ocp_index, data); | ||
| 121 | |||
| 122 | out1: | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg) | ||
| 127 | { | ||
| 128 | struct usbnet *dev = netdev_priv(netdev); | ||
| 129 | int ret; | ||
| 130 | |||
| 131 | if (phy_id != R815x_PHY_ID) | ||
| 132 | return -EINVAL; | ||
| 133 | |||
| 134 | if (usb_autopm_get_interface(dev->intf) < 0) | ||
| 135 | return -ENODEV; | ||
| 136 | |||
| 137 | ret = ocp_reg_read(dev, BASE_MII + reg * 2); | ||
| 138 | |||
| 139 | usb_autopm_put_interface(dev->intf); | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | static | ||
| 144 | void r815x_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) | ||
| 145 | { | ||
| 146 | struct usbnet *dev = netdev_priv(netdev); | ||
| 147 | |||
| 148 | if (phy_id != R815x_PHY_ID) | ||
| 149 | return; | ||
| 150 | |||
| 151 | if (usb_autopm_get_interface(dev->intf) < 0) | ||
| 152 | return; | ||
| 153 | |||
| 154 | ocp_reg_write(dev, BASE_MII + reg * 2, val); | ||
| 155 | |||
| 156 | usb_autopm_put_interface(dev->intf); | ||
| 157 | } | ||
| 158 | |||
| 159 | static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) | ||
| 160 | { | ||
| 161 | int status; | ||
| 162 | |||
| 163 | status = usbnet_cdc_bind(dev, intf); | ||
| 164 | if (status < 0) | ||
| 165 | return status; | ||
| 166 | |||
| 167 | dev->mii.dev = dev->net; | ||
| 168 | dev->mii.mdio_read = r815x_mdio_read; | ||
| 169 | dev->mii.mdio_write = r815x_mdio_write; | ||
| 170 | dev->mii.phy_id_mask = 0x3f; | ||
| 171 | dev->mii.reg_num_mask = 0x1f; | ||
| 172 | dev->mii.phy_id = R815x_PHY_ID; | ||
| 173 | dev->mii.supports_gmii = 1; | ||
| 174 | |||
| 175 | return status; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) | ||
| 179 | { | ||
| 180 | int status; | ||
| 181 | |||
| 182 | status = usbnet_cdc_bind(dev, intf); | ||
| 183 | if (status < 0) | ||
| 184 | return status; | ||
| 185 | |||
| 186 | dev->mii.dev = dev->net; | ||
| 187 | dev->mii.mdio_read = r815x_mdio_read; | ||
| 188 | dev->mii.mdio_write = r815x_mdio_write; | ||
| 189 | dev->mii.phy_id_mask = 0x3f; | ||
| 190 | dev->mii.reg_num_mask = 0x1f; | ||
| 191 | dev->mii.phy_id = R815x_PHY_ID; | ||
| 192 | dev->mii.supports_gmii = 0; | ||
| 193 | |||
| 194 | return status; | ||
| 195 | } | ||
| 196 | |||
| 197 | static const struct driver_info r8152_info = { | ||
| 198 | .description = "RTL8152 ECM Device", | ||
| 199 | .flags = FLAG_ETHER | FLAG_POINTTOPOINT, | ||
| 200 | .bind = r8152_bind, | ||
| 201 | .unbind = usbnet_cdc_unbind, | ||
| 202 | .status = usbnet_cdc_status, | ||
| 203 | .manage_power = usbnet_manage_power, | ||
| 204 | }; | ||
| 205 | |||
| 206 | static const struct driver_info r8153_info = { | ||
| 207 | .description = "RTL8153 ECM Device", | ||
| 208 | .flags = FLAG_ETHER | FLAG_POINTTOPOINT, | ||
| 209 | .bind = r8153_bind, | ||
| 210 | .unbind = usbnet_cdc_unbind, | ||
| 211 | .status = usbnet_cdc_status, | ||
| 212 | .manage_power = usbnet_manage_power, | ||
| 213 | }; | ||
| 214 | |||
| 215 | static const struct usb_device_id products[] = { | ||
| 216 | { | ||
| 217 | USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, | ||
| 218 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), | ||
| 219 | .driver_info = (unsigned long) &r8152_info, | ||
| 220 | }, | ||
| 221 | |||
| 222 | { | ||
| 223 | USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, | ||
| 224 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), | ||
| 225 | .driver_info = (unsigned long) &r8153_info, | ||
| 226 | }, | ||
| 227 | |||
| 228 | { }, /* END */ | ||
| 229 | }; | ||
| 230 | MODULE_DEVICE_TABLE(usb, products); | ||
| 231 | |||
| 232 | static struct usb_driver r815x_driver = { | ||
| 233 | .name = "r815x", | ||
| 234 | .id_table = products, | ||
| 235 | .probe = usbnet_probe, | ||
| 236 | .disconnect = usbnet_disconnect, | ||
| 237 | .suspend = usbnet_suspend, | ||
| 238 | .resume = usbnet_resume, | ||
| 239 | .reset_resume = usbnet_resume, | ||
| 240 | .supports_autosuspend = 1, | ||
| 241 | .disable_hub_initiated_lpm = 1, | ||
| 242 | }; | ||
| 243 | |||
| 244 | module_usb_driver(r815x_driver); | ||
| 245 | |||
| 246 | MODULE_AUTHOR("Hayes Wang"); | ||
| 247 | MODULE_DESCRIPTION("Realtek USB ECM device"); | ||
| 248 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index a48bc0f20c1a..524a47a28120 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c | |||
| @@ -492,6 +492,10 @@ EXPORT_SYMBOL_GPL(rndis_unbind); | |||
| 492 | */ | 492 | */ |
| 493 | int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 493 | int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) |
| 494 | { | 494 | { |
| 495 | /* This check is no longer done by usbnet */ | ||
| 496 | if (skb->len < dev->net->hard_header_len) | ||
| 497 | return 0; | ||
| 498 | |||
| 495 | /* peripheral may have batched packets to us... */ | 499 | /* peripheral may have batched packets to us... */ |
| 496 | while (likely(skb->len)) { | 500 | while (likely(skb->len)) { |
| 497 | struct rndis_data_hdr *hdr = (void *)skb->data; | 501 | struct rndis_data_hdr *hdr = (void *)skb->data; |
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index f17b9e02dd34..d9e7892262fa 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c | |||
| @@ -2106,6 +2106,10 @@ static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, | |||
| 2106 | 2106 | ||
| 2107 | static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 2107 | static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) |
| 2108 | { | 2108 | { |
| 2109 | /* This check is no longer done by usbnet */ | ||
| 2110 | if (skb->len < dev->net->hard_header_len) | ||
| 2111 | return 0; | ||
| 2112 | |||
| 2109 | while (skb->len > 0) { | 2113 | while (skb->len > 0) { |
| 2110 | u32 rx_cmd_a, rx_cmd_b, align_count, size; | 2114 | u32 rx_cmd_a, rx_cmd_b, align_count, size; |
| 2111 | struct sk_buff *ax_skb; | 2115 | struct sk_buff *ax_skb; |
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 8dd54a0f7b29..424db65e4396 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c | |||
| @@ -1723,6 +1723,10 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb) | |||
| 1723 | 1723 | ||
| 1724 | static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 1724 | static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) |
| 1725 | { | 1725 | { |
| 1726 | /* This check is no longer done by usbnet */ | ||
| 1727 | if (skb->len < dev->net->hard_header_len) | ||
| 1728 | return 0; | ||
| 1729 | |||
| 1726 | while (skb->len > 0) { | 1730 | while (skb->len > 0) { |
| 1727 | u32 header, align_count; | 1731 | u32 header, align_count; |
| 1728 | struct sk_buff *ax_skb; | 1732 | struct sk_buff *ax_skb; |
diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c new file mode 100644 index 000000000000..b94a0fbb8b3b --- /dev/null +++ b/drivers/net/usb/sr9800.c | |||
| @@ -0,0 +1,874 @@ | |||
| 1 | /* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices | ||
| 2 | * | ||
| 3 | * Author : Liu Junliang <liujunliang_ljl@163.com> | ||
| 4 | * | ||
| 5 | * Based on asix_common.c, asix_devices.c | ||
| 6 | * | ||
| 7 | * This file is licensed under the terms of the GNU General Public License | ||
| 8 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 9 | * kind, whether express or implied.* | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/kmod.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/netdevice.h> | ||
| 16 | #include <linux/etherdevice.h> | ||
| 17 | #include <linux/ethtool.h> | ||
| 18 | #include <linux/workqueue.h> | ||
| 19 | #include <linux/mii.h> | ||
| 20 | #include <linux/usb.h> | ||
| 21 | #include <linux/crc32.h> | ||
| 22 | #include <linux/usb/usbnet.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/if_vlan.h> | ||
| 25 | |||
| 26 | #include "sr9800.h" | ||
| 27 | |||
| 28 | static int sr_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
| 29 | u16 size, void *data) | ||
| 30 | { | ||
| 31 | int err; | ||
| 32 | |||
| 33 | err = usbnet_read_cmd(dev, cmd, SR_REQ_RD_REG, value, index, | ||
| 34 | data, size); | ||
| 35 | if ((err != size) && (err >= 0)) | ||
| 36 | err = -EINVAL; | ||
| 37 | |||
| 38 | return err; | ||
| 39 | } | ||
| 40 | |||
| 41 | static int sr_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
| 42 | u16 size, void *data) | ||
| 43 | { | ||
| 44 | int err; | ||
| 45 | |||
| 46 | err = usbnet_write_cmd(dev, cmd, SR_REQ_WR_REG, value, index, | ||
| 47 | data, size); | ||
| 48 | if ((err != size) && (err >= 0)) | ||
| 49 | err = -EINVAL; | ||
| 50 | |||
| 51 | return err; | ||
| 52 | } | ||
| 53 | |||
| 54 | static void | ||
| 55 | sr_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
| 56 | u16 size, void *data) | ||
| 57 | { | ||
| 58 | usbnet_write_cmd_async(dev, cmd, SR_REQ_WR_REG, value, index, data, | ||
| 59 | size); | ||
| 60 | } | ||
| 61 | |||
| 62 | static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
| 63 | { | ||
| 64 | int offset = 0; | ||
| 65 | |||
| 66 | /* This check is no longer done by usbnet */ | ||
| 67 | if (skb->len < dev->net->hard_header_len) | ||
| 68 | return 0; | ||
| 69 | |||
| 70 | while (offset + sizeof(u32) < skb->len) { | ||
| 71 | struct sk_buff *sr_skb; | ||
| 72 | u16 size; | ||
| 73 | u32 header = get_unaligned_le32(skb->data + offset); | ||
| 74 | |||
| 75 | offset += sizeof(u32); | ||
| 76 | /* get the packet length */ | ||
| 77 | size = (u16) (header & 0x7ff); | ||
| 78 | if (size != ((~header >> 16) & 0x07ff)) { | ||
| 79 | netdev_err(dev->net, "%s : Bad Header Length\n", | ||
| 80 | __func__); | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || | ||
| 85 | (size + offset > skb->len)) { | ||
| 86 | netdev_err(dev->net, "%s : Bad RX Length %d\n", | ||
| 87 | __func__, size); | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | sr_skb = netdev_alloc_skb_ip_align(dev->net, size); | ||
| 91 | if (!sr_skb) | ||
| 92 | return 0; | ||
| 93 | |||
| 94 | skb_put(sr_skb, size); | ||
| 95 | memcpy(sr_skb->data, skb->data + offset, size); | ||
| 96 | usbnet_skb_return(dev, sr_skb); | ||
| 97 | |||
| 98 | offset += (size + 1) & 0xfffe; | ||
| 99 | } | ||
| 100 | |||
| 101 | if (skb->len != offset) { | ||
| 102 | netdev_err(dev->net, "%s : Bad SKB Length %d\n", __func__, | ||
| 103 | skb->len); | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | return 1; | ||
| 108 | } | ||
| 109 | |||
| 110 | static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | ||
| 111 | gfp_t flags) | ||
| 112 | { | ||
| 113 | int headroom = skb_headroom(skb); | ||
| 114 | int tailroom = skb_tailroom(skb); | ||
| 115 | u32 padbytes = 0xffff0000; | ||
| 116 | u32 packet_len; | ||
| 117 | int padlen; | ||
| 118 | |||
| 119 | padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4; | ||
| 120 | |||
| 121 | if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) { | ||
| 122 | if ((headroom < 4) || (tailroom < padlen)) { | ||
| 123 | skb->data = memmove(skb->head + 4, skb->data, | ||
| 124 | skb->len); | ||
| 125 | skb_set_tail_pointer(skb, skb->len); | ||
| 126 | } | ||
| 127 | } else { | ||
| 128 | struct sk_buff *skb2; | ||
| 129 | skb2 = skb_copy_expand(skb, 4, padlen, flags); | ||
| 130 | dev_kfree_skb_any(skb); | ||
| 131 | skb = skb2; | ||
| 132 | if (!skb) | ||
| 133 | return NULL; | ||
| 134 | } | ||
| 135 | |||
| 136 | skb_push(skb, 4); | ||
| 137 | packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); | ||
| 138 | cpu_to_le32s(&packet_len); | ||
| 139 | skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); | ||
| 140 | |||
| 141 | if (padlen) { | ||
| 142 | cpu_to_le32s(&padbytes); | ||
| 143 | memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); | ||
| 144 | skb_put(skb, sizeof(padbytes)); | ||
| 145 | } | ||
| 146 | |||
| 147 | return skb; | ||
| 148 | } | ||
| 149 | |||
| 150 | static void sr_status(struct usbnet *dev, struct urb *urb) | ||
| 151 | { | ||
| 152 | struct sr9800_int_data *event; | ||
| 153 | int link; | ||
| 154 | |||
| 155 | if (urb->actual_length < 8) | ||
| 156 | return; | ||
| 157 | |||
| 158 | event = urb->transfer_buffer; | ||
| 159 | link = event->link & 0x01; | ||
| 160 | if (netif_carrier_ok(dev->net) != link) { | ||
| 161 | usbnet_link_change(dev, link, 1); | ||
| 162 | netdev_dbg(dev->net, "Link Status is: %d\n", link); | ||
| 163 | } | ||
| 164 | |||
| 165 | return; | ||
| 166 | } | ||
| 167 | |||
| 168 | static inline int sr_set_sw_mii(struct usbnet *dev) | ||
| 169 | { | ||
| 170 | int ret; | ||
| 171 | |||
| 172 | ret = sr_write_cmd(dev, SR_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); | ||
| 173 | if (ret < 0) | ||
| 174 | netdev_err(dev->net, "Failed to enable software MII access\n"); | ||
| 175 | return ret; | ||
| 176 | } | ||
| 177 | |||
| 178 | static inline int sr_set_hw_mii(struct usbnet *dev) | ||
| 179 | { | ||
| 180 | int ret; | ||
| 181 | |||
| 182 | ret = sr_write_cmd(dev, SR_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); | ||
| 183 | if (ret < 0) | ||
| 184 | netdev_err(dev->net, "Failed to enable hardware MII access\n"); | ||
| 185 | return ret; | ||
| 186 | } | ||
| 187 | |||
| 188 | static inline int sr_get_phy_addr(struct usbnet *dev) | ||
| 189 | { | ||
| 190 | u8 buf[2]; | ||
| 191 | int ret; | ||
| 192 | |||
| 193 | ret = sr_read_cmd(dev, SR_CMD_READ_PHY_ID, 0, 0, 2, buf); | ||
| 194 | if (ret < 0) { | ||
| 195 | netdev_err(dev->net, "%s : Error reading PHYID register:%02x\n", | ||
| 196 | __func__, ret); | ||
| 197 | goto out; | ||
| 198 | } | ||
| 199 | netdev_dbg(dev->net, "%s : returning 0x%04x\n", __func__, | ||
| 200 | *((__le16 *)buf)); | ||
| 201 | |||
| 202 | ret = buf[1]; | ||
| 203 | |||
| 204 | out: | ||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int sr_sw_reset(struct usbnet *dev, u8 flags) | ||
| 209 | { | ||
| 210 | int ret; | ||
| 211 | |||
| 212 | ret = sr_write_cmd(dev, SR_CMD_SW_RESET, flags, 0, 0, NULL); | ||
| 213 | if (ret < 0) | ||
| 214 | netdev_err(dev->net, "Failed to send software reset:%02x\n", | ||
| 215 | ret); | ||
| 216 | |||
| 217 | return ret; | ||
| 218 | } | ||
| 219 | |||
| 220 | static u16 sr_read_rx_ctl(struct usbnet *dev) | ||
| 221 | { | ||
| 222 | __le16 v; | ||
| 223 | int ret; | ||
| 224 | |||
| 225 | ret = sr_read_cmd(dev, SR_CMD_READ_RX_CTL, 0, 0, 2, &v); | ||
| 226 | if (ret < 0) { | ||
| 227 | netdev_err(dev->net, "Error reading RX_CTL register:%02x\n", | ||
| 228 | ret); | ||
| 229 | goto out; | ||
| 230 | } | ||
| 231 | |||
| 232 | ret = le16_to_cpu(v); | ||
| 233 | out: | ||
| 234 | return ret; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int sr_write_rx_ctl(struct usbnet *dev, u16 mode) | ||
| 238 | { | ||
| 239 | int ret; | ||
| 240 | |||
| 241 | netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); | ||
| 242 | ret = sr_write_cmd(dev, SR_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); | ||
| 243 | if (ret < 0) | ||
| 244 | netdev_err(dev->net, | ||
| 245 | "Failed to write RX_CTL mode to 0x%04x:%02x\n", | ||
| 246 | mode, ret); | ||
| 247 | |||
| 248 | return ret; | ||
| 249 | } | ||
| 250 | |||
| 251 | static u16 sr_read_medium_status(struct usbnet *dev) | ||
| 252 | { | ||
| 253 | __le16 v; | ||
| 254 | int ret; | ||
| 255 | |||
| 256 | ret = sr_read_cmd(dev, SR_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); | ||
| 257 | if (ret < 0) { | ||
| 258 | netdev_err(dev->net, | ||
| 259 | "Error reading Medium Status register:%02x\n", ret); | ||
| 260 | return ret; /* TODO: callers not checking for error ret */ | ||
| 261 | } | ||
| 262 | |||
| 263 | return le16_to_cpu(v); | ||
| 264 | } | ||
| 265 | |||
| 266 | static int sr_write_medium_mode(struct usbnet *dev, u16 mode) | ||
| 267 | { | ||
| 268 | int ret; | ||
| 269 | |||
| 270 | netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); | ||
| 271 | ret = sr_write_cmd(dev, SR_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); | ||
| 272 | if (ret < 0) | ||
| 273 | netdev_err(dev->net, | ||
| 274 | "Failed to write Medium Mode mode to 0x%04x:%02x\n", | ||
| 275 | mode, ret); | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int sr_write_gpio(struct usbnet *dev, u16 value, int sleep) | ||
| 280 | { | ||
| 281 | int ret; | ||
| 282 | |||
| 283 | netdev_dbg(dev->net, "%s : value = 0x%04x\n", __func__, value); | ||
| 284 | ret = sr_write_cmd(dev, SR_CMD_WRITE_GPIOS, value, 0, 0, NULL); | ||
| 285 | if (ret < 0) | ||
| 286 | netdev_err(dev->net, "Failed to write GPIO value 0x%04x:%02x\n", | ||
| 287 | value, ret); | ||
| 288 | if (sleep) | ||
| 289 | msleep(sleep); | ||
| 290 | |||
| 291 | return ret; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* SR9800 have a 16-bit RX_CTL value */ | ||
| 295 | static void sr_set_multicast(struct net_device *net) | ||
| 296 | { | ||
| 297 | struct usbnet *dev = netdev_priv(net); | ||
| 298 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
| 299 | u16 rx_ctl = SR_DEFAULT_RX_CTL; | ||
| 300 | |||
| 301 | if (net->flags & IFF_PROMISC) { | ||
| 302 | rx_ctl |= SR_RX_CTL_PRO; | ||
| 303 | } else if (net->flags & IFF_ALLMULTI || | ||
| 304 | netdev_mc_count(net) > SR_MAX_MCAST) { | ||
| 305 | rx_ctl |= SR_RX_CTL_AMALL; | ||
| 306 | } else if (netdev_mc_empty(net)) { | ||
| 307 | /* just broadcast and directed */ | ||
| 308 | } else { | ||
| 309 | /* We use the 20 byte dev->data | ||
| 310 | * for our 8 byte filter buffer | ||
| 311 | * to avoid allocating memory that | ||
| 312 | * is tricky to free later | ||
| 313 | */ | ||
| 314 | struct netdev_hw_addr *ha; | ||
| 315 | u32 crc_bits; | ||
| 316 | |||
| 317 | memset(data->multi_filter, 0, SR_MCAST_FILTER_SIZE); | ||
| 318 | |||
| 319 | /* Build the multicast hash filter. */ | ||
| 320 | netdev_for_each_mc_addr(ha, net) { | ||
| 321 | crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; | ||
| 322 | data->multi_filter[crc_bits >> 3] |= | ||
| 323 | 1 << (crc_bits & 7); | ||
| 324 | } | ||
| 325 | |||
| 326 | sr_write_cmd_async(dev, SR_CMD_WRITE_MULTI_FILTER, 0, 0, | ||
| 327 | SR_MCAST_FILTER_SIZE, data->multi_filter); | ||
| 328 | |||
| 329 | rx_ctl |= SR_RX_CTL_AM; | ||
| 330 | } | ||
| 331 | |||
| 332 | sr_write_cmd_async(dev, SR_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); | ||
| 333 | } | ||
| 334 | |||
| 335 | static int sr_mdio_read(struct net_device *net, int phy_id, int loc) | ||
| 336 | { | ||
| 337 | struct usbnet *dev = netdev_priv(net); | ||
| 338 | __le16 res; | ||
| 339 | |||
| 340 | mutex_lock(&dev->phy_mutex); | ||
| 341 | sr_set_sw_mii(dev); | ||
| 342 | sr_read_cmd(dev, SR_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res); | ||
| 343 | sr_set_hw_mii(dev); | ||
| 344 | mutex_unlock(&dev->phy_mutex); | ||
| 345 | |||
| 346 | netdev_dbg(dev->net, | ||
| 347 | "%s : phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", __func__, | ||
| 348 | phy_id, loc, le16_to_cpu(res)); | ||
| 349 | |||
| 350 | return le16_to_cpu(res); | ||
| 351 | } | ||
| 352 | |||
| 353 | static void | ||
| 354 | sr_mdio_write(struct net_device *net, int phy_id, int loc, int val) | ||
| 355 | { | ||
| 356 | struct usbnet *dev = netdev_priv(net); | ||
| 357 | __le16 res = cpu_to_le16(val); | ||
| 358 | |||
| 359 | netdev_dbg(dev->net, | ||
| 360 | "%s : phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", __func__, | ||
| 361 | phy_id, loc, val); | ||
| 362 | mutex_lock(&dev->phy_mutex); | ||
| 363 | sr_set_sw_mii(dev); | ||
| 364 | sr_write_cmd(dev, SR_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); | ||
| 365 | sr_set_hw_mii(dev); | ||
| 366 | mutex_unlock(&dev->phy_mutex); | ||
| 367 | } | ||
| 368 | |||
| 369 | /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ | ||
| 370 | static u32 sr_get_phyid(struct usbnet *dev) | ||
| 371 | { | ||
| 372 | int phy_reg; | ||
| 373 | u32 phy_id; | ||
| 374 | int i; | ||
| 375 | |||
| 376 | /* Poll for the rare case the FW or phy isn't ready yet. */ | ||
| 377 | for (i = 0; i < 100; i++) { | ||
| 378 | phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); | ||
| 379 | if (phy_reg != 0 && phy_reg != 0xFFFF) | ||
| 380 | break; | ||
| 381 | mdelay(1); | ||
| 382 | } | ||
| 383 | |||
| 384 | if (phy_reg <= 0 || phy_reg == 0xFFFF) | ||
| 385 | return 0; | ||
| 386 | |||
| 387 | phy_id = (phy_reg & 0xffff) << 16; | ||
| 388 | |||
| 389 | phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2); | ||
| 390 | if (phy_reg < 0) | ||
| 391 | return 0; | ||
| 392 | |||
| 393 | phy_id |= (phy_reg & 0xffff); | ||
| 394 | |||
| 395 | return phy_id; | ||
| 396 | } | ||
| 397 | |||
| 398 | static void | ||
| 399 | sr_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
| 400 | { | ||
| 401 | struct usbnet *dev = netdev_priv(net); | ||
| 402 | u8 opt; | ||
| 403 | |||
| 404 | if (sr_read_cmd(dev, SR_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { | ||
| 405 | wolinfo->supported = 0; | ||
| 406 | wolinfo->wolopts = 0; | ||
| 407 | return; | ||
| 408 | } | ||
| 409 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | ||
| 410 | wolinfo->wolopts = 0; | ||
| 411 | if (opt & SR_MONITOR_LINK) | ||
| 412 | wolinfo->wolopts |= WAKE_PHY; | ||
| 413 | if (opt & SR_MONITOR_MAGIC) | ||
| 414 | wolinfo->wolopts |= WAKE_MAGIC; | ||
| 415 | } | ||
| 416 | |||
| 417 | static int | ||
| 418 | sr_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
| 419 | { | ||
| 420 | struct usbnet *dev = netdev_priv(net); | ||
| 421 | u8 opt = 0; | ||
| 422 | |||
| 423 | if (wolinfo->wolopts & WAKE_PHY) | ||
| 424 | opt |= SR_MONITOR_LINK; | ||
| 425 | if (wolinfo->wolopts & WAKE_MAGIC) | ||
| 426 | opt |= SR_MONITOR_MAGIC; | ||
| 427 | |||
| 428 | if (sr_write_cmd(dev, SR_CMD_WRITE_MONITOR_MODE, | ||
| 429 | opt, 0, 0, NULL) < 0) | ||
| 430 | return -EINVAL; | ||
| 431 | |||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | |||
| 435 | static int sr_get_eeprom_len(struct net_device *net) | ||
| 436 | { | ||
| 437 | struct usbnet *dev = netdev_priv(net); | ||
| 438 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
| 439 | |||
| 440 | return data->eeprom_len; | ||
| 441 | } | ||
| 442 | |||
| 443 | static int sr_get_eeprom(struct net_device *net, | ||
| 444 | struct ethtool_eeprom *eeprom, u8 *data) | ||
| 445 | { | ||
| 446 | struct usbnet *dev = netdev_priv(net); | ||
| 447 | __le16 *ebuf = (__le16 *)data; | ||
| 448 | int ret; | ||
| 449 | int i; | ||
| 450 | |||
| 451 | /* Crude hack to ensure that we don't overwrite memory | ||
| 452 | * if an odd length is supplied | ||
| 453 | */ | ||
| 454 | if (eeprom->len % 2) | ||
| 455 | return -EINVAL; | ||
| 456 | |||
| 457 | eeprom->magic = SR_EEPROM_MAGIC; | ||
| 458 | |||
| 459 | /* sr9800 returns 2 bytes from eeprom on read */ | ||
| 460 | for (i = 0; i < eeprom->len / 2; i++) { | ||
| 461 | ret = sr_read_cmd(dev, SR_CMD_READ_EEPROM, eeprom->offset + i, | ||
| 462 | 0, 2, &ebuf[i]); | ||
| 463 | if (ret < 0) | ||
| 464 | return -EINVAL; | ||
| 465 | } | ||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | static void sr_get_drvinfo(struct net_device *net, | ||
| 470 | struct ethtool_drvinfo *info) | ||
| 471 | { | ||
| 472 | struct usbnet *dev = netdev_priv(net); | ||
| 473 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
| 474 | |||
| 475 | /* Inherit standard device info */ | ||
| 476 | usbnet_get_drvinfo(net, info); | ||
| 477 | strncpy(info->driver, DRIVER_NAME, sizeof(info->driver)); | ||
| 478 | strncpy(info->version, DRIVER_VERSION, sizeof(info->version)); | ||
| 479 | info->eedump_len = data->eeprom_len; | ||
| 480 | } | ||
| 481 | |||
| 482 | static u32 sr_get_link(struct net_device *net) | ||
| 483 | { | ||
| 484 | struct usbnet *dev = netdev_priv(net); | ||
| 485 | |||
| 486 | return mii_link_ok(&dev->mii); | ||
| 487 | } | ||
| 488 | |||
| 489 | static int sr_ioctl(struct net_device *net, struct ifreq *rq, int cmd) | ||
| 490 | { | ||
| 491 | struct usbnet *dev = netdev_priv(net); | ||
| 492 | |||
| 493 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
| 494 | } | ||
| 495 | |||
| 496 | static int sr_set_mac_address(struct net_device *net, void *p) | ||
| 497 | { | ||
| 498 | struct usbnet *dev = netdev_priv(net); | ||
| 499 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
| 500 | struct sockaddr *addr = p; | ||
| 501 | |||
| 502 | if (netif_running(net)) | ||
| 503 | return -EBUSY; | ||
| 504 | if (!is_valid_ether_addr(addr->sa_data)) | ||
| 505 | return -EADDRNOTAVAIL; | ||
| 506 | |||
| 507 | memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); | ||
| 508 | |||
| 509 | /* We use the 20 byte dev->data | ||
| 510 | * for our 6 byte mac buffer | ||
| 511 | * to avoid allocating memory that | ||
| 512 | * is tricky to free later | ||
| 513 | */ | ||
| 514 | memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); | ||
| 515 | sr_write_cmd_async(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, | ||
| 516 | data->mac_addr); | ||
| 517 | |||
| 518 | return 0; | ||
| 519 | } | ||
| 520 | |||
| 521 | static const struct ethtool_ops sr9800_ethtool_ops = { | ||
| 522 | .get_drvinfo = sr_get_drvinfo, | ||
| 523 | .get_link = sr_get_link, | ||
| 524 | .get_msglevel = usbnet_get_msglevel, | ||
| 525 | .set_msglevel = usbnet_set_msglevel, | ||
| 526 | .get_wol = sr_get_wol, | ||
| 527 | .set_wol = sr_set_wol, | ||
| 528 | .get_eeprom_len = sr_get_eeprom_len, | ||
| 529 | .get_eeprom = sr_get_eeprom, | ||
| 530 | .get_settings = usbnet_get_settings, | ||
| 531 | .set_settings = usbnet_set_settings, | ||
| 532 | .nway_reset = usbnet_nway_reset, | ||
| 533 | }; | ||
| 534 | |||
| 535 | static int sr9800_link_reset(struct usbnet *dev) | ||
| 536 | { | ||
| 537 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; | ||
| 538 | u16 mode; | ||
| 539 | |||
| 540 | mii_check_media(&dev->mii, 1, 1); | ||
| 541 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
| 542 | mode = SR9800_MEDIUM_DEFAULT; | ||
| 543 | |||
| 544 | if (ethtool_cmd_speed(&ecmd) != SPEED_100) | ||
| 545 | mode &= ~SR_MEDIUM_PS; | ||
| 546 | |||
| 547 | if (ecmd.duplex != DUPLEX_FULL) | ||
| 548 | mode &= ~SR_MEDIUM_FD; | ||
| 549 | |||
| 550 | netdev_dbg(dev->net, "%s : speed: %u duplex: %d mode: 0x%04x\n", | ||
| 551 | __func__, ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); | ||
| 552 | |||
| 553 | sr_write_medium_mode(dev, mode); | ||
| 554 | |||
| 555 | return 0; | ||
| 556 | } | ||
| 557 | |||
| 558 | |||
| 559 | static int sr9800_set_default_mode(struct usbnet *dev) | ||
| 560 | { | ||
| 561 | u16 rx_ctl; | ||
| 562 | int ret; | ||
| 563 | |||
| 564 | sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | ||
| 565 | sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
| 566 | ADVERTISE_ALL | ADVERTISE_CSMA); | ||
| 567 | mii_nway_restart(&dev->mii); | ||
| 568 | |||
| 569 | ret = sr_write_medium_mode(dev, SR9800_MEDIUM_DEFAULT); | ||
| 570 | if (ret < 0) | ||
| 571 | goto out; | ||
| 572 | |||
| 573 | ret = sr_write_cmd(dev, SR_CMD_WRITE_IPG012, | ||
| 574 | SR9800_IPG0_DEFAULT | SR9800_IPG1_DEFAULT, | ||
| 575 | SR9800_IPG2_DEFAULT, 0, NULL); | ||
| 576 | if (ret < 0) { | ||
| 577 | netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret); | ||
| 578 | goto out; | ||
| 579 | } | ||
| 580 | |||
| 581 | /* Set RX_CTL to default values with 2k buffer, and enable cactus */ | ||
| 582 | ret = sr_write_rx_ctl(dev, SR_DEFAULT_RX_CTL); | ||
| 583 | if (ret < 0) | ||
| 584 | goto out; | ||
| 585 | |||
| 586 | rx_ctl = sr_read_rx_ctl(dev); | ||
| 587 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n", | ||
| 588 | rx_ctl); | ||
| 589 | |||
| 590 | rx_ctl = sr_read_medium_status(dev); | ||
| 591 | netdev_dbg(dev->net, "Medium Status:0x%04x after all initializations\n", | ||
| 592 | rx_ctl); | ||
| 593 | |||
| 594 | return 0; | ||
| 595 | out: | ||
| 596 | return ret; | ||
| 597 | } | ||
| 598 | |||
| 599 | static int sr9800_reset(struct usbnet *dev) | ||
| 600 | { | ||
| 601 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
| 602 | int ret, embd_phy; | ||
| 603 | u16 rx_ctl; | ||
| 604 | |||
| 605 | ret = sr_write_gpio(dev, | ||
| 606 | SR_GPIO_RSE | SR_GPIO_GPO_2 | SR_GPIO_GPO2EN, 5); | ||
| 607 | if (ret < 0) | ||
| 608 | goto out; | ||
| 609 | |||
| 610 | embd_phy = ((sr_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); | ||
| 611 | |||
| 612 | ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); | ||
| 613 | if (ret < 0) { | ||
| 614 | netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); | ||
| 615 | goto out; | ||
| 616 | } | ||
| 617 | |||
| 618 | ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_PRL); | ||
| 619 | if (ret < 0) | ||
| 620 | goto out; | ||
| 621 | |||
| 622 | msleep(150); | ||
| 623 | |||
| 624 | ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); | ||
| 625 | if (ret < 0) | ||
| 626 | goto out; | ||
| 627 | |||
| 628 | msleep(150); | ||
| 629 | |||
| 630 | if (embd_phy) { | ||
| 631 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
| 632 | if (ret < 0) | ||
| 633 | goto out; | ||
| 634 | } else { | ||
| 635 | ret = sr_sw_reset(dev, SR_SWRESET_PRTE); | ||
| 636 | if (ret < 0) | ||
| 637 | goto out; | ||
| 638 | } | ||
| 639 | |||
| 640 | msleep(150); | ||
| 641 | rx_ctl = sr_read_rx_ctl(dev); | ||
| 642 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); | ||
| 643 | ret = sr_write_rx_ctl(dev, 0x0000); | ||
| 644 | if (ret < 0) | ||
| 645 | goto out; | ||
| 646 | |||
| 647 | rx_ctl = sr_read_rx_ctl(dev); | ||
| 648 | netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); | ||
| 649 | |||
| 650 | ret = sr_sw_reset(dev, SR_SWRESET_PRL); | ||
| 651 | if (ret < 0) | ||
| 652 | goto out; | ||
| 653 | |||
| 654 | msleep(150); | ||
| 655 | |||
| 656 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL | SR_SWRESET_PRL); | ||
| 657 | if (ret < 0) | ||
| 658 | goto out; | ||
| 659 | |||
| 660 | msleep(150); | ||
| 661 | |||
| 662 | ret = sr9800_set_default_mode(dev); | ||
| 663 | if (ret < 0) | ||
| 664 | goto out; | ||
| 665 | |||
| 666 | /* Rewrite MAC address */ | ||
| 667 | memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN); | ||
| 668 | ret = sr_write_cmd(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, | ||
| 669 | data->mac_addr); | ||
| 670 | if (ret < 0) | ||
| 671 | goto out; | ||
| 672 | |||
| 673 | return 0; | ||
| 674 | |||
| 675 | out: | ||
| 676 | return ret; | ||
| 677 | } | ||
| 678 | |||
| 679 | static const struct net_device_ops sr9800_netdev_ops = { | ||
| 680 | .ndo_open = usbnet_open, | ||
| 681 | .ndo_stop = usbnet_stop, | ||
| 682 | .ndo_start_xmit = usbnet_start_xmit, | ||
| 683 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
| 684 | .ndo_change_mtu = usbnet_change_mtu, | ||
| 685 | .ndo_set_mac_address = sr_set_mac_address, | ||
| 686 | .ndo_validate_addr = eth_validate_addr, | ||
| 687 | .ndo_do_ioctl = sr_ioctl, | ||
| 688 | .ndo_set_rx_mode = sr_set_multicast, | ||
| 689 | }; | ||
| 690 | |||
| 691 | static int sr9800_phy_powerup(struct usbnet *dev) | ||
| 692 | { | ||
| 693 | int ret; | ||
| 694 | |||
| 695 | /* set the embedded Ethernet PHY in power-down state */ | ||
| 696 | ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_IPRL); | ||
| 697 | if (ret < 0) { | ||
| 698 | netdev_err(dev->net, "Failed to power down PHY : %d\n", ret); | ||
| 699 | return ret; | ||
| 700 | } | ||
| 701 | msleep(20); | ||
| 702 | |||
| 703 | /* set the embedded Ethernet PHY in power-up state */ | ||
| 704 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
| 705 | if (ret < 0) { | ||
| 706 | netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); | ||
| 707 | return ret; | ||
| 708 | } | ||
| 709 | msleep(600); | ||
| 710 | |||
| 711 | /* set the embedded Ethernet PHY in reset state */ | ||
| 712 | ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); | ||
| 713 | if (ret < 0) { | ||
| 714 | netdev_err(dev->net, "Failed to power up PHY: %d\n", ret); | ||
| 715 | return ret; | ||
| 716 | } | ||
| 717 | msleep(20); | ||
| 718 | |||
| 719 | /* set the embedded Ethernet PHY in power-up state */ | ||
| 720 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
| 721 | if (ret < 0) { | ||
| 722 | netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); | ||
| 723 | return ret; | ||
| 724 | } | ||
| 725 | |||
| 726 | return 0; | ||
| 727 | } | ||
| 728 | |||
| 729 | static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf) | ||
| 730 | { | ||
| 731 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
| 732 | u16 led01_mux, led23_mux; | ||
| 733 | int ret, embd_phy; | ||
| 734 | u32 phyid; | ||
| 735 | u16 rx_ctl; | ||
| 736 | |||
| 737 | data->eeprom_len = SR9800_EEPROM_LEN; | ||
| 738 | |||
| 739 | usbnet_get_endpoints(dev, intf); | ||
| 740 | |||
| 741 | /* LED Setting Rule : | ||
| 742 | * AABB:CCDD | ||
| 743 | * AA : MFA0(LED0) | ||
| 744 | * BB : MFA1(LED1) | ||
| 745 | * CC : MFA2(LED2), Reserved for SR9800 | ||
| 746 | * DD : MFA3(LED3), Reserved for SR9800 | ||
| 747 | */ | ||
| 748 | led01_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_LINK; | ||
| 749 | led23_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_TX_ACTIVE; | ||
| 750 | ret = sr_write_cmd(dev, SR_CMD_LED_MUX, led01_mux, led23_mux, 0, NULL); | ||
| 751 | if (ret < 0) { | ||
| 752 | netdev_err(dev->net, "set LINK LED failed : %d\n", ret); | ||
| 753 | goto out; | ||
| 754 | } | ||
| 755 | |||
| 756 | /* Get the MAC address */ | ||
| 757 | ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, | ||
| 758 | dev->net->dev_addr); | ||
| 759 | if (ret < 0) { | ||
| 760 | netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret); | ||
| 761 | return ret; | ||
| 762 | } | ||
| 763 | netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr); | ||
| 764 | |||
| 765 | /* Initialize MII structure */ | ||
| 766 | dev->mii.dev = dev->net; | ||
| 767 | dev->mii.mdio_read = sr_mdio_read; | ||
| 768 | dev->mii.mdio_write = sr_mdio_write; | ||
| 769 | dev->mii.phy_id_mask = 0x1f; | ||
| 770 | dev->mii.reg_num_mask = 0x1f; | ||
| 771 | dev->mii.phy_id = sr_get_phy_addr(dev); | ||
| 772 | |||
| 773 | dev->net->netdev_ops = &sr9800_netdev_ops; | ||
| 774 | dev->net->ethtool_ops = &sr9800_ethtool_ops; | ||
| 775 | |||
| 776 | embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); | ||
| 777 | /* Reset the PHY to normal operation mode */ | ||
| 778 | ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); | ||
| 779 | if (ret < 0) { | ||
| 780 | netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); | ||
| 781 | return ret; | ||
| 782 | } | ||
| 783 | |||
| 784 | /* Init PHY routine */ | ||
| 785 | ret = sr9800_phy_powerup(dev); | ||
| 786 | if (ret < 0) | ||
| 787 | goto out; | ||
| 788 | |||
| 789 | rx_ctl = sr_read_rx_ctl(dev); | ||
| 790 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); | ||
| 791 | ret = sr_write_rx_ctl(dev, 0x0000); | ||
| 792 | if (ret < 0) | ||
| 793 | goto out; | ||
| 794 | |||
| 795 | rx_ctl = sr_read_rx_ctl(dev); | ||
| 796 | netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); | ||
| 797 | |||
| 798 | /* Read PHYID register *AFTER* the PHY was reset properly */ | ||
| 799 | phyid = sr_get_phyid(dev); | ||
| 800 | netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid); | ||
| 801 | |||
| 802 | /* medium mode setting */ | ||
| 803 | ret = sr9800_set_default_mode(dev); | ||
| 804 | if (ret < 0) | ||
| 805 | goto out; | ||
| 806 | |||
| 807 | if (dev->udev->speed == USB_SPEED_HIGH) { | ||
| 808 | ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, | ||
| 809 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].byte_cnt, | ||
| 810 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].threshold, | ||
| 811 | 0, NULL); | ||
| 812 | if (ret < 0) { | ||
| 813 | netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); | ||
| 814 | goto out; | ||
| 815 | } | ||
| 816 | dev->rx_urb_size = | ||
| 817 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].size; | ||
| 818 | } else { | ||
| 819 | ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, | ||
| 820 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].byte_cnt, | ||
| 821 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].threshold, | ||
| 822 | 0, NULL); | ||
| 823 | if (ret < 0) { | ||
| 824 | netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); | ||
| 825 | goto out; | ||
| 826 | } | ||
| 827 | dev->rx_urb_size = | ||
| 828 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size; | ||
| 829 | } | ||
| 830 | netdev_dbg(dev->net, "%s : setting rx_urb_size with : %zu\n", __func__, | ||
| 831 | dev->rx_urb_size); | ||
| 832 | return 0; | ||
| 833 | |||
| 834 | out: | ||
| 835 | return ret; | ||
| 836 | } | ||
| 837 | |||
| 838 | static const struct driver_info sr9800_driver_info = { | ||
| 839 | .description = "CoreChip SR9800 USB 2.0 Ethernet", | ||
| 840 | .bind = sr9800_bind, | ||
| 841 | .status = sr_status, | ||
| 842 | .link_reset = sr9800_link_reset, | ||
| 843 | .reset = sr9800_reset, | ||
| 844 | .flags = DRIVER_FLAG, | ||
| 845 | .rx_fixup = sr_rx_fixup, | ||
| 846 | .tx_fixup = sr_tx_fixup, | ||
| 847 | }; | ||
| 848 | |||
| 849 | static const struct usb_device_id products[] = { | ||
| 850 | { | ||
| 851 | USB_DEVICE(0x0fe6, 0x9800), /* SR9800 Device */ | ||
| 852 | .driver_info = (unsigned long) &sr9800_driver_info, | ||
| 853 | }, | ||
| 854 | {}, /* END */ | ||
| 855 | }; | ||
| 856 | |||
| 857 | MODULE_DEVICE_TABLE(usb, products); | ||
| 858 | |||
| 859 | static struct usb_driver sr_driver = { | ||
| 860 | .name = DRIVER_NAME, | ||
| 861 | .id_table = products, | ||
| 862 | .probe = usbnet_probe, | ||
| 863 | .suspend = usbnet_suspend, | ||
| 864 | .resume = usbnet_resume, | ||
| 865 | .disconnect = usbnet_disconnect, | ||
| 866 | .supports_autosuspend = 1, | ||
| 867 | }; | ||
| 868 | |||
| 869 | module_usb_driver(sr_driver); | ||
| 870 | |||
| 871 | MODULE_AUTHOR("Liu Junliang <liujunliang_ljl@163.com"); | ||
| 872 | MODULE_VERSION(DRIVER_VERSION); | ||
| 873 | MODULE_DESCRIPTION("SR9800 USB 2.0 USB2NET Dev : http://www.corechip-sz.com"); | ||
| 874 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/sr9800.h b/drivers/net/usb/sr9800.h new file mode 100644 index 000000000000..18f670251275 --- /dev/null +++ b/drivers/net/usb/sr9800.h | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | /* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices | ||
| 2 | * | ||
| 3 | * Author : Liu Junliang <liujunliang_ljl@163.com> | ||
| 4 | * | ||
| 5 | * This file is licensed under the terms of the GNU General Public License | ||
| 6 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 7 | * kind, whether express or implied. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef _SR9800_H | ||
| 11 | #define _SR9800_H | ||
| 12 | |||
| 13 | /* SR9800 spec. command table on Linux Platform */ | ||
| 14 | |||
| 15 | /* command : Software Station Management Control Reg */ | ||
| 16 | #define SR_CMD_SET_SW_MII 0x06 | ||
| 17 | /* command : PHY Read Reg */ | ||
| 18 | #define SR_CMD_READ_MII_REG 0x07 | ||
| 19 | /* command : PHY Write Reg */ | ||
| 20 | #define SR_CMD_WRITE_MII_REG 0x08 | ||
| 21 | /* command : Hardware Station Management Control Reg */ | ||
| 22 | #define SR_CMD_SET_HW_MII 0x0a | ||
| 23 | /* command : SROM Read Reg */ | ||
| 24 | #define SR_CMD_READ_EEPROM 0x0b | ||
| 25 | /* command : SROM Write Reg */ | ||
| 26 | #define SR_CMD_WRITE_EEPROM 0x0c | ||
| 27 | /* command : SROM Write Enable Reg */ | ||
| 28 | #define SR_CMD_WRITE_ENABLE 0x0d | ||
| 29 | /* command : SROM Write Disable Reg */ | ||
| 30 | #define SR_CMD_WRITE_DISABLE 0x0e | ||
| 31 | /* command : RX Control Read Reg */ | ||
| 32 | #define SR_CMD_READ_RX_CTL 0x0f | ||
| 33 | #define SR_RX_CTL_PRO (1 << 0) | ||
| 34 | #define SR_RX_CTL_AMALL (1 << 1) | ||
| 35 | #define SR_RX_CTL_SEP (1 << 2) | ||
| 36 | #define SR_RX_CTL_AB (1 << 3) | ||
| 37 | #define SR_RX_CTL_AM (1 << 4) | ||
| 38 | #define SR_RX_CTL_AP (1 << 5) | ||
| 39 | #define SR_RX_CTL_ARP (1 << 6) | ||
| 40 | #define SR_RX_CTL_SO (1 << 7) | ||
| 41 | #define SR_RX_CTL_RH1M (1 << 8) | ||
| 42 | #define SR_RX_CTL_RH2M (1 << 9) | ||
| 43 | #define SR_RX_CTL_RH3M (1 << 10) | ||
| 44 | /* command : RX Control Write Reg */ | ||
| 45 | #define SR_CMD_WRITE_RX_CTL 0x10 | ||
| 46 | /* command : IPG0/IPG1/IPG2 Control Read Reg */ | ||
| 47 | #define SR_CMD_READ_IPG012 0x11 | ||
| 48 | /* command : IPG0/IPG1/IPG2 Control Write Reg */ | ||
| 49 | #define SR_CMD_WRITE_IPG012 0x12 | ||
| 50 | /* command : Node ID Read Reg */ | ||
| 51 | #define SR_CMD_READ_NODE_ID 0x13 | ||
| 52 | /* command : Node ID Write Reg */ | ||
| 53 | #define SR_CMD_WRITE_NODE_ID 0x14 | ||
| 54 | /* command : Multicast Filter Array Read Reg */ | ||
| 55 | #define SR_CMD_READ_MULTI_FILTER 0x15 | ||
| 56 | /* command : Multicast Filter Array Write Reg */ | ||
| 57 | #define SR_CMD_WRITE_MULTI_FILTER 0x16 | ||
| 58 | /* command : Eth/HomePNA PHY Address Reg */ | ||
| 59 | #define SR_CMD_READ_PHY_ID 0x19 | ||
| 60 | /* command : Medium Status Read Reg */ | ||
| 61 | #define SR_CMD_READ_MEDIUM_STATUS 0x1a | ||
| 62 | #define SR_MONITOR_LINK (1 << 1) | ||
| 63 | #define SR_MONITOR_MAGIC (1 << 2) | ||
| 64 | #define SR_MONITOR_HSFS (1 << 4) | ||
| 65 | /* command : Medium Status Write Reg */ | ||
| 66 | #define SR_CMD_WRITE_MEDIUM_MODE 0x1b | ||
| 67 | #define SR_MEDIUM_GM (1 << 0) | ||
| 68 | #define SR_MEDIUM_FD (1 << 1) | ||
| 69 | #define SR_MEDIUM_AC (1 << 2) | ||
| 70 | #define SR_MEDIUM_ENCK (1 << 3) | ||
| 71 | #define SR_MEDIUM_RFC (1 << 4) | ||
| 72 | #define SR_MEDIUM_TFC (1 << 5) | ||
| 73 | #define SR_MEDIUM_JFE (1 << 6) | ||
| 74 | #define SR_MEDIUM_PF (1 << 7) | ||
| 75 | #define SR_MEDIUM_RE (1 << 8) | ||
| 76 | #define SR_MEDIUM_PS (1 << 9) | ||
| 77 | #define SR_MEDIUM_RSV (1 << 10) | ||
| 78 | #define SR_MEDIUM_SBP (1 << 11) | ||
| 79 | #define SR_MEDIUM_SM (1 << 12) | ||
| 80 | /* command : Monitor Mode Status Read Reg */ | ||
| 81 | #define SR_CMD_READ_MONITOR_MODE 0x1c | ||
| 82 | /* command : Monitor Mode Status Write Reg */ | ||
| 83 | #define SR_CMD_WRITE_MONITOR_MODE 0x1d | ||
| 84 | /* command : GPIO Status Read Reg */ | ||
| 85 | #define SR_CMD_READ_GPIOS 0x1e | ||
| 86 | #define SR_GPIO_GPO0EN (1 << 0) /* GPIO0 Output enable */ | ||
| 87 | #define SR_GPIO_GPO_0 (1 << 1) /* GPIO0 Output value */ | ||
| 88 | #define SR_GPIO_GPO1EN (1 << 2) /* GPIO1 Output enable */ | ||
| 89 | #define SR_GPIO_GPO_1 (1 << 3) /* GPIO1 Output value */ | ||
| 90 | #define SR_GPIO_GPO2EN (1 << 4) /* GPIO2 Output enable */ | ||
| 91 | #define SR_GPIO_GPO_2 (1 << 5) /* GPIO2 Output value */ | ||
| 92 | #define SR_GPIO_RESERVED (1 << 6) /* Reserved */ | ||
| 93 | #define SR_GPIO_RSE (1 << 7) /* Reload serial EEPROM */ | ||
| 94 | /* command : GPIO Status Write Reg */ | ||
| 95 | #define SR_CMD_WRITE_GPIOS 0x1f | ||
| 96 | /* command : Eth PHY Power and Reset Control Reg */ | ||
| 97 | #define SR_CMD_SW_RESET 0x20 | ||
| 98 | #define SR_SWRESET_CLEAR 0x00 | ||
| 99 | #define SR_SWRESET_RR (1 << 0) | ||
| 100 | #define SR_SWRESET_RT (1 << 1) | ||
| 101 | #define SR_SWRESET_PRTE (1 << 2) | ||
| 102 | #define SR_SWRESET_PRL (1 << 3) | ||
| 103 | #define SR_SWRESET_BZ (1 << 4) | ||
| 104 | #define SR_SWRESET_IPRL (1 << 5) | ||
| 105 | #define SR_SWRESET_IPPD (1 << 6) | ||
| 106 | /* command : Software Interface Selection Status Read Reg */ | ||
| 107 | #define SR_CMD_SW_PHY_STATUS 0x21 | ||
| 108 | /* command : Software Interface Selection Status Write Reg */ | ||
| 109 | #define SR_CMD_SW_PHY_SELECT 0x22 | ||
| 110 | /* command : BULK in Buffer Size Reg */ | ||
| 111 | #define SR_CMD_BULKIN_SIZE 0x2A | ||
| 112 | /* command : LED_MUX Control Reg */ | ||
| 113 | #define SR_CMD_LED_MUX 0x70 | ||
| 114 | #define SR_LED_MUX_TX_ACTIVE (1 << 0) | ||
| 115 | #define SR_LED_MUX_RX_ACTIVE (1 << 1) | ||
| 116 | #define SR_LED_MUX_COLLISION (1 << 2) | ||
| 117 | #define SR_LED_MUX_DUP_COL (1 << 3) | ||
| 118 | #define SR_LED_MUX_DUP (1 << 4) | ||
| 119 | #define SR_LED_MUX_SPEED (1 << 5) | ||
| 120 | #define SR_LED_MUX_LINK_ACTIVE (1 << 6) | ||
| 121 | #define SR_LED_MUX_LINK (1 << 7) | ||
| 122 | |||
| 123 | /* Register Access Flags */ | ||
| 124 | #define SR_REQ_RD_REG (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE) | ||
| 125 | #define SR_REQ_WR_REG (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) | ||
| 126 | |||
| 127 | /* Multicast Filter Array size & Max Number */ | ||
| 128 | #define SR_MCAST_FILTER_SIZE 8 | ||
| 129 | #define SR_MAX_MCAST 64 | ||
| 130 | |||
| 131 | /* IPG0/1/2 Default Value */ | ||
| 132 | #define SR9800_IPG0_DEFAULT 0x15 | ||
| 133 | #define SR9800_IPG1_DEFAULT 0x0c | ||
| 134 | #define SR9800_IPG2_DEFAULT 0x12 | ||
| 135 | |||
| 136 | /* Medium Status Default Mode */ | ||
| 137 | #define SR9800_MEDIUM_DEFAULT \ | ||
| 138 | (SR_MEDIUM_FD | SR_MEDIUM_RFC | \ | ||
| 139 | SR_MEDIUM_TFC | SR_MEDIUM_PS | \ | ||
| 140 | SR_MEDIUM_AC | SR_MEDIUM_RE) | ||
| 141 | |||
| 142 | /* RX Control Default Setting */ | ||
| 143 | #define SR_DEFAULT_RX_CTL \ | ||
| 144 | (SR_RX_CTL_SO | SR_RX_CTL_AB | SR_RX_CTL_RH1M) | ||
| 145 | |||
| 146 | /* EEPROM Magic Number & EEPROM Size */ | ||
| 147 | #define SR_EEPROM_MAGIC 0xdeadbeef | ||
| 148 | #define SR9800_EEPROM_LEN 0xff | ||
| 149 | |||
| 150 | /* SR9800 Driver Version and Driver Name */ | ||
| 151 | #define DRIVER_VERSION "11-Nov-2013" | ||
| 152 | #define DRIVER_NAME "CoreChips" | ||
| 153 | #define DRIVER_FLAG \ | ||
| 154 | (FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET) | ||
| 155 | |||
| 156 | /* SR9800 BULKIN Buffer Size */ | ||
| 157 | #define SR9800_MAX_BULKIN_2K 0 | ||
| 158 | #define SR9800_MAX_BULKIN_4K 1 | ||
| 159 | #define SR9800_MAX_BULKIN_6K 2 | ||
| 160 | #define SR9800_MAX_BULKIN_8K 3 | ||
| 161 | #define SR9800_MAX_BULKIN_16K 4 | ||
| 162 | #define SR9800_MAX_BULKIN_20K 5 | ||
| 163 | #define SR9800_MAX_BULKIN_24K 6 | ||
| 164 | #define SR9800_MAX_BULKIN_32K 7 | ||
| 165 | |||
| 166 | struct {unsigned short size, byte_cnt, threshold; } SR9800_BULKIN_SIZE[] = { | ||
| 167 | /* 2k */ | ||
| 168 | {2048, 0x8000, 0x8001}, | ||
| 169 | /* 4k */ | ||
| 170 | {4096, 0x8100, 0x8147}, | ||
| 171 | /* 6k */ | ||
| 172 | {6144, 0x8200, 0x81EB}, | ||
| 173 | /* 8k */ | ||
| 174 | {8192, 0x8300, 0x83D7}, | ||
| 175 | /* 16 */ | ||
| 176 | {16384, 0x8400, 0x851E}, | ||
| 177 | /* 20k */ | ||
| 178 | {20480, 0x8500, 0x8666}, | ||
| 179 | /* 24k */ | ||
| 180 | {24576, 0x8600, 0x87AE}, | ||
| 181 | /* 32k */ | ||
| 182 | {32768, 0x8700, 0x8A3D}, | ||
| 183 | }; | ||
| 184 | |||
| 185 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ | ||
| 186 | struct sr_data { | ||
| 187 | u8 multi_filter[SR_MCAST_FILTER_SIZE]; | ||
| 188 | u8 mac_addr[ETH_ALEN]; | ||
| 189 | u8 phymode; | ||
| 190 | u8 ledmode; | ||
| 191 | u8 eeprom_len; | ||
| 192 | }; | ||
| 193 | |||
| 194 | struct sr9800_int_data { | ||
| 195 | __le16 res1; | ||
| 196 | u8 link; | ||
| 197 | __le16 res2; | ||
| 198 | u8 status; | ||
| 199 | __le16 res3; | ||
| 200 | } __packed; | ||
| 201 | |||
| 202 | #endif /* _SR9800_H */ | ||
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 4671da755e7b..dd10d5817d2a 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -542,17 +542,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) | |||
| 542 | } | 542 | } |
| 543 | // else network stack removes extra byte if we forced a short packet | 543 | // else network stack removes extra byte if we forced a short packet |
| 544 | 544 | ||
| 545 | if (skb->len) { | 545 | /* all data was already cloned from skb inside the driver */ |
| 546 | /* all data was already cloned from skb inside the driver */ | 546 | if (dev->driver_info->flags & FLAG_MULTI_PACKET) |
| 547 | if (dev->driver_info->flags & FLAG_MULTI_PACKET) | 547 | goto done; |
| 548 | dev_kfree_skb_any(skb); | 548 | |
| 549 | else | 549 | if (skb->len < ETH_HLEN) { |
| 550 | usbnet_skb_return(dev, skb); | 550 | dev->net->stats.rx_errors++; |
| 551 | dev->net->stats.rx_length_errors++; | ||
| 552 | netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len); | ||
| 553 | } else { | ||
| 554 | usbnet_skb_return(dev, skb); | ||
| 551 | return; | 555 | return; |
| 552 | } | 556 | } |
| 553 | 557 | ||
| 554 | netif_dbg(dev, rx_err, dev->net, "drop\n"); | ||
| 555 | dev->net->stats.rx_errors++; | ||
| 556 | done: | 558 | done: |
| 557 | skb_queue_tail(&dev->done, skb); | 559 | skb_queue_tail(&dev->done, skb); |
| 558 | } | 560 | } |
| @@ -574,13 +576,6 @@ static void rx_complete (struct urb *urb) | |||
| 574 | switch (urb_status) { | 576 | switch (urb_status) { |
| 575 | /* success */ | 577 | /* success */ |
| 576 | case 0: | 578 | case 0: |
| 577 | if (skb->len < dev->net->hard_header_len) { | ||
| 578 | state = rx_cleanup; | ||
| 579 | dev->net->stats.rx_errors++; | ||
| 580 | dev->net->stats.rx_length_errors++; | ||
| 581 | netif_dbg(dev, rx_err, dev->net, | ||
| 582 | "rx length %d\n", skb->len); | ||
| 583 | } | ||
| 584 | break; | 579 | break; |
| 585 | 580 | ||
| 586 | /* stalls need manual reset. this is rare ... except that | 581 | /* stalls need manual reset. this is rare ... except that |
