1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /*************************************************************************** |
3 | * |
4 | * Copyright (C) 2007-2010 SMSC |
5 | * |
6 | *****************************************************************************/ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/kmod.h> |
10 | #include <linux/netdevice.h> |
11 | #include <linux/etherdevice.h> |
12 | #include <linux/ethtool.h> |
13 | #include <linux/mii.h> |
14 | #include <linux/usb.h> |
15 | #include <linux/bitrev.h> |
16 | #include <linux/crc16.h> |
17 | #include <linux/crc32.h> |
18 | #include <linux/usb/usbnet.h> |
19 | #include <linux/slab.h> |
20 | #include <linux/of_net.h> |
21 | #include "smsc75xx.h" |
22 | |
23 | #define SMSC_CHIPNAME "smsc75xx" |
24 | #define SMSC_DRIVER_VERSION "1.0.0" |
25 | #define HS_USB_PKT_SIZE (512) |
26 | #define FS_USB_PKT_SIZE (64) |
27 | #define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE) |
28 | #define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE) |
29 | #define DEFAULT_BULK_IN_DELAY (0x00002000) |
30 | #define MAX_SINGLE_PACKET_SIZE (9000) |
31 | #define LAN75XX_EEPROM_MAGIC (0x7500) |
32 | #define EEPROM_MAC_OFFSET (0x01) |
33 | #define DEFAULT_TX_CSUM_ENABLE (true) |
34 | #define DEFAULT_RX_CSUM_ENABLE (true) |
35 | #define SMSC75XX_INTERNAL_PHY_ID (1) |
36 | #define SMSC75XX_TX_OVERHEAD (8) |
37 | #define MAX_RX_FIFO_SIZE (20 * 1024) |
38 | #define MAX_TX_FIFO_SIZE (12 * 1024) |
39 | #define USB_VENDOR_ID_SMSC (0x0424) |
40 | #define USB_PRODUCT_ID_LAN7500 (0x7500) |
41 | #define USB_PRODUCT_ID_LAN7505 (0x7505) |
42 | #define RXW_PADDING 2 |
43 | #define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \ |
44 | WAKE_MCAST | WAKE_ARP | WAKE_MAGIC) |
45 | |
46 | #define SUSPEND_SUSPEND0 (0x01) |
47 | #define SUSPEND_SUSPEND1 (0x02) |
48 | #define SUSPEND_SUSPEND2 (0x04) |
49 | #define SUSPEND_SUSPEND3 (0x08) |
50 | #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ |
51 | SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) |
52 | |
53 | struct smsc75xx_priv { |
54 | struct usbnet *dev; |
55 | u32 rfe_ctl; |
56 | u32 wolopts; |
57 | u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN]; |
58 | struct mutex dataport_mutex; |
59 | spinlock_t rfe_ctl_lock; |
60 | struct work_struct set_multicast; |
61 | u8 suspend_flags; |
62 | }; |
63 | |
64 | struct usb_context { |
65 | struct usb_ctrlrequest req; |
66 | struct usbnet *dev; |
67 | }; |
68 | |
69 | static bool turbo_mode = true; |
70 | module_param(turbo_mode, bool, 0644); |
71 | MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction" ); |
72 | |
73 | static int smsc75xx_link_ok_nopm(struct usbnet *dev); |
74 | static int smsc75xx_phy_gig_workaround(struct usbnet *dev); |
75 | |
76 | static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, |
77 | u32 *data, int in_pm) |
78 | { |
79 | u32 buf; |
80 | int ret; |
81 | int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); |
82 | |
83 | BUG_ON(!dev); |
84 | |
85 | if (!in_pm) |
86 | fn = usbnet_read_cmd; |
87 | else |
88 | fn = usbnet_read_cmd_nopm; |
89 | |
90 | ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN |
91 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
92 | 0, index, &buf, 4); |
93 | if (unlikely(ret < 4)) { |
94 | ret = ret < 0 ? ret : -ENODATA; |
95 | |
96 | netdev_warn(dev: dev->net, format: "Failed to read reg index 0x%08x: %d\n" , |
97 | index, ret); |
98 | return ret; |
99 | } |
100 | |
101 | le32_to_cpus(&buf); |
102 | *data = buf; |
103 | |
104 | return ret; |
105 | } |
106 | |
107 | static int __must_check __smsc75xx_write_reg(struct usbnet *dev, u32 index, |
108 | u32 data, int in_pm) |
109 | { |
110 | u32 buf; |
111 | int ret; |
112 | int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); |
113 | |
114 | BUG_ON(!dev); |
115 | |
116 | if (!in_pm) |
117 | fn = usbnet_write_cmd; |
118 | else |
119 | fn = usbnet_write_cmd_nopm; |
120 | |
121 | buf = data; |
122 | cpu_to_le32s(&buf); |
123 | |
124 | ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT |
125 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
126 | 0, index, &buf, 4); |
127 | if (unlikely(ret < 0)) |
128 | netdev_warn(dev: dev->net, format: "Failed to write reg index 0x%08x: %d\n" , |
129 | index, ret); |
130 | |
131 | return ret; |
132 | } |
133 | |
134 | static int __must_check smsc75xx_read_reg_nopm(struct usbnet *dev, u32 index, |
135 | u32 *data) |
136 | { |
137 | return __smsc75xx_read_reg(dev, index, data, in_pm: 1); |
138 | } |
139 | |
140 | static int __must_check smsc75xx_write_reg_nopm(struct usbnet *dev, u32 index, |
141 | u32 data) |
142 | { |
143 | return __smsc75xx_write_reg(dev, index, data, in_pm: 1); |
144 | } |
145 | |
146 | static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index, |
147 | u32 *data) |
148 | { |
149 | return __smsc75xx_read_reg(dev, index, data, in_pm: 0); |
150 | } |
151 | |
152 | static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index, |
153 | u32 data) |
154 | { |
155 | return __smsc75xx_write_reg(dev, index, data, in_pm: 0); |
156 | } |
157 | |
158 | /* Loop until the read is completed with timeout |
159 | * called with phy_mutex held */ |
160 | static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev, |
161 | int in_pm) |
162 | { |
163 | unsigned long start_time = jiffies; |
164 | u32 val; |
165 | int ret; |
166 | |
167 | do { |
168 | ret = __smsc75xx_read_reg(dev, MII_ACCESS, data: &val, in_pm); |
169 | if (ret < 0) { |
170 | netdev_warn(dev: dev->net, format: "Error reading MII_ACCESS\n" ); |
171 | return ret; |
172 | } |
173 | |
174 | if (!(val & MII_ACCESS_BUSY)) |
175 | return 0; |
176 | } while (!time_after(jiffies, start_time + HZ)); |
177 | |
178 | return -EIO; |
179 | } |
180 | |
181 | static int __smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx, |
182 | int in_pm) |
183 | { |
184 | struct usbnet *dev = netdev_priv(dev: netdev); |
185 | u32 val, addr; |
186 | int ret; |
187 | |
188 | mutex_lock(&dev->phy_mutex); |
189 | |
190 | /* confirm MII not busy */ |
191 | ret = __smsc75xx_phy_wait_not_busy(dev, in_pm); |
192 | if (ret < 0) { |
193 | netdev_warn(dev: dev->net, format: "MII is busy in smsc75xx_mdio_read\n" ); |
194 | goto done; |
195 | } |
196 | |
197 | /* set the address, index & direction (read from PHY) */ |
198 | phy_id &= dev->mii.phy_id_mask; |
199 | idx &= dev->mii.reg_num_mask; |
200 | addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) |
201 | | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) |
202 | | MII_ACCESS_READ | MII_ACCESS_BUSY; |
203 | ret = __smsc75xx_write_reg(dev, MII_ACCESS, data: addr, in_pm); |
204 | if (ret < 0) { |
205 | netdev_warn(dev: dev->net, format: "Error writing MII_ACCESS\n" ); |
206 | goto done; |
207 | } |
208 | |
209 | ret = __smsc75xx_phy_wait_not_busy(dev, in_pm); |
210 | if (ret < 0) { |
211 | netdev_warn(dev: dev->net, format: "Timed out reading MII reg %02X\n" , idx); |
212 | goto done; |
213 | } |
214 | |
215 | ret = __smsc75xx_read_reg(dev, MII_DATA, data: &val, in_pm); |
216 | if (ret < 0) { |
217 | netdev_warn(dev: dev->net, format: "Error reading MII_DATA\n" ); |
218 | goto done; |
219 | } |
220 | |
221 | ret = (u16)(val & 0xFFFF); |
222 | |
223 | done: |
224 | mutex_unlock(lock: &dev->phy_mutex); |
225 | return ret; |
226 | } |
227 | |
228 | static void __smsc75xx_mdio_write(struct net_device *netdev, int phy_id, |
229 | int idx, int regval, int in_pm) |
230 | { |
231 | struct usbnet *dev = netdev_priv(dev: netdev); |
232 | u32 val, addr; |
233 | int ret; |
234 | |
235 | mutex_lock(&dev->phy_mutex); |
236 | |
237 | /* confirm MII not busy */ |
238 | ret = __smsc75xx_phy_wait_not_busy(dev, in_pm); |
239 | if (ret < 0) { |
240 | netdev_warn(dev: dev->net, format: "MII is busy in smsc75xx_mdio_write\n" ); |
241 | goto done; |
242 | } |
243 | |
244 | val = regval; |
245 | ret = __smsc75xx_write_reg(dev, MII_DATA, data: val, in_pm); |
246 | if (ret < 0) { |
247 | netdev_warn(dev: dev->net, format: "Error writing MII_DATA\n" ); |
248 | goto done; |
249 | } |
250 | |
251 | /* set the address, index & direction (write to PHY) */ |
252 | phy_id &= dev->mii.phy_id_mask; |
253 | idx &= dev->mii.reg_num_mask; |
254 | addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) |
255 | | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) |
256 | | MII_ACCESS_WRITE | MII_ACCESS_BUSY; |
257 | ret = __smsc75xx_write_reg(dev, MII_ACCESS, data: addr, in_pm); |
258 | if (ret < 0) { |
259 | netdev_warn(dev: dev->net, format: "Error writing MII_ACCESS\n" ); |
260 | goto done; |
261 | } |
262 | |
263 | ret = __smsc75xx_phy_wait_not_busy(dev, in_pm); |
264 | if (ret < 0) { |
265 | netdev_warn(dev: dev->net, format: "Timed out writing MII reg %02X\n" , idx); |
266 | goto done; |
267 | } |
268 | |
269 | done: |
270 | mutex_unlock(lock: &dev->phy_mutex); |
271 | } |
272 | |
273 | static int smsc75xx_mdio_read_nopm(struct net_device *netdev, int phy_id, |
274 | int idx) |
275 | { |
276 | return __smsc75xx_mdio_read(netdev, phy_id, idx, in_pm: 1); |
277 | } |
278 | |
279 | static void smsc75xx_mdio_write_nopm(struct net_device *netdev, int phy_id, |
280 | int idx, int regval) |
281 | { |
282 | __smsc75xx_mdio_write(netdev, phy_id, idx, regval, in_pm: 1); |
283 | } |
284 | |
285 | static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx) |
286 | { |
287 | return __smsc75xx_mdio_read(netdev, phy_id, idx, in_pm: 0); |
288 | } |
289 | |
290 | static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx, |
291 | int regval) |
292 | { |
293 | __smsc75xx_mdio_write(netdev, phy_id, idx, regval, in_pm: 0); |
294 | } |
295 | |
296 | static int smsc75xx_wait_eeprom(struct usbnet *dev) |
297 | { |
298 | unsigned long start_time = jiffies; |
299 | u32 val; |
300 | int ret; |
301 | |
302 | do { |
303 | ret = smsc75xx_read_reg(dev, E2P_CMD, data: &val); |
304 | if (ret < 0) { |
305 | netdev_warn(dev: dev->net, format: "Error reading E2P_CMD\n" ); |
306 | return ret; |
307 | } |
308 | |
309 | if (!(val & E2P_CMD_BUSY) || (val & E2P_CMD_TIMEOUT)) |
310 | break; |
311 | udelay(40); |
312 | } while (!time_after(jiffies, start_time + HZ)); |
313 | |
314 | if (val & (E2P_CMD_TIMEOUT | E2P_CMD_BUSY)) { |
315 | netdev_warn(dev: dev->net, format: "EEPROM read operation timeout\n" ); |
316 | return -EIO; |
317 | } |
318 | |
319 | return 0; |
320 | } |
321 | |
322 | static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev) |
323 | { |
324 | unsigned long start_time = jiffies; |
325 | u32 val; |
326 | int ret; |
327 | |
328 | do { |
329 | ret = smsc75xx_read_reg(dev, E2P_CMD, data: &val); |
330 | if (ret < 0) { |
331 | netdev_warn(dev: dev->net, format: "Error reading E2P_CMD\n" ); |
332 | return ret; |
333 | } |
334 | |
335 | if (!(val & E2P_CMD_BUSY)) |
336 | return 0; |
337 | |
338 | udelay(40); |
339 | } while (!time_after(jiffies, start_time + HZ)); |
340 | |
341 | netdev_warn(dev: dev->net, format: "EEPROM is busy\n" ); |
342 | return -EIO; |
343 | } |
344 | |
345 | static int smsc75xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length, |
346 | u8 *data) |
347 | { |
348 | u32 val; |
349 | int i, ret; |
350 | |
351 | BUG_ON(!dev); |
352 | BUG_ON(!data); |
353 | |
354 | ret = smsc75xx_eeprom_confirm_not_busy(dev); |
355 | if (ret) |
356 | return ret; |
357 | |
358 | for (i = 0; i < length; i++) { |
359 | val = E2P_CMD_BUSY | E2P_CMD_READ | (offset & E2P_CMD_ADDR); |
360 | ret = smsc75xx_write_reg(dev, E2P_CMD, data: val); |
361 | if (ret < 0) { |
362 | netdev_warn(dev: dev->net, format: "Error writing E2P_CMD\n" ); |
363 | return ret; |
364 | } |
365 | |
366 | ret = smsc75xx_wait_eeprom(dev); |
367 | if (ret < 0) |
368 | return ret; |
369 | |
370 | ret = smsc75xx_read_reg(dev, E2P_DATA, data: &val); |
371 | if (ret < 0) { |
372 | netdev_warn(dev: dev->net, format: "Error reading E2P_DATA\n" ); |
373 | return ret; |
374 | } |
375 | |
376 | data[i] = val & 0xFF; |
377 | offset++; |
378 | } |
379 | |
380 | return 0; |
381 | } |
382 | |
383 | static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length, |
384 | u8 *data) |
385 | { |
386 | u32 val; |
387 | int i, ret; |
388 | |
389 | BUG_ON(!dev); |
390 | BUG_ON(!data); |
391 | |
392 | ret = smsc75xx_eeprom_confirm_not_busy(dev); |
393 | if (ret) |
394 | return ret; |
395 | |
396 | /* Issue write/erase enable command */ |
397 | val = E2P_CMD_BUSY | E2P_CMD_EWEN; |
398 | ret = smsc75xx_write_reg(dev, E2P_CMD, data: val); |
399 | if (ret < 0) { |
400 | netdev_warn(dev: dev->net, format: "Error writing E2P_CMD\n" ); |
401 | return ret; |
402 | } |
403 | |
404 | ret = smsc75xx_wait_eeprom(dev); |
405 | if (ret < 0) |
406 | return ret; |
407 | |
408 | for (i = 0; i < length; i++) { |
409 | |
410 | /* Fill data register */ |
411 | val = data[i]; |
412 | ret = smsc75xx_write_reg(dev, E2P_DATA, data: val); |
413 | if (ret < 0) { |
414 | netdev_warn(dev: dev->net, format: "Error writing E2P_DATA\n" ); |
415 | return ret; |
416 | } |
417 | |
418 | /* Send "write" command */ |
419 | val = E2P_CMD_BUSY | E2P_CMD_WRITE | (offset & E2P_CMD_ADDR); |
420 | ret = smsc75xx_write_reg(dev, E2P_CMD, data: val); |
421 | if (ret < 0) { |
422 | netdev_warn(dev: dev->net, format: "Error writing E2P_CMD\n" ); |
423 | return ret; |
424 | } |
425 | |
426 | ret = smsc75xx_wait_eeprom(dev); |
427 | if (ret < 0) |
428 | return ret; |
429 | |
430 | offset++; |
431 | } |
432 | |
433 | return 0; |
434 | } |
435 | |
436 | static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev) |
437 | { |
438 | int i, ret; |
439 | |
440 | for (i = 0; i < 100; i++) { |
441 | u32 dp_sel; |
442 | ret = smsc75xx_read_reg(dev, DP_SEL, data: &dp_sel); |
443 | if (ret < 0) { |
444 | netdev_warn(dev: dev->net, format: "Error reading DP_SEL\n" ); |
445 | return ret; |
446 | } |
447 | |
448 | if (dp_sel & DP_SEL_DPRDY) |
449 | return 0; |
450 | |
451 | udelay(40); |
452 | } |
453 | |
454 | netdev_warn(dev: dev->net, format: "smsc75xx_dataport_wait_not_busy timed out\n" ); |
455 | |
456 | return -EIO; |
457 | } |
458 | |
459 | static int smsc75xx_dataport_write(struct usbnet *dev, u32 ram_select, u32 addr, |
460 | u32 length, u32 *buf) |
461 | { |
462 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
463 | u32 dp_sel; |
464 | int i, ret; |
465 | |
466 | mutex_lock(&pdata->dataport_mutex); |
467 | |
468 | ret = smsc75xx_dataport_wait_not_busy(dev); |
469 | if (ret < 0) { |
470 | netdev_warn(dev: dev->net, format: "smsc75xx_dataport_write busy on entry\n" ); |
471 | goto done; |
472 | } |
473 | |
474 | ret = smsc75xx_read_reg(dev, DP_SEL, data: &dp_sel); |
475 | if (ret < 0) { |
476 | netdev_warn(dev: dev->net, format: "Error reading DP_SEL\n" ); |
477 | goto done; |
478 | } |
479 | |
480 | dp_sel &= ~DP_SEL_RSEL; |
481 | dp_sel |= ram_select; |
482 | ret = smsc75xx_write_reg(dev, DP_SEL, data: dp_sel); |
483 | if (ret < 0) { |
484 | netdev_warn(dev: dev->net, format: "Error writing DP_SEL\n" ); |
485 | goto done; |
486 | } |
487 | |
488 | for (i = 0; i < length; i++) { |
489 | ret = smsc75xx_write_reg(dev, DP_ADDR, data: addr + i); |
490 | if (ret < 0) { |
491 | netdev_warn(dev: dev->net, format: "Error writing DP_ADDR\n" ); |
492 | goto done; |
493 | } |
494 | |
495 | ret = smsc75xx_write_reg(dev, DP_DATA, data: buf[i]); |
496 | if (ret < 0) { |
497 | netdev_warn(dev: dev->net, format: "Error writing DP_DATA\n" ); |
498 | goto done; |
499 | } |
500 | |
501 | ret = smsc75xx_write_reg(dev, DP_CMD, DP_CMD_WRITE); |
502 | if (ret < 0) { |
503 | netdev_warn(dev: dev->net, format: "Error writing DP_CMD\n" ); |
504 | goto done; |
505 | } |
506 | |
507 | ret = smsc75xx_dataport_wait_not_busy(dev); |
508 | if (ret < 0) { |
509 | netdev_warn(dev: dev->net, format: "smsc75xx_dataport_write timeout\n" ); |
510 | goto done; |
511 | } |
512 | } |
513 | |
514 | done: |
515 | mutex_unlock(lock: &pdata->dataport_mutex); |
516 | return ret; |
517 | } |
518 | |
519 | /* returns hash bit number for given MAC address */ |
520 | static u32 smsc75xx_hash(char addr[ETH_ALEN]) |
521 | { |
522 | return (ether_crc(ETH_ALEN, addr) >> 23) & 0x1ff; |
523 | } |
524 | |
525 | static void smsc75xx_deferred_multicast_write(struct work_struct *param) |
526 | { |
527 | struct smsc75xx_priv *pdata = |
528 | container_of(param, struct smsc75xx_priv, set_multicast); |
529 | struct usbnet *dev = pdata->dev; |
530 | int ret; |
531 | |
532 | netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n" , |
533 | pdata->rfe_ctl); |
534 | |
535 | smsc75xx_dataport_write(dev, DP_SEL_VHF, DP_SEL_VHF_VLAN_LEN, |
536 | DP_SEL_VHF_HASH_LEN, buf: pdata->multicast_hash_table); |
537 | |
538 | ret = smsc75xx_write_reg(dev, RFE_CTL, data: pdata->rfe_ctl); |
539 | if (ret < 0) |
540 | netdev_warn(dev: dev->net, format: "Error writing RFE_CRL\n" ); |
541 | } |
542 | |
543 | static void smsc75xx_set_multicast(struct net_device *netdev) |
544 | { |
545 | struct usbnet *dev = netdev_priv(dev: netdev); |
546 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
547 | unsigned long flags; |
548 | int i; |
549 | |
550 | spin_lock_irqsave(&pdata->rfe_ctl_lock, flags); |
551 | |
552 | pdata->rfe_ctl &= |
553 | ~(RFE_CTL_AU | RFE_CTL_AM | RFE_CTL_DPF | RFE_CTL_MHF); |
554 | pdata->rfe_ctl |= RFE_CTL_AB; |
555 | |
556 | for (i = 0; i < DP_SEL_VHF_HASH_LEN; i++) |
557 | pdata->multicast_hash_table[i] = 0; |
558 | |
559 | if (dev->net->flags & IFF_PROMISC) { |
560 | netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n" ); |
561 | pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_AU; |
562 | } else if (dev->net->flags & IFF_ALLMULTI) { |
563 | netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n" ); |
564 | pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_DPF; |
565 | } else if (!netdev_mc_empty(dev->net)) { |
566 | struct netdev_hw_addr *ha; |
567 | |
568 | netif_dbg(dev, drv, dev->net, "receive multicast hash filter\n" ); |
569 | |
570 | pdata->rfe_ctl |= RFE_CTL_MHF | RFE_CTL_DPF; |
571 | |
572 | netdev_for_each_mc_addr(ha, netdev) { |
573 | u32 bitnum = smsc75xx_hash(addr: ha->addr); |
574 | pdata->multicast_hash_table[bitnum / 32] |= |
575 | (1 << (bitnum % 32)); |
576 | } |
577 | } else { |
578 | netif_dbg(dev, drv, dev->net, "receive own packets only\n" ); |
579 | pdata->rfe_ctl |= RFE_CTL_DPF; |
580 | } |
581 | |
582 | spin_unlock_irqrestore(lock: &pdata->rfe_ctl_lock, flags); |
583 | |
584 | /* defer register writes to a sleepable context */ |
585 | schedule_work(work: &pdata->set_multicast); |
586 | } |
587 | |
588 | static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex, |
589 | u16 lcladv, u16 rmtadv) |
590 | { |
591 | u32 flow = 0, fct_flow = 0; |
592 | int ret; |
593 | |
594 | if (duplex == DUPLEX_FULL) { |
595 | u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv); |
596 | |
597 | if (cap & FLOW_CTRL_TX) { |
598 | flow = (FLOW_TX_FCEN | 0xFFFF); |
599 | /* set fct_flow thresholds to 20% and 80% */ |
600 | fct_flow = (8 << 8) | 32; |
601 | } |
602 | |
603 | if (cap & FLOW_CTRL_RX) |
604 | flow |= FLOW_RX_FCEN; |
605 | |
606 | netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n" , |
607 | (cap & FLOW_CTRL_RX ? "enabled" : "disabled" ), |
608 | (cap & FLOW_CTRL_TX ? "enabled" : "disabled" )); |
609 | } else { |
610 | netif_dbg(dev, link, dev->net, "half duplex\n" ); |
611 | } |
612 | |
613 | ret = smsc75xx_write_reg(dev, FLOW, data: flow); |
614 | if (ret < 0) { |
615 | netdev_warn(dev: dev->net, format: "Error writing FLOW\n" ); |
616 | return ret; |
617 | } |
618 | |
619 | ret = smsc75xx_write_reg(dev, FCT_FLOW, data: fct_flow); |
620 | if (ret < 0) { |
621 | netdev_warn(dev: dev->net, format: "Error writing FCT_FLOW\n" ); |
622 | return ret; |
623 | } |
624 | |
625 | return 0; |
626 | } |
627 | |
628 | static int smsc75xx_link_reset(struct usbnet *dev) |
629 | { |
630 | struct mii_if_info *mii = &dev->mii; |
631 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; |
632 | u16 lcladv, rmtadv; |
633 | int ret; |
634 | |
635 | /* write to clear phy interrupt status */ |
636 | smsc75xx_mdio_write(netdev: dev->net, phy_id: mii->phy_id, PHY_INT_SRC, |
637 | PHY_INT_SRC_CLEAR_ALL); |
638 | |
639 | ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL); |
640 | if (ret < 0) { |
641 | netdev_warn(dev: dev->net, format: "Error writing INT_STS\n" ); |
642 | return ret; |
643 | } |
644 | |
645 | mii_check_media(mii, ok_to_print: 1, init_media: 1); |
646 | mii_ethtool_gset(mii: &dev->mii, ecmd: &ecmd); |
647 | lcladv = smsc75xx_mdio_read(netdev: dev->net, phy_id: mii->phy_id, MII_ADVERTISE); |
648 | rmtadv = smsc75xx_mdio_read(netdev: dev->net, phy_id: mii->phy_id, MII_LPA); |
649 | |
650 | netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n" , |
651 | ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv); |
652 | |
653 | return smsc75xx_update_flowcontrol(dev, duplex: ecmd.duplex, lcladv, rmtadv); |
654 | } |
655 | |
656 | static void smsc75xx_status(struct usbnet *dev, struct urb *urb) |
657 | { |
658 | u32 intdata; |
659 | |
660 | if (urb->actual_length != 4) { |
661 | netdev_warn(dev: dev->net, format: "unexpected urb length %d\n" , |
662 | urb->actual_length); |
663 | return; |
664 | } |
665 | |
666 | intdata = get_unaligned_le32(p: urb->transfer_buffer); |
667 | |
668 | netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n" , intdata); |
669 | |
670 | if (intdata & INT_ENP_PHY_INT) |
671 | usbnet_defer_kevent(dev, EVENT_LINK_RESET); |
672 | else |
673 | netdev_warn(dev: dev->net, format: "unexpected interrupt, intdata=0x%08X\n" , |
674 | intdata); |
675 | } |
676 | |
677 | static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net) |
678 | { |
679 | return MAX_EEPROM_SIZE; |
680 | } |
681 | |
682 | static int smsc75xx_ethtool_get_eeprom(struct net_device *netdev, |
683 | struct ethtool_eeprom *ee, u8 *data) |
684 | { |
685 | struct usbnet *dev = netdev_priv(dev: netdev); |
686 | |
687 | ee->magic = LAN75XX_EEPROM_MAGIC; |
688 | |
689 | return smsc75xx_read_eeprom(dev, offset: ee->offset, length: ee->len, data); |
690 | } |
691 | |
692 | static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev, |
693 | struct ethtool_eeprom *ee, u8 *data) |
694 | { |
695 | struct usbnet *dev = netdev_priv(dev: netdev); |
696 | |
697 | if (ee->magic != LAN75XX_EEPROM_MAGIC) { |
698 | netdev_warn(dev: dev->net, format: "EEPROM: magic value mismatch: 0x%x\n" , |
699 | ee->magic); |
700 | return -EINVAL; |
701 | } |
702 | |
703 | return smsc75xx_write_eeprom(dev, offset: ee->offset, length: ee->len, data); |
704 | } |
705 | |
706 | static void smsc75xx_ethtool_get_wol(struct net_device *net, |
707 | struct ethtool_wolinfo *wolinfo) |
708 | { |
709 | struct usbnet *dev = netdev_priv(dev: net); |
710 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
711 | |
712 | wolinfo->supported = SUPPORTED_WAKE; |
713 | wolinfo->wolopts = pdata->wolopts; |
714 | } |
715 | |
716 | static int smsc75xx_ethtool_set_wol(struct net_device *net, |
717 | struct ethtool_wolinfo *wolinfo) |
718 | { |
719 | struct usbnet *dev = netdev_priv(dev: net); |
720 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
721 | int ret; |
722 | |
723 | if (wolinfo->wolopts & ~SUPPORTED_WAKE) |
724 | return -EINVAL; |
725 | |
726 | pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE; |
727 | |
728 | ret = device_set_wakeup_enable(dev: &dev->udev->dev, enable: pdata->wolopts); |
729 | if (ret < 0) |
730 | netdev_warn(dev: dev->net, format: "device_set_wakeup_enable error %d\n" , ret); |
731 | |
732 | return ret; |
733 | } |
734 | |
735 | static const struct ethtool_ops smsc75xx_ethtool_ops = { |
736 | .get_link = usbnet_get_link, |
737 | .nway_reset = usbnet_nway_reset, |
738 | .get_drvinfo = usbnet_get_drvinfo, |
739 | .get_msglevel = usbnet_get_msglevel, |
740 | .set_msglevel = usbnet_set_msglevel, |
741 | .get_eeprom_len = smsc75xx_ethtool_get_eeprom_len, |
742 | .get_eeprom = smsc75xx_ethtool_get_eeprom, |
743 | .set_eeprom = smsc75xx_ethtool_set_eeprom, |
744 | .get_wol = smsc75xx_ethtool_get_wol, |
745 | .set_wol = smsc75xx_ethtool_set_wol, |
746 | .get_link_ksettings = usbnet_get_link_ksettings_mii, |
747 | .set_link_ksettings = usbnet_set_link_ksettings_mii, |
748 | }; |
749 | |
750 | static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) |
751 | { |
752 | struct usbnet *dev = netdev_priv(dev: netdev); |
753 | |
754 | if (!netif_running(dev: netdev)) |
755 | return -EINVAL; |
756 | |
757 | return generic_mii_ioctl(mii_if: &dev->mii, mii_data: if_mii(rq), cmd, NULL); |
758 | } |
759 | |
760 | static void smsc75xx_init_mac_address(struct usbnet *dev) |
761 | { |
762 | u8 addr[ETH_ALEN]; |
763 | |
764 | /* maybe the boot loader passed the MAC address in devicetree */ |
765 | if (!platform_get_ethdev_address(dev: &dev->udev->dev, netdev: dev->net)) { |
766 | if (is_valid_ether_addr(addr: dev->net->dev_addr)) { |
767 | /* device tree values are valid so use them */ |
768 | netif_dbg(dev, ifup, dev->net, "MAC address read from the device tree\n" ); |
769 | return; |
770 | } |
771 | } |
772 | |
773 | /* try reading mac address from EEPROM */ |
774 | if (smsc75xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, data: addr) == 0) { |
775 | eth_hw_addr_set(dev: dev->net, addr); |
776 | if (is_valid_ether_addr(addr: dev->net->dev_addr)) { |
777 | /* eeprom values are valid so use them */ |
778 | netif_dbg(dev, ifup, dev->net, |
779 | "MAC address read from EEPROM\n" ); |
780 | return; |
781 | } |
782 | } |
783 | |
784 | /* no useful static MAC address found. generate a random one */ |
785 | eth_hw_addr_random(dev: dev->net); |
786 | netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n" ); |
787 | } |
788 | |
789 | static int smsc75xx_set_mac_address(struct usbnet *dev) |
790 | { |
791 | u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 | |
792 | dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24; |
793 | u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8; |
794 | |
795 | int ret = smsc75xx_write_reg(dev, RX_ADDRH, data: addr_hi); |
796 | if (ret < 0) { |
797 | netdev_warn(dev: dev->net, format: "Failed to write RX_ADDRH: %d\n" , ret); |
798 | return ret; |
799 | } |
800 | |
801 | ret = smsc75xx_write_reg(dev, RX_ADDRL, data: addr_lo); |
802 | if (ret < 0) { |
803 | netdev_warn(dev: dev->net, format: "Failed to write RX_ADDRL: %d\n" , ret); |
804 | return ret; |
805 | } |
806 | |
807 | addr_hi |= ADDR_FILTX_FB_VALID; |
808 | ret = smsc75xx_write_reg(dev, ADDR_FILTX, data: addr_hi); |
809 | if (ret < 0) { |
810 | netdev_warn(dev: dev->net, format: "Failed to write ADDR_FILTX: %d\n" , ret); |
811 | return ret; |
812 | } |
813 | |
814 | ret = smsc75xx_write_reg(dev, ADDR_FILTX + 4, data: addr_lo); |
815 | if (ret < 0) |
816 | netdev_warn(dev: dev->net, format: "Failed to write ADDR_FILTX+4: %d\n" , ret); |
817 | |
818 | return ret; |
819 | } |
820 | |
821 | static int smsc75xx_phy_initialize(struct usbnet *dev) |
822 | { |
823 | int bmcr, ret, timeout = 0; |
824 | |
825 | /* Initialize MII structure */ |
826 | dev->mii.dev = dev->net; |
827 | dev->mii.mdio_read = smsc75xx_mdio_read; |
828 | dev->mii.mdio_write = smsc75xx_mdio_write; |
829 | dev->mii.phy_id_mask = 0x1f; |
830 | dev->mii.reg_num_mask = 0x1f; |
831 | dev->mii.supports_gmii = 1; |
832 | dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID; |
833 | |
834 | /* reset phy and wait for reset to complete */ |
835 | smsc75xx_mdio_write(netdev: dev->net, phy_id: dev->mii.phy_id, MII_BMCR, BMCR_RESET); |
836 | |
837 | do { |
838 | msleep(msecs: 10); |
839 | bmcr = smsc75xx_mdio_read(netdev: dev->net, phy_id: dev->mii.phy_id, MII_BMCR); |
840 | if (bmcr < 0) { |
841 | netdev_warn(dev: dev->net, format: "Error reading MII_BMCR\n" ); |
842 | return bmcr; |
843 | } |
844 | timeout++; |
845 | } while ((bmcr & BMCR_RESET) && (timeout < 100)); |
846 | |
847 | if (timeout >= 100) { |
848 | netdev_warn(dev: dev->net, format: "timeout on PHY Reset\n" ); |
849 | return -EIO; |
850 | } |
851 | |
852 | /* phy workaround for gig link */ |
853 | smsc75xx_phy_gig_workaround(dev); |
854 | |
855 | smsc75xx_mdio_write(netdev: dev->net, phy_id: dev->mii.phy_id, MII_ADVERTISE, |
856 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | |
857 | ADVERTISE_PAUSE_ASYM); |
858 | smsc75xx_mdio_write(netdev: dev->net, phy_id: dev->mii.phy_id, MII_CTRL1000, |
859 | ADVERTISE_1000FULL); |
860 | |
861 | /* read and write to clear phy interrupt status */ |
862 | ret = smsc75xx_mdio_read(netdev: dev->net, phy_id: dev->mii.phy_id, PHY_INT_SRC); |
863 | if (ret < 0) { |
864 | netdev_warn(dev: dev->net, format: "Error reading PHY_INT_SRC\n" ); |
865 | return ret; |
866 | } |
867 | |
868 | smsc75xx_mdio_write(netdev: dev->net, phy_id: dev->mii.phy_id, PHY_INT_SRC, regval: 0xffff); |
869 | |
870 | smsc75xx_mdio_write(netdev: dev->net, phy_id: dev->mii.phy_id, PHY_INT_MASK, |
871 | PHY_INT_MASK_DEFAULT); |
872 | mii_nway_restart(mii: &dev->mii); |
873 | |
874 | netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n" ); |
875 | return 0; |
876 | } |
877 | |
878 | static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size) |
879 | { |
880 | int ret = 0; |
881 | u32 buf; |
882 | bool rxenabled; |
883 | |
884 | ret = smsc75xx_read_reg(dev, MAC_RX, data: &buf); |
885 | if (ret < 0) { |
886 | netdev_warn(dev: dev->net, format: "Failed to read MAC_RX: %d\n" , ret); |
887 | return ret; |
888 | } |
889 | |
890 | rxenabled = ((buf & MAC_RX_RXEN) != 0); |
891 | |
892 | if (rxenabled) { |
893 | buf &= ~MAC_RX_RXEN; |
894 | ret = smsc75xx_write_reg(dev, MAC_RX, data: buf); |
895 | if (ret < 0) { |
896 | netdev_warn(dev: dev->net, format: "Failed to write MAC_RX: %d\n" , ret); |
897 | return ret; |
898 | } |
899 | } |
900 | |
901 | /* add 4 to size for FCS */ |
902 | buf &= ~MAC_RX_MAX_SIZE; |
903 | buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT) & MAC_RX_MAX_SIZE); |
904 | |
905 | ret = smsc75xx_write_reg(dev, MAC_RX, data: buf); |
906 | if (ret < 0) { |
907 | netdev_warn(dev: dev->net, format: "Failed to write MAC_RX: %d\n" , ret); |
908 | return ret; |
909 | } |
910 | |
911 | if (rxenabled) { |
912 | buf |= MAC_RX_RXEN; |
913 | ret = smsc75xx_write_reg(dev, MAC_RX, data: buf); |
914 | if (ret < 0) { |
915 | netdev_warn(dev: dev->net, format: "Failed to write MAC_RX: %d\n" , ret); |
916 | return ret; |
917 | } |
918 | } |
919 | |
920 | return 0; |
921 | } |
922 | |
923 | static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu) |
924 | { |
925 | struct usbnet *dev = netdev_priv(dev: netdev); |
926 | int ret; |
927 | |
928 | ret = smsc75xx_set_rx_max_frame_length(dev, size: new_mtu + ETH_HLEN); |
929 | if (ret < 0) { |
930 | netdev_warn(dev: dev->net, format: "Failed to set mac rx frame length\n" ); |
931 | return ret; |
932 | } |
933 | |
934 | return usbnet_change_mtu(net: netdev, new_mtu); |
935 | } |
936 | |
937 | /* Enable or disable Rx checksum offload engine */ |
938 | static int smsc75xx_set_features(struct net_device *netdev, |
939 | netdev_features_t features) |
940 | { |
941 | struct usbnet *dev = netdev_priv(dev: netdev); |
942 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
943 | unsigned long flags; |
944 | int ret; |
945 | |
946 | spin_lock_irqsave(&pdata->rfe_ctl_lock, flags); |
947 | |
948 | if (features & NETIF_F_RXCSUM) |
949 | pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM; |
950 | else |
951 | pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM); |
952 | |
953 | spin_unlock_irqrestore(lock: &pdata->rfe_ctl_lock, flags); |
954 | /* it's racing here! */ |
955 | |
956 | ret = smsc75xx_write_reg(dev, RFE_CTL, data: pdata->rfe_ctl); |
957 | if (ret < 0) { |
958 | netdev_warn(dev: dev->net, format: "Error writing RFE_CTL\n" ); |
959 | return ret; |
960 | } |
961 | return 0; |
962 | } |
963 | |
964 | static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm) |
965 | { |
966 | int timeout = 0; |
967 | |
968 | do { |
969 | u32 buf; |
970 | int ret; |
971 | |
972 | ret = __smsc75xx_read_reg(dev, PMT_CTL, data: &buf, in_pm); |
973 | |
974 | if (ret < 0) { |
975 | netdev_warn(dev: dev->net, format: "Failed to read PMT_CTL: %d\n" , ret); |
976 | return ret; |
977 | } |
978 | |
979 | if (buf & PMT_CTL_DEV_RDY) |
980 | return 0; |
981 | |
982 | msleep(msecs: 10); |
983 | timeout++; |
984 | } while (timeout < 100); |
985 | |
986 | netdev_warn(dev: dev->net, format: "timeout waiting for device ready\n" ); |
987 | return -EIO; |
988 | } |
989 | |
990 | static int smsc75xx_phy_gig_workaround(struct usbnet *dev) |
991 | { |
992 | struct mii_if_info *mii = &dev->mii; |
993 | int ret = 0, timeout = 0; |
994 | u32 buf, link_up = 0; |
995 | |
996 | /* Set the phy in Gig loopback */ |
997 | smsc75xx_mdio_write(netdev: dev->net, phy_id: mii->phy_id, MII_BMCR, regval: 0x4040); |
998 | |
999 | /* Wait for the link up */ |
1000 | do { |
1001 | link_up = smsc75xx_link_ok_nopm(dev); |
1002 | usleep_range(min: 10000, max: 20000); |
1003 | timeout++; |
1004 | } while ((!link_up) && (timeout < 1000)); |
1005 | |
1006 | if (timeout >= 1000) { |
1007 | netdev_warn(dev: dev->net, format: "Timeout waiting for PHY link up\n" ); |
1008 | return -EIO; |
1009 | } |
1010 | |
1011 | /* phy reset */ |
1012 | ret = smsc75xx_read_reg(dev, PMT_CTL, data: &buf); |
1013 | if (ret < 0) { |
1014 | netdev_warn(dev: dev->net, format: "Failed to read PMT_CTL: %d\n" , ret); |
1015 | return ret; |
1016 | } |
1017 | |
1018 | buf |= PMT_CTL_PHY_RST; |
1019 | |
1020 | ret = smsc75xx_write_reg(dev, PMT_CTL, data: buf); |
1021 | if (ret < 0) { |
1022 | netdev_warn(dev: dev->net, format: "Failed to write PMT_CTL: %d\n" , ret); |
1023 | return ret; |
1024 | } |
1025 | |
1026 | timeout = 0; |
1027 | do { |
1028 | usleep_range(min: 10000, max: 20000); |
1029 | ret = smsc75xx_read_reg(dev, PMT_CTL, data: &buf); |
1030 | if (ret < 0) { |
1031 | netdev_warn(dev: dev->net, format: "Failed to read PMT_CTL: %d\n" , |
1032 | ret); |
1033 | return ret; |
1034 | } |
1035 | timeout++; |
1036 | } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100)); |
1037 | |
1038 | if (timeout >= 100) { |
1039 | netdev_warn(dev: dev->net, format: "timeout waiting for PHY Reset\n" ); |
1040 | return -EIO; |
1041 | } |
1042 | |
1043 | return 0; |
1044 | } |
1045 | |
1046 | static int smsc75xx_reset(struct usbnet *dev) |
1047 | { |
1048 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1049 | u32 buf; |
1050 | int ret = 0, timeout; |
1051 | |
1052 | netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset\n" ); |
1053 | |
1054 | ret = smsc75xx_wait_ready(dev, in_pm: 0); |
1055 | if (ret < 0) { |
1056 | netdev_warn(dev: dev->net, format: "device not ready in smsc75xx_reset\n" ); |
1057 | return ret; |
1058 | } |
1059 | |
1060 | ret = smsc75xx_read_reg(dev, HW_CFG, data: &buf); |
1061 | if (ret < 0) { |
1062 | netdev_warn(dev: dev->net, format: "Failed to read HW_CFG: %d\n" , ret); |
1063 | return ret; |
1064 | } |
1065 | |
1066 | buf |= HW_CFG_LRST; |
1067 | |
1068 | ret = smsc75xx_write_reg(dev, HW_CFG, data: buf); |
1069 | if (ret < 0) { |
1070 | netdev_warn(dev: dev->net, format: "Failed to write HW_CFG: %d\n" , ret); |
1071 | return ret; |
1072 | } |
1073 | |
1074 | timeout = 0; |
1075 | do { |
1076 | msleep(msecs: 10); |
1077 | ret = smsc75xx_read_reg(dev, HW_CFG, data: &buf); |
1078 | if (ret < 0) { |
1079 | netdev_warn(dev: dev->net, format: "Failed to read HW_CFG: %d\n" , ret); |
1080 | return ret; |
1081 | } |
1082 | timeout++; |
1083 | } while ((buf & HW_CFG_LRST) && (timeout < 100)); |
1084 | |
1085 | if (timeout >= 100) { |
1086 | netdev_warn(dev: dev->net, format: "timeout on completion of Lite Reset\n" ); |
1087 | return -EIO; |
1088 | } |
1089 | |
1090 | netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY\n" ); |
1091 | |
1092 | ret = smsc75xx_read_reg(dev, PMT_CTL, data: &buf); |
1093 | if (ret < 0) { |
1094 | netdev_warn(dev: dev->net, format: "Failed to read PMT_CTL: %d\n" , ret); |
1095 | return ret; |
1096 | } |
1097 | |
1098 | buf |= PMT_CTL_PHY_RST; |
1099 | |
1100 | ret = smsc75xx_write_reg(dev, PMT_CTL, data: buf); |
1101 | if (ret < 0) { |
1102 | netdev_warn(dev: dev->net, format: "Failed to write PMT_CTL: %d\n" , ret); |
1103 | return ret; |
1104 | } |
1105 | |
1106 | timeout = 0; |
1107 | do { |
1108 | msleep(msecs: 10); |
1109 | ret = smsc75xx_read_reg(dev, PMT_CTL, data: &buf); |
1110 | if (ret < 0) { |
1111 | netdev_warn(dev: dev->net, format: "Failed to read PMT_CTL: %d\n" , ret); |
1112 | return ret; |
1113 | } |
1114 | timeout++; |
1115 | } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100)); |
1116 | |
1117 | if (timeout >= 100) { |
1118 | netdev_warn(dev: dev->net, format: "timeout waiting for PHY Reset\n" ); |
1119 | return -EIO; |
1120 | } |
1121 | |
1122 | netif_dbg(dev, ifup, dev->net, "PHY reset complete\n" ); |
1123 | |
1124 | ret = smsc75xx_set_mac_address(dev); |
1125 | if (ret < 0) { |
1126 | netdev_warn(dev: dev->net, format: "Failed to set mac address\n" ); |
1127 | return ret; |
1128 | } |
1129 | |
1130 | netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n" , |
1131 | dev->net->dev_addr); |
1132 | |
1133 | ret = smsc75xx_read_reg(dev, HW_CFG, data: &buf); |
1134 | if (ret < 0) { |
1135 | netdev_warn(dev: dev->net, format: "Failed to read HW_CFG: %d\n" , ret); |
1136 | return ret; |
1137 | } |
1138 | |
1139 | netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n" , |
1140 | buf); |
1141 | |
1142 | buf |= HW_CFG_BIR; |
1143 | |
1144 | ret = smsc75xx_write_reg(dev, HW_CFG, data: buf); |
1145 | if (ret < 0) { |
1146 | netdev_warn(dev: dev->net, format: "Failed to write HW_CFG: %d\n" , ret); |
1147 | return ret; |
1148 | } |
1149 | |
1150 | ret = smsc75xx_read_reg(dev, HW_CFG, data: &buf); |
1151 | if (ret < 0) { |
1152 | netdev_warn(dev: dev->net, format: "Failed to read HW_CFG: %d\n" , ret); |
1153 | return ret; |
1154 | } |
1155 | |
1156 | netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR: 0x%08x\n" , |
1157 | buf); |
1158 | |
1159 | if (!turbo_mode) { |
1160 | buf = 0; |
1161 | dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE; |
1162 | } else if (dev->udev->speed == USB_SPEED_HIGH) { |
1163 | buf = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE; |
1164 | dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE; |
1165 | } else { |
1166 | buf = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE; |
1167 | dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE; |
1168 | } |
1169 | |
1170 | netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n" , |
1171 | (ulong)dev->rx_urb_size); |
1172 | |
1173 | ret = smsc75xx_write_reg(dev, BURST_CAP, data: buf); |
1174 | if (ret < 0) { |
1175 | netdev_warn(dev: dev->net, format: "Failed to write BURST_CAP: %d\n" , ret); |
1176 | return ret; |
1177 | } |
1178 | |
1179 | ret = smsc75xx_read_reg(dev, BURST_CAP, data: &buf); |
1180 | if (ret < 0) { |
1181 | netdev_warn(dev: dev->net, format: "Failed to read BURST_CAP: %d\n" , ret); |
1182 | return ret; |
1183 | } |
1184 | |
1185 | netif_dbg(dev, ifup, dev->net, |
1186 | "Read Value from BURST_CAP after writing: 0x%08x\n" , buf); |
1187 | |
1188 | ret = smsc75xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY); |
1189 | if (ret < 0) { |
1190 | netdev_warn(dev: dev->net, format: "Failed to write BULK_IN_DLY: %d\n" , ret); |
1191 | return ret; |
1192 | } |
1193 | |
1194 | ret = smsc75xx_read_reg(dev, BULK_IN_DLY, data: &buf); |
1195 | if (ret < 0) { |
1196 | netdev_warn(dev: dev->net, format: "Failed to read BULK_IN_DLY: %d\n" , ret); |
1197 | return ret; |
1198 | } |
1199 | |
1200 | netif_dbg(dev, ifup, dev->net, |
1201 | "Read Value from BULK_IN_DLY after writing: 0x%08x\n" , buf); |
1202 | |
1203 | if (turbo_mode) { |
1204 | ret = smsc75xx_read_reg(dev, HW_CFG, data: &buf); |
1205 | if (ret < 0) { |
1206 | netdev_warn(dev: dev->net, format: "Failed to read HW_CFG: %d\n" , ret); |
1207 | return ret; |
1208 | } |
1209 | |
1210 | netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n" , buf); |
1211 | |
1212 | buf |= (HW_CFG_MEF | HW_CFG_BCE); |
1213 | |
1214 | ret = smsc75xx_write_reg(dev, HW_CFG, data: buf); |
1215 | if (ret < 0) { |
1216 | netdev_warn(dev: dev->net, format: "Failed to write HW_CFG: %d\n" , ret); |
1217 | return ret; |
1218 | } |
1219 | |
1220 | ret = smsc75xx_read_reg(dev, HW_CFG, data: &buf); |
1221 | if (ret < 0) { |
1222 | netdev_warn(dev: dev->net, format: "Failed to read HW_CFG: %d\n" , ret); |
1223 | return ret; |
1224 | } |
1225 | |
1226 | netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n" , buf); |
1227 | } |
1228 | |
1229 | /* set FIFO sizes */ |
1230 | buf = (MAX_RX_FIFO_SIZE - 512) / 512; |
1231 | ret = smsc75xx_write_reg(dev, FCT_RX_FIFO_END, data: buf); |
1232 | if (ret < 0) { |
1233 | netdev_warn(dev: dev->net, format: "Failed to write FCT_RX_FIFO_END: %d\n" , ret); |
1234 | return ret; |
1235 | } |
1236 | |
1237 | netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x\n" , buf); |
1238 | |
1239 | buf = (MAX_TX_FIFO_SIZE - 512) / 512; |
1240 | ret = smsc75xx_write_reg(dev, FCT_TX_FIFO_END, data: buf); |
1241 | if (ret < 0) { |
1242 | netdev_warn(dev: dev->net, format: "Failed to write FCT_TX_FIFO_END: %d\n" , ret); |
1243 | return ret; |
1244 | } |
1245 | |
1246 | netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x\n" , buf); |
1247 | |
1248 | ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL); |
1249 | if (ret < 0) { |
1250 | netdev_warn(dev: dev->net, format: "Failed to write INT_STS: %d\n" , ret); |
1251 | return ret; |
1252 | } |
1253 | |
1254 | ret = smsc75xx_read_reg(dev, ID_REV, data: &buf); |
1255 | if (ret < 0) { |
1256 | netdev_warn(dev: dev->net, format: "Failed to read ID_REV: %d\n" , ret); |
1257 | return ret; |
1258 | } |
1259 | |
1260 | netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n" , buf); |
1261 | |
1262 | ret = smsc75xx_read_reg(dev, E2P_CMD, data: &buf); |
1263 | if (ret < 0) { |
1264 | netdev_warn(dev: dev->net, format: "Failed to read E2P_CMD: %d\n" , ret); |
1265 | return ret; |
1266 | } |
1267 | |
1268 | /* only set default GPIO/LED settings if no EEPROM is detected */ |
1269 | if (!(buf & E2P_CMD_LOADED)) { |
1270 | ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, data: &buf); |
1271 | if (ret < 0) { |
1272 | netdev_warn(dev: dev->net, format: "Failed to read LED_GPIO_CFG: %d\n" , ret); |
1273 | return ret; |
1274 | } |
1275 | |
1276 | buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL); |
1277 | buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL; |
1278 | |
1279 | ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, data: buf); |
1280 | if (ret < 0) { |
1281 | netdev_warn(dev: dev->net, format: "Failed to write LED_GPIO_CFG: %d\n" , ret); |
1282 | return ret; |
1283 | } |
1284 | } |
1285 | |
1286 | ret = smsc75xx_write_reg(dev, FLOW, data: 0); |
1287 | if (ret < 0) { |
1288 | netdev_warn(dev: dev->net, format: "Failed to write FLOW: %d\n" , ret); |
1289 | return ret; |
1290 | } |
1291 | |
1292 | ret = smsc75xx_write_reg(dev, FCT_FLOW, data: 0); |
1293 | if (ret < 0) { |
1294 | netdev_warn(dev: dev->net, format: "Failed to write FCT_FLOW: %d\n" , ret); |
1295 | return ret; |
1296 | } |
1297 | |
1298 | /* Don't need rfe_ctl_lock during initialisation */ |
1299 | ret = smsc75xx_read_reg(dev, RFE_CTL, data: &pdata->rfe_ctl); |
1300 | if (ret < 0) { |
1301 | netdev_warn(dev: dev->net, format: "Failed to read RFE_CTL: %d\n" , ret); |
1302 | return ret; |
1303 | } |
1304 | |
1305 | pdata->rfe_ctl |= RFE_CTL_AB | RFE_CTL_DPF; |
1306 | |
1307 | ret = smsc75xx_write_reg(dev, RFE_CTL, data: pdata->rfe_ctl); |
1308 | if (ret < 0) { |
1309 | netdev_warn(dev: dev->net, format: "Failed to write RFE_CTL: %d\n" , ret); |
1310 | return ret; |
1311 | } |
1312 | |
1313 | ret = smsc75xx_read_reg(dev, RFE_CTL, data: &pdata->rfe_ctl); |
1314 | if (ret < 0) { |
1315 | netdev_warn(dev: dev->net, format: "Failed to read RFE_CTL: %d\n" , ret); |
1316 | return ret; |
1317 | } |
1318 | |
1319 | netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x\n" , |
1320 | pdata->rfe_ctl); |
1321 | |
1322 | /* Enable or disable checksum offload engines */ |
1323 | smsc75xx_set_features(netdev: dev->net, features: dev->net->features); |
1324 | |
1325 | smsc75xx_set_multicast(netdev: dev->net); |
1326 | |
1327 | ret = smsc75xx_phy_initialize(dev); |
1328 | if (ret < 0) { |
1329 | netdev_warn(dev: dev->net, format: "Failed to initialize PHY: %d\n" , ret); |
1330 | return ret; |
1331 | } |
1332 | |
1333 | ret = smsc75xx_read_reg(dev, INT_EP_CTL, data: &buf); |
1334 | if (ret < 0) { |
1335 | netdev_warn(dev: dev->net, format: "Failed to read INT_EP_CTL: %d\n" , ret); |
1336 | return ret; |
1337 | } |
1338 | |
1339 | /* enable PHY interrupts */ |
1340 | buf |= INT_ENP_PHY_INT; |
1341 | |
1342 | ret = smsc75xx_write_reg(dev, INT_EP_CTL, data: buf); |
1343 | if (ret < 0) { |
1344 | netdev_warn(dev: dev->net, format: "Failed to write INT_EP_CTL: %d\n" , ret); |
1345 | return ret; |
1346 | } |
1347 | |
1348 | /* allow mac to detect speed and duplex from phy */ |
1349 | ret = smsc75xx_read_reg(dev, MAC_CR, data: &buf); |
1350 | if (ret < 0) { |
1351 | netdev_warn(dev: dev->net, format: "Failed to read MAC_CR: %d\n" , ret); |
1352 | return ret; |
1353 | } |
1354 | |
1355 | buf |= (MAC_CR_ADD | MAC_CR_ASD); |
1356 | ret = smsc75xx_write_reg(dev, MAC_CR, data: buf); |
1357 | if (ret < 0) { |
1358 | netdev_warn(dev: dev->net, format: "Failed to write MAC_CR: %d\n" , ret); |
1359 | return ret; |
1360 | } |
1361 | |
1362 | ret = smsc75xx_read_reg(dev, MAC_TX, data: &buf); |
1363 | if (ret < 0) { |
1364 | netdev_warn(dev: dev->net, format: "Failed to read MAC_TX: %d\n" , ret); |
1365 | return ret; |
1366 | } |
1367 | |
1368 | buf |= MAC_TX_TXEN; |
1369 | |
1370 | ret = smsc75xx_write_reg(dev, MAC_TX, data: buf); |
1371 | if (ret < 0) { |
1372 | netdev_warn(dev: dev->net, format: "Failed to write MAC_TX: %d\n" , ret); |
1373 | return ret; |
1374 | } |
1375 | |
1376 | netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x\n" , buf); |
1377 | |
1378 | ret = smsc75xx_read_reg(dev, FCT_TX_CTL, data: &buf); |
1379 | if (ret < 0) { |
1380 | netdev_warn(dev: dev->net, format: "Failed to read FCT_TX_CTL: %d\n" , ret); |
1381 | return ret; |
1382 | } |
1383 | |
1384 | buf |= FCT_TX_CTL_EN; |
1385 | |
1386 | ret = smsc75xx_write_reg(dev, FCT_TX_CTL, data: buf); |
1387 | if (ret < 0) { |
1388 | netdev_warn(dev: dev->net, format: "Failed to write FCT_TX_CTL: %d\n" , ret); |
1389 | return ret; |
1390 | } |
1391 | |
1392 | netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n" , buf); |
1393 | |
1394 | ret = smsc75xx_set_rx_max_frame_length(dev, size: dev->net->mtu + ETH_HLEN); |
1395 | if (ret < 0) { |
1396 | netdev_warn(dev: dev->net, format: "Failed to set max rx frame length\n" ); |
1397 | return ret; |
1398 | } |
1399 | |
1400 | ret = smsc75xx_read_reg(dev, MAC_RX, data: &buf); |
1401 | if (ret < 0) { |
1402 | netdev_warn(dev: dev->net, format: "Failed to read MAC_RX: %d\n" , ret); |
1403 | return ret; |
1404 | } |
1405 | |
1406 | buf |= MAC_RX_RXEN; |
1407 | |
1408 | ret = smsc75xx_write_reg(dev, MAC_RX, data: buf); |
1409 | if (ret < 0) { |
1410 | netdev_warn(dev: dev->net, format: "Failed to write MAC_RX: %d\n" , ret); |
1411 | return ret; |
1412 | } |
1413 | |
1414 | netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x\n" , buf); |
1415 | |
1416 | ret = smsc75xx_read_reg(dev, FCT_RX_CTL, data: &buf); |
1417 | if (ret < 0) { |
1418 | netdev_warn(dev: dev->net, format: "Failed to read FCT_RX_CTL: %d\n" , ret); |
1419 | return ret; |
1420 | } |
1421 | |
1422 | buf |= FCT_RX_CTL_EN; |
1423 | |
1424 | ret = smsc75xx_write_reg(dev, FCT_RX_CTL, data: buf); |
1425 | if (ret < 0) { |
1426 | netdev_warn(dev: dev->net, format: "Failed to write FCT_RX_CTL: %d\n" , ret); |
1427 | return ret; |
1428 | } |
1429 | |
1430 | netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x\n" , buf); |
1431 | |
1432 | netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0\n" ); |
1433 | return 0; |
1434 | } |
1435 | |
1436 | static const struct net_device_ops smsc75xx_netdev_ops = { |
1437 | .ndo_open = usbnet_open, |
1438 | .ndo_stop = usbnet_stop, |
1439 | .ndo_start_xmit = usbnet_start_xmit, |
1440 | .ndo_tx_timeout = usbnet_tx_timeout, |
1441 | .ndo_get_stats64 = dev_get_tstats64, |
1442 | .ndo_change_mtu = smsc75xx_change_mtu, |
1443 | .ndo_set_mac_address = eth_mac_addr, |
1444 | .ndo_validate_addr = eth_validate_addr, |
1445 | .ndo_eth_ioctl = smsc75xx_ioctl, |
1446 | .ndo_set_rx_mode = smsc75xx_set_multicast, |
1447 | .ndo_set_features = smsc75xx_set_features, |
1448 | }; |
1449 | |
1450 | static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) |
1451 | { |
1452 | struct smsc75xx_priv *pdata = NULL; |
1453 | int ret; |
1454 | |
1455 | printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n" ); |
1456 | |
1457 | ret = usbnet_get_endpoints(dev, intf); |
1458 | if (ret < 0) { |
1459 | netdev_warn(dev: dev->net, format: "usbnet_get_endpoints failed: %d\n" , ret); |
1460 | return ret; |
1461 | } |
1462 | |
1463 | dev->data[0] = (unsigned long)kzalloc(size: sizeof(struct smsc75xx_priv), |
1464 | GFP_KERNEL); |
1465 | |
1466 | pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1467 | if (!pdata) |
1468 | return -ENOMEM; |
1469 | |
1470 | pdata->dev = dev; |
1471 | |
1472 | spin_lock_init(&pdata->rfe_ctl_lock); |
1473 | mutex_init(&pdata->dataport_mutex); |
1474 | |
1475 | INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write); |
1476 | |
1477 | if (DEFAULT_TX_CSUM_ENABLE) |
1478 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; |
1479 | |
1480 | if (DEFAULT_RX_CSUM_ENABLE) |
1481 | dev->net->features |= NETIF_F_RXCSUM; |
1482 | |
1483 | dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
1484 | NETIF_F_RXCSUM; |
1485 | |
1486 | ret = smsc75xx_wait_ready(dev, in_pm: 0); |
1487 | if (ret < 0) { |
1488 | netdev_warn(dev: dev->net, format: "device not ready in smsc75xx_bind\n" ); |
1489 | goto free_pdata; |
1490 | } |
1491 | |
1492 | smsc75xx_init_mac_address(dev); |
1493 | |
1494 | /* Init all registers */ |
1495 | ret = smsc75xx_reset(dev); |
1496 | if (ret < 0) { |
1497 | netdev_warn(dev: dev->net, format: "smsc75xx_reset error %d\n" , ret); |
1498 | goto cancel_work; |
1499 | } |
1500 | |
1501 | dev->net->netdev_ops = &smsc75xx_netdev_ops; |
1502 | dev->net->ethtool_ops = &smsc75xx_ethtool_ops; |
1503 | dev->net->flags |= IFF_MULTICAST; |
1504 | dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD; |
1505 | dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; |
1506 | dev->net->max_mtu = MAX_SINGLE_PACKET_SIZE; |
1507 | return 0; |
1508 | |
1509 | cancel_work: |
1510 | cancel_work_sync(work: &pdata->set_multicast); |
1511 | free_pdata: |
1512 | kfree(objp: pdata); |
1513 | dev->data[0] = 0; |
1514 | return ret; |
1515 | } |
1516 | |
1517 | static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf) |
1518 | { |
1519 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1520 | if (pdata) { |
1521 | cancel_work_sync(work: &pdata->set_multicast); |
1522 | netif_dbg(dev, ifdown, dev->net, "free pdata\n" ); |
1523 | kfree(objp: pdata); |
1524 | dev->data[0] = 0; |
1525 | } |
1526 | } |
1527 | |
1528 | static u16 smsc_crc(const u8 *buffer, size_t len) |
1529 | { |
1530 | return bitrev16(crc16(0xFFFF, buffer, len)); |
1531 | } |
1532 | |
1533 | static int smsc75xx_write_wuff(struct usbnet *dev, int filter, u32 wuf_cfg, |
1534 | u32 wuf_mask1) |
1535 | { |
1536 | int cfg_base = WUF_CFGX + filter * 4; |
1537 | int mask_base = WUF_MASKX + filter * 16; |
1538 | int ret; |
1539 | |
1540 | ret = smsc75xx_write_reg(dev, index: cfg_base, data: wuf_cfg); |
1541 | if (ret < 0) { |
1542 | netdev_warn(dev: dev->net, format: "Error writing WUF_CFGX\n" ); |
1543 | return ret; |
1544 | } |
1545 | |
1546 | ret = smsc75xx_write_reg(dev, index: mask_base, data: wuf_mask1); |
1547 | if (ret < 0) { |
1548 | netdev_warn(dev: dev->net, format: "Error writing WUF_MASKX\n" ); |
1549 | return ret; |
1550 | } |
1551 | |
1552 | ret = smsc75xx_write_reg(dev, index: mask_base + 4, data: 0); |
1553 | if (ret < 0) { |
1554 | netdev_warn(dev: dev->net, format: "Error writing WUF_MASKX\n" ); |
1555 | return ret; |
1556 | } |
1557 | |
1558 | ret = smsc75xx_write_reg(dev, index: mask_base + 8, data: 0); |
1559 | if (ret < 0) { |
1560 | netdev_warn(dev: dev->net, format: "Error writing WUF_MASKX\n" ); |
1561 | return ret; |
1562 | } |
1563 | |
1564 | ret = smsc75xx_write_reg(dev, index: mask_base + 12, data: 0); |
1565 | if (ret < 0) { |
1566 | netdev_warn(dev: dev->net, format: "Error writing WUF_MASKX\n" ); |
1567 | return ret; |
1568 | } |
1569 | |
1570 | return 0; |
1571 | } |
1572 | |
1573 | static int smsc75xx_enter_suspend0(struct usbnet *dev) |
1574 | { |
1575 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1576 | u32 val; |
1577 | int ret; |
1578 | |
1579 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
1580 | if (ret < 0) { |
1581 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
1582 | return ret; |
1583 | } |
1584 | |
1585 | val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_PHY_RST)); |
1586 | val |= PMT_CTL_SUS_MODE_0 | PMT_CTL_WOL_EN | PMT_CTL_WUPS; |
1587 | |
1588 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
1589 | if (ret < 0) { |
1590 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
1591 | return ret; |
1592 | } |
1593 | |
1594 | pdata->suspend_flags |= SUSPEND_SUSPEND0; |
1595 | |
1596 | return 0; |
1597 | } |
1598 | |
1599 | static int smsc75xx_enter_suspend1(struct usbnet *dev) |
1600 | { |
1601 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1602 | u32 val; |
1603 | int ret; |
1604 | |
1605 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
1606 | if (ret < 0) { |
1607 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
1608 | return ret; |
1609 | } |
1610 | |
1611 | val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST); |
1612 | val |= PMT_CTL_SUS_MODE_1; |
1613 | |
1614 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
1615 | if (ret < 0) { |
1616 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
1617 | return ret; |
1618 | } |
1619 | |
1620 | /* clear wol status, enable energy detection */ |
1621 | val &= ~PMT_CTL_WUPS; |
1622 | val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN); |
1623 | |
1624 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
1625 | if (ret < 0) { |
1626 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
1627 | return ret; |
1628 | } |
1629 | |
1630 | pdata->suspend_flags |= SUSPEND_SUSPEND1; |
1631 | |
1632 | return 0; |
1633 | } |
1634 | |
1635 | static int smsc75xx_enter_suspend2(struct usbnet *dev) |
1636 | { |
1637 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1638 | u32 val; |
1639 | int ret; |
1640 | |
1641 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
1642 | if (ret < 0) { |
1643 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
1644 | return ret; |
1645 | } |
1646 | |
1647 | val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST); |
1648 | val |= PMT_CTL_SUS_MODE_2; |
1649 | |
1650 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
1651 | if (ret < 0) { |
1652 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
1653 | return ret; |
1654 | } |
1655 | |
1656 | pdata->suspend_flags |= SUSPEND_SUSPEND2; |
1657 | |
1658 | return 0; |
1659 | } |
1660 | |
1661 | static int smsc75xx_enter_suspend3(struct usbnet *dev) |
1662 | { |
1663 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1664 | u32 val; |
1665 | int ret; |
1666 | |
1667 | ret = smsc75xx_read_reg_nopm(dev, FCT_RX_CTL, data: &val); |
1668 | if (ret < 0) { |
1669 | netdev_warn(dev: dev->net, format: "Error reading FCT_RX_CTL\n" ); |
1670 | return ret; |
1671 | } |
1672 | |
1673 | if (val & FCT_RX_CTL_RXUSED) { |
1674 | netdev_dbg(dev->net, "rx fifo not empty in autosuspend\n" ); |
1675 | return -EBUSY; |
1676 | } |
1677 | |
1678 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
1679 | if (ret < 0) { |
1680 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
1681 | return ret; |
1682 | } |
1683 | |
1684 | val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST); |
1685 | val |= PMT_CTL_SUS_MODE_3 | PMT_CTL_RES_CLR_WKP_EN; |
1686 | |
1687 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
1688 | if (ret < 0) { |
1689 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
1690 | return ret; |
1691 | } |
1692 | |
1693 | /* clear wol status */ |
1694 | val &= ~PMT_CTL_WUPS; |
1695 | val |= PMT_CTL_WUPS_WOL; |
1696 | |
1697 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
1698 | if (ret < 0) { |
1699 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
1700 | return ret; |
1701 | } |
1702 | |
1703 | pdata->suspend_flags |= SUSPEND_SUSPEND3; |
1704 | |
1705 | return 0; |
1706 | } |
1707 | |
1708 | static int smsc75xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask) |
1709 | { |
1710 | struct mii_if_info *mii = &dev->mii; |
1711 | int ret; |
1712 | |
1713 | netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n" ); |
1714 | |
1715 | /* read to clear */ |
1716 | ret = smsc75xx_mdio_read_nopm(netdev: dev->net, phy_id: mii->phy_id, PHY_INT_SRC); |
1717 | if (ret < 0) { |
1718 | netdev_warn(dev: dev->net, format: "Error reading PHY_INT_SRC\n" ); |
1719 | return ret; |
1720 | } |
1721 | |
1722 | /* enable interrupt source */ |
1723 | ret = smsc75xx_mdio_read_nopm(netdev: dev->net, phy_id: mii->phy_id, PHY_INT_MASK); |
1724 | if (ret < 0) { |
1725 | netdev_warn(dev: dev->net, format: "Error reading PHY_INT_MASK\n" ); |
1726 | return ret; |
1727 | } |
1728 | |
1729 | ret |= mask; |
1730 | |
1731 | smsc75xx_mdio_write_nopm(netdev: dev->net, phy_id: mii->phy_id, PHY_INT_MASK, regval: ret); |
1732 | |
1733 | return 0; |
1734 | } |
1735 | |
1736 | static int smsc75xx_link_ok_nopm(struct usbnet *dev) |
1737 | { |
1738 | struct mii_if_info *mii = &dev->mii; |
1739 | int ret; |
1740 | |
1741 | /* first, a dummy read, needed to latch some MII phys */ |
1742 | ret = smsc75xx_mdio_read_nopm(netdev: dev->net, phy_id: mii->phy_id, MII_BMSR); |
1743 | if (ret < 0) { |
1744 | netdev_warn(dev: dev->net, format: "Error reading MII_BMSR\n" ); |
1745 | return ret; |
1746 | } |
1747 | |
1748 | ret = smsc75xx_mdio_read_nopm(netdev: dev->net, phy_id: mii->phy_id, MII_BMSR); |
1749 | if (ret < 0) { |
1750 | netdev_warn(dev: dev->net, format: "Error reading MII_BMSR\n" ); |
1751 | return ret; |
1752 | } |
1753 | |
1754 | return !!(ret & BMSR_LSTATUS); |
1755 | } |
1756 | |
1757 | static int smsc75xx_autosuspend(struct usbnet *dev, u32 link_up) |
1758 | { |
1759 | int ret; |
1760 | |
1761 | if (!netif_running(dev: dev->net)) { |
1762 | /* interface is ifconfig down so fully power down hw */ |
1763 | netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n" ); |
1764 | return smsc75xx_enter_suspend2(dev); |
1765 | } |
1766 | |
1767 | if (!link_up) { |
1768 | /* link is down so enter EDPD mode */ |
1769 | netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n" ); |
1770 | |
1771 | /* enable PHY wakeup events for if cable is attached */ |
1772 | ret = smsc75xx_enable_phy_wakeup_interrupts(dev, |
1773 | PHY_INT_MASK_ANEG_COMP); |
1774 | if (ret < 0) { |
1775 | netdev_warn(dev: dev->net, format: "error enabling PHY wakeup ints\n" ); |
1776 | return ret; |
1777 | } |
1778 | |
1779 | netdev_info(dev: dev->net, format: "entering SUSPEND1 mode\n" ); |
1780 | return smsc75xx_enter_suspend1(dev); |
1781 | } |
1782 | |
1783 | /* enable PHY wakeup events so we remote wakeup if cable is pulled */ |
1784 | ret = smsc75xx_enable_phy_wakeup_interrupts(dev, |
1785 | PHY_INT_MASK_LINK_DOWN); |
1786 | if (ret < 0) { |
1787 | netdev_warn(dev: dev->net, format: "error enabling PHY wakeup ints\n" ); |
1788 | return ret; |
1789 | } |
1790 | |
1791 | netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n" ); |
1792 | return smsc75xx_enter_suspend3(dev); |
1793 | } |
1794 | |
1795 | static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message) |
1796 | { |
1797 | struct usbnet *dev = usb_get_intfdata(intf); |
1798 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
1799 | u32 val, link_up; |
1800 | int ret; |
1801 | |
1802 | ret = usbnet_suspend(intf, message); |
1803 | if (ret < 0) { |
1804 | netdev_warn(dev: dev->net, format: "usbnet_suspend error\n" ); |
1805 | return ret; |
1806 | } |
1807 | |
1808 | if (pdata->suspend_flags) { |
1809 | netdev_warn(dev: dev->net, format: "error during last resume\n" ); |
1810 | pdata->suspend_flags = 0; |
1811 | } |
1812 | |
1813 | /* determine if link is up using only _nopm functions */ |
1814 | link_up = smsc75xx_link_ok_nopm(dev); |
1815 | |
1816 | if (message.event == PM_EVENT_AUTO_SUSPEND) { |
1817 | ret = smsc75xx_autosuspend(dev, link_up); |
1818 | goto done; |
1819 | } |
1820 | |
1821 | /* if we get this far we're not autosuspending */ |
1822 | /* if no wol options set, or if link is down and we're not waking on |
1823 | * PHY activity, enter lowest power SUSPEND2 mode |
1824 | */ |
1825 | if (!(pdata->wolopts & SUPPORTED_WAKE) || |
1826 | !(link_up || (pdata->wolopts & WAKE_PHY))) { |
1827 | netdev_info(dev: dev->net, format: "entering SUSPEND2 mode\n" ); |
1828 | |
1829 | /* disable energy detect (link up) & wake up events */ |
1830 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
1831 | if (ret < 0) { |
1832 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
1833 | goto done; |
1834 | } |
1835 | |
1836 | val &= ~(WUCSR_MPEN | WUCSR_WUEN); |
1837 | |
1838 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
1839 | if (ret < 0) { |
1840 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
1841 | goto done; |
1842 | } |
1843 | |
1844 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
1845 | if (ret < 0) { |
1846 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
1847 | goto done; |
1848 | } |
1849 | |
1850 | val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN); |
1851 | |
1852 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
1853 | if (ret < 0) { |
1854 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
1855 | goto done; |
1856 | } |
1857 | |
1858 | ret = smsc75xx_enter_suspend2(dev); |
1859 | goto done; |
1860 | } |
1861 | |
1862 | if (pdata->wolopts & WAKE_PHY) { |
1863 | ret = smsc75xx_enable_phy_wakeup_interrupts(dev, |
1864 | mask: (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN)); |
1865 | if (ret < 0) { |
1866 | netdev_warn(dev: dev->net, format: "error enabling PHY wakeup ints\n" ); |
1867 | goto done; |
1868 | } |
1869 | |
1870 | /* if link is down then configure EDPD and enter SUSPEND1, |
1871 | * otherwise enter SUSPEND0 below |
1872 | */ |
1873 | if (!link_up) { |
1874 | struct mii_if_info *mii = &dev->mii; |
1875 | netdev_info(dev: dev->net, format: "entering SUSPEND1 mode\n" ); |
1876 | |
1877 | /* enable energy detect power-down mode */ |
1878 | ret = smsc75xx_mdio_read_nopm(netdev: dev->net, phy_id: mii->phy_id, |
1879 | PHY_MODE_CTRL_STS); |
1880 | if (ret < 0) { |
1881 | netdev_warn(dev: dev->net, format: "Error reading PHY_MODE_CTRL_STS\n" ); |
1882 | goto done; |
1883 | } |
1884 | |
1885 | ret |= MODE_CTRL_STS_EDPWRDOWN; |
1886 | |
1887 | smsc75xx_mdio_write_nopm(netdev: dev->net, phy_id: mii->phy_id, |
1888 | PHY_MODE_CTRL_STS, regval: ret); |
1889 | |
1890 | /* enter SUSPEND1 mode */ |
1891 | ret = smsc75xx_enter_suspend1(dev); |
1892 | goto done; |
1893 | } |
1894 | } |
1895 | |
1896 | if (pdata->wolopts & (WAKE_MCAST | WAKE_ARP)) { |
1897 | int i, filter = 0; |
1898 | |
1899 | /* disable all filters */ |
1900 | for (i = 0; i < WUF_NUM; i++) { |
1901 | ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, data: 0); |
1902 | if (ret < 0) { |
1903 | netdev_warn(dev: dev->net, format: "Error writing WUF_CFGX\n" ); |
1904 | goto done; |
1905 | } |
1906 | } |
1907 | |
1908 | if (pdata->wolopts & WAKE_MCAST) { |
1909 | const u8 mcast[] = {0x01, 0x00, 0x5E}; |
1910 | netdev_info(dev: dev->net, format: "enabling multicast detection\n" ); |
1911 | |
1912 | val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST |
1913 | | smsc_crc(buffer: mcast, len: 3); |
1914 | ret = smsc75xx_write_wuff(dev, filter: filter++, wuf_cfg: val, wuf_mask1: 0x0007); |
1915 | if (ret < 0) { |
1916 | netdev_warn(dev: dev->net, format: "Error writing wakeup filter\n" ); |
1917 | goto done; |
1918 | } |
1919 | } |
1920 | |
1921 | if (pdata->wolopts & WAKE_ARP) { |
1922 | const u8 arp[] = {0x08, 0x06}; |
1923 | netdev_info(dev: dev->net, format: "enabling ARP detection\n" ); |
1924 | |
1925 | val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16) |
1926 | | smsc_crc(buffer: arp, len: 2); |
1927 | ret = smsc75xx_write_wuff(dev, filter: filter++, wuf_cfg: val, wuf_mask1: 0x0003); |
1928 | if (ret < 0) { |
1929 | netdev_warn(dev: dev->net, format: "Error writing wakeup filter\n" ); |
1930 | goto done; |
1931 | } |
1932 | } |
1933 | |
1934 | /* clear any pending pattern match packet status */ |
1935 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
1936 | if (ret < 0) { |
1937 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
1938 | goto done; |
1939 | } |
1940 | |
1941 | val |= WUCSR_WUFR; |
1942 | |
1943 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
1944 | if (ret < 0) { |
1945 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
1946 | goto done; |
1947 | } |
1948 | |
1949 | netdev_info(dev: dev->net, format: "enabling packet match detection\n" ); |
1950 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
1951 | if (ret < 0) { |
1952 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
1953 | goto done; |
1954 | } |
1955 | |
1956 | val |= WUCSR_WUEN; |
1957 | |
1958 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
1959 | if (ret < 0) { |
1960 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
1961 | goto done; |
1962 | } |
1963 | } else { |
1964 | netdev_info(dev: dev->net, format: "disabling packet match detection\n" ); |
1965 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
1966 | if (ret < 0) { |
1967 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
1968 | goto done; |
1969 | } |
1970 | |
1971 | val &= ~WUCSR_WUEN; |
1972 | |
1973 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
1974 | if (ret < 0) { |
1975 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
1976 | goto done; |
1977 | } |
1978 | } |
1979 | |
1980 | /* disable magic, bcast & unicast wakeup sources */ |
1981 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
1982 | if (ret < 0) { |
1983 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
1984 | goto done; |
1985 | } |
1986 | |
1987 | val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN); |
1988 | |
1989 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
1990 | if (ret < 0) { |
1991 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
1992 | goto done; |
1993 | } |
1994 | |
1995 | if (pdata->wolopts & WAKE_PHY) { |
1996 | netdev_info(dev: dev->net, format: "enabling PHY wakeup\n" ); |
1997 | |
1998 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
1999 | if (ret < 0) { |
2000 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
2001 | goto done; |
2002 | } |
2003 | |
2004 | /* clear wol status, enable energy detection */ |
2005 | val &= ~PMT_CTL_WUPS; |
2006 | val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN); |
2007 | |
2008 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
2009 | if (ret < 0) { |
2010 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
2011 | goto done; |
2012 | } |
2013 | } |
2014 | |
2015 | if (pdata->wolopts & WAKE_MAGIC) { |
2016 | netdev_info(dev: dev->net, format: "enabling magic packet wakeup\n" ); |
2017 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
2018 | if (ret < 0) { |
2019 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
2020 | goto done; |
2021 | } |
2022 | |
2023 | /* clear any pending magic packet status */ |
2024 | val |= WUCSR_MPR | WUCSR_MPEN; |
2025 | |
2026 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
2027 | if (ret < 0) { |
2028 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
2029 | goto done; |
2030 | } |
2031 | } |
2032 | |
2033 | if (pdata->wolopts & WAKE_BCAST) { |
2034 | netdev_info(dev: dev->net, format: "enabling broadcast detection\n" ); |
2035 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
2036 | if (ret < 0) { |
2037 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
2038 | goto done; |
2039 | } |
2040 | |
2041 | val |= WUCSR_BCAST_FR | WUCSR_BCST_EN; |
2042 | |
2043 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
2044 | if (ret < 0) { |
2045 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
2046 | goto done; |
2047 | } |
2048 | } |
2049 | |
2050 | if (pdata->wolopts & WAKE_UCAST) { |
2051 | netdev_info(dev: dev->net, format: "enabling unicast detection\n" ); |
2052 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
2053 | if (ret < 0) { |
2054 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
2055 | goto done; |
2056 | } |
2057 | |
2058 | val |= WUCSR_WUFR | WUCSR_PFDA_EN; |
2059 | |
2060 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
2061 | if (ret < 0) { |
2062 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
2063 | goto done; |
2064 | } |
2065 | } |
2066 | |
2067 | /* enable receiver to enable frame reception */ |
2068 | ret = smsc75xx_read_reg_nopm(dev, MAC_RX, data: &val); |
2069 | if (ret < 0) { |
2070 | netdev_warn(dev: dev->net, format: "Failed to read MAC_RX: %d\n" , ret); |
2071 | goto done; |
2072 | } |
2073 | |
2074 | val |= MAC_RX_RXEN; |
2075 | |
2076 | ret = smsc75xx_write_reg_nopm(dev, MAC_RX, data: val); |
2077 | if (ret < 0) { |
2078 | netdev_warn(dev: dev->net, format: "Failed to write MAC_RX: %d\n" , ret); |
2079 | goto done; |
2080 | } |
2081 | |
2082 | /* some wol options are enabled, so enter SUSPEND0 */ |
2083 | netdev_info(dev: dev->net, format: "entering SUSPEND0 mode\n" ); |
2084 | ret = smsc75xx_enter_suspend0(dev); |
2085 | |
2086 | done: |
2087 | /* |
2088 | * TODO: resume() might need to handle the suspend failure |
2089 | * in system sleep |
2090 | */ |
2091 | if (ret && PMSG_IS_AUTO(message)) |
2092 | usbnet_resume(intf); |
2093 | return ret; |
2094 | } |
2095 | |
2096 | static int smsc75xx_resume(struct usb_interface *intf) |
2097 | { |
2098 | struct usbnet *dev = usb_get_intfdata(intf); |
2099 | struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); |
2100 | u8 suspend_flags = pdata->suspend_flags; |
2101 | int ret; |
2102 | u32 val; |
2103 | |
2104 | netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n" , suspend_flags); |
2105 | |
2106 | /* do this first to ensure it's cleared even in error case */ |
2107 | pdata->suspend_flags = 0; |
2108 | |
2109 | if (suspend_flags & SUSPEND_ALLMODES) { |
2110 | /* Disable wakeup sources */ |
2111 | ret = smsc75xx_read_reg_nopm(dev, WUCSR, data: &val); |
2112 | if (ret < 0) { |
2113 | netdev_warn(dev: dev->net, format: "Error reading WUCSR\n" ); |
2114 | return ret; |
2115 | } |
2116 | |
2117 | val &= ~(WUCSR_WUEN | WUCSR_MPEN | WUCSR_PFDA_EN |
2118 | | WUCSR_BCST_EN); |
2119 | |
2120 | ret = smsc75xx_write_reg_nopm(dev, WUCSR, data: val); |
2121 | if (ret < 0) { |
2122 | netdev_warn(dev: dev->net, format: "Error writing WUCSR\n" ); |
2123 | return ret; |
2124 | } |
2125 | |
2126 | /* clear wake-up status */ |
2127 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
2128 | if (ret < 0) { |
2129 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
2130 | return ret; |
2131 | } |
2132 | |
2133 | val &= ~PMT_CTL_WOL_EN; |
2134 | val |= PMT_CTL_WUPS; |
2135 | |
2136 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
2137 | if (ret < 0) { |
2138 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
2139 | return ret; |
2140 | } |
2141 | } |
2142 | |
2143 | if (suspend_flags & SUSPEND_SUSPEND2) { |
2144 | netdev_info(dev: dev->net, format: "resuming from SUSPEND2\n" ); |
2145 | |
2146 | ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, data: &val); |
2147 | if (ret < 0) { |
2148 | netdev_warn(dev: dev->net, format: "Error reading PMT_CTL\n" ); |
2149 | return ret; |
2150 | } |
2151 | |
2152 | val |= PMT_CTL_PHY_PWRUP; |
2153 | |
2154 | ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, data: val); |
2155 | if (ret < 0) { |
2156 | netdev_warn(dev: dev->net, format: "Error writing PMT_CTL\n" ); |
2157 | return ret; |
2158 | } |
2159 | } |
2160 | |
2161 | ret = smsc75xx_wait_ready(dev, in_pm: 1); |
2162 | if (ret < 0) { |
2163 | netdev_warn(dev: dev->net, format: "device not ready in smsc75xx_resume\n" ); |
2164 | return ret; |
2165 | } |
2166 | |
2167 | return usbnet_resume(intf); |
2168 | } |
2169 | |
2170 | static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb, |
2171 | u32 rx_cmd_a, u32 rx_cmd_b) |
2172 | { |
2173 | if (!(dev->net->features & NETIF_F_RXCSUM) || |
2174 | unlikely(rx_cmd_a & RX_CMD_A_LCSM)) { |
2175 | skb->ip_summed = CHECKSUM_NONE; |
2176 | } else { |
2177 | skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT)); |
2178 | skb->ip_summed = CHECKSUM_COMPLETE; |
2179 | } |
2180 | } |
2181 | |
2182 | static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) |
2183 | { |
2184 | /* This check is no longer done by usbnet */ |
2185 | if (skb->len < dev->net->hard_header_len) |
2186 | return 0; |
2187 | |
2188 | while (skb->len > 0) { |
2189 | u32 rx_cmd_a, rx_cmd_b, align_count, size; |
2190 | struct sk_buff *ax_skb; |
2191 | unsigned char *packet; |
2192 | |
2193 | rx_cmd_a = get_unaligned_le32(p: skb->data); |
2194 | skb_pull(skb, len: 4); |
2195 | |
2196 | rx_cmd_b = get_unaligned_le32(p: skb->data); |
2197 | skb_pull(skb, len: 4 + RXW_PADDING); |
2198 | |
2199 | packet = skb->data; |
2200 | |
2201 | /* get the packet length */ |
2202 | size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING; |
2203 | align_count = (4 - ((size + RXW_PADDING) % 4)) % 4; |
2204 | |
2205 | if (unlikely(size > skb->len)) { |
2206 | netif_dbg(dev, rx_err, dev->net, |
2207 | "size err rx_cmd_a=0x%08x\n" , |
2208 | rx_cmd_a); |
2209 | return 0; |
2210 | } |
2211 | |
2212 | if (unlikely(rx_cmd_a & RX_CMD_A_RED)) { |
2213 | netif_dbg(dev, rx_err, dev->net, |
2214 | "Error rx_cmd_a=0x%08x\n" , rx_cmd_a); |
2215 | dev->net->stats.rx_errors++; |
2216 | dev->net->stats.rx_dropped++; |
2217 | |
2218 | if (rx_cmd_a & RX_CMD_A_FCS) |
2219 | dev->net->stats.rx_crc_errors++; |
2220 | else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT)) |
2221 | dev->net->stats.rx_frame_errors++; |
2222 | } else { |
2223 | /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */ |
2224 | if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) { |
2225 | netif_dbg(dev, rx_err, dev->net, |
2226 | "size err rx_cmd_a=0x%08x\n" , |
2227 | rx_cmd_a); |
2228 | return 0; |
2229 | } |
2230 | |
2231 | /* last frame in this batch */ |
2232 | if (skb->len == size) { |
2233 | smsc75xx_rx_csum_offload(dev, skb, rx_cmd_a, |
2234 | rx_cmd_b); |
2235 | |
2236 | skb_trim(skb, len: skb->len - 4); /* remove fcs */ |
2237 | skb->truesize = size + sizeof(struct sk_buff); |
2238 | |
2239 | return 1; |
2240 | } |
2241 | |
2242 | ax_skb = skb_clone(skb, GFP_ATOMIC); |
2243 | if (unlikely(!ax_skb)) { |
2244 | netdev_warn(dev: dev->net, format: "Error allocating skb\n" ); |
2245 | return 0; |
2246 | } |
2247 | |
2248 | ax_skb->len = size; |
2249 | ax_skb->data = packet; |
2250 | skb_set_tail_pointer(skb: ax_skb, offset: size); |
2251 | |
2252 | smsc75xx_rx_csum_offload(dev, skb: ax_skb, rx_cmd_a, |
2253 | rx_cmd_b); |
2254 | |
2255 | skb_trim(skb: ax_skb, len: ax_skb->len - 4); /* remove fcs */ |
2256 | ax_skb->truesize = size + sizeof(struct sk_buff); |
2257 | |
2258 | usbnet_skb_return(dev, ax_skb); |
2259 | } |
2260 | |
2261 | skb_pull(skb, len: size); |
2262 | |
2263 | /* padding bytes before the next frame starts */ |
2264 | if (skb->len) |
2265 | skb_pull(skb, len: align_count); |
2266 | } |
2267 | |
2268 | return 1; |
2269 | } |
2270 | |
2271 | static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev, |
2272 | struct sk_buff *skb, gfp_t flags) |
2273 | { |
2274 | u32 tx_cmd_a, tx_cmd_b; |
2275 | void *ptr; |
2276 | |
2277 | if (skb_cow_head(skb, SMSC75XX_TX_OVERHEAD)) { |
2278 | dev_kfree_skb_any(skb); |
2279 | return NULL; |
2280 | } |
2281 | |
2282 | tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS; |
2283 | |
2284 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
2285 | tx_cmd_a |= TX_CMD_A_IPE | TX_CMD_A_TPE; |
2286 | |
2287 | if (skb_is_gso(skb)) { |
2288 | u16 mss = max(skb_shinfo(skb)->gso_size, TX_MSS_MIN); |
2289 | tx_cmd_b = (mss << TX_CMD_B_MSS_SHIFT) & TX_CMD_B_MSS; |
2290 | |
2291 | tx_cmd_a |= TX_CMD_A_LSO; |
2292 | } else { |
2293 | tx_cmd_b = 0; |
2294 | } |
2295 | |
2296 | ptr = skb_push(skb, len: 8); |
2297 | put_unaligned_le32(val: tx_cmd_a, p: ptr); |
2298 | put_unaligned_le32(val: tx_cmd_b, p: ptr + 4); |
2299 | |
2300 | return skb; |
2301 | } |
2302 | |
2303 | static int smsc75xx_manage_power(struct usbnet *dev, int on) |
2304 | { |
2305 | dev->intf->needs_remote_wakeup = on; |
2306 | return 0; |
2307 | } |
2308 | |
2309 | static const struct driver_info smsc75xx_info = { |
2310 | .description = "smsc75xx USB 2.0 Gigabit Ethernet" , |
2311 | .bind = smsc75xx_bind, |
2312 | .unbind = smsc75xx_unbind, |
2313 | .link_reset = smsc75xx_link_reset, |
2314 | .reset = smsc75xx_reset, |
2315 | .rx_fixup = smsc75xx_rx_fixup, |
2316 | .tx_fixup = smsc75xx_tx_fixup, |
2317 | .status = smsc75xx_status, |
2318 | .manage_power = smsc75xx_manage_power, |
2319 | .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR, |
2320 | }; |
2321 | |
2322 | static const struct usb_device_id products[] = { |
2323 | { |
2324 | /* SMSC7500 USB Gigabit Ethernet Device */ |
2325 | USB_DEVICE(USB_VENDOR_ID_SMSC, USB_PRODUCT_ID_LAN7500), |
2326 | .driver_info = (unsigned long) &smsc75xx_info, |
2327 | }, |
2328 | { |
2329 | /* SMSC7500 USB Gigabit Ethernet Device */ |
2330 | USB_DEVICE(USB_VENDOR_ID_SMSC, USB_PRODUCT_ID_LAN7505), |
2331 | .driver_info = (unsigned long) &smsc75xx_info, |
2332 | }, |
2333 | { }, /* END */ |
2334 | }; |
2335 | MODULE_DEVICE_TABLE(usb, products); |
2336 | |
2337 | static struct usb_driver smsc75xx_driver = { |
2338 | .name = SMSC_CHIPNAME, |
2339 | .id_table = products, |
2340 | .probe = usbnet_probe, |
2341 | .suspend = smsc75xx_suspend, |
2342 | .resume = smsc75xx_resume, |
2343 | .reset_resume = smsc75xx_resume, |
2344 | .disconnect = usbnet_disconnect, |
2345 | .disable_hub_initiated_lpm = 1, |
2346 | .supports_autosuspend = 1, |
2347 | }; |
2348 | |
2349 | module_usb_driver(smsc75xx_driver); |
2350 | |
2351 | MODULE_AUTHOR("Nancy Lin" ); |
2352 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>" ); |
2353 | MODULE_DESCRIPTION("SMSC75XX USB 2.0 Gigabit Ethernet Devices" ); |
2354 | MODULE_LICENSE("GPL" ); |
2355 | |