diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-11 15:05:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-11 15:05:55 -0500 |
commit | 16e5a2ed5920f511666a8714f43987bb0e2ad751 (patch) | |
tree | 318c36ed6e45733b9ef0e0d9c498df99d40eab93 /drivers/net/usb | |
parent | 6792dfe383dd20ed270da198aa0676bac47245b4 (diff) | |
parent | 20e7c4e80dcd01dad5e6c8b32455228b8fe9c619 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking updates from David Miller:
1) Fix flexcan build on big endian, from Arnd Bergmann
2) Correctly attach cpsw to GPIO bitbang MDIO drive, from Stefan Roese
3) udp_add_offload has to use GFP_ATOMIC since it can be invoked from
non-sleepable contexts. From Or Gerlitz
4) vxlan_gro_receive() does not iterate over all possible flows
properly, fix also from Or Gerlitz
5) CAN core doesn't use a proper SKB destructor when it hooks up
sockets to SKBs. Fix from Oliver Hartkopp
6) ip_tunnel_xmit() can use an uninitialized route pointer, fix from
Eric Dumazet
7) Fix address family assignment in IPVS, from Michal Kubecek
8) Fix ath9k build on ARM, from Sujith Manoharan
9) Make sure fail_over_mac only applies for the correct bonding modes,
from Ding Tianhong
10) The udp offload code doesn't use RCU correctly, from Shlomo Pongratz
11) Handle gigabit features properly in generic PHY code, from Florian
Fainelli
12) Don't blindly invoke link operations in
rtnl_link_get_slave_info_data_size, they are optional. Fix from
Fernando Luis Vazquez Cao
13) Add USB IDs for Netgear Aircard 340U, from Bjørn Mork
14) Handle netlink packet padding properly in openvswitch, from Thomas
Graf
15) Fix oops when deleting chains in nf_tables, from Patrick McHardy
16) Fix RX stalls in xen-netback driver, from Zoltan Kiss
17) Fix deadlock in mac80211 stack, from Emmanuel Grumbach
18) inet_nlmsg_size() forgets to consider ifa_cacheinfo, fix from Geert
Uytterhoeven
19) tg3_change_mtu() can deadlock, fix from Nithin Sujir
20) Fix regression in setting SCTP local source addresses on accepted
sockets, caused by some generic ipv6 socket changes. Fix from
Matija Glavinic Pecotic
21) IPPROTO_* must be pure defines, otherwise module aliases don't get
constructed properly. Fix from Jan Moskyto
22) IPV6 netconsole setup doesn't work properly unless an explicit
source address is specified, fix from Sabrina Dubroca
23) Use __GFP_NORETRY for high order skb page allocations in
sock_alloc_send_pskb and skb_page_frag_refill. From Eric Dumazet
24) Fix a regression added in netconsole over bridging, from Cong Wang
25) TCP uses an artificial offset of 1ms for SRTT, but this doesn't jive
well with TCP pacing which needs the SRTT to be accurate. Fix from
Eric Dumazet
26) Several cases of missing header file includes from Rashika Kheria
27) Add ZTE MF667 device ID to qmi_wwan driver, from Raymond Wanyoike
28) TCP Small Queues doesn't handle nonagle properly in some corner
cases, fix from Eric Dumazet
29) Remove extraneous read_unlock in bond_enslave, whoops. From Ding
Tianhong
30) Fix 9p trans_virtio handling of vmalloc buffers, from Richard Yao
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (136 commits)
6lowpan: fix lockdep splats
alx: add missing stats_lock spinlock init
9p/trans_virtio.c: Fix broken zero-copy on vmalloc() buffers
bonding: remove unwanted bond lock for enslave processing
USB2NET : SR9800 : One chip USB2.0 USB2NET SR9800 Device Driver Support
tcp: tsq: fix nonagle handling
bridge: Prevent possible race condition in br_fdb_change_mac_address
bridge: Properly check if local fdb entry can be deleted when deleting vlan
bridge: Properly check if local fdb entry can be deleted in br_fdb_delete_by_port
bridge: Properly check if local fdb entry can be deleted in br_fdb_change_mac_address
bridge: Fix the way to check if a local fdb entry can be deleted
bridge: Change local fdb entries whenever mac address of bridge device changes
bridge: Fix the way to find old local fdb entries in br_fdb_change_mac_address
bridge: Fix the way to insert new local fdb entries in br_fdb_changeaddr
bridge: Fix the way to find old local fdb entries in br_fdb_changeaddr
tcp: correct code comment stating 3 min timeout for FIN_WAIT2, we only do 1 min
net: vxge: Remove unused device pointer
net: qmi_wwan: add ZTE MF667
3c59x: Remove unused pointer in vortex_eisa_cleanup()
net: fix 'ip rule' iif/oif device rename
...
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/Kconfig | 16 | ||||
-rw-r--r-- | drivers/net/usb/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/usb/hso.c | 32 | ||||
-rw-r--r-- | drivers/net/usb/qmi_wwan.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/r8152.c | 17 | ||||
-rw-r--r-- | drivers/net/usb/sr9800.c | 870 | ||||
-rw-r--r-- | drivers/net/usb/sr9800.h | 202 |
7 files changed, 1110 insertions, 30 deletions
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 6b638a066c1d..409499fdb157 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -292,6 +292,22 @@ 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 | default y | ||
300 | ---help--- | ||
301 | Say Y if you want to use one of the following 100Mbps USB Ethernet | ||
302 | device based on the CoreChip-sz SR9800 chip. | ||
303 | |||
304 | This driver makes the adapter appear as a normal Ethernet interface, | ||
305 | typically on eth0, if it is the only ethernet device, or perhaps on | ||
306 | eth1, if you have a PCI or ISA ethernet card installed. | ||
307 | |||
308 | To compile this driver as a module, choose M here: the | ||
309 | module will be called sr9800. | ||
310 | |||
295 | config USB_NET_SMSC75XX | 311 | config USB_NET_SMSC75XX |
296 | tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices" | 312 | tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices" |
297 | depends on USB_USBNET | 313 | depends on USB_USBNET |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index b17b5e88bbaf..433f0a00c683 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.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/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/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 23bdd5b9274d..ff5c87128ffe 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
@@ -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 */ |
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index e8fac732c6f1..d89dbe395ad2 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
@@ -2273,22 +2273,21 @@ static int rtl8152_open(struct net_device *netdev) | |||
2273 | struct r8152 *tp = netdev_priv(netdev); | 2273 | struct r8152 *tp = netdev_priv(netdev); |
2274 | int res = 0; | 2274 | int res = 0; |
2275 | 2275 | ||
2276 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | ||
2277 | tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, | ||
2278 | DUPLEX_FULL); | ||
2279 | tp->speed = 0; | ||
2280 | netif_carrier_off(netdev); | ||
2281 | netif_start_queue(netdev); | ||
2282 | set_bit(WORK_ENABLE, &tp->flags); | ||
2276 | res = usb_submit_urb(tp->intr_urb, GFP_KERNEL); | 2283 | res = usb_submit_urb(tp->intr_urb, GFP_KERNEL); |
2277 | if (res) { | 2284 | if (res) { |
2278 | if (res == -ENODEV) | 2285 | if (res == -ENODEV) |
2279 | netif_device_detach(tp->netdev); | 2286 | netif_device_detach(tp->netdev); |
2280 | netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n", | 2287 | netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n", |
2281 | res); | 2288 | res); |
2282 | return res; | ||
2283 | } | 2289 | } |
2284 | 2290 | ||
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 | 2291 | ||
2293 | return res; | 2292 | return res; |
2294 | } | 2293 | } |
@@ -2298,8 +2297,8 @@ static int rtl8152_close(struct net_device *netdev) | |||
2298 | struct r8152 *tp = netdev_priv(netdev); | 2297 | struct r8152 *tp = netdev_priv(netdev); |
2299 | int res = 0; | 2298 | int res = 0; |
2300 | 2299 | ||
2301 | usb_kill_urb(tp->intr_urb); | ||
2302 | clear_bit(WORK_ENABLE, &tp->flags); | 2300 | clear_bit(WORK_ENABLE, &tp->flags); |
2301 | usb_kill_urb(tp->intr_urb); | ||
2303 | cancel_delayed_work_sync(&tp->schedule); | 2302 | cancel_delayed_work_sync(&tp->schedule); |
2304 | netif_stop_queue(netdev); | 2303 | netif_stop_queue(netdev); |
2305 | tasklet_disable(&tp->tl); | 2304 | tasklet_disable(&tp->tl); |
diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c new file mode 100644 index 000000000000..4175eb9fdeca --- /dev/null +++ b/drivers/net/usb/sr9800.c | |||
@@ -0,0 +1,870 @@ | |||
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 | while (offset + sizeof(u32) < skb->len) { | ||
67 | struct sk_buff *sr_skb; | ||
68 | u16 size; | ||
69 | u32 header = get_unaligned_le32(skb->data + offset); | ||
70 | |||
71 | offset += sizeof(u32); | ||
72 | /* get the packet length */ | ||
73 | size = (u16) (header & 0x7ff); | ||
74 | if (size != ((~header >> 16) & 0x07ff)) { | ||
75 | netdev_err(dev->net, "%s : Bad Header Length\n", | ||
76 | __func__); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || | ||
81 | (size + offset > skb->len)) { | ||
82 | netdev_err(dev->net, "%s : Bad RX Length %d\n", | ||
83 | __func__, size); | ||
84 | return 0; | ||
85 | } | ||
86 | sr_skb = netdev_alloc_skb_ip_align(dev->net, size); | ||
87 | if (!sr_skb) | ||
88 | return 0; | ||
89 | |||
90 | skb_put(sr_skb, size); | ||
91 | memcpy(sr_skb->data, skb->data + offset, size); | ||
92 | usbnet_skb_return(dev, sr_skb); | ||
93 | |||
94 | offset += (size + 1) & 0xfffe; | ||
95 | } | ||
96 | |||
97 | if (skb->len != offset) { | ||
98 | netdev_err(dev->net, "%s : Bad SKB Length %d\n", __func__, | ||
99 | skb->len); | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | return 1; | ||
104 | } | ||
105 | |||
106 | static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | ||
107 | gfp_t flags) | ||
108 | { | ||
109 | int headroom = skb_headroom(skb); | ||
110 | int tailroom = skb_tailroom(skb); | ||
111 | u32 padbytes = 0xffff0000; | ||
112 | u32 packet_len; | ||
113 | int padlen; | ||
114 | |||
115 | padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4; | ||
116 | |||
117 | if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) { | ||
118 | if ((headroom < 4) || (tailroom < padlen)) { | ||
119 | skb->data = memmove(skb->head + 4, skb->data, | ||
120 | skb->len); | ||
121 | skb_set_tail_pointer(skb, skb->len); | ||
122 | } | ||
123 | } else { | ||
124 | struct sk_buff *skb2; | ||
125 | skb2 = skb_copy_expand(skb, 4, padlen, flags); | ||
126 | dev_kfree_skb_any(skb); | ||
127 | skb = skb2; | ||
128 | if (!skb) | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | skb_push(skb, 4); | ||
133 | packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); | ||
134 | cpu_to_le32s(&packet_len); | ||
135 | skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); | ||
136 | |||
137 | if (padlen) { | ||
138 | cpu_to_le32s(&padbytes); | ||
139 | memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); | ||
140 | skb_put(skb, sizeof(padbytes)); | ||
141 | } | ||
142 | |||
143 | return skb; | ||
144 | } | ||
145 | |||
146 | static void sr_status(struct usbnet *dev, struct urb *urb) | ||
147 | { | ||
148 | struct sr9800_int_data *event; | ||
149 | int link; | ||
150 | |||
151 | if (urb->actual_length < 8) | ||
152 | return; | ||
153 | |||
154 | event = urb->transfer_buffer; | ||
155 | link = event->link & 0x01; | ||
156 | if (netif_carrier_ok(dev->net) != link) { | ||
157 | usbnet_link_change(dev, link, 1); | ||
158 | netdev_dbg(dev->net, "Link Status is: %d\n", link); | ||
159 | } | ||
160 | |||
161 | return; | ||
162 | } | ||
163 | |||
164 | static inline int sr_set_sw_mii(struct usbnet *dev) | ||
165 | { | ||
166 | int ret; | ||
167 | |||
168 | ret = sr_write_cmd(dev, SR_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); | ||
169 | if (ret < 0) | ||
170 | netdev_err(dev->net, "Failed to enable software MII access\n"); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | static inline int sr_set_hw_mii(struct usbnet *dev) | ||
175 | { | ||
176 | int ret; | ||
177 | |||
178 | ret = sr_write_cmd(dev, SR_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); | ||
179 | if (ret < 0) | ||
180 | netdev_err(dev->net, "Failed to enable hardware MII access\n"); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static inline int sr_get_phy_addr(struct usbnet *dev) | ||
185 | { | ||
186 | u8 buf[2]; | ||
187 | int ret; | ||
188 | |||
189 | ret = sr_read_cmd(dev, SR_CMD_READ_PHY_ID, 0, 0, 2, buf); | ||
190 | if (ret < 0) { | ||
191 | netdev_err(dev->net, "%s : Error reading PHYID register:%02x\n", | ||
192 | __func__, ret); | ||
193 | goto out; | ||
194 | } | ||
195 | netdev_dbg(dev->net, "%s : returning 0x%04x\n", __func__, | ||
196 | *((__le16 *)buf)); | ||
197 | |||
198 | ret = buf[1]; | ||
199 | |||
200 | out: | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static int sr_sw_reset(struct usbnet *dev, u8 flags) | ||
205 | { | ||
206 | int ret; | ||
207 | |||
208 | ret = sr_write_cmd(dev, SR_CMD_SW_RESET, flags, 0, 0, NULL); | ||
209 | if (ret < 0) | ||
210 | netdev_err(dev->net, "Failed to send software reset:%02x\n", | ||
211 | ret); | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static u16 sr_read_rx_ctl(struct usbnet *dev) | ||
217 | { | ||
218 | __le16 v; | ||
219 | int ret; | ||
220 | |||
221 | ret = sr_read_cmd(dev, SR_CMD_READ_RX_CTL, 0, 0, 2, &v); | ||
222 | if (ret < 0) { | ||
223 | netdev_err(dev->net, "Error reading RX_CTL register:%02x\n", | ||
224 | ret); | ||
225 | goto out; | ||
226 | } | ||
227 | |||
228 | ret = le16_to_cpu(v); | ||
229 | out: | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | static int sr_write_rx_ctl(struct usbnet *dev, u16 mode) | ||
234 | { | ||
235 | int ret; | ||
236 | |||
237 | netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); | ||
238 | ret = sr_write_cmd(dev, SR_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); | ||
239 | if (ret < 0) | ||
240 | netdev_err(dev->net, | ||
241 | "Failed to write RX_CTL mode to 0x%04x:%02x\n", | ||
242 | mode, ret); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static u16 sr_read_medium_status(struct usbnet *dev) | ||
248 | { | ||
249 | __le16 v; | ||
250 | int ret; | ||
251 | |||
252 | ret = sr_read_cmd(dev, SR_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); | ||
253 | if (ret < 0) { | ||
254 | netdev_err(dev->net, | ||
255 | "Error reading Medium Status register:%02x\n", ret); | ||
256 | return ret; /* TODO: callers not checking for error ret */ | ||
257 | } | ||
258 | |||
259 | return le16_to_cpu(v); | ||
260 | } | ||
261 | |||
262 | static int sr_write_medium_mode(struct usbnet *dev, u16 mode) | ||
263 | { | ||
264 | int ret; | ||
265 | |||
266 | netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); | ||
267 | ret = sr_write_cmd(dev, SR_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); | ||
268 | if (ret < 0) | ||
269 | netdev_err(dev->net, | ||
270 | "Failed to write Medium Mode mode to 0x%04x:%02x\n", | ||
271 | mode, ret); | ||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | static int sr_write_gpio(struct usbnet *dev, u16 value, int sleep) | ||
276 | { | ||
277 | int ret; | ||
278 | |||
279 | netdev_dbg(dev->net, "%s : value = 0x%04x\n", __func__, value); | ||
280 | ret = sr_write_cmd(dev, SR_CMD_WRITE_GPIOS, value, 0, 0, NULL); | ||
281 | if (ret < 0) | ||
282 | netdev_err(dev->net, "Failed to write GPIO value 0x%04x:%02x\n", | ||
283 | value, ret); | ||
284 | if (sleep) | ||
285 | msleep(sleep); | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | /* SR9800 have a 16-bit RX_CTL value */ | ||
291 | static void sr_set_multicast(struct net_device *net) | ||
292 | { | ||
293 | struct usbnet *dev = netdev_priv(net); | ||
294 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
295 | u16 rx_ctl = SR_DEFAULT_RX_CTL; | ||
296 | |||
297 | if (net->flags & IFF_PROMISC) { | ||
298 | rx_ctl |= SR_RX_CTL_PRO; | ||
299 | } else if (net->flags & IFF_ALLMULTI || | ||
300 | netdev_mc_count(net) > SR_MAX_MCAST) { | ||
301 | rx_ctl |= SR_RX_CTL_AMALL; | ||
302 | } else if (netdev_mc_empty(net)) { | ||
303 | /* just broadcast and directed */ | ||
304 | } else { | ||
305 | /* We use the 20 byte dev->data | ||
306 | * for our 8 byte filter buffer | ||
307 | * to avoid allocating memory that | ||
308 | * is tricky to free later | ||
309 | */ | ||
310 | struct netdev_hw_addr *ha; | ||
311 | u32 crc_bits; | ||
312 | |||
313 | memset(data->multi_filter, 0, SR_MCAST_FILTER_SIZE); | ||
314 | |||
315 | /* Build the multicast hash filter. */ | ||
316 | netdev_for_each_mc_addr(ha, net) { | ||
317 | crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; | ||
318 | data->multi_filter[crc_bits >> 3] |= | ||
319 | 1 << (crc_bits & 7); | ||
320 | } | ||
321 | |||
322 | sr_write_cmd_async(dev, SR_CMD_WRITE_MULTI_FILTER, 0, 0, | ||
323 | SR_MCAST_FILTER_SIZE, data->multi_filter); | ||
324 | |||
325 | rx_ctl |= SR_RX_CTL_AM; | ||
326 | } | ||
327 | |||
328 | sr_write_cmd_async(dev, SR_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); | ||
329 | } | ||
330 | |||
331 | static int sr_mdio_read(struct net_device *net, int phy_id, int loc) | ||
332 | { | ||
333 | struct usbnet *dev = netdev_priv(net); | ||
334 | __le16 res; | ||
335 | |||
336 | mutex_lock(&dev->phy_mutex); | ||
337 | sr_set_sw_mii(dev); | ||
338 | sr_read_cmd(dev, SR_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res); | ||
339 | sr_set_hw_mii(dev); | ||
340 | mutex_unlock(&dev->phy_mutex); | ||
341 | |||
342 | netdev_dbg(dev->net, | ||
343 | "%s : phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", __func__, | ||
344 | phy_id, loc, le16_to_cpu(res)); | ||
345 | |||
346 | return le16_to_cpu(res); | ||
347 | } | ||
348 | |||
349 | static void | ||
350 | sr_mdio_write(struct net_device *net, int phy_id, int loc, int val) | ||
351 | { | ||
352 | struct usbnet *dev = netdev_priv(net); | ||
353 | __le16 res = cpu_to_le16(val); | ||
354 | |||
355 | netdev_dbg(dev->net, | ||
356 | "%s : phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", __func__, | ||
357 | phy_id, loc, val); | ||
358 | mutex_lock(&dev->phy_mutex); | ||
359 | sr_set_sw_mii(dev); | ||
360 | sr_write_cmd(dev, SR_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); | ||
361 | sr_set_hw_mii(dev); | ||
362 | mutex_unlock(&dev->phy_mutex); | ||
363 | } | ||
364 | |||
365 | /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ | ||
366 | static u32 sr_get_phyid(struct usbnet *dev) | ||
367 | { | ||
368 | int phy_reg; | ||
369 | u32 phy_id; | ||
370 | int i; | ||
371 | |||
372 | /* Poll for the rare case the FW or phy isn't ready yet. */ | ||
373 | for (i = 0; i < 100; i++) { | ||
374 | phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); | ||
375 | if (phy_reg != 0 && phy_reg != 0xFFFF) | ||
376 | break; | ||
377 | mdelay(1); | ||
378 | } | ||
379 | |||
380 | if (phy_reg <= 0 || phy_reg == 0xFFFF) | ||
381 | return 0; | ||
382 | |||
383 | phy_id = (phy_reg & 0xffff) << 16; | ||
384 | |||
385 | phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2); | ||
386 | if (phy_reg < 0) | ||
387 | return 0; | ||
388 | |||
389 | phy_id |= (phy_reg & 0xffff); | ||
390 | |||
391 | return phy_id; | ||
392 | } | ||
393 | |||
394 | static void | ||
395 | sr_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
396 | { | ||
397 | struct usbnet *dev = netdev_priv(net); | ||
398 | u8 opt; | ||
399 | |||
400 | if (sr_read_cmd(dev, SR_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { | ||
401 | wolinfo->supported = 0; | ||
402 | wolinfo->wolopts = 0; | ||
403 | return; | ||
404 | } | ||
405 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | ||
406 | wolinfo->wolopts = 0; | ||
407 | if (opt & SR_MONITOR_LINK) | ||
408 | wolinfo->wolopts |= WAKE_PHY; | ||
409 | if (opt & SR_MONITOR_MAGIC) | ||
410 | wolinfo->wolopts |= WAKE_MAGIC; | ||
411 | } | ||
412 | |||
413 | static int | ||
414 | sr_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
415 | { | ||
416 | struct usbnet *dev = netdev_priv(net); | ||
417 | u8 opt = 0; | ||
418 | |||
419 | if (wolinfo->wolopts & WAKE_PHY) | ||
420 | opt |= SR_MONITOR_LINK; | ||
421 | if (wolinfo->wolopts & WAKE_MAGIC) | ||
422 | opt |= SR_MONITOR_MAGIC; | ||
423 | |||
424 | if (sr_write_cmd(dev, SR_CMD_WRITE_MONITOR_MODE, | ||
425 | opt, 0, 0, NULL) < 0) | ||
426 | return -EINVAL; | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int sr_get_eeprom_len(struct net_device *net) | ||
432 | { | ||
433 | struct usbnet *dev = netdev_priv(net); | ||
434 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
435 | |||
436 | return data->eeprom_len; | ||
437 | } | ||
438 | |||
439 | static int sr_get_eeprom(struct net_device *net, | ||
440 | struct ethtool_eeprom *eeprom, u8 *data) | ||
441 | { | ||
442 | struct usbnet *dev = netdev_priv(net); | ||
443 | __le16 *ebuf = (__le16 *)data; | ||
444 | int ret; | ||
445 | int i; | ||
446 | |||
447 | /* Crude hack to ensure that we don't overwrite memory | ||
448 | * if an odd length is supplied | ||
449 | */ | ||
450 | if (eeprom->len % 2) | ||
451 | return -EINVAL; | ||
452 | |||
453 | eeprom->magic = SR_EEPROM_MAGIC; | ||
454 | |||
455 | /* sr9800 returns 2 bytes from eeprom on read */ | ||
456 | for (i = 0; i < eeprom->len / 2; i++) { | ||
457 | ret = sr_read_cmd(dev, SR_CMD_READ_EEPROM, eeprom->offset + i, | ||
458 | 0, 2, &ebuf[i]); | ||
459 | if (ret < 0) | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static void sr_get_drvinfo(struct net_device *net, | ||
466 | struct ethtool_drvinfo *info) | ||
467 | { | ||
468 | struct usbnet *dev = netdev_priv(net); | ||
469 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
470 | |||
471 | /* Inherit standard device info */ | ||
472 | usbnet_get_drvinfo(net, info); | ||
473 | strncpy(info->driver, DRIVER_NAME, sizeof(info->driver)); | ||
474 | strncpy(info->version, DRIVER_VERSION, sizeof(info->version)); | ||
475 | info->eedump_len = data->eeprom_len; | ||
476 | } | ||
477 | |||
478 | static u32 sr_get_link(struct net_device *net) | ||
479 | { | ||
480 | struct usbnet *dev = netdev_priv(net); | ||
481 | |||
482 | return mii_link_ok(&dev->mii); | ||
483 | } | ||
484 | |||
485 | static int sr_ioctl(struct net_device *net, struct ifreq *rq, int cmd) | ||
486 | { | ||
487 | struct usbnet *dev = netdev_priv(net); | ||
488 | |||
489 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
490 | } | ||
491 | |||
492 | static int sr_set_mac_address(struct net_device *net, void *p) | ||
493 | { | ||
494 | struct usbnet *dev = netdev_priv(net); | ||
495 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
496 | struct sockaddr *addr = p; | ||
497 | |||
498 | if (netif_running(net)) | ||
499 | return -EBUSY; | ||
500 | if (!is_valid_ether_addr(addr->sa_data)) | ||
501 | return -EADDRNOTAVAIL; | ||
502 | |||
503 | memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); | ||
504 | |||
505 | /* We use the 20 byte dev->data | ||
506 | * for our 6 byte mac buffer | ||
507 | * to avoid allocating memory that | ||
508 | * is tricky to free later | ||
509 | */ | ||
510 | memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); | ||
511 | sr_write_cmd_async(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, | ||
512 | data->mac_addr); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static const struct ethtool_ops sr9800_ethtool_ops = { | ||
518 | .get_drvinfo = sr_get_drvinfo, | ||
519 | .get_link = sr_get_link, | ||
520 | .get_msglevel = usbnet_get_msglevel, | ||
521 | .set_msglevel = usbnet_set_msglevel, | ||
522 | .get_wol = sr_get_wol, | ||
523 | .set_wol = sr_set_wol, | ||
524 | .get_eeprom_len = sr_get_eeprom_len, | ||
525 | .get_eeprom = sr_get_eeprom, | ||
526 | .get_settings = usbnet_get_settings, | ||
527 | .set_settings = usbnet_set_settings, | ||
528 | .nway_reset = usbnet_nway_reset, | ||
529 | }; | ||
530 | |||
531 | static int sr9800_link_reset(struct usbnet *dev) | ||
532 | { | ||
533 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; | ||
534 | u16 mode; | ||
535 | |||
536 | mii_check_media(&dev->mii, 1, 1); | ||
537 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
538 | mode = SR9800_MEDIUM_DEFAULT; | ||
539 | |||
540 | if (ethtool_cmd_speed(&ecmd) != SPEED_100) | ||
541 | mode &= ~SR_MEDIUM_PS; | ||
542 | |||
543 | if (ecmd.duplex != DUPLEX_FULL) | ||
544 | mode &= ~SR_MEDIUM_FD; | ||
545 | |||
546 | netdev_dbg(dev->net, "%s : speed: %u duplex: %d mode: 0x%04x\n", | ||
547 | __func__, ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); | ||
548 | |||
549 | sr_write_medium_mode(dev, mode); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | |||
555 | static int sr9800_set_default_mode(struct usbnet *dev) | ||
556 | { | ||
557 | u16 rx_ctl; | ||
558 | int ret; | ||
559 | |||
560 | sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | ||
561 | sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
562 | ADVERTISE_ALL | ADVERTISE_CSMA); | ||
563 | mii_nway_restart(&dev->mii); | ||
564 | |||
565 | ret = sr_write_medium_mode(dev, SR9800_MEDIUM_DEFAULT); | ||
566 | if (ret < 0) | ||
567 | goto out; | ||
568 | |||
569 | ret = sr_write_cmd(dev, SR_CMD_WRITE_IPG012, | ||
570 | SR9800_IPG0_DEFAULT | SR9800_IPG1_DEFAULT, | ||
571 | SR9800_IPG2_DEFAULT, 0, NULL); | ||
572 | if (ret < 0) { | ||
573 | netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret); | ||
574 | goto out; | ||
575 | } | ||
576 | |||
577 | /* Set RX_CTL to default values with 2k buffer, and enable cactus */ | ||
578 | ret = sr_write_rx_ctl(dev, SR_DEFAULT_RX_CTL); | ||
579 | if (ret < 0) | ||
580 | goto out; | ||
581 | |||
582 | rx_ctl = sr_read_rx_ctl(dev); | ||
583 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n", | ||
584 | rx_ctl); | ||
585 | |||
586 | rx_ctl = sr_read_medium_status(dev); | ||
587 | netdev_dbg(dev->net, "Medium Status:0x%04x after all initializations\n", | ||
588 | rx_ctl); | ||
589 | |||
590 | return 0; | ||
591 | out: | ||
592 | return ret; | ||
593 | } | ||
594 | |||
595 | static int sr9800_reset(struct usbnet *dev) | ||
596 | { | ||
597 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
598 | int ret, embd_phy; | ||
599 | u16 rx_ctl; | ||
600 | |||
601 | ret = sr_write_gpio(dev, | ||
602 | SR_GPIO_RSE | SR_GPIO_GPO_2 | SR_GPIO_GPO2EN, 5); | ||
603 | if (ret < 0) | ||
604 | goto out; | ||
605 | |||
606 | embd_phy = ((sr_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); | ||
607 | |||
608 | ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); | ||
609 | if (ret < 0) { | ||
610 | netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); | ||
611 | goto out; | ||
612 | } | ||
613 | |||
614 | ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_PRL); | ||
615 | if (ret < 0) | ||
616 | goto out; | ||
617 | |||
618 | msleep(150); | ||
619 | |||
620 | ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); | ||
621 | if (ret < 0) | ||
622 | goto out; | ||
623 | |||
624 | msleep(150); | ||
625 | |||
626 | if (embd_phy) { | ||
627 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
628 | if (ret < 0) | ||
629 | goto out; | ||
630 | } else { | ||
631 | ret = sr_sw_reset(dev, SR_SWRESET_PRTE); | ||
632 | if (ret < 0) | ||
633 | goto out; | ||
634 | } | ||
635 | |||
636 | msleep(150); | ||
637 | rx_ctl = sr_read_rx_ctl(dev); | ||
638 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); | ||
639 | ret = sr_write_rx_ctl(dev, 0x0000); | ||
640 | if (ret < 0) | ||
641 | goto out; | ||
642 | |||
643 | rx_ctl = sr_read_rx_ctl(dev); | ||
644 | netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); | ||
645 | |||
646 | ret = sr_sw_reset(dev, SR_SWRESET_PRL); | ||
647 | if (ret < 0) | ||
648 | goto out; | ||
649 | |||
650 | msleep(150); | ||
651 | |||
652 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL | SR_SWRESET_PRL); | ||
653 | if (ret < 0) | ||
654 | goto out; | ||
655 | |||
656 | msleep(150); | ||
657 | |||
658 | ret = sr9800_set_default_mode(dev); | ||
659 | if (ret < 0) | ||
660 | goto out; | ||
661 | |||
662 | /* Rewrite MAC address */ | ||
663 | memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN); | ||
664 | ret = sr_write_cmd(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, | ||
665 | data->mac_addr); | ||
666 | if (ret < 0) | ||
667 | goto out; | ||
668 | |||
669 | return 0; | ||
670 | |||
671 | out: | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static const struct net_device_ops sr9800_netdev_ops = { | ||
676 | .ndo_open = usbnet_open, | ||
677 | .ndo_stop = usbnet_stop, | ||
678 | .ndo_start_xmit = usbnet_start_xmit, | ||
679 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
680 | .ndo_change_mtu = usbnet_change_mtu, | ||
681 | .ndo_set_mac_address = sr_set_mac_address, | ||
682 | .ndo_validate_addr = eth_validate_addr, | ||
683 | .ndo_do_ioctl = sr_ioctl, | ||
684 | .ndo_set_rx_mode = sr_set_multicast, | ||
685 | }; | ||
686 | |||
687 | static int sr9800_phy_powerup(struct usbnet *dev) | ||
688 | { | ||
689 | int ret; | ||
690 | |||
691 | /* set the embedded Ethernet PHY in power-down state */ | ||
692 | ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_IPRL); | ||
693 | if (ret < 0) { | ||
694 | netdev_err(dev->net, "Failed to power down PHY : %d\n", ret); | ||
695 | return ret; | ||
696 | } | ||
697 | msleep(20); | ||
698 | |||
699 | /* set the embedded Ethernet PHY in power-up state */ | ||
700 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
701 | if (ret < 0) { | ||
702 | netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); | ||
703 | return ret; | ||
704 | } | ||
705 | msleep(600); | ||
706 | |||
707 | /* set the embedded Ethernet PHY in reset state */ | ||
708 | ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); | ||
709 | if (ret < 0) { | ||
710 | netdev_err(dev->net, "Failed to power up PHY: %d\n", ret); | ||
711 | return ret; | ||
712 | } | ||
713 | msleep(20); | ||
714 | |||
715 | /* set the embedded Ethernet PHY in power-up state */ | ||
716 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
717 | if (ret < 0) { | ||
718 | netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); | ||
719 | return ret; | ||
720 | } | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf) | ||
726 | { | ||
727 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
728 | u16 led01_mux, led23_mux; | ||
729 | int ret, embd_phy; | ||
730 | u32 phyid; | ||
731 | u16 rx_ctl; | ||
732 | |||
733 | data->eeprom_len = SR9800_EEPROM_LEN; | ||
734 | |||
735 | usbnet_get_endpoints(dev, intf); | ||
736 | |||
737 | /* LED Setting Rule : | ||
738 | * AABB:CCDD | ||
739 | * AA : MFA0(LED0) | ||
740 | * BB : MFA1(LED1) | ||
741 | * CC : MFA2(LED2), Reserved for SR9800 | ||
742 | * DD : MFA3(LED3), Reserved for SR9800 | ||
743 | */ | ||
744 | led01_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_LINK; | ||
745 | led23_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_TX_ACTIVE; | ||
746 | ret = sr_write_cmd(dev, SR_CMD_LED_MUX, led01_mux, led23_mux, 0, NULL); | ||
747 | if (ret < 0) { | ||
748 | netdev_err(dev->net, "set LINK LED failed : %d\n", ret); | ||
749 | goto out; | ||
750 | } | ||
751 | |||
752 | /* Get the MAC address */ | ||
753 | ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, | ||
754 | dev->net->dev_addr); | ||
755 | if (ret < 0) { | ||
756 | netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret); | ||
757 | return ret; | ||
758 | } | ||
759 | netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr); | ||
760 | |||
761 | /* Initialize MII structure */ | ||
762 | dev->mii.dev = dev->net; | ||
763 | dev->mii.mdio_read = sr_mdio_read; | ||
764 | dev->mii.mdio_write = sr_mdio_write; | ||
765 | dev->mii.phy_id_mask = 0x1f; | ||
766 | dev->mii.reg_num_mask = 0x1f; | ||
767 | dev->mii.phy_id = sr_get_phy_addr(dev); | ||
768 | |||
769 | dev->net->netdev_ops = &sr9800_netdev_ops; | ||
770 | dev->net->ethtool_ops = &sr9800_ethtool_ops; | ||
771 | |||
772 | embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); | ||
773 | /* Reset the PHY to normal operation mode */ | ||
774 | ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); | ||
775 | if (ret < 0) { | ||
776 | netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); | ||
777 | return ret; | ||
778 | } | ||
779 | |||
780 | /* Init PHY routine */ | ||
781 | ret = sr9800_phy_powerup(dev); | ||
782 | if (ret < 0) | ||
783 | goto out; | ||
784 | |||
785 | rx_ctl = sr_read_rx_ctl(dev); | ||
786 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); | ||
787 | ret = sr_write_rx_ctl(dev, 0x0000); | ||
788 | if (ret < 0) | ||
789 | goto out; | ||
790 | |||
791 | rx_ctl = sr_read_rx_ctl(dev); | ||
792 | netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); | ||
793 | |||
794 | /* Read PHYID register *AFTER* the PHY was reset properly */ | ||
795 | phyid = sr_get_phyid(dev); | ||
796 | netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid); | ||
797 | |||
798 | /* medium mode setting */ | ||
799 | ret = sr9800_set_default_mode(dev); | ||
800 | if (ret < 0) | ||
801 | goto out; | ||
802 | |||
803 | if (dev->udev->speed == USB_SPEED_HIGH) { | ||
804 | ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, | ||
805 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].byte_cnt, | ||
806 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].threshold, | ||
807 | 0, NULL); | ||
808 | if (ret < 0) { | ||
809 | netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); | ||
810 | goto out; | ||
811 | } | ||
812 | dev->rx_urb_size = | ||
813 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].size; | ||
814 | } else { | ||
815 | ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, | ||
816 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].byte_cnt, | ||
817 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].threshold, | ||
818 | 0, NULL); | ||
819 | if (ret < 0) { | ||
820 | netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); | ||
821 | goto out; | ||
822 | } | ||
823 | dev->rx_urb_size = | ||
824 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size; | ||
825 | } | ||
826 | netdev_dbg(dev->net, "%s : setting rx_urb_size with : %ld\n", __func__, | ||
827 | dev->rx_urb_size); | ||
828 | return 0; | ||
829 | |||
830 | out: | ||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | static const struct driver_info sr9800_driver_info = { | ||
835 | .description = "CoreChip SR9800 USB 2.0 Ethernet", | ||
836 | .bind = sr9800_bind, | ||
837 | .status = sr_status, | ||
838 | .link_reset = sr9800_link_reset, | ||
839 | .reset = sr9800_reset, | ||
840 | .flags = DRIVER_FLAG, | ||
841 | .rx_fixup = sr_rx_fixup, | ||
842 | .tx_fixup = sr_tx_fixup, | ||
843 | }; | ||
844 | |||
845 | static const struct usb_device_id products[] = { | ||
846 | { | ||
847 | USB_DEVICE(0x0fe6, 0x9800), /* SR9800 Device */ | ||
848 | .driver_info = (unsigned long) &sr9800_driver_info, | ||
849 | }, | ||
850 | {}, /* END */ | ||
851 | }; | ||
852 | |||
853 | MODULE_DEVICE_TABLE(usb, products); | ||
854 | |||
855 | static struct usb_driver sr_driver = { | ||
856 | .name = DRIVER_NAME, | ||
857 | .id_table = products, | ||
858 | .probe = usbnet_probe, | ||
859 | .suspend = usbnet_suspend, | ||
860 | .resume = usbnet_resume, | ||
861 | .disconnect = usbnet_disconnect, | ||
862 | .supports_autosuspend = 1, | ||
863 | }; | ||
864 | |||
865 | module_usb_driver(sr_driver); | ||
866 | |||
867 | MODULE_AUTHOR("Liu Junliang <liujunliang_ljl@163.com"); | ||
868 | MODULE_VERSION(DRIVER_VERSION); | ||
869 | MODULE_DESCRIPTION("SR9800 USB 2.0 USB2NET Dev : http://www.corechip-sz.com"); | ||
870 | 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 */ | ||